diff --git a/.bandit.yml b/.bandit.yml new file mode 100644 index 0000000..2bba86a --- /dev/null +++ b/.bandit.yml @@ -0,0 +1,2 @@ +assert_used: + skips: ["*test*.py"] diff --git a/.checkstyle/checkstyle.xml b/.checkstyle/checkstyle.xml index ee59903..696e2b3 100644 --- a/.checkstyle/checkstyle.xml +++ b/.checkstyle/checkstyle.xml @@ -1,323 +1,388 @@ - + - - + + - + - + + + - + - - + + - + - - - + + + - + - - - + + + - - - + + + - - + + - + - - + + - + - + OBJBLOCK, STATIC_INIT, RECORD_DEF, COMPACT_CTOR_DEF" /> - - + + - - - + + + COMPACT_CTOR_DEF" /> - - + + - + - - - - - - - + + + + + + - - - - - - - - - - + SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND" /> + + + + + + + + + + - - + COMPACT_CTOR_DEF" /> + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - - - + + + + - - - - - - + + + + + + - - - + + + RECORD_COMPONENT_DEF" /> - - - + + + - - - - + + + + - + - - + + - + RECORD_DEF" /> - - + + TYPE_EXTENSION_AND " /> - - + + - - - + + + - - - + + + - + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - + - + - + - - + + + + + + + + + + + + + + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93b568d..c0f51be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: CI +name: ci on: push: @@ -8,29 +8,25 @@ on: pull_request: branches: [master] +permissions: read-all + +env: + IMAGE_NAME: ghcr.io/${{ github.repository }} + jobs: - lint: - name: Lint Code Base - runs-on: ubuntu-20.04 + trivy: + name: trivy scan Code Base + runs-on: ubuntu-22.04 + permissions: + security-events: write steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3 with: fetch-depth: 0 - - uses: actions/setup-python@v4 - - name: Run pre-commit - uses: pre-commit/action@v3.0.0 - - name: Lint code base - uses: github/super-linter@v4 - env: - VALIDATE_ALL_CODEBASE: false - VALIDATE_DOCKERFILE: false - DEFAULT_BRANCH: master - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - FILTER_REGEX_EXCLUDE: "gradlew" - VALIDATE_JAVA: false + - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@9ab158e8597f3b310480b9a69402b419bc03dbd5 # 0.8.0 with: scan-type: "fs" ignore-unfixed: true @@ -38,123 +34,158 @@ jobs: template: "@/contrib/sarif.tpl" output: "trivy-results.sarif" severity: "CRITICAL" + - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37 with: sarif_file: "trivy-results.sarif" + build: - name: Build - runs-on: ubuntu-20.04 - needs: lint + name: build + runs-on: ubuntu-22.04 + outputs: + image-tags: ${{ steps.container_meta.outputs.tags }} + image-digest: ${{ steps.build.outputs.digest }} + image-name: ${{ env.IMAGE_NAME }} steps: - name: Checkout code - uses: actions/checkout@v3 - - name: Docker meta - id: docker_meta - uses: docker/metadata-action@v4 - with: - images: | - ghcr.io/${{ github.repository }} - harbor.miracum.org/miracum-etl/fhir-gateway + uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3 + + - name: Validate Gradle wrapper + uses: gradle/wrapper-validation-action@55e685c48d84285a5b0418cd094606e199cca3b6 # v1 + - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2 + - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@8c0edbc76e98fa90f69d9a2c020dcb50019dc325 # v2 + + - name: Container meta + id: container_meta + uses: docker/metadata-action@57396166ad8aefe6098280995947635806a0e6ea # v4 + with: + images: | + ${{ env.IMAGE_NAME }} + - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2 if: ${{ github.event_name != 'pull_request' }} with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Login to MIRACUM Container Registry - uses: docker/login-action@v2 - if: ${{ github.event_name != 'pull_request' }} - with: - registry: harbor.miracum.org - username: "robot$miracum-etl+github-actions" - password: ${{ secrets.MIRACUM_HARBOR_ETL_TOKEN }} - - name: Cache Docker layers - uses: actions/cache@v3 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-buildx- + - name: Get platforms to build id: platforms run: | if [ "$IS_PULL_REQUEST" == "true" ]; then - echo "::set-output name=platforms::linux/amd64" + echo "{platforms}={linux/amd64}" >> "$GITHUB_OUTPUT" else - echo "::set-output name=platforms::linux/amd64" + echo "{platforms}={linux/amd64}" >> "$GITHUB_OUTPUT" fi env: IS_PULL_REQUEST: ${{ github.event_name == 'pull_request' }} + - name: Build and push - id: docker_build - uses: docker/build-push-action@v3 + id: build + uses: docker/build-push-action@c56af957549030174b10d6867f20e78cfd7debc5 # v3 with: - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache + cache-from: type=gha + cache-to: type=gha,mode=max push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.docker_meta.outputs.tags }} - labels: ${{ steps.docker_meta.outputs.labels }} + tags: ${{ steps.container_meta.outputs.tags }} + labels: ${{ steps.container_meta.outputs.labels }} load: ${{ github.event_name == 'pull_request' }} platforms: ${{ steps.platforms.outputs.platforms }} - - name: List images - id: list_images - run: | - docker image ls - IMAGES=(${{ steps.docker_meta.outputs.tags }}) - echo "##[set-output name=image_name;]${IMAGES[0]}" + + - uses: KengoTODA/actions-setup-docker-compose@main + with: + version: '2.14.2' # the full version of `docker-compose` command + - name: Run E2E tests env: - FHIR_GATEWAY_IMAGE_NAME: "${{ steps.list_images.outputs.image_name }}" + FHIR_GATEWAY_IMAGE_NAME: "${{ fromJson(steps.container_meta.outputs.json).tags[0] }}" run: | - docker-compose -p "$GITHUB_JOB-e2e" -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml -f tests/e2e/docker-compose.yml --project-directory=tests/e2e build - docker-compose -p "$GITHUB_JOB-e2e" -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml -f tests/e2e/docker-compose.yml --project-directory=tests/e2e run gpasinit - docker-compose -p "$GITHUB_JOB-e2e" -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml -f tests/e2e/docker-compose.yml --project-directory=tests/e2e run tester + docker-compose -p e2e -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml -f tests/e2e/docker-compose.yml --project-directory=tests/e2e build + docker-compose -p e2e -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml --project-directory=tests/e2e up -d + docker-compose -p e2e -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml -f tests/e2e/docker-compose.yml --project-directory=tests/e2e run tester + - name: Print E2E logs - if: always() + env: + FHIR_GATEWAY_IMAGE_NAME: "${{ fromJson(steps.container_meta.outputs.json).tags[0] }}" + if: ${{ always() }} run: | - docker-compose -p "$GITHUB_JOB-e2e" -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml -f tests/e2e/docker-compose.yml logs - docker-compose -p "$GITHUB_JOB-e2e" -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml -f tests/e2e/docker-compose.yml down --volumes --remove-orphans + docker-compose -p e2e -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml -f tests/e2e/docker-compose.yml logs + docker-compose -p e2e -f deploy/docker-compose.yml -f deploy/docker-compose.gw-deps.yml -f tests/e2e/docker-compose.yml down --volumes --remove-orphans + + sign-images: + name: sign images + runs-on: ubuntu-22.04 + if: ${{ github.event_name != 'pull_request' }} + needs: + - build + permissions: + id-token: write + packages: write + steps: + - name: Login to GitHub Container Registry + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Install Cosign - if: ${{ github.event_name != 'pull_request' }} - uses: sigstore/cosign-installer@main - - name: Store signing key in tmp file - if: ${{ github.event_name != 'pull_request' }} - env: - COSIGN_KEY: ${{ secrets.MIRACUM_COSIGN_PRIVATE_KEY }} - run: echo "$COSIGN_KEY" > /tmp/cosign.key - - name: Sign images - if: ${{ github.event_name != 'pull_request' }} + uses: sigstore/cosign-installer@9becc617647dfa20ae7b1151972e9b3a2c338a2b # v2.8.1 + + - name: Sign image env: - COSIGN_PASSWORD: ${{ secrets.MIRACUM_COSIGN_PASSWORD }} - IMAGES: ${{ steps.docker_meta.outputs.tags }} + IMAGES: ${{ needs.build.outputs.image-tags }} + DIGEST: ${{ needs.build.outputs.image-digest }} + COSIGN_EXPERIMENTAL: "true" run: | while read -r image; do - echo "Signing $image" - cosign sign --key /tmp/cosign.key "$image" + echo "Signing '$image' using keyless approach" + cosign sign "$image@$DIGEST" done <<< "$IMAGES" + + container-provenance: + if: ${{ startsWith(github.ref, 'refs/tags/') }} + needs: + - build + permissions: + actions: read # for detecting the Github Actions environment. + id-token: write # for creating OIDC tokens for signing. + packages: write # for uploading attestations. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.4.0 + with: + image: ${{ needs.build.outputs.image-name }} + digest: ${{ needs.build.outputs.image-digest }} + registry-username: ${{ github.actor }} + # TODO(https://github.com/slsa-framework/slsa-github-generator/issues/492): Remove after GA release. + compile-generator: true + secrets: + registry-password: ${{ secrets.GITHUB_TOKEN }} + release: - needs: build - name: Release - runs-on: ubuntu-20.04 + needs: + - build + name: release + runs-on: ubuntu-22.04 if: ${{ github.event_name != 'pull_request' }} + permissions: + contents: write + pull-requests: write steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3 with: fetch-depth: 0 - - name: Setup Node.js - uses: actions/setup-node@v3 + + - name: Semantic Release + uses: cycjimmy/semantic-release-action@3b88c82b34098e8b51e401c1082c9170b0a3ec3c # tag=v3 with: - node-version: 14 - - name: Install semantic release - run: npm install -g semantic-release@17 @semantic-release/github @semantic-release/exec @semantic-release/error @semantic-release/changelog @commitlint/cli @semantic-release/commit-analyzer @semantic-release/release-notes-generator conventional-changelog-conventionalcommits - - name: Release + extra_plugins: | + conventional-changelog-conventionalcommits@5.0.0 env: GITHUB_TOKEN: ${{ secrets.MIRACUM_BOT_SEMANTIC_RELEASE_TOKEN }} - run: npx semantic-release diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml new file mode 100644 index 0000000..aefd434 --- /dev/null +++ b/.github/workflows/codeql.yaml @@ -0,0 +1,84 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +permissions: read-all + +on: + push: + branches: ["master"] + pull_request: + # The branches below must be a subset of the branches above + branches: ["master"] + schedule: + - cron: "32 16 * * 3" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-22.04 + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ["java"] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3 + + - name: Set up Java + uses: actions/setup-java@1df8dbefe2a8cbc99770194893dd902763bee34b # v3 + with: + java-version: "17" + distribution: "adopt" + cache: gradle + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@896079047b4bb059ba6f150a5d87d47dde99e6e5 # v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@896079047b4bb059ba6f150a5d87d47dde99e6e5 # v2 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@896079047b4bb059ba6f150a5d87d47dde99e6e5 # v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/mega-linter.yaml b/.github/workflows/mega-linter.yaml new file mode 100644 index 0000000..d72f97b --- /dev/null +++ b/.github/workflows/mega-linter.yaml @@ -0,0 +1,59 @@ +--- +# MegaLinter GitHub Action configuration file +# More info at https://oxsecurity.github.io/megalinter +name: MegaLinter + +on: + # Trigger mega-linter at every push. Action will also be visible from Pull Requests to master + pull_request: + branches: [master] + +permissions: read-all + +env: # Comment env block if you do not want to apply fixes + # Apply linter fixes configuration + APPLY_FIXES: none # When active, APPLY_FIXES must also be defined as environment variable (in github/workflows/mega-linter.yml or other CI tool) + APPLY_FIXES_EVENT: pull_request # Decide which event triggers application of fixes in a commit or a PR (pull_request, push, all) + APPLY_FIXES_MODE: commit # If APPLY_FIXES is used, defines if the fixes are directly committed (commit) or posted in a PR (pull_request) + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + build: + name: MegaLinter + runs-on: ubuntu-22.04 + permissions: + contents: read + pull-requests: write + steps: + # Git Checkout + - name: Checkout Code + uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3 + with: + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + fetch-depth: 0 # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to improve performances + + # MegaLinter + - name: MegaLinter + id: ml + # You can override MegaLinter flavor used to have faster performances + # More info at https://oxsecurity.github.io/megalinter/flavors/ + uses: oxsecurity/megalinter@d9cc1b4179f513fcb50fa438babf54816f8037d5 # v6.17.0 + env: + # All available variables are described in documentation + # https://oxsecurity.github.io/megalinter/configuration/ + VALIDATE_ALL_CODEBASE: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} # Validates all source when push on main, else just the git diff with main. Set 'true' if you always want to lint all sources + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # ADD YOUR CUSTOM ENV VARIABLES HERE TO OVERRIDE VALUES OF .mega-linter.yml AT THE ROOT OF YOUR REPOSITORY + + # Upload MegaLinter artifacts + - name: Archive production artifacts + if: ${{ always() }} + uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1 + with: + name: MegaLinter reports + path: | + megalinter-reports + mega-linter.log diff --git a/.github/workflows/scorecard.yaml b/.github/workflows/scorecard.yaml new file mode 100644 index 0000000..f780f2a --- /dev/null +++ b/.github/workflows/scorecard.yaml @@ -0,0 +1,72 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecards supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: "38 22 * * 0" + push: + branches: ["master"] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecards analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3.2.0 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2 + with: + results_file: results.sarif + results_format: sarif + # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecards on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_READ_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@959cbb7472c4d4ad70cdfe6f4976053fe48ab394 # v2.1.37 + with: + sarif_file: results.sarif diff --git a/.gitignore b/.gitignore index 53ddcf3..6305bf0 100644 --- a/.gitignore +++ b/.gitignore @@ -141,3 +141,38 @@ dmypy.json .pyre/ # End of https://www.gitignore.io/api/python + +# Created by https://www.toptal.com/developers/gitignore/api/java +# Edit at https://www.toptal.com/developers/gitignore?templates=java + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +# End of https://www.toptal.com/developers/gitignore/api/java + +bin/ + +megalinter-reports/ diff --git a/.mega-linter.yml b/.mega-linter.yml new file mode 100644 index 0000000..3a6d831 --- /dev/null +++ b/.mega-linter.yml @@ -0,0 +1,30 @@ +# Configuration file for MegaLinter +# See all available variables at https://megalinter.io/configuration/ and in linters documentation + +APPLY_FIXES: none # all, none, or list of linter keys +# ENABLE: # If you use ENABLE variable, all other languages/formats/tooling-formats will be disabled by default +# ENABLE_LINTERS: # If you use ENABLE_LINTERS variable, all other linters will be disabled by default +DISABLE: + - COPYPASTE # Uncomment to disable checks of excessive copy-pastes + - SPELL # Uncomment to disable checks of spelling mistakes +SHOW_ELAPSED_TIME: true +FILEIO_REPORTER: false +# DISABLE_ERRORS: true # Uncomment if you want MegaLinter to detect errors but not block CI to pass + +DISABLE_LINTERS: + - JAVA_PMD + - MARKDOWN_MARKDOWN_LINK_CHECK + - PYTHON_PYRIGHT + - PYTHON_PYLINT + - REPOSITORY_DEVSKIM + - REPOSITORY_DUSTILOCK + - SQL_TSQLLINT + +GROOVY_NPM_GROOVY_LINT_ARGUMENTS: + - "--failon=warning" + +REPOSITORY_TRIVY_ARGUMENTS: + - "--severity=MEDIUM,HIGH,CRITICAL" + - "--ignore-unfixed" + +JAVA_CHECKSTYLE_CONFIG_FILE: .checkstyle/checkstyle.xml diff --git a/.renovaterc.json b/.renovaterc.json new file mode 100644 index 0000000..9f2ffd5 --- /dev/null +++ b/.renovaterc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["github>miracum/.github//renovate/default"] +} diff --git a/Dockerfile b/Dockerfile index 66a77a5..9edc281 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,28 @@ -FROM gradle:7.5.1-jdk17 AS build +# syntax=docker/dockerfile:1.4 +FROM docker.io/library/gradle:7.6.0-jdk17@sha256:9073fad2045e28b86d2d1669bc219739a84771635f033aed0fa293835dd5fad0 AS build WORKDIR /home/gradle/src ENV GRADLE_USER_HOME /gradle -COPY build.gradle settings.gradle ./ +COPY build.gradle settings.gradle gradle.properties ./ -# Only download dependencies -# see https://zwbetz.com/why-is-my-gradle-build-in-docker-so-slow/ -RUN gradle clean build --no-daemon > /dev/null 2>&1 || true +RUN gradle --no-daemon build || true COPY --chown=gradle:gradle . . -RUN gradle build --info && \ - gradle jacocoTestReport && \ - awk -F"," '{ instructions += $4 + $5; covered += $5 } END { print covered, "/", instructions, " instructions covered"; print 100*covered/instructions, "% covered" }' build/jacoco/coverage.csv && \ - java -Djarmode=layertools -jar build/libs/*.jar extract -FROM gcr.io/distroless/java17-debian11:nonroot +RUN < "while true; do - kafkacat -b kafka1:19092 -K: -t fhir.all -P -l /data/mock-data.ndjson; - kafkacat -b kafka1:19092 -K: -t fhir.all-2 -P -l /data/mock-data-2.ndjson; + kcat -b kafka1:19092 -K: -t fhir.all -P -l /data/mock-data.ndjson; + kcat -b kafka1:19092 -K: -t fhir.all-2 -P -l /data/mock-data-2.ndjson; sleep 10; done" volumes: @@ -17,7 +15,7 @@ services: - kafka1 kafka1: - image: docker.vectorized.io/vectorized/redpanda:v22.2.6 + image: docker.io/vectorized/redpanda:v22.3.9 container_name: kafka1 command: - redpanda @@ -39,7 +37,7 @@ services: - 9644:9644 akhq: - image: tchiotludo/akhq:0.22.0 + image: tchiotludo/akhq:0.23.0 environment: AKHQ_CONFIGURATION: | akhq: diff --git a/deploy/docker-compose.exposed.yml b/deploy/docker-compose.exposed.yml index 50fc7b1..fae3113 100644 --- a/deploy/docker-compose.exposed.yml +++ b/deploy/docker-compose.exposed.yml @@ -1,5 +1,3 @@ -version: "3.7" - services: jaeger: ports: @@ -10,9 +8,9 @@ services: ports: - 127.0.0.1:15432:5432 - gpas: + vfps: ports: - - 127.0.0.1:18081:8080 + - "127.0.0.1:8083:8080" fhir-server: ports: diff --git a/deploy/docker-compose.gw-deps.yml b/deploy/docker-compose.gw-deps.yml index 9d2fe4c..f09561e 100644 --- a/deploy/docker-compose.gw-deps.yml +++ b/deploy/docker-compose.gw-deps.yml @@ -1,102 +1,117 @@ -version: "3.9" - services: jaeger: - image: jaegertracing/all-in-one:1.38 + image: jaegertracing/all-in-one:1.40 fhir-pseudonymizer: - image: harbor.miracum.org/miracum-etl/fhir-pseudonymizer:v1.6.0 + image: ghcr.io/miracum/fhir-pseudonymizer:v2.15.0@sha256:8953eb45d1c66d52631fab51a525b0479df7a7811fa4ac0aef0ef2e6515fb12f environment: - JAEGER__HOST: jaeger - JAEGER__PORT: 6831 - GPAS__URL: ${GPAS_URL:-http://gpas:8080/gpas/gpasService} + Tracing__Enabled: "true" + Tracing__Jaeger__AgentHost: jaeger + Tracing__Jaeger__AgentPort: 6831 + Vfps__Address: "dns:///vfps:8081" + UseSystemTextJsonFhirSerializer: "true" + PseudonymizationService: "Vfps" volumes: - - ./anonymization.yaml:/etc/anonymization.yaml:ro + - ${PWD}/deploy/anonymization.yaml:/etc/anonymization.yaml:ro depends_on: - jaeger - - gpas + - vfps loinc-converter: - image: harbor.miracum.org/miracum-etl/loinc-conversion:v1.13.3 + image: harbor.miracum.org/miracum-etl/loinc-conversion:v1.13.4@sha256:3522a3e463239c80a0d4ac7751fe188b160681a7e5dbeea3d998499eb7570125 environment: JAEGER_AGENT_HOST: jaeger depends_on: - jaeger - fhir-db: - image: postgres:14.5 + vfps-db: + image: docker.io/library/postgres:15.1@sha256:f4cd32e7a418d9c9ba043e7d561243388202b654c740bcc85ca40b41d9fb4f1e + restart: unless-stopped + deploy: + resources: + limits: + memory: 1g + cpus: "1" + reservations: + memory: 1g + cpus: "1" + ipc: private + security_opt: + - "no-new-privileges:true" + privileged: false environment: POSTGRES_PASSWORD: postgres - POSTGRES_DB: fhir + POSTGRES_DB: vfps - gpas: - image: tmfev/gpas:1.9.1 + vfps: + image: ghcr.io/miracum/vfps:v1.1.3@sha256:a4940766829e5d5f330030e8813049d2f074651876853f672f45de0709e35fbf + restart: unless-stopped + deploy: + resources: + limits: + memory: 512m + cpus: "2" + reservations: + memory: 512m + cpus: "2" + ipc: none + cap_drop: + - ALL + read_only: true + privileged: false + security_opt: + - "no-new-privileges:true" environment: - JAVA_OPTS: >- - -Xms512m - -Xmx1G - -XX:MetaspaceSize=96M - -XX:MaxMetaspaceSize=256m - -Djava.net.preferIPv4Stack=true - -Djava.awt.headless=true + COMPlus_EnableDiagnostics: "0" + ForceRunDatabaseMigrations: "true" + ConnectionStrings__PostgreSQL: "Host=vfps-db:5432;Database=vfps;Timeout=60;Max Auto Prepare=5;Application Name=vfps;Maximum Pool Size=50;" + PGUSER: postgres + PGPASSWORD: postgres + Tracing__IsEnabled: "true" + Tracing__Jaeger__AgentHost: "jaeger" + Pseudonymization__Caching__Namespaces__IsEnabled: "true" + depends_on: + - vfps-db fhir-server: - image: docker.io/hapiproject/hapi:v5.6.0-distroless + image: docker.io/hapiproject/hapi:v6.2.2@sha256:9c4e8af94d81ac0049dbb589e4cd855bf78c9c13be6f6844e814c63d63545b44 + + fhir-db: + image: docker.io/library/postgres:15.1@sha256:f4cd32e7a418d9c9ba043e7d561243388202b654c740bcc85ca40b41d9fb4f1e + environment: + POSTGRES_PASSWORD: postgres + POSTGRES_DB: fhir - gpasinit-patient: - image: curlimages/curl:7.85.0 + vfps-init-patient: + image: docker.io/curlimages/curl:7.87.0 command: | -X POST - -H 'Content-Type:application/xml' - -d ' - - - - - - PATIENT - org.emau.icmvc.ganimed.ttp.psn.generator.ReedSolomonLagrange - org.emau.icmvc.ganimed.ttp.psn.alphabets.Symbol31 - PSN_LENGTH=31;PSN_PREFIX=p;INCLUDE_PREFIX_IN_CHECK_DIGIT_CALCULATION=false;PSNS_DELETABLE=true;MAX_DETECTED_ERRORS=2; - PATIENT Domain - - - - ' + -H 'Content-Type: application/json' + --fail --retry-connrefuse --connect-timeout 10 --max-time 120 --retry 10 --retry-delay 10 - http://gpas:8080/gpas/DomainService + -d '{"name": "PATIENT", "pseudonymGenerationMethod": 0, "pseudonymLength": 32, "pseudonymPrefix": "p-"}' + http://vfps:8080/v1/namespaces depends_on: - - gpas + vfps: + condition: service_started - gpasinit-fall: - image: curlimages/curl:7.85.0 + vfps-init-fall: + image: docker.io/curlimages/curl:7.87.0 command: | -X POST - -H 'Content-Type:application/xml' - -d ' - - - - - - FALL - org.emau.icmvc.ganimed.ttp.psn.generator.ReedSolomonLagrange - org.emau.icmvc.ganimed.ttp.psn.alphabets.Symbol31 - PSN_LENGTH=31;PSN_PREFIX=f;INCLUDE_PREFIX_IN_CHECK_DIGIT_CALCULATION=false;PSNS_DELETABLE=true;MAX_DETECTED_ERRORS=2; - FALL Domain - - - - ' + -H 'Content-Type: application/json' + --fail --retry-connrefuse --connect-timeout 10 --max-time 120 --retry 10 --retry-delay 10 - http://gpas:8080/gpas/DomainService + -d '{"name": "FALL", "pseudonymGenerationMethod": 0, "pseudonymLength": 32, "pseudonymPrefix": "f-"}' + http://vfps:8080/v1/namespaces depends_on: - - gpas + vfps: + condition: service_started diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 52e9cc0..65a1c0a 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -1,8 +1,6 @@ -version: "3.9" - services: gateway: - image: ${FHIR_GATEWAY_IMAGE_NAME:-ghcr.io/miracum/fhir-gateway:v3.10.5} + image: ${FHIR_GATEWAY_IMAGE_NAME:-ghcr.io/miracum/fhir-gateway:v3.10.6} restart: on-failure environment: SPRING_DATASOURCE_URL: ${SPRING_DATASOURCE_URL:-jdbc:postgresql://fhir-db:5432/fhir} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e583..943f0cb 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8fad3f5..2b22d05 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index a69d9cb..65dcd68 100644 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/gradlew.bat b/gradlew.bat index 53a6b23..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% diff --git a/renovate.json b/renovate.json deleted file mode 100644 index b627478..0000000 --- a/renovate.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "github>whitesource/merge-confidence:beta", - "config:base", - "group:allNonMajor", - ":disableDependencyDashboard" - ] -} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index dae1b46..7f285ce 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -7,7 +7,7 @@ services: loinc: conversions: url: "http://localhost:19090/api/v1" - enabled: true + enabled: false failOnError: false pseudonymizer: enabled: true diff --git a/src/main/resources/static/fhir-metadata.json b/src/main/resources/static/fhir-metadata.json index d8dfaec..2c9479f 100644 --- a/src/main/resources/static/fhir-metadata.json +++ b/src/main/resources/static/fhir-metadata.json @@ -13,10 +13,7 @@ "url": "http://localhost:8080/fhir" }, "fhirVersion": "4.0.0", - "format": [ - "application/fhir+xml", - "application/fhir+json" - ], + "format": ["application/fhir+xml", "application/fhir+json"], "rest": [ { "extension": [ @@ -1046,9 +1043,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -1098,9 +1093,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -1150,10 +1143,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "BodyStructure:patient" - ], + "searchInclude": ["*", "BodyStructure:patient"], "searchParam": [ { "name": "_language", @@ -1223,11 +1213,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "Bundle:composition", - "Bundle:message" - ], + "searchInclude": ["*", "Bundle:composition", "Bundle:message"], "searchParam": [ { "name": "_language", @@ -1732,9 +1718,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -1930,9 +1914,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -2443,10 +2425,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "CodeSystem:supplements" - ], + "searchInclude": ["*", "CodeSystem:supplements"], "searchParam": [ { "name": "_language", @@ -2871,9 +2850,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -4235,10 +4212,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "DeviceDefinition:parent" - ], + "searchInclude": ["*", "DeviceDefinition:parent"], "searchParam": [ { "name": "_language", @@ -4303,11 +4277,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "DeviceMetric:parent", - "DeviceMetric:source" - ], + "searchInclude": ["*", "DeviceMetric:parent", "DeviceMetric:source"], "searchParam": [ { "name": "_language", @@ -5058,9 +5028,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -5370,10 +5338,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "Endpoint:organization" - ], + "searchInclude": ["*", "Endpoint:organization"], "searchParam": [ { "name": "_language", @@ -5527,10 +5492,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "EnrollmentResponse:request" - ], + "searchInclude": ["*", "EnrollmentResponse:request"], "searchParam": [ { "name": "_language", @@ -6198,9 +6160,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -6650,11 +6610,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "Goal:patient", - "Goal:subject" - ], + "searchInclude": ["*", "Goal:patient", "Goal:subject"], "searchParam": [ { "name": "_language", @@ -6744,9 +6700,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -6866,11 +6820,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "Group:managing-entity", - "Group:member" - ], + "searchInclude": ["*", "Group:managing-entity", "Group:member"], "searchParam": [ { "name": "_language", @@ -9637,9 +9587,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -9783,10 +9731,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "MedicinalProductContraindication:subject" - ], + "searchInclude": ["*", "MedicinalProductContraindication:subject"], "searchParam": [ { "name": "_language", @@ -9841,10 +9786,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "MedicinalProductIndication:subject" - ], + "searchInclude": ["*", "MedicinalProductIndication:subject"], "searchParam": [ { "name": "_language", @@ -9899,9 +9841,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -9951,10 +9891,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "MedicinalProductInteraction:subject" - ], + "searchInclude": ["*", "MedicinalProductInteraction:subject"], "searchParam": [ { "name": "_language", @@ -10009,9 +9946,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -10061,10 +9996,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "MedicinalProductPackaged:subject" - ], + "searchInclude": ["*", "MedicinalProductPackaged:subject"], "searchParam": [ { "name": "_language", @@ -10124,9 +10056,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -10191,10 +10121,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "MedicinalProductUndesirableEffect:subject" - ], + "searchInclude": ["*", "MedicinalProductUndesirableEffect:subject"], "searchParam": [ { "name": "_language", @@ -10249,9 +10176,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -10525,10 +10450,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "MolecularSequence:patient" - ], + "searchInclude": ["*", "MolecularSequence:patient"], "searchParam": [ { "name": "_language", @@ -10643,9 +10565,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -11159,9 +11079,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -11376,9 +11294,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -11675,9 +11591,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -12412,9 +12326,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -12919,9 +12831,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -13181,10 +13091,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "RelatedPerson:patient" - ], + "searchInclude": ["*", "RelatedPerson:patient"], "searchParam": [ { "name": "_language", @@ -14095,9 +14002,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -14227,10 +14132,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "Schedule:actor" - ], + "searchInclude": ["*", "Schedule:actor"], "searchParam": [ { "name": "_language", @@ -14630,10 +14532,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "Slot:schedule" - ], + "searchInclude": ["*", "Slot:schedule"], "searchParam": [ { "name": "_language", @@ -14839,9 +14738,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -15090,9 +14987,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -15217,9 +15112,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -15304,10 +15197,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "Substance:substance-reference" - ], + "searchInclude": ["*", "Substance:substance-reference"], "searchParam": [ { "name": "_language", @@ -15397,9 +15287,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -15449,9 +15337,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -15501,9 +15387,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -15553,9 +15437,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -15605,9 +15487,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -15657,9 +15537,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -16039,9 +15917,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -16161,10 +16037,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "TestReport:testscript" - ], + "searchInclude": ["*", "TestReport:testscript"], "searchParam": [ { "name": "_language", @@ -16244,9 +16117,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -16376,9 +16247,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*" - ], + "searchInclude": ["*"], "searchParam": [ { "name": "_language", @@ -16518,10 +16387,7 @@ "conditionalCreate": true, "conditionalUpdate": true, "conditionalDelete": "multiple", - "searchInclude": [ - "*", - "VerificationResult:target" - ], + "searchInclude": ["*", "VerificationResult:target"], "searchParam": [ { "name": "_language", diff --git a/tests/e2e/Dockerfile b/tests/e2e/Dockerfile index 24b1c82..102a617 100644 --- a/tests/e2e/Dockerfile +++ b/tests/e2e/Dockerfile @@ -1,12 +1,13 @@ -FROM python:3.9-alpine +FROM docker.io/library/python:3.11-alpine@sha256:af8fef83397b3886ed93d2c81bf3b4e70d39c0789c1c6feb1ecb86ca9bc42a0a # hadolint ignore=DL3018 RUN apk --no-cache add git WORKDIR /opt/tests COPY requirements.txt . -RUN pip install -r requirements.txt +RUN pip install --require-hashes --no-cache-dir -r requirements.txt COPY . . +USER 65534:65534 ENTRYPOINT ["pytest"] -CMD [ "test.py" ] +CMD [ "-p", "no:cacheprovider", "test.py" ] diff --git a/tests/e2e/data/anonymization.yaml b/tests/e2e/data/anonymization.yaml deleted file mode 100644 index 90cdb7a..0000000 --- a/tests/e2e/data/anonymization.yaml +++ /dev/null @@ -1,49 +0,0 @@ ---- -fhirVersion: R4 -fhirPathRules: - - path: Patient.id - method: pseudonymize - domain: TEST - - path: Encounter.id - method: pseudonymize - domain: TEST - - path: nodesByType('Reference').where(reference.startsWith('Encounter/')).reference - method: pseudonymize - domain: TEST - - path: nodesByType('Reference').where(reference.startsWith('Patient/')).reference - method: pseudonymize - domain: TEST - # Bundle.entry.where(resource.ofType(Patient)).fullUrl is unfortunately not supported by the FhirPath implementation - - path: Bundle.entry.where(fullUrl.startsWith('Patient/')).fullUrl - method: pseudonymize - domain: TEST - - path: Bundle.entry.request.where(url.startsWith('Patient/')).url - method: pseudonymize - domain: TEST - - path: Bundle.entry.where(fullUrl.startsWith('Encounter/')).fullUrl - method: pseudonymize - domain: TEST - - path: Bundle.entry.request.where(url.startsWith('Encounter/')).url - method: pseudonymize - domain: TEST - - path: nodesByType('Reference').display - method: redact - - path: nodesByType('HumanName') - method: redact - - path: nodesByType('Identifier').where(type.coding.system='http://terminology.hl7.org/CodeSystem/v2-0203' and type.coding.code='VN').value - method: pseudonymize - domain: TEST - - path: nodesByType('Identifier').where(type.coding.system='http://terminology.hl7.org/CodeSystem/v2-0203' and type.coding.code='MR').value - method: pseudonymize - domain: TEST - - path: nodesByType('Identifier').where(type.coding.system='http://fhir.de/CodeSystem/identifier-type-de-basis' and type.coding.code='GKV' or type.coding.code='PKV') - method: redact -parameters: - dateShiftKey: "" - dateShiftScope: resource - cryptoHashKey: miracum - encryptKey: "" - enablePartialAgesForRedact: true - enablePartialDatesForRedact: true - enablePartialZipCodesForRedact: true - restrictedZipCodeTabulationAreas: [] diff --git a/tests/e2e/data/bundle.json b/tests/e2e/data/bundle.json index 0e6d4de..1339a3e 100644 --- a/tests/e2e/data/bundle.json +++ b/tests/e2e/data/bundle.json @@ -94,9 +94,7 @@ "name": [ { "family": "Wisozk", - "given": [ - "Mariana" - ] + "given": ["Mariana"] } ], "gender": "male", diff --git a/tests/e2e/docker-compose.yml b/tests/e2e/docker-compose.yml index 9a26987..afca9c3 100644 --- a/tests/e2e/docker-compose.yml +++ b/tests/e2e/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.7" - services: tester: build: . @@ -7,35 +5,3 @@ services: FHIR_SERVER_URL: "http://gateway:8080/fhir" depends_on: - gateway - - fhir-pseudonymizer: - volumes: - - ${PWD}/tests/e2e/data/anonymization.yaml:/etc/anonymization.yaml:ro - - gpasinit: - image: curlimages/curl:7.77.0 - command: -X POST - -H 'Content-Type:application/xml' - -d ' - - - - - - TEST - org.emau.icmvc.ganimed.ttp.psn.generator.ReedSolomonLagrange - org.emau.icmvc.ganimed.ttp.psn.alphabets.Symbol31 - PSN_LENGTH=10;PSN_PREFIX=TEST-ID.;INCLUDE_PREFIX_IN_CHECK_DIGIT_CALCULATION=false;PSNS_DELETABLE=true;MAX_DETECTED_ERRORS=2; - TEST Domain - - - - ' - --retry-connrefuse - --connect-timeout 10 - --max-time 60 - --retry 5 - --retry-delay 10 - http://gpas:8080/gpas/DomainService - depends_on: - - gpas diff --git a/tests/e2e/requirements.in b/tests/e2e/requirements.in new file mode 100644 index 0000000..5c2fd8a --- /dev/null +++ b/tests/e2e/requirements.in @@ -0,0 +1,3 @@ +fhirclient==4.1.0 +retrying==1.3.3 +pytest==7.2.0 diff --git a/tests/e2e/requirements.txt b/tests/e2e/requirements.txt index 1ad5c03..259af11 100644 --- a/tests/e2e/requirements.txt +++ b/tests/e2e/requirements.txt @@ -1,3 +1,67 @@ -git+http://github.com/smart-on-fhir/client-py@v4.0.0#egg=fhirclient -pytest==6.2.4 -retrying==1.3.3 +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --generate-hashes requirements.in +# +attrs==22.2.0 \ + --hash=sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836 \ + --hash=sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99 + # via pytest +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 + # via requests +charset-normalizer==2.1.1 \ + --hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 \ + --hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f + # via requests +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via pytest +fhirclient==4.1.0 \ + --hash=sha256:4f64f7967c9fe5f74cce068f29b0e5e4485848a73ec327765a8f3c188b9948a4 \ + --hash=sha256:fe9c92b3649a4d2829d91c40cd7765c6f729971d12d1dec39a7ee6e81f83384c + # via -r requirements.in +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via requests +iniconfig==1.1.1 \ + --hash=sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3 \ + --hash=sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32 + # via pytest +isodate==0.6.1 \ + --hash=sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96 \ + --hash=sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9 + # via fhirclient +packaging==22.0 \ + --hash=sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3 \ + --hash=sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3 + # via pytest +pluggy==1.0.0 \ + --hash=sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159 \ + --hash=sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3 + # via pytest +pytest==7.2.0 \ + --hash=sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71 \ + --hash=sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59 + # via -r requirements.in +requests==2.28.1 \ + --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \ + --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349 + # via fhirclient +retrying==1.3.3 \ + --hash=sha256:08c039560a6da2fe4f2c426d0766e284d3b736e355f8dd24b37367b0bb41973b + # via -r requirements.in +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via + # isodate + # retrying +urllib3==1.26.13 \ + --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ + --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 + # via requests diff --git a/tests/e2e/test.py b/tests/e2e/test.py index 654982c..37e190f 100644 --- a/tests/e2e/test.py +++ b/tests/e2e/test.py @@ -1,7 +1,8 @@ -import fhirclient.models.bundle as b import json import logging import os + +import fhirclient.models.bundle as b import pytest import requests from fhirclient import client @@ -75,13 +76,13 @@ def test_observation_is_pseudonymized(smart, bundle): observation_response = bundle_response.entry[0].resource assert ( - not encounter_id_part - in observation_response.encounter.processedReferenceIdentifier() + encounter_id_part + not in observation_response.encounter.processedReferenceIdentifier() ) assert ( - not subject_id_part - in observation_response.subject.processedReferenceIdentifier() + subject_id_part + not in observation_response.subject.processedReferenceIdentifier() ) @@ -90,7 +91,7 @@ def test_patient_is_pseudonymized(smart, bundle): response_json = bundle.create(smart.server) bundle_response = b.Bundle(response_json) - assert not original_patient_id in bundle_response.entry[1].resource.id + assert original_patient_id not in bundle_response.entry[1].resource.id def test_send_delete_bundle(smart, delete_bundle):