Compare commits

...

12 Commits

Author SHA1 Message Date
Bas Kloosterman 325d8ac7c2 Use different certificates for retrieval from different services 12 months ago
Bas Kloosterman c49da5c76e Remove extbin 12 months ago
Bas Kloosterman 76f8f4cb29 Remove logging 12 months ago
Bas Kloosterman 55b333bb98 dvza make external addr possible, rebase 12 months ago
Bas Kloosterman cf91da65d3 Remove js output 12 months ago
Bas Kloosterman d1b06bc3c6 Fix docker compose 12 months ago
Bas Kloosterman 3e237b8ef3 Update ignore files 12 months ago
Bas Kloosterman 1670759499 Rename certgen -> cryptoutil 12 months ago
Bas Kloosterman b90d8fe800 Update module name end dependencies, change case 12 months ago
Bas Kloosterman 32926ad3e7 Add different versions of ediviewer (amd64|arm64) 12 months ago
Bas Kloosterman 3461e04283 Make external grpc address configurable 12 months ago
Bas Kloosterman 674b3505ef Move patients 12 months ago
  1. 5
      .dockerignore
  2. 5
      .gitignore
  3. 11
      Dockerfile.dvza
  4. 12
      Dockerfile.his
  5. 13
      Dockerfile.wbx
  6. 2
      cryptoutil/certgen.go
  7. 6
      docker-compose.yaml
  8. 2
      dvzaservice/app/src/Connection.js
  9. 2
      dvzaservice/app/src/Home.js
  10. 1
      dvzaservice/app/src/Registrations.js
  11. 25
      dvzaservice/main.go
  12. 4
      dvzaservice/model/db.go
  13. 12
      dvzaservice/openapisrv.go
  14. 7
      dvzaservice/srv.go
  15. 1
      dvzaservice/templates/index.html
  16. 6
      go.mod
  17. 4
      go.sum
  18. 2
      his/model/db.go
  19. 4
      his/model/models.go
  20. 11
      his/openapiclient.go
  21. 0
      his/patients/cbries.edi
  22. 0
      his/patients/cbries.fhir.json
  23. 0
      his/patients/jkorts.edi
  24. 0
      his/patients/jkorts.fhir.json
  25. 18
      his/srv.go
  26. 6
      sharedmodel/auth.go
  27. 2
      sharedmodel/model.go
  28. 6
      sharedmodel/registration.go
  29. 2
      sharedmodel/service.go
  30. 2
      whiteboxservice/app/src/Connection.js
  31. 2
      whiteboxservice/app/src/Home.js
  32. 1
      whiteboxservice/app/src/Registrations.js
  33. 0
      whiteboxservice/bin/amd64/ediviewer
  34. 0
      whiteboxservice/bin/amd64/medeur.json
  35. 0
      whiteboxservice/bin/amd64/template.html
  36. 0
      whiteboxservice/bin/arm64/ediviewer
  37. 0
      whiteboxservice/bin/arm64/medeur.json
  38. 300
      whiteboxservice/bin/arm64/template.html
  39. 31
      whiteboxservice/main.go
  40. 4
      whiteboxservice/model/db.go
  41. 30
      whiteboxservice/openapisrv.go
  42. 38
      whiteboxservice/srv.go
  43. 1
      whiteboxservice/templates/index.html

@ -1,4 +1,5 @@
**/.git **/.git
**/node_modules **/node_modules
**/app **/assets
**/data/data.db **/data/data.db
**/certs

5
.gitignore vendored

@ -1,3 +1,4 @@
node_modules node_modules
data/data.db data.db
certs certs
assets

@ -3,11 +3,12 @@
## ##
## Build ## Build
## ##
FROM golang:1.18-alpine AS build FROM golang:1.19-alpine AS build
RUN apk update RUN apk update
RUN apk upgrade RUN apk upgrade
RUN apk add build-base git RUN apk add build-base git
RUN apk add --update npm
WORKDIR /app WORKDIR /app
@ -20,16 +21,20 @@ WORKDIR /app/dvzaservice
RUN go build -o /app/bin/dvza RUN go build -o /app/bin/dvza
WORKDIR /app/dvzaservice/app
RUN npm i
RUN npx webpack
## ##
## Deploy ## Deploy
## ##
FROM golang:1.18-alpine FROM alpine
WORKDIR / WORKDIR /
COPY ./dvzaservice/assets /assets
COPY ./dvzaservice/templates /templates COPY ./dvzaservice/templates /templates
COPY --from=build /app/bin/dvza ./dvza COPY --from=build /app/bin/dvza ./dvza
COPY --from=build /app/dvzaservice/assets ./assets
RUN adduser -D nonroot RUN adduser -D nonroot
USER nonroot:nonroot USER nonroot:nonroot

@ -3,11 +3,12 @@
## ##
## Build ## Build
## ##
FROM golang:1.18-alpine AS build FROM golang:1.19-alpine AS build
RUN apk update RUN apk update
RUN apk upgrade RUN apk upgrade
RUN apk add build-base git RUN apk add build-base git
RUN apk add --update npm
WORKDIR /app WORKDIR /app
@ -20,16 +21,21 @@ WORKDIR /app/his
RUN go build -o /app/bin/his RUN go build -o /app/bin/his
WORKDIR /app/his/app
RUN npm i
RUN npx webpack
## ##
## Deploy ## Deploy
## ##
FROM golang:1.18-alpine FROM alpine
WORKDIR / WORKDIR /
COPY ./his/assets /assets
COPY ./his/templates /templates COPY ./his/templates /templates
COPY ./his/patients /patients
COPY --from=build /app/bin/his ./his COPY --from=build /app/bin/his ./his
COPY --from=build /app/his/assets ./assets
RUN adduser -D nonroot RUN adduser -D nonroot
USER nonroot:nonroot USER nonroot:nonroot

