Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
abee46d
feat(pep): integrate with real Nuts node for token introspection and …
JorisHeadease Jan 29, 2026
cff5b22
fix(pep): add dnsmasq for DNS resolution of host.docker.internal
JorisHeadease Jan 29, 2026
abd6ac0
refactor(pep): switch from ngx.fetch to nginx subrequests
JorisHeadease Jan 29, 2026
d89142a
fix(pep): add input validation and security headers
JorisHeadease Jan 29, 2026
93cc43f
refactor(pdp): remove patient_bsn from PEP→PDP contract
JorisHeadease Jan 30, 2026
04f7074
docs: fix inaccurate README and test comments
JorisHeadease Jan 30, 2026
1f3e592
Merge branch 'main' into feat/pep-nuts-node-integration
JorisHeadease Jan 30, 2026
19681ce
Revert "refactor(pdp): remove patient_bsn from PEP→PDP contract"
JorisHeadease Jan 30, 2026
431bfb7
fix(pdp): check Resource.Type instead of Content-Type for capability …
JorisHeadease Jan 30, 2026
566edcf
Apply suggestions from code review
JorisHeadease Jan 30, 2026
21e2a8e
Update pep/nginx/js/authorize.js
JorisHeadease Jan 30, 2026
1fad529
fix(pdp): correct comment about capability checking skip condition
JorisHeadease Jan 30, 2026
e7d9d88
docs(pep): reference PlantUML diagram and expand production notes
JorisHeadease Feb 2, 2026
b612fad
fix(pep): return 400 on malformed URL encoding instead of silent fall…
JorisHeadease Feb 2, 2026
922439a
refactor(pep): use FHIR_BASE_PATH for configurable API path
JorisHeadease Feb 2, 2026
3cf72ae
feat(pep): pass request body to PDP for POST search
JorisHeadease Feb 2, 2026
1ba537c
fix(pep): separate incoming and upstream FHIR paths
JorisHeadease Feb 2, 2026
b07a18f
docs(pep): add log security note to production considerations
JorisHeadease Feb 2, 2026
124cda8
fix(pep): split FHIR_BASE_PATH and FHIR_UPSTREAM_PATH in docker-compose
JorisHeadease Feb 2, 2026
7f8d576
fix(pep): add PEP_HOSTNAME to prevent Host header spoofing in DPoP
JorisHeadease Feb 2, 2026
b96f659
fix(pep): preserve primitive types in normalizeClaimValue
JorisHeadease Feb 4, 2026
bdc8b6c
refactor(pep): use embedded Nuts node and clean up e2e test harness
JorisHeadease Feb 4, 2026
de6b127
Merge branch 'main' into feat/pep-nuts-node-integration
JorisHeadease Feb 4, 2026
888dff5
fix(pdp): align PatientBSN assignment position with main
JorisHeadease Feb 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions component/pdp/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ func capabilityForScope(ctx context.Context, scope string) (fhir.CapabilityState
}