@ -3,11 +3,12 @@
## ##
## Build ## Build
## ##
FROM golang:1.18-alpine AS build FROM golang:1.19-alpine AS build
RUN apk update RUN apk update
RUN apk upgrade RUN apk upgrade
RUN apk add build-base git RUN apk add build-base git
RUN apk add --update npm
WORKDIR /app WORKDIR /app
@ -20,17 +21,21 @@ WORKDIR /app/whiteboxservice
RUN go build -o /app/bin/wbx RUN go build -o /app/bin/wbx
WORKDIR /app/whiteboxservice/app
RUN npm i
RUN npx webpack
## ##
## Deploy ## Deploy
## ##
FROM golang:1.18-alpine FROM alpine
WORKDIR / WORKDIR /
COPY ./whiteboxservice/assets /assets
COPY ./whiteboxservice/templates /templates COPY ./whiteboxservice/templates /templates
COPY ./whiteboxservice/bin /bin COPY ./whiteboxservice/bin/amd64 /wbxbin
COPY --from=build /app/bin/wbx ./wbx COPY --from=build /app/bin/wbx ./wbx
COPY --from=build /app/whiteboxservice/assets ./assets
RUN adduser -D nonroot RUN adduser -D nonroot
USER nonroot:nonroot USER nonroot:nonroot

@ -1,4 +1,4 @@
package certgen package cryptoutil
import ( import (
"bytes" "bytes"

@ -16,7 +16,7 @@ services:
container_name: okapi_wbx container_name: okapi_wbx
restart: always restart: always
environment: environment:
EXT_ADDR: "okapi_wbx:8888" EXT_ADDR: "okapi_wbx"
BIN_FOLDER: "/wbxbin" BIN_FOLDER: "/wbxbin"
volumes: volumes:
- "./wbx/data:/data" - "./wbx/data:/data"
@ -24,11 +24,11 @@ services:
ports: ports:
- 8085:8085 - 8085:8085
okapi_dvza: okapi_dvza:
image: src.whiteboxsystems.nl/decozo/okapidemo/whitebox image: src.whiteboxsystems.nl/decozo/okapidemo/dvza
container_name: okapi_dvza container_name: okapi_dvza
restart: always restart: always
environment: environment:
EXT_ADDR: "okapi_dvza:9999" EXT_ADDR: "okapi_dvza"
volumes: volumes:
- "./dvza/data:/data" - "./dvza/data:/data"
- "./dvza/certs:/certs" - "./dvza/certs:/certs"

@ -40,8 +40,6 @@ const Connection = () => {
useEffect(() => { useEffect(() => {
fetch(`/api/connections/${params.connId}/${params.serviceId}`).then(x => x.json()).then(x => setService(x) ) fetch(`/api/connections/${params.connId}/${params.serviceId}`).then(x => x.json()).then(x => setService(x) )
}, []) }, [])
console.log('connection', connection)
console.log('service', service)
return ( return (
<div> <div>
<h1 className="t-page-header">Verbinding</h1> <h1 className="t-page-header">Verbinding</h1>

@ -5,7 +5,7 @@ const App = () => {
return ( return (
<div> <div>
<h1 className="t-page-header">Welkom bij DVZA</h1> <h1 className="t-page-header">Welkom bij DVZA</h1>
<p>Dit systeem is beschikbaar op: <code>dvza.openkv.mcsr.nl:9999</code></p> <p>Dit systeem is beschikbaar op: <code>{window.externalUrl}</code></p>
</div> </div>
); );
}; };

@ -7,7 +7,6 @@ const App = () => {
useEffect(() => { useEffect(() => {
fetch('/api/registrations').then(x => x.json()).then(x => setRegistrations(x) ) fetch('/api/registrations').then(x => x.json()).then(x => setRegistrations(x) )
}, []) }, [])
console.log('registrations', registrations)
return ( return (
<div> <div>
<h1 className="t-page-header">Registratie verzoeken</h1> <h1 className="t-page-header">Registratie verzoeken</h1>

@ -12,18 +12,20 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
) )
var rpcAddr = "0.0.0.0:9999" var rpcPort = "9999"
var rpcAddr = "0.0.0.0:" + rpcPort
var extRpcAddr = "localhost:" + rpcPort
var uiAddr = "0.0.0.0:9095" var uiAddr = "0.0.0.0:9095"
func loadCert() *tls.Certificate { func loadCert() *tls.Certificate {
_, err := os.Stat("certs/client.crt") _, err := os.Stat("certs/client.crt")
if err != nil { if err != nil {
_, _, certPem, keyPem, err := certgen.GenCert("dvza", "dvza") _, _, certPem, keyPem, err := cryptoutil.GenCert("dvza", "dvza")
if err != nil { if err != nil {
panic(err) panic(err)
@ -53,20 +55,9 @@ func loadCert() *tls.Certificate {
func loadKeyPair() credentials.TransportCredentials { func loadKeyPair() credentials.TransportCredentials {
certificate := loadCert() certificate := loadCert()
// data, err := ioutil.ReadFile("certs/ca.crt")
// if err != nil {
// panic("failed to load CA file: " + err.Error())
// }
// capool := x509.NewCertPool()
// if !capool.AppendCertsFromPEM(data) {
// panic("can't add ca cert")
// }
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ClientAuth: tls.RequestClientCert, ClientAuth: tls.RequestClientCert,
Certificates: []tls.Certificate{*certificate}, Certificates: []tls.Certificate{*certificate},
// ClientCAs: capool,
} }
return credentials.NewTLS(tlsConfig) return credentials.NewTLS(tlsConfig)
} }
@ -84,6 +75,10 @@ func main() {
grpcServer := grpc.NewServer(opts...) grpcServer := grpc.NewServer(opts...)
if ext := os.Getenv("EXT_ADDR"); ext != "" {
extRpcAddr = ext + ":" + rpcPort
}
go func() { go func() {
lis, err := net.Listen("tcp", rpcAddr) lis, err := net.Listen("tcp", rpcAddr)
if err != nil { if err != nil {

@ -4,8 +4,8 @@ import (
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func GetDB(location string) (*gorm.DB, error) { func GetDB(location string) (*gorm.DB, error) {

@ -13,10 +13,10 @@ import (
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
"src.whiteboxsystems.nl/DECOZO/okapidemo/dvzaservice/model" "src.whiteboxsystems.nl/decozo/okapidemo/dvzaservice/model"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
var errNotAuthorized = fmt.Errorf("Not Authorized") var errNotAuthorized = fmt.Errorf("Not Authorized")
@ -59,7 +59,7 @@ func requireConnection(db *gorm.DB, ctx context.Context) (*sharedmodel.Connectio
if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok { if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok {
item := mtls.State.PeerCertificates[0] item := mtls.State.PeerCertificates[0]
log.Println("request certificate subject:", item.Subject) log.Println("request certificate subject:", item.Subject)
pk, err := certgen.PublicKeyToJWK(item.PublicKey) pk, err := cryptoutil.PublicKeyToJWK(item.PublicKey)
if err != nil { if err != nil {
return nil, errNotAuthorized return nil, errNotAuthorized
} }
@ -240,7 +240,7 @@ func (srv *OkAPIServer) CompleteRegistration(
if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok { if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok {
item := mtls.State.PeerCertificates[0] item := mtls.State.PeerCertificates[0]
pk, err := certgen.PublicKeyToJWK(item.PublicKey) pk, err := cryptoutil.PublicKeyToJWK(item.PublicKey)
if err != nil { if err != nil {
return nil, errNotAuthorized return nil, errNotAuthorized
} }

@ -10,8 +10,8 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapidemo/dvzaservice/model" "src.whiteboxsystems.nl/decozo/okapidemo/dvzaservice/model"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
type UIService struct { type UIService struct {
@ -69,7 +69,8 @@ func (srv *UIService) init() {
} }
func (srv *UIService) GetIndex(c *gin.Context) { func (srv *UIService) GetIndex(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{})
c.HTML(http.StatusOK, "index.html", gin.H{"externalURL": extRpcAddr})
} }
func (srv *UIService) GetConnection(c *gin.Context) { func (srv *UIService) GetConnection(c *gin.Context) {

@ -8,6 +8,7 @@
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script>window.externalUrl = '{{.externalURL}}'</script>
<script src="/assets/js/index.js"></script> <script src="/assets/js/index.js"></script>
</body> </body>
</html> </html>

@ -1,14 +1,16 @@
module src.whiteboxsystems.nl/DECOZO/okapidemo module src.whiteboxsystems.nl/decozo/okapidemo
go 1.18 go 1.18
require ( require (
github.com/gin-gonic/gin v1.8.1 github.com/gin-gonic/gin v1.8.1
github.com/gofrs/uuid v4.2.0+incompatible github.com/gofrs/uuid v4.2.0+incompatible
github.com/lestrrat-go/jwx v1.2.25
google.golang.org/grpc v1.48.0 google.golang.org/grpc v1.48.0
google.golang.org/protobuf v1.28.0 google.golang.org/protobuf v1.28.0
gorm.io/driver/sqlite v1.3.6 gorm.io/driver/sqlite v1.3.6
gorm.io/gorm v1.23.8 gorm.io/gorm v1.23.8
src.whiteboxsystems.nl/decozo/okapi v0.0.5
) )
require ( require (
@ -27,7 +29,6 @@ require (
github.com/lestrrat-go/blackmagic v1.0.0 // indirect github.com/lestrrat-go/blackmagic v1.0.0 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/iter v1.0.1 // indirect github.com/lestrrat-go/iter v1.0.1 // indirect
github.com/lestrrat-go/jwx v1.2.25 // indirect
github.com/lestrrat-go/option v1.0.0 // indirect github.com/lestrrat-go/option v1.0.0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.12 // indirect github.com/mattn/go-sqlite3 v1.14.12 // indirect
@ -42,5 +43,4 @@ require (
golang.org/x/text v0.3.6 // indirect golang.org/x/text v0.3.6 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
src.whiteboxsystems.nl/DECOZO/okapi v0.0.4 // indirect
) )

@ -229,5 +229,5 @@ gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE=
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
src.whiteboxsystems.nl/DECOZO/okapi v0.0.4 h1:Hn/zWj14zknYYQr2rxkpwgZxpE+lH/qqeBp2RL9A/xY= src.whiteboxsystems.nl/decozo/okapi v0.0.5 h1:iAvxdLSib7M8+LwOufPa1rF5usufzG0Vv2qWp2gjzi0=
src.whiteboxsystems.nl/DECOZO/okapi v0.0.4/go.mod h1:zzd5uxSJdsWDyIu2LOpyBLme9Nvo6GaXsbd1CL7BmDU= src.whiteboxsystems.nl/decozo/okapi v0.0.5/go.mod h1:NTi+fO+ZkB01CVZlCDPiyWjbxEfaiPS2ECBPmu/XWek=

@ -4,7 +4,7 @@ import (
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func GetDB(location string) (*gorm.DB, error) { func GetDB(location string) (*gorm.DB, error) {

@ -4,8 +4,8 @@ import (
"time" "time"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
type ConnectionState string type ConnectionState string

@ -11,10 +11,10 @@ import (
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
"src.whiteboxsystems.nl/DECOZO/okapidemo/his/model" "src.whiteboxsystems.nl/decozo/okapidemo/his/model"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func toStruct(m map[string]interface{}) *structpb.Struct { func toStruct(m map[string]interface{}) *structpb.Struct {
@ -40,7 +40,6 @@ func getUnauthenticatedClient(addr string) (okapi.OkAPIClient, error) {
return nil, err return nil, err
} }
// defer serviceProvider.Close()
return okapi.NewOkAPIClient(conn), nil return okapi.NewOkAPIClient(conn), nil
} }
@ -88,7 +87,7 @@ func (srv *HISServer) register(addr string) (*model.ServiceProvider, error) {
return nil, err return nil, err
} }
jwkBytes, err := certgen.PublicKeyToJWKJson(certgen.ExtractPublicKey(srv.clientCert.PrivateKey)) jwkBytes, err := cryptoutil.PublicKeyToJWKJson(cryptoutil.ExtractPublicKey(srv.clientCert.PrivateKey))
if err != nil { if err != nil {
return nil, err return nil, err

@ -18,17 +18,17 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
"src.whiteboxsystems.nl/DECOZO/okapidemo/his/model" "src.whiteboxsystems.nl/decozo/okapidemo/his/model"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func loadCert() *tls.Certificate { func loadCert() *tls.Certificate {
_, err := os.Stat("certs/client.crt") _, err := os.Stat("certs/client.crt")
if err != nil { if err != nil {
_, _, certPem, keyPem, err := certgen.GenCert("whitebox", "whitebox") _, _, certPem, keyPem, err := cryptoutil.GenCert("whitebox", "whitebox")
if err != nil { if err != nil {
panic(err) panic(err)
@ -61,7 +61,6 @@ func loadKeyPair() credentials.TransportCredentials {
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ClientAuth: tls.RequestClientCert, ClientAuth: tls.RequestClientCert,
Certificates: []tls.Certificate{*certificate}, Certificates: []tls.Certificate{*certificate},
// ClientCAs: capool,
} }
return credentials.NewTLS(tlsConfig) return credentials.NewTLS(tlsConfig)
} }
@ -265,8 +264,9 @@ func (srv *HISServer) Authenticate(c *gin.Context) {
raw := "" raw := ""
method := "" method := ""
if len(c.Request.TLS.PeerCertificates) > 0 { if len(c.Request.TLS.PeerCertificates) > 0 {
jwk, err := certgen.PublicKeyToJWK(c.Request.TLS.PeerCertificates[0].PublicKey) jwk, err := cryptoutil.PublicKeyToJWK(c.Request.TLS.PeerCertificates[0].PublicKey)
if err != nil { if err != nil {
log.Printf("Error extracting public key JKW: %v", err) log.Printf("Error extracting public key JKW: %v", err)
@ -568,7 +568,7 @@ func (srv *HISServer) GetPatient(c *gin.Context) {
return return
} }
f, err := os.Open(path.Join("./data/patients", patient.FileBase+".edi")) f, err := os.Open(path.Join("./patients", patient.FileBase+".edi"))
if err != nil { if err != nil {
c.Error(err) c.Error(err)
return return
@ -599,7 +599,7 @@ func (srv *HISServer) GetFHIRPatient(c *gin.Context) {
return return
} }
f, err := os.Open(path.Join("./data/patients", patient.FileBase+".fhir.json")) f, err := os.Open(path.Join("./patients", patient.FileBase+".fhir.json"))
if err != nil { if err != nil {
c.Error(err) c.Error(err)
return return

@ -6,8 +6,8 @@ import (
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
) )
const AuthMethodDecozoMTLS = "http://decozo.org/proto/auth/mtls" const AuthMethodDecozoMTLS = "http://decozo.org/proto/auth/mtls"
@ -56,7 +56,7 @@ func NewAuthConfig(cfg *okapi.ProtocolAuthConfiguration) *AuthConfig {
authConfig.Raw, _ = cfg.GetConfiguration().AsMap()["token"].(string) authConfig.Raw, _ = cfg.GetConfiguration().AsMap()["token"].(string)
case AuthMethodDecozoMTLS: case AuthMethodDecozoMTLS:
k, _ := cfg.GetConfiguration().AsMap()["publicKey"].(string) k, _ := cfg.GetConfiguration().AsMap()["publicKey"].(string)
jwk, _ := certgen.StringToJWK(k) jwk, _ := cryptoutil.StringToJWK(k)
if jwk != nil { if jwk != nil {
rawBytes, _ := jwk.Thumbprint(crypto.SHA256) rawBytes, _ := jwk.Thumbprint(crypto.SHA256)
authConfig.Raw = fmt.Sprintf("%X", rawBytes) authConfig.Raw = fmt.Sprintf("%X", rawBytes)

@ -6,7 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
) )
type Protocol struct { type Protocol struct {

@ -5,8 +5,8 @@ import (
"fmt" "fmt"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
) )
type RegistrationStatus string type RegistrationStatus string
@ -35,7 +35,7 @@ func (r *Registration) SetAuthConfig(cfg *okapi.XISAuthConfiguration) error {
switch cfg.Method { switch cfg.Method {
case okapi.XISAuthMethod_mTLS: case okapi.XISAuthMethod_mTLS:
k, err := certgen.StringToJWK(cfg.GetMtlsConfiguration().GetPublicKey()) k, err := cryptoutil.StringToJWK(cfg.GetMtlsConfiguration().GetPublicKey())
if err != nil { if err != nil {
return err return err

@ -5,7 +5,7 @@ import (
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
) )
type ServiceDefinition struct { type ServiceDefinition struct {

@ -40,8 +40,6 @@ const Connection = () => {
useEffect(() => { useEffect(() => {
fetch(`/api/connections/${params.connId}/${params.serviceId}`).then(x => x.json()).then(x => setService(x) ) fetch(`/api/connections/${params.connId}/${params.serviceId}`).then(x => x.json()).then(x => setService(x) )
}, []) }, [])
console.log('connection', connection)
console.log('service', service)
return ( return (
<div> <div>
<h1 className="t-page-header">Patiënten</h1> <h1 className="t-page-header">Patiënten</h1>

@ -5,7 +5,7 @@ const App = () => {
return ( return (
<div> <div>
<h1 className="t-page-header">Welkom bij Whitebox</h1> <h1 className="t-page-header">Welkom bij Whitebox</h1>
<p>Dit systeem is beschikbaar op: <code>wbx.openkv.mcsr.nl:8888</code></p> <p>Dit systeem is beschikbaar op: <code>{window.externalUrl}</code></p>
</div> </div>
); );
}; };

@ -7,7 +7,6 @@ const App = () => {
useEffect(() => { useEffect(() => {
fetch('/api/registrations').then(x => x.json()).then(x => setRegistrations(x) ) fetch('/api/registrations').then(x => x.json()).then(x => setRegistrations(x) )
}, []) }, [])
console.log('registrations', registrations)
return ( return (
<div> <div>
<h1 className="t-page-header">Registratie verzoeken</h1> <h1 className="t-page-header">Registratie verzoeken</h1>

@ -1,103 +1,98 @@
<!DOCTYPE html><html><head>
<meta charset="utf-8">
<title>{{.Patient.Name}} — MEDEUR</title>
<style> <style>
body { margin: 1em auto; font-size: 12pt; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; } .container { margin: 1em auto; font-size: 12pt; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; }
@media screen and (max-width: 700px) { @media screen and (max-width: 700px) {
body { width: 700px; } .container { width: 700px; }
} }
@media screen and (min-width: 1200px) { @media screen and (min-width: 1200px) {
body { width: 1200px; } .container { width: 1200px; }
} }
* { margin: 0; padding: 0; box-sizing: border-box; } .container h3 { margin-bottom: 8px; }
h3 { margin-bottom: 8px; } .container ul { list-style-type: none; }
ul { list-style-type: none; } .container li + li { margin-top: 10px; }
li + li { margin-top: 10px; } .container td { vertical-align: top; }
td { vertical-align: top; } .container .seg { margin-top: 8px; padding: 8px 10px; border: 0 solid #e7e7e7; border-width: 0 1px 1px 1px; }
.seg { margin-top: 8px; padding: 8px 10px; border: 0 solid #e7e7e7; border-width: 0 1px 1px 1px; } .container .seg-hdr { margin-top: 8px; border-top-width: 1px; background: #F8F8F8; }
.seg-hdr { margin-top: 8px; border-top-width: 1px; background: #F8F8F8; } .container .seg-hdr-white { margin-top: 8px; background: #FFFFFF; border-color: transparent; }
.seg-hdr-white { margin-top: 8px; background: #FFFFFF; border-color: transparent; }
.container a { color: royalblue }
a { color: royalblue }
.container table.patient th { text-align: left; padding-right: 1em }
table.patient th { text-align: left; padding-right: 1em }
.container table.SOEPkind { margin: -6px 0 }
table.SOEPkind { margin: -6px 0 } .container table.SOEPkind tr { height: 1em }
table.SOEPkind tr { height: 1em } .container table.SOEPkind th { text-align: left; width: 32px; height: 1em; font-weight: normal }
table.SOEPkind th { text-align: left; width: 32px; height: 1em; font-weight: normal }
.container table.results th { text-align: left }
table.results th { text-align: left }
.container .error { position: fixed; top: 10px; margin-left: 32px; border: 2px solid #000000; background-color: #FF2222; }
.error { position: fixed; top: 10px; margin-left: 32px; border: 2px solid #000000; background-color: #FF2222; }
.row + .row { margin-top: 4px; }
.row + .row { margin-top: 4px; }
.table { font-size: 100%; width: 100%; border-spacing: 0; border-collapse: collapse; }
.table { font-size: 100%; width: 100%; border-spacing: 0; border-collapse: collapse; } .table tr { font-size: 100% }
.table tr { font-size: 100% } .table td { font-size: 100% }
.table td { font-size: 100% } .table th { font-size: 100%; text-align: left; }
.table th { font-size: 100%; text-align: left; } .table tbody td { font-size: 100%; text-align: left; padding: 2px 8px 2px 0; }
.table tbody td { font-size: 100%; text-align: left; padding: 2px 8px 2px 0; } .table thead th { font-size: 100%; padding: 0 0 2px 0; }
.table thead th { font-size: 100%; padding: 0 0 2px 0; } .table tr.highlight { background: #E3E9E3 }
.table tr.highlight { background: #E3E9E3 }
.column-attn { width: 1em; }
.column-attn { width: 1em; } .column-code { width: 4em; }
.column-code { width: 4em; } .column-date { width: 6.5em; }
.column-date { width: 6.5em; } .column-small-name { width: 10em; }
.column-small-name { width: 10em; } .column-medium-name { width: 14em; }
.column-medium-name { width: 14em; } .column-large-name { width: 28em; }
.column-large-name { width: 28em; } .column-name { width: 20em; }
.column-name { width: 20em; } .column-instr{ width: 15em; }
.column-instr{ width: 15em; } .column-quantity { width: 12em; }
.column-quantity { width: 12em; }
.no-margin { margin-bottom: 0px; }
.no-margin { margin-bottom: 0px; }
.seg-date { float: left; width: 6.5em; }
.seg-date { float: left; width: 6.5em; } .seg-content-offset { margin-left: 6.5em }
.seg-content-offset { margin-left: 6.5em }
.column-result-id { width: 16em }
.column-result-id { width: 16em } .column-result-name { width: 10em }
.column-result-name { width: 10em }
.container h3.fold-toggle { margin-bottom: 8px }
h3.fold-toggle { margin-bottom: 8px } .container h4.fold-toggle { margin-bottom: 0; margin-top: 4px }
h4.fold-toggle { margin-bottom: 0; margin-top: 4px } .container h3.fold-toggle.fold-toggle-hidden { margin-bottom: 0 }
h3.fold-toggle.fold-toggle-hidden { margin-bottom: 0 } .container h4.fold-toggle.fold-toggle-hidden { margin-bottom: 4px }
h4.fold-toggle.fold-toggle-hidden { margin-bottom: 4px } .fold-toggle .fold-marker:before,
.fold-toggle .fold-marker:before, .container h3.fold-toggle:before,
h3.fold-toggle:before, .container h4.fold-toggle:before { content: "▾ " }
h4.fold-toggle:before { content: "▾ " } .fold-toggle.fold-toggle-hidden .fold-marker:before,
.fold-toggle.fold-toggle-hidden .fold-marker:before, .container h3.fold-toggle.fold-toggle-hidden:before,
h3.fold-toggle.fold-toggle-hidden:before, .container h4.fold-toggle.fold-toggle-hidden:before { content: "▸ " }
h4.fold-toggle.fold-toggle-hidden:before { content: "▸ " } .fold-toggle { cursor: pointer; }
.fold-toggle { cursor: pointer; } .fold-hidden {display: none}
.fold-hidden {display: none}
.hidden
.hidden {
{ display: none !important
display: none !important }
}
textarea .container textarea
{ {
border: 1px solid #333; border: 1px solid #333;
padding: .5em; padding: .5em;
font-size: 100% font-size: 100%
} }
input[type=submit] .container input[type=submit]
{ {
font-size: 90%; font-size: 90%;
padding: .25em padding: .25em
} }
button .container button
{ {
font-size: 75%; font-size: 75%;
padding: .25em padding: .25em
} }
</style></head> </style>
<body>
<div class="container"> <div class="container">
{{define "person-row"}} {{define "person-row"}}
@ -114,9 +109,6 @@ button
<thead> <thead>
<tr> <tr>
<th class="column-date">Datum</th> <th class="column-date">Datum</th>
{{if HasEndDates .Episodes }}
<th class="column-date">Einddatum</th>
{{end}}
<th class="column-code">Type</th> <th class="column-code">Type</th>
<th class="column-date">ICPC</th> <th class="column-date">ICPC</th>
<th class="column-name">Beschrijving</th> <th class="column-name">Beschrijving</th>
@ -128,32 +120,26 @@ button
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{range .Episodes}} {{range .Episodes}}
<tr {{if .Anchor}} id="medigroup-{{.Anchor}}"{{end}}> <tr{{if .Anchor}} id="medigroup-{{.Anchor}}"{{end}}>
<td>{{.Date}}</td> <td>{{.Date}}</td>
<td>{{.Type}}</td>
{{if HasEndDates $.Episodes }} <td>{{.ICPC}}</td>
<td style="{{if EndDateInPast .EndDate}}color: red;{{end}}">{{.EndDate}}</td>
{{end}}
<td>{{.Type}}</td> {{if eq $root.Extra.verbose_icpc_description "true"}}
<td>{{.ICPC}}</td> <td>{{.Title}}</td>
<td>{{.Description}}</td>
{{if eq $root.Extra.verbose_icpc_description "true"}} {{else}}
<td>{{.Title}}</td> {{if eq .Description ""}}
<td>{{.Description}}</td> <td colspan="2">{{.Title}}</td>
{{else}} {{else}}
{{if eq .Description ""}} <td colspan="2">{{.Description}}</td>
<td colspan="2">{{.Title}}</td> {{end}}
{{else}} {{end}}
<td colspan="2">{{.Description}}</td> </tr>{{end}}
{{end}}
{{end}}
</tr>
{{end}}
</tbody> </tbody>
</table> </table>
{{end}} {{end}}
{{define "medi-group-ica"}} {{define "medi-group-ica"}}
{{$root := .}} {{$root := .}}
@ -244,7 +230,7 @@ button
{{if .Episodes}} {{if .Episodes}}
<div class="seg seg-hdr"> <div class="seg seg-hdr">
<h3>Episodelijst</h3> <h3>Episodelijst</h3>
{{template "medi-group-epi" .}} {{template "medi-group-epi" .}}
</div> </div>
{{end}} {{end}}
@ -363,14 +349,14 @@ button
{{if .Extra.csrf_token }} {{if .Extra.csrf_token }}
<div class="seg seg-hdr-white"> <div class="seg seg-hdr-white">
<br> <br>
<h3 id="feedback-header"><button onClick="feedbackHeaderClicked()">Notitie schrijven</button></h3> <h3 id="feedback-header"><button onClick="feedbackHeaderClicked()">Notitie schrijven</button></h3>
<form id="feedback-form" class="hidden" method="POST" onSubmit="sendFeedback(); return false"> <!-- TODO: contruct proper URL in golang --> <form id="feedback-form" class="hidden" method="POST" onSubmit="sendFeedback(); return false"> <!-- TODO: contruct proper URL in golang -->
<input type="hidden" name="csrf_token" value="{{.Extra.csrf_token}}" id="csrf"> <input type="hidden" name="csrf_token" value="{{.Extra.csrf_token}}" id="csrf">
<p><br><textarea id="feedback-textarea" rows="7" cols="50"></textarea> <p><br><textarea id="feedback-textarea" rows="7" cols="50"></textarea>
<p><br><input type="submit" value="Opsturen"> <p><br><input type="submit" value="Opsturen">
</form> </form>
</div> </div>
@ -453,68 +439,4 @@ function getXMLHttpRequest()
} }
} }
function sendFeedback()
{
var URL = document.location.href.replace('preview', '') + 'pushback'
var textarea = document.getElementById('feedback-textarea')
var message = textarea.value
var csrf_element = document.getElementById('csrf')
var csrf= csrf_element.value
var xmlhttp = getXMLHttpRequest()
xmlhttp.onreadystatechange = function() { sendFeedbackHandler(xmlhttp) }
params = '';
params += 'csrf_token=' + encodeURIComponent(csrf) + '&'
params += 'message=' + encodeURIComponent(message)
xmlhttp.open('POST', URL, true)
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xmlhttp.setRequestHeader('Content-length', params.length)
xmlhttp.setRequestHeader('Connection', 'close')
xmlhttp.send(params)
}
function sendFeedbackHandler(xmlhttp)
{
if (xmlhttp.readyState != 4) { return }
if (xmlhttp.status == 200)
{
try
{
var response = JSON.parse(xmlhttp.responseText)
if (response.success) {
alert('Feedback is succesvol verstuurd.')
toggle('feedback-form')
} else {
alert('Er is iets fout gegaan: ' + response.error)
}
}
catch (e)
{
alert('Fout bij versturen feedback.')
}
}
else
{
alert('Fout bij versturen feedback.')
}
}
function send_height_to_parent() {
var body = document.body,
html = document.documentElement;
var height = Math.max( body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight );
var msg = {
"height": height,
};
parent.postMessage(msg, "*");
}
send_height_to_parent();
</script></body></html> </script></body></html>

@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net" "net"
@ -12,19 +13,22 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
) )
var srvaddr = "0.0.0.0:8888" var rpcPort = "8888"
var srvaddr = "0.0.0.0:" + rpcPort
var extRpcAddr = "localhost:" + rpcPort
var patientIf = "0.0.0.0:8085" var patientIf = "0.0.0.0:8085"
var binFolder = "./bin"
func loadCert() *tls.Certificate { var binFolder = "./bin/arm64"
_, err := os.Stat("certs/client.crt")
func loadCert(name string) *tls.Certificate {
_, err := os.Stat(fmt.Sprintf("certs/%s.crt", name))
if err != nil { if err != nil {
_, _, certPem, keyPem, err := certgen.GenCert("whitebox", "whitebox") _, _, certPem, keyPem, err := cryptoutil.GenCert("whitebox", "whitebox")
if err != nil { if err != nil {
panic(err) panic(err)
@ -34,15 +38,15 @@ func loadCert() *tls.Certificate {
panic(err) panic(err)
} }
if err := ioutil.WriteFile("certs/client.crt", []byte(certPem), 0600); err != nil { if err := ioutil.WriteFile(fmt.Sprintf("certs/%s.crt", name), []byte(certPem), 0600); err != nil {
panic(err) panic(err)
} }
if err := ioutil.WriteFile("certs/client.key", []byte(keyPem), 0600); err != nil { if err := ioutil.WriteFile(fmt.Sprintf("certs/%s.key", name), []byte(keyPem), 0600); err != nil {
panic(err) panic(err)
} }
} }
certificate, err := tls.LoadX509KeyPair("certs/client.crt", "certs/client.key") certificate, err := tls.LoadX509KeyPair(fmt.Sprintf("certs/%s.crt", name), fmt.Sprintf("certs/%s.key", name))
if err != nil { if err != nil {
panic("Load client certification failed: " + err.Error()) panic("Load client certification failed: " + err.Error())
@ -52,12 +56,11 @@ func loadCert() *tls.Certificate {
} }
func loadKeyPair() credentials.TransportCredentials { func loadKeyPair() credentials.TransportCredentials {
certificate := loadCert() certificate := loadCert("client")
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ClientAuth: tls.RequestClientCert, ClientAuth: tls.RequestClientCert,
Certificates: []tls.Certificate{*certificate}, Certificates: []tls.Certificate{*certificate},
// ClientCAs: capool,
} }
return credentials.NewTLS(tlsConfig) return credentials.NewTLS(tlsConfig)
} }
@ -71,6 +74,10 @@ func main() {
binFolder = os.Getenv("BIN_FOLDER") binFolder = os.Getenv("BIN_FOLDER")
} }
if ext := os.Getenv("EXT_ADDR"); ext != "" {
extRpcAddr = ext + ":" + rpcPort
}
openapisrv := NewServer() openapisrv := NewServer()
openapisrv.LoadData("./data/data.db") openapisrv.LoadData("./data/data.db")
opts := []grpc.ServerOption{ opts := []grpc.ServerOption{

@ -4,8 +4,8 @@ import (
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger" "gorm.io/gorm/logger"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
) )
func GetDB(location string) (*gorm.DB, error) { func GetDB(location string) (*gorm.DB, error) {

@ -14,10 +14,10 @@ import (
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapi" "src.whiteboxsystems.nl/decozo/okapi"
"src.whiteboxsystems.nl/DECOZO/okapidemo/certgen" "src.whiteboxsystems.nl/decozo/okapidemo/cryptoutil"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
"src.whiteboxsystems.nl/DECOZO/okapidemo/whiteboxservice/model" "src.whiteboxsystems.nl/decozo/okapidemo/whiteboxservice/model"
) )
var errNotAuthorized = fmt.Errorf("Not Authorized") var errNotAuthorized = fmt.Errorf("Not Authorized")
@ -45,6 +45,8 @@ type OkAPIServer struct {
okapi.UnimplementedOkAPIServer okapi.UnimplementedOkAPIServer
data *gorm.DB data *gorm.DB
clientCert tls.Certificate clientCert tls.Certificate
visiteCert tls.Certificate
wnhCert tls.Certificate
} }
func (srv *OkAPIServer) LoadData(location string) error { func (srv *OkAPIServer) LoadData(location string) error {
@ -61,7 +63,7 @@ func requireConnection(db *gorm.DB, ctx context.Context) (*sharedmodel.Connectio
if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok { if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok {
item := mtls.State.PeerCertificates[0] item := mtls.State.PeerCertificates[0]
log.Println("request certificate subject:", item.Subject) log.Println("request certificate subject:", item.Subject)
pk, err := certgen.PublicKeyToJWK(item.PublicKey) pk, err := cryptoutil.PublicKeyToJWK(item.PublicKey)
if err != nil { if err != nil {
return nil, errNotAuthorized return nil, errNotAuthorized
} }
@ -224,7 +226,7 @@ func (srv *OkAPIServer) CompleteRegistration(
if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok { if mtls, ok := p.AuthInfo.(credentials.TLSInfo); ok {
item := mtls.State.PeerCertificates[0] item := mtls.State.PeerCertificates[0]
pk, err := certgen.PublicKeyToJWK(item.PublicKey) pk, err := cryptoutil.PublicKeyToJWK(item.PublicKey)
if err != nil { if err != nil {
return nil, errNotAuthorized return nil, errNotAuthorized
} }
@ -307,7 +309,15 @@ func (srv *OkAPIServer) EnableService(
AuthConfig: sharedmodel.NewAuthConfig(in.Fetch.Auth), AuthConfig: sharedmodel.NewAuthConfig(in.Fetch.Auth),
} }
publicKey, err := certgen.PublicKeyToJWKJson(certgen.ExtractPublicKey(srv.clientCert.PrivateKey)) var cert tls.Certificate
if in.ServiceId == "wbx:visitelijst" {
cert = srv.visiteCert
} else if in.ServiceId == "wbx:waarneming" {
cert = srv.wnhCert
}
publicKey, err := cryptoutil.PublicKeyToJWKJson(cryptoutil.ExtractPublicKey(cert.PrivateKey))
if err != nil { if err != nil {
return nil, fmt.Errorf("Error retrieving pub key: %v", err) return nil, fmt.Errorf("Error retrieving pub key: %v", err)
@ -621,9 +631,13 @@ func (srv *OkAPIServer) ListPatientRegistrations(
} }
func NewServer() *OkAPIServer { func NewServer() *OkAPIServer {
cert := loadCert() cert := loadCert("client")
visiteCert := loadCert("visite")
wnhCert := loadCert("wnh")
return &OkAPIServer{ return &OkAPIServer{
clientCert: *cert, clientCert: *cert,
visiteCert: *visiteCert,
wnhCert: *wnhCert,
} }
} }

@ -13,14 +13,16 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gorm.io/gorm" "gorm.io/gorm"
"src.whiteboxsystems.nl/DECOZO/okapidemo/sharedmodel" "src.whiteboxsystems.nl/decozo/okapidemo/sharedmodel"
"src.whiteboxsystems.nl/DECOZO/okapidemo/whiteboxservice/model" "src.whiteboxsystems.nl/decozo/okapidemo/whiteboxservice/model"
) )
type UIService struct { type UIService struct {
srv *http.Server srv *http.Server
inited bool inited bool
clientCert tls.Certificate clientCert tls.Certificate
visiteCert tls.Certificate
wnhCert tls.Certificate
data *gorm.DB data *gorm.DB
} }
@ -70,7 +72,7 @@ func (srv *UIService) init() {
} }
func (srv *UIService) GetIndex(c *gin.Context) { func (srv *UIService) GetIndex(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{}) c.HTML(http.StatusOK, "index.html", gin.H{"externalURL": extRpcAddr})
} }
func (srv *UIService) GetConnection(c *gin.Context) { func (srv *UIService) GetConnection(c *gin.Context) {
@ -117,14 +119,21 @@ func (srv *UIService) GetPatient(c *gin.Context) {
} }
url := fmt.Sprintf("%v/%v/%v", protoconfig["url"], "patients", protometa["patientID"]) url := fmt.Sprintf("%v/%v/%v", protoconfig["url"], "patients", protometa["patientID"])
req, _ := http.NewRequest("GET", url, nil) req, _ := http.NewRequest("GET", url, nil)
var cert tls.Certificate
if serviceConfig.Service.ServiceID == "wbx:visitelijst" {
cert = srv.visiteCert
} else if serviceConfig.Service.ServiceID == "wbx:waarneming" {
cert = srv.wnhCert
}
client := &http.Client{ client := &http.Client{
Transport: &http.Transport{ Transport: &http.Transport{
TLSClientConfig: &tls.Config{ TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
Certificates: []tls.Certificate{srv.clientCert}, Certificates: []tls.Certificate{cert},
}, },
}, },
} }
@ -224,12 +233,19 @@ func (srv *UIService) GetRegistrations(c *gin.Context) {
} }
func NewUIServer(addr string) *UIService { func NewUIServer(addr string) *UIService {
cert := loadCert() cert := loadCert("client")
visiteCert := loadCert("visite")
srv := &UIService{srv: &http.Server{ wnhCert := loadCert("wnh")
Addr: addr,
Handler: gin.Default(), srv := &UIService{
}, clientCert: *cert} srv: &http.Server{
Addr: addr,
Handler: gin.Default(),
},
clientCert: *cert,
visiteCert: *visiteCert,
wnhCert: *wnhCert,
}
return srv return srv
} }

@ -8,6 +8,7 @@
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
<script>window.externalUrl = '{{.externalURL}}'</script>
<script src="/assets/js/index.js"></script> <script src="/assets/js/index.js"></script>
</body> </body>
</html> </html>
Loading…
Cancel
Save