func evalCapabilityPolicy(ctx context.Context, input PolicyInput) (PolicyInput, PolicyResult) {
if input.Action.Properties.ContentType != "application/fhir+json" {
// Skip capability checking for requests that don't target a specific resource type (e.g., /metadata, /)
if input.Resource.Type == nil {
return input, Allow()
}

Expand Down Expand Up @@ -100,7 +101,7 @@ func evalInteraction(
var resourceDescriptions []fhir.CapabilityStatementRestResource
for _, rest := range statement.Rest {
for _, res := range rest.Resource {
if res.Type == input.Resource.Type {
if res.Type == *input.Resource.Type {
resourceDescriptions = append(resourceDescriptions, res)
}
}
Expand Down
20 changes: 12 additions & 8 deletions component/pdp/capabilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"testing"

"github.com/nuts-foundation/nuts-knooppunt/lib/to"
"github.com/stretchr/testify/assert"
"github.com/zorgbijjou/golang-fhir-models/fhir-models/fhir"
)
Expand All @@ -17,7 +18,7 @@ func TestComponent_reject_interaction(t *testing.T) {
},
},
Resource: PolicyResource{
Type: fhir.ResourceTypeOrganization,
Type: to.Ptr(fhir.ResourceTypeOrganization),
Properties: PolicyResourceProperties{
ResourceId: "118876",
},
Expand Down Expand Up @@ -47,7 +48,7 @@ func TestComponent_allow_interaction(t *testing.T) {
},
},
Resource: PolicyResource{
Type: fhir.ResourceTypeOrganization,
Type: to.Ptr(fhir.ResourceTypeOrganization),
Properties: PolicyResourceProperties{
ResourceId: "118876",
},
Expand Down Expand Up @@ -77,7 +78,7 @@ func TestComponent_allow_search_param(t *testing.T) {
},
},
Resource: PolicyResource{
Type: fhir.ResourceTypeOrganization,
Type: to.Ptr(fhir.ResourceTypeOrganization),
Properties: PolicyResourceProperties{
ResourceId: "118876",
},
Expand Down Expand Up @@ -108,7 +109,7 @@ func TestComponent_reject_search_param(t *testing.T) {
},
},
Resource: PolicyResource{
Type: fhir.ResourceTypeOrganization,
Type: to.Ptr(fhir.ResourceTypeOrganization),
Properties: PolicyResourceProperties{
ResourceId: "118876",
},
Expand Down Expand Up @@ -138,6 +139,9 @@ func TestComponent_reject_interaction_type(t *testing.T) {
SubjectOrganizationId: "00000666",
},
},
Resource: PolicyResource{
Type: to.Ptr(fhir.ResourceTypeOrganization),
},
Action: PolicyAction{
Properties: PolicyActionProperties{
ContentType: "application/fhir+json",
Expand All @@ -163,7 +167,7 @@ func TestComponent_allow_include(t *testing.T) {
},
},
Resource: PolicyResource{
Type: fhir.ResourceTypeLocation,
Type: to.Ptr(fhir.ResourceTypeLocation),
Properties: PolicyResourceProperties{
ResourceId: "88716123",
},
Expand Down Expand Up @@ -194,7 +198,7 @@ func TestComponent_reject_include(t *testing.T) {
},
},
Resource: PolicyResource{
Type: fhir.ResourceTypeEndpoint,
Type: to.Ptr(fhir.ResourceTypeEndpoint),
Properties: PolicyResourceProperties{
ResourceId: "88716123",
},
Expand Down Expand Up @@ -225,7 +229,7 @@ func TestComponent_reject_revinclude(t *testing.T) {
},
},
Resource: PolicyResource{
Type: fhir.ResourceTypePractitioner,
Type: to.Ptr(fhir.ResourceTypePractitioner),
Properties: PolicyResourceProperties{
ResourceId: "88716123",
},
Expand Down Expand Up @@ -256,7 +260,7 @@ func TestComponent_allow_revinclude(t *testing.T) {
},
},
Resource: PolicyResource{
Type: fhir.ResourceTypeOrganization,
Type: to.Ptr(fhir.ResourceTypeOrganization),
Properties: PolicyResourceProperties{
ResourceId: "88716123",
},
Expand Down
2 changes: 1 addition & 1 deletion component/pdp/fhirreq.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ func NewPolicyInput(request PDPRequest) (PolicyInput, PolicyResult) {
}

if tokens.ResourceType != nil {
policyInput.Resource.Type = *tokens.ResourceType
policyInput.Resource.Type = tokens.ResourceType
if tokens.ResourceId != "" {
policyInput.Resource.Properties.ResourceId = tokens.ResourceId
}
Expand Down
2 changes: 1 addition & 1 deletion component/pdp/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type PolicyInput struct {
}

type PolicyResource struct {
Type fhir.ResourceType `json:"type"`
Type *fhir.ResourceType `json:"type"`
Properties PolicyResourceProperties `json:"properties"`
}

Expand Down
11 changes: 8 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,17 +183,22 @@ services:
volumes:
- ./pep/logs:/var/log/nginx
environment:
# Backend connections
- FHIR_BACKEND_HOST=hapi-fhir
- FHIR_BACKEND_PORT=7050
- FHIR_BASE_PATH=/fhir
- FHIR_UPSTREAM_PATH=/fhir/DEFAULT
- KNOOPPUNT_PDP_HOST=knooppunt
- KNOOPPUNT_PDP_PORT=8081
# Nuts node connection (Authorization Server)
- NUTS_NODE_HOST=knooppunt
- NUTS_NODE_INTERNAL_PORT=8081
# Data holder (this organization)
- DATA_HOLDER_ORGANIZATION_URA=00000666
- DATA_HOLDER_FACILITY_TYPE=Z3
- REQUESTING_FACILITY_TYPE=Z3
- PURPOSE_OF_USE=treatment
depends_on:
- hapi-fhir
- knooppunt # Knooppunt provides the PDP endpoint
- knooppunt # Knooppunt provides the PDP and proxies to Nuts node
healthcheck:
test:
["CMD", "wget", "--spider", "--quiet", "http://localhost:8080/health"]
Expand Down
12 changes: 8 additions & 4 deletions helm/pep/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,22 @@ spec:
value: {{ .Values.env.fhirBackendHost | quote }}
- name: FHIR_BACKEND_PORT
value: {{ .Values.env.fhirBackendPort | quote }}
- name: FHIR_BASE_PATH
value: {{ .Values.env.fhirBasePath | quote }}
- name: KNOOPPUNT_PDP_HOST
value: {{ .Values.env.knooppuntPdpHost | quote }}
- name: KNOOPPUNT_PDP_PORT
value: {{ .Values.env.knooppuntPdpPort | quote }}
- name: NUTS_NODE_HOST
value: {{ .Values.env.nutsNodeHost | quote }}
- name: NUTS_NODE_INTERNAL_PORT
value: {{ .Values.env.nutsNodeInternalPort | quote }}
- name: DATA_HOLDER_ORGANIZATION_URA
value: {{ .Values.env.dataHolderOrganizationUra | quote }}
- name: DATA_HOLDER_FACILITY_TYPE
value: {{ .Values.env.dataHolderFacilityType | quote }}
- name: REQUESTING_FACILITY_TYPE
value: {{ .Values.env.requestingFacilityType | quote }}
- name: PURPOSE_OF_USE
value: {{ .Values.env.purposeOfUse | quote }}
- name: NGINX_PORT
value: {{ .Values.service.port | quote }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
Expand Down
9 changes: 7 additions & 2 deletions helm/pep/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,19 @@ image:

# PEP configuration environment variables
env:
# FHIR backend (upstream server)
fhirBackendHost: "hapi-fhir"
fhirBackendPort: "7050"
fhirBasePath: "/fhir"
# Knooppunt PDP for authorization decisions
knooppuntPdpHost: "knooppunt"
knooppuntPdpPort: "8081"
# Nuts node for token introspection (RFC 7662)
nutsNodeHost: "nuts-node"
nutsNodeInternalPort: "8081"
# Data holder organization identity
dataHolderOrganizationUra: "00000001"
dataHolderFacilityType: "Z3"
requestingFacilityType: "Z3"
purposeOfUse: "treatment"

# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
imagePullSecrets: []
Expand Down
Loading
Loading