diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml
index 2b1c07a7d..a5caf4681 100644
--- a/.github/dependabot.yaml
+++ b/.github/dependabot.yaml
@@ -9,13 +9,6 @@ updates:
- "neicnordic/sensitive-data-development-collaboration"
# Each subfolder needs to be checked separately
- - package-ecosystem: docker
- directory: "/sda-auth"
- schedule:
- interval: weekly
- open-pull-requests-limit: 10
- reviewers:
- - "neicnordic/sensitive-data-development-collaboration"
- package-ecosystem: docker
directory: "/postgresql"
schedule:
@@ -54,18 +47,6 @@ updates:
# Each subfolder needs to be checked separately
- package-ecosystem: gomod
- directory: "/sda-auth"
- groups:
- all-modules:
- patterns:
- - "*"
- open-pull-requests-limit: 10
- reviewers:
- - "neicnordic/sensitive-data-development-collaboration"
- schedule:
- interval: weekly
-
- - package-ecosystem: "gomod"
directory: "/sda"
groups:
all-modules:
diff --git a/.github/integration/sda-posix-integration.yml b/.github/integration/sda-posix-integration.yml
index 33e1c3821..6e9915114 100644
--- a/.github/integration/sda-posix-integration.yml
+++ b/.github/integration/sda-posix-integration.yml
@@ -46,7 +46,7 @@ services:
command:
[
"python",
- "/cega/users.py",
+ "/users.py",
"0.0.0.0",
"8443",
"/shared/users.json"
@@ -58,7 +58,7 @@ services:
ports:
- "8443:8443"
volumes:
- - ./sda/users.py:/cega/users.py
+ - ./sda/users.py:/users.py
- certs:/certs
- shared:/shared
diff --git a/.github/integration/sda-s3-integration.yml b/.github/integration/sda-s3-integration.yml
index 3c5671ae7..e753cc9fa 100644
--- a/.github/integration/sda-s3-integration.yml
+++ b/.github/integration/sda-s3-integration.yml
@@ -317,6 +317,65 @@ services:
- ./sda/config.yaml:/config.yaml
- shared:/shared
+ cega-nss:
+ container_name: cega-nss
+ depends_on:
+ credentials:
+ condition: service_completed_successfully
+ command:
+ [
+ "python",
+ "/cega/users.py",
+ "0.0.0.0",
+ "8443",
+ "/shared/users.json"
+ ]
+ environment:
+ - CEGA_USERS_PASSWORD=test
+ - CEGA_USERS_USER=test
+ image: "egarchive/lega-base:release.v0.2.0"
+ ports:
+ - "8443:8443"
+ volumes:
+ - ./sda/users.py:/cega/users.py
+ - shared:/shared
+
+ auth-cega:
+ command: [ sda-auth ]
+ container_name: auth-cega
+ depends_on:
+ cega-nss:
+ condition: service_started
+ environment:
+ - AUTH_RESIGNJWT=true
+ - AUTH_CEGA_ID=test
+ - AUTH_CEGA_SECRET=test
+ image: ghcr.io/neicnordic/sensitive-data-archive:PR${PR_NUMBER}
+ ports:
+ - "8888:8080"
+ restart: always
+ volumes:
+ - ./sda/config.yaml:/config.yaml
+ - shared:/shared
+
+ auth-oidc:
+ command: [ sda-auth ]
+ container_name: auth-oidc
+ depends_on:
+ oidc:
+ condition: service_healthy
+ environment:
+ - AUTH_RESIGNJWT=false
+ - OIDC_ID=XC56EL11xx
+ - OIDC_SECRET=wHPVQaYXmdDHg
+ image: ghcr.io/neicnordic/sensitive-data-archive:PR${PR_NUMBER}
+ ports:
+ - "8889:8080"
+ restart: always
+ volumes:
+ - ./sda/config.yaml:/config.yaml
+ - shared:/shared
+
integration_test:
container_name: tester
command:
@@ -324,6 +383,12 @@ services:
- "/tests/run_scripts.sh"
- "/tests/sda"
depends_on:
+ auth-cega:
+ condition: service_started
+ auth-oidc:
+ condition: service_started
+ cega-nss:
+ condition: service_started
credentials:
condition: service_completed_successfully
finalize:
diff --git a/.github/integration/sda/config.yaml b/.github/integration/sda/config.yaml
index 9b44e5d75..24cd95a86 100644
--- a/.github/integration/sda/config.yaml
+++ b/.github/integration/sda/config.yaml
@@ -10,6 +10,22 @@ archive:
secretKey: "secretKey"
bucket: "archive"
region: "us-east-1"
+
+auth:
+ cega:
+ authUrl: "http://cega-nss:8443/username/"
+ id:
+ secret:
+ infoText: "About service text"
+ infoURL: "http://example.org/about"
+ jwt:
+ issuer: "https://auth:8888"
+ privateKey: /shared/keys/jwt.key
+ signatureAlg: ES256
+ publicFile: "/shared/c4gh.pub.pem"
+ resignJwt:
+ s3Inbox: "http://inbox:8000"
+
backup:
type: s3
url: "http://s3"
@@ -52,6 +68,13 @@ c4gh:
passphrase: "c4ghpass"
syncPubKeyPath: /shared/sync.pub.pem
+oidc:
+ id:
+ jwkPath: /jwk
+ provider: http://oidc:8080
+ redirectUrl: http://auth_oidc:8080/oidc/login
+ secret:
+
server:
cert: ""
key: ""
@@ -78,4 +101,4 @@ sync:
password: "pass"
user: "user"
-schema.type: "isolated"
\ No newline at end of file
+schema.type: "isolated"
diff --git a/.github/integration/sda/users.py b/.github/integration/sda/users.py
index 60e80fe22..8cf3dfc4f 100644
--- a/.github/integration/sda/users.py
+++ b/.github/integration/sda/users.py
@@ -7,7 +7,7 @@
import json
from base64 import b64decode
import ssl
-
+from pathlib import Path
from aiohttp import web
logging.basicConfig(format="[%(levelname)-8s] (L:%(lineno)s) %(message)s")
@@ -49,6 +49,7 @@ async def user(request):
raise web.HTTPBadRequest(text=f"No info for that user\n")
return web.json_response(user_info)
+HTTP_PROTOCOL = "http"
def main():
@@ -69,14 +70,20 @@ def main():
server.router.add_get("/username/{identifier}", user, name="user")
# SSL settings
- cacertfile = "/certs/ca.crt"
- certfile = "/certs/server.crt"
- keyfile = "/certs/server.key"
-
- ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=cacertfile)
- ssl_ctx.check_hostname = False
- ssl_ctx.verify_mode = ssl.CERT_NONE
- ssl_ctx.load_cert_chain(certfile, keyfile=keyfile)
+ here = Path(__file__)
+ cacertfile = here.parent / "certs" / "ca.crt"
+ certfile = here.parent / "certs" / "server.crt"
+ keyfile = here.parent / "certs" / "server.key"
+
+ global HTTP_PROTOCOL
+ if keyfile.is_file():
+ ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=cacertfile)
+ ssl_ctx.check_hostname = False
+ ssl_ctx.verify_mode = ssl.CERT_NONE
+ ssl_ctx.load_cert_chain(certfile, keyfile=keyfile)
+ HTTP_PROTOCOL = "https"
+ else:
+ ssl_ctx = None
web.run_app(server, host=host, port=port, shutdown_timeout=0, ssl_context=ssl_ctx)
diff --git a/.github/integration/tests/sda/99_auth_test.sh b/.github/integration/tests/sda/99_auth_test.sh
new file mode 100644
index 000000000..eb63dbba4
--- /dev/null
+++ b/.github/integration/tests/sda/99_auth_test.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -e
+
+python -m pip install --upgrade pip
+pip install tox
+
+tox -e unit_tests -c /tests/sda/auth/tox.ini
+
+echo "auth test completes successfully"
diff --git a/.github/integration/tests/sda/auth/integration/test_auth.py b/.github/integration/tests/sda/auth/integration/test_auth.py
new file mode 100644
index 000000000..c1eea863f
--- /dev/null
+++ b/.github/integration/tests/sda/auth/integration/test_auth.py
@@ -0,0 +1,28 @@
+import unittest
+import requests
+
+class TestEGAAuth(unittest.TestCase):
+ """Testing EgaAuth."""
+
+ def setUp(self):
+ """Initialise authenticator."""
+ self.backend_url = "http://auth-cega:8080/ega"
+
+
+ def tearDown(self):
+ """Finalise test."""
+ print("Finishing test")
+
+
+ def test_valid_ega_login(self):
+ """Test that the login is successful."""
+ creds_payload = { "username":'dummy@example.com', "password":'dummy', "submit": 'log+in' }
+ login_response = requests.post(self.backend_url, allow_redirects=False, data=creds_payload, cookies=None)
+ self.assertEqual(login_response.status_code, 200)
+
+
+ def test_invalid_ega_login(self):
+ """Test that the login is not successful."""
+ creds_payload = { "username":'dummy@foo.bar', "password":'wrongpassword', "submit": 'log+in' }
+ login_response = requests.post(self.backend_url, allow_redirects=False, data=creds_payload, cookies=None)
+ self.assertEqual(login_response.status_code, 303)
diff --git a/sda-auth/tests/requirements.txt b/.github/integration/tests/sda/auth/requirements.txt
similarity index 100%
rename from sda-auth/tests/requirements.txt
rename to .github/integration/tests/sda/auth/requirements.txt
diff --git a/sda-auth/tests/tox.ini b/.github/integration/tests/sda/auth/tox.ini
similarity index 100%
rename from sda-auth/tests/tox.ini
rename to .github/integration/tests/sda/auth/tox.ini
diff --git a/.github/workflows/build_pr_container.yaml b/.github/workflows/build_pr_container.yaml
index 2ffedbf7e..86308274b 100644
--- a/.github/workflows/build_pr_container.yaml
+++ b/.github/workflows/build_pr_container.yaml
@@ -33,19 +33,6 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- - name: Build container for sda-auth
- uses: docker/build-push-action@v5
- with:
- context: ./sda-auth
- push: true
- tags: |
- ghcr.io/${{ github.repository }}:sha-${{ github.sha }}-auth
- ghcr.io/${{ github.repository }}:PR${{ github.event.number }}-auth
- labels: |
- org.opencontainers.image.source=${{ github.event.repository.clone_url }}
- org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- org.opencontainers.image.revision=${{ github.sha }}
-
- name: Build container for sda-download
uses: docker/build-push-action@v5
with:
@@ -300,7 +287,10 @@ jobs:
- name: Check deployment
run: |
sleep 30
- for n in download finalize inbox ingest mapper verify; do
+ for n in auth download finalize inbox ingest mapper verify; do
+ if [ ${{matrix.storage}} == "posix" ] && [ "$n" == "auth" ]; then
+ continue
+ fi
if [ ! $(kubectl get pods -l role="$n" -o=jsonpath='{.items[*].status.containerStatuses[0].ready}' | grep true) ]; then
echo "$n is not ready after 30s, exiting"
exit 1
diff --git a/.github/workflows/code-linter.yaml b/.github/workflows/code-linter.yaml
index 49b15b909..19df3094c 100644
--- a/.github/workflows/code-linter.yaml
+++ b/.github/workflows/code-linter.yaml
@@ -8,29 +8,6 @@ on:
- '**/go.*'
jobs:
- lint_auth:
- name: Lint auth code
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- go-version: ['1.21']
- steps:
- - name: Set up Go ${{ matrix.go-version }}
- uses: actions/setup-go@v5
- with:
- go-version: ${{ matrix.go-version }}
- id: go
-
- - name: Check out code into the Go module directory
- uses: actions/checkout@v4
-
- - name: Run golangci-lint
- uses: golangci/golangci-lint-action@v4.0.0
- with:
- args: -E bodyclose,gocritic,gofmt,gosec,govet,nestif,nlreturn,revive,rowserrcheck --timeout 5m
- working-directory: sda-auth
-
lint_download:
name: Lint download code
runs-on: ubuntu-latest
diff --git a/.github/workflows/functionality.yml b/.github/workflows/functionality.yml
index 886285410..c14d360ea 100644
--- a/.github/workflows/functionality.yml
+++ b/.github/workflows/functionality.yml
@@ -7,7 +7,6 @@ on:
jobs:
check_changes:
outputs:
- sda-auth: ${{ steps.changes.outputs.sda-auth }}
sda-download: ${{ steps.changes.outputs.sda-download }}
sftp-inbox: ${{ steps.changes.outputs.sftp-inbox }}
runs-on: ubuntu-latest
@@ -24,38 +23,6 @@ jobs:
sftp-inbox:
- 'sftp-inbox/**'
- sda-auth:
- needs: check_changes
- if: needs.check_changes.outputs.sda-auth == 'true'
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- go-version: ['1.21']
- steps:
- - name: Set up Go ${{ matrix.go-version }}
- uses: actions/setup-go@v5
- with:
- go-version: ${{ matrix.go-version }}
- - uses: actions/checkout@v4
- - name: Set up Python 3.11
- uses: actions/setup-python@v5
- with:
- python-version: "3.11"
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install tox tox-gh-actions
- - name: Add oidc to /etc/hosts
- run: |
- sudo echo "127.0.0.1 oidc" | sudo tee -a /etc/hosts
- - name: Start virtual infrastructure
- run: |
- cd sda-auth
- GOLANG_VERSION=${{ matrix.go-version }} docker-compose -f ./dev-server/docker-compose.yml up -d --force-recreate --build
- - name: Run unit tests
- run: tox -e unit_tests -c sda-auth/tests/tox.ini
-
sda-download:
needs: check_changes
if: needs.check_changes.outputs.sda-download == 'true'
diff --git a/.github/workflows/publish_container.yml b/.github/workflows/publish_container.yml
index 44e4e2ee3..41d8aeffa 100644
--- a/.github/workflows/publish_container.yml
+++ b/.github/workflows/publish_container.yml
@@ -54,16 +54,11 @@ jobs:
- name: Pull PR containers
run : |
- for t in -auth -download -postgres -rabbitmq -sftp-inbox; do
+ for t in -download -postgres -rabbitmq -sftp-inbox; do
docker pull ghcr.io/${{ github.repository }}:PR${{ github.event.number }}$t
done
docker pull ghcr.io/${{ github.repository }}:PR${{ github.event.number }}
- - name: Retag PR image for auth
- run: |
- docker tag ghcr.io/${{ github.repository }}:PR${{ github.event.number }}-auth ghcr.io/${{ github.repository }}:${{ needs.tag_release.outputs.tag }}-auth
- docker push ghcr.io/${{ github.repository }}:${{ needs.tag_release.outputs.tag }}-auth
-
- name: Retag PR image for download
run: |
docker tag ghcr.io/${{ github.repository }}:PR${{ github.event.number }}-download ghcr.io/${{ github.repository }}:${{ needs.tag_release.outputs.tag }}-download
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..4f7599e22
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,20 @@
+### Go ###
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+### Go Patch ###
+/vendor/
+/Godeps/
+
+### Exclude test files ###
+.github/integration/tests/sda/auth/integration/__*
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 6d760d05e..f4a2012ca 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ help:
@echo 'In-depth description of how to use this Makefile can be found in the README.md'
bootstrap: go-version-check docker-version-check
- @for dir in sda sda-auth sda-download; do \
+ @for dir in sda sda-download; do \
cd $$dir; \
go get ./...; \
cd ..; \
@@ -23,15 +23,13 @@ bootstrap: go-version-check docker-version-check
GO111MODULE=off go get golang.org/x/tools/cmd/goimports
# build containers
-build-all: build-postgresql build-rabbitmq build-sda build-sda-auth build-sda-download build-sda-sftp-inbox
+build-all: build-postgresql build-rabbitmq build-sda build-sda-download build-sda-sftp-inbox
build-postgresql:
@cd postgresql && docker build -t ghcr.io/neicnordic/sensitive-data-archive:PR$$(date +%F)-postgres .
build-rabbitmq:
@cd rabbitmq && docker build -t ghcr.io/neicnordic/sensitive-data-archive:PR$$(date +%F)-rabbitmq .
build-sda:
@cd sda && docker build -t ghcr.io/neicnordic/sensitive-data-archive:PR$$(date +%F) .
-build-sda-auth:
- @cd sda-auth && docker build -t ghcr.io/neicnordic/sensitive-data-archive:PR$$(date +%F)-auth .
build-sda-download:
@cd sda-download && docker build -t ghcr.io/neicnordic/sensitive-data-archive:PR$$(date +%F)-download .
build-sda-sftp-inbox:
@@ -83,23 +81,18 @@ integrationtest-sda: build-all
@PR_NUMBER=$$(date +%F) docker compose -f .github/integration/sda-posix-integration.yml down -v --remove-orphans
# lint go code
-lint-all: lint-sda lint-sda-auth lint-sda-download
+lint-all: lint-sda lint-sda-download
lint-sda:
@echo 'Running golangci-lint in the `sda` folder'
@cd sda && golangci-lint run $(LINT_INCLUDE) $(LINT_EXCLUDE)
-lint-sda-auth:
- @echo 'Running golangci-lint in the `sda-auth` folder'
- @cd sda-auth && golangci-lint run $(LINT_INCLUDE) $(LINT_EXCLUDE)
lint-sda-download:
@echo 'Running golangci-lint in the `sda-download` folder'
@cd sda-download && golangci-lint run $(LINT_INCLUDE) $(LINT_EXCLUDE)
# run static code tests
-test-all: test-sda test-sda-auth test-sda-download test-sda-sftp-inbox
+test-all: test-sda test-sda-download test-sda-sftp-inbox
test-sda:
@cd sda && go test ./... -count=1
-test-sda-auth:
- @cd sda-auth && go test ./... -count=1
test-sda-download:
@cd sda-download && go test ./... -count=1
test-sda-sftp-inbox:
diff --git a/charts/sda-db/Chart.yaml b/charts/sda-db/Chart.yaml
index 1ff539fa0..e8b3bade7 100644
--- a/charts/sda-db/Chart.yaml
+++ b/charts/sda-db/Chart.yaml
@@ -1,7 +1,7 @@
apiVersion: v2
name: sda-db
version: 0.8.16
-appVersion: v0.2.112
+appVersion: v0.3.0
kubeVersion: '>= 1.26.0'
description: Database component for Sensitive Data Archive (SDA) installation
home: https://neic-sda.readthedocs.io
diff --git a/charts/sda-mq/Chart.yaml b/charts/sda-mq/Chart.yaml
index b6d66cb87..07898bccc 100644
--- a/charts/sda-mq/Chart.yaml
+++ b/charts/sda-mq/Chart.yaml
@@ -1,7 +1,7 @@
apiVersion: v2
name: sda-mq
version: 0.7.17
-appVersion: v0.2.112
+appVersion: v0.3.0
kubeVersion: '>= 1.26.0'
description: RabbitMQ component for Sensitive Data Archive (SDA) installation
home: https://neic-sda.readthedocs.io
diff --git a/charts/sda-svc/Chart.yaml b/charts/sda-svc/Chart.yaml
index 06b701f35..fa7fa4a78 100644
--- a/charts/sda-svc/Chart.yaml
+++ b/charts/sda-svc/Chart.yaml
@@ -1,7 +1,7 @@
apiVersion: v2
name: sda-svc
-version: 0.23.12
-appVersion: v0.2.112
+version: 0.24.0
+appVersion: v0.3.0
kubeVersion: '>= 1.26.0'
description: Components for Sensitive Data Archive (SDA) installation
home: https://neic-sda.readthedocs.io
diff --git a/charts/sda-svc/templates/auth-deploy.yaml b/charts/sda-svc/templates/auth-deploy.yaml
index 559d5e849..679e98561 100644
--- a/charts/sda-svc/templates/auth-deploy.yaml
+++ b/charts/sda-svc/templates/auth-deploy.yaml
@@ -58,7 +58,7 @@ spec:
fsGroup: 65534
containers:
- name: auth
- image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}-auth"
+ image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
securityContext:
allowPrivilegeEscalation: false
@@ -70,35 +70,28 @@ spec:
{{- if .Values.global.extraSecurityContext }}
{{- toYaml .Values.global.extraSecurityContext | nindent 10 -}}
{{- end }}
+ command: ["sda-auth"]
env:
- {{- if .Values.global.log.format }}
- - name: LOG_FORMAT
- value: {{ .Values.global.log.format | quote }}
- {{- end }}
- {{- if .Values.global.log.level }}
- - name: LOG_LEVEL
- value: {{ .Values.global.log.level | quote }}
- {{- end }}
{{- if not .Values.global.vaultSecrets }}
- {{- if and (ne "" .Values.global.oidc.id) (ne "" .Values.global.oidc.secret) }}
- - name: ELIXIR_ID
+ {{- if and (ne "" .Values.global.oidc.id) (ne "" .Values.global.oidc.secret) }}
+ - name: OIDC_ID
valueFrom:
secretKeyRef:
name: {{ template "sda.fullname" . }}-auth
key: oidcID
- - name: ELIXIR_SECRET
+ - name: OIDC_SECRET
valueFrom:
secretKeyRef:
name: {{ template "sda.fullname" . }}-auth
key: oidcSecret
- {{- end }}
+ {{- end }}
{{- if or ( eq "federated" .Values.global.schemaType) ( eq "" .Values.global.schemaType) }}
- - name: CEGA_ID
+ - name: AUTH_CEGA_ID
valueFrom:
secretKeyRef:
name: {{ template "sda.fullname" . }}-auth
key: cegaID
- - name: CEGA_SECRET
+ - name: AUTH_CEGA_SECRET
valueFrom:
secretKeyRef:
name: {{ template "sda.fullname" . }}-auth
@@ -108,54 +101,60 @@ spec:
- name: SERVER_CONFFILE
value: {{ include "confFile" . }}
{{- end }}
- - name: ELIXIR_REDIRECTURL
- value: {{ template "authRedirect" .}}
- - name: ELIXIR_PROVIDER
- value: "{{ .Values.global.oidc.provider }}"
- - name: ELIXIR_SCOPE
- value: "ga4gh_passport_v1"
- - name: ELIXIR_JWKPATH
- value: {{ .Values.global.oidc.jwkPath | quote }}
+ {{- if or ( eq "federated" .Values.global.schemaType) ( eq "" .Values.global.schemaType) }}
+ - name: AUTH_CEGA_AUTHURL
+ value: {{ .Values.global.cega.host | quote }}
+ {{- end }}
{{- if .Values.global.auth.corsOrigins }}
- - name: CORS_ORIGINS
+ - name: AUTH_CORS_ORIGINS
value: {{ .Values.global.auth.corsOrigins | quote }}
- - name: CORS_METHODS
+ - name: AUTH_CORS_METHODS
value: {{ .Values.global.auth.corsMethods | quote }}
- - name: CORS_CREDENTIALS
+ - name: AUTH_CORS_CREDENTIALS
value: {{ .Values.global.auth.corsCreds | quote }}
{{- end }}
- {{- if or ( eq "federated" .Values.global.schemaType) ( eq "" .Values.global.schemaType) }}
- - name: CEGA_AUTHURL
- value: {{ .Values.global.cega.host | quote }}
- {{- end }}
+ - name: AUTH_INFOTEXT
+ value: {{ .Values.global.auth.infoText }}
+ - name: AUTH_INFOURL
+ value: {{ .Values.global.auth.inforURL }}
{{- if .Values.global.auth.resignJwt }}
- - name: JWTISSUER
+ - name: AUTH_JWT_ISSUER
{{- if .Values.global.tls.enabled }}
value: "https://{{ .Values.global.ingress.hostName.auth }}"
{{- else }}
value: "http://{{ .Values.global.ingress.hostName.auth }}"
{{- end }}
- - name: JWTPRIVATEKEY
+ - name: AUTH_JWT_PRIVATEKEY
value: "{{ template "jwtPath" . }}/{{ .Values.global.auth.jwtKey }}"
- - name: JWTSIGNATUREALG
+ - name: AUTH_JWT_SIGNATUREALG
value: {{ .Values.global.auth.jwtAlg }}
{{- end }}
- - name: RESIGNJWT
- value: {{ .Values.global.auth.resignJwt | quote }}
- - name: PUBLICFILE
+ - name: AUTH_PUBLICFILE
value: "{{ template "c4ghPath" . }}/{{ .Values.global.c4gh.publicFile }}"
+ - name: AUTH_RESIGNJWT
+ value: {{ .Values.global.auth.resignJwt | quote }}
+ - name: AUTH_S3INBOX
+ value: {{ .Values.global.ingress.hostName.s3Inbox }}
+ {{- if .Values.global.log.format }}
+ - name: LOG_FORMAT
+ value: {{ .Values.global.log.format | quote }}
+ {{- end }}
+ {{- if .Values.global.log.level }}
+ - name: LOG_LEVEL
+ value: {{ .Values.global.log.level | quote }}
+ {{- end }}
+ - name: OIDC_REDIRECTURL
+ value: {{ template "authRedirect" .}}
+ - name: OIDC_PROVIDER
+ value: "{{ .Values.global.oidc.provider }}"
+ - name: OIDC_JWKPATH
+ value: {{ .Values.global.oidc.jwkPath | quote }}
{{- if .Values.global.tls.enabled}}
- name: SERVER_CERT
value: {{ template "tlsPath" . }}/tls.crt
- name: SERVER_KEY
value: {{ template "tlsPath" . }}/tls.key
{{- end }}
- - name: S3INBOX
- value: {{ .Values.global.ingress.hostName.s3Inbox }}
- - name: INFOTEXT
- value: {{ .Values.global.auth.infoText }}
- - name: INFOURL
- value: {{ .Values.global.auth.inforURL }}
ports:
- name: auth
containerPort: 8080
diff --git a/sda-auth/.dockerignore b/sda-auth/.dockerignore
deleted file mode 100644
index ecb753fce..000000000
--- a/sda-auth/.dockerignore
+++ /dev/null
@@ -1,49 +0,0 @@
-# MacOS specific
-*.DS_Store
-
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-
-# vscode
-*.vscode
-
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-
-# Test binary, build with `go test -c`
-*.test
-
-# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
-
-# log dumps
-*.dump
-
-# deployment
-dev-server/
-deployment/
-Dockerfile
-config.yaml
-
-# Distribution / packaging
-.Python
-env/
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-*.egg-info/
-.installed.cfg
-*.egg
diff --git a/sda-auth/.github/dependabot.yml b/sda-auth/.github/dependabot.yml
deleted file mode 100644
index ac1a2d70e..000000000
--- a/sda-auth/.github/dependabot.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-version: 2
-updates:
- - package-ecosystem: "gomod"
- directory: "/"
- # Check the npm registry for updates every day (weekdays)
- schedule:
- interval: "weekly"
- reviewers:
- - "neicnordic/sensitive-data-development-collaboration"
-
- - package-ecosystem: "docker"
- # Look for a `Dockerfile` in the `root` directory
- directory: "/"
- # Check for updates once a week
- schedule:
- interval: "weekly"
- reviewers:
- - "neicnordic/sensitive-data-development-collaboration"
-
- - package-ecosystem: "github-actions"
- directory: "/"
- schedule:
- interval: "weekly"
- open-pull-requests-limit: 10
- reviewers:
- - "neicnordic/sensitive-data-development-collaboration"
diff --git a/sda-auth/.github/workflows/build_pr_container.yaml b/sda-auth/.github/workflows/build_pr_container.yaml
deleted file mode 100644
index eaa7739d2..000000000
--- a/sda-auth/.github/workflows/build_pr_container.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
-name: build PR container
-
-on:
- pull_request:
- paths:
- - "Dockerfile"
- - "*.go"
- - "frontend/**"
-
-jobs:
- build:
- name: Build PR image
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Log in to the Github Container registry
- uses: docker/login-action@v2
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Build container
- uses: docker/build-push-action@v4
- with:
- context: .
- file: ./Dockerfile
- push: true
- tags: |
- ghcr.io/${{ github.repository }}:PR${{ github.event.number }}
- ghcr.io/${{ github.repository }}:sha-${{ github.sha }}
- labels: |
- org.opencontainers.image.source=${{ github.event.repository.clone_url }}
- org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- org.opencontainers.image.revision=${{ github.sha }}
diff --git a/sda-auth/.github/workflows/functionality.yml b/sda-auth/.github/workflows/functionality.yml
deleted file mode 100644
index eba0d1470..000000000
--- a/sda-auth/.github/workflows/functionality.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-name: Functionality
-
-on: [push]
-
-jobs:
- build:
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- go-version: [1.19]
- steps:
- - name: Set up Go ${{ matrix.go-version }}
- uses: actions/setup-go@v4
- with:
- go-version: ${{ matrix.go-version }}
- - uses: actions/checkout@v3
- - name: Set up Python 3.11
- uses: actions/setup-python@v4
- with:
- python-version: "3.11"
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install tox tox-gh-actions
- - name: Add oidc to /etc/hosts
- run: |
- sudo echo "127.0.0.1 oidc" | sudo tee -a /etc/hosts
- - name: Start virtual infrastructure
- run: GOLANG_VERSION=${{ matrix.go-version }} docker-compose -f ./dev-server/docker-compose.yml up -d --force-recreate --build
- - name: Run unit tests
- run: tox -e unit_tests -c tests/tox.ini
diff --git a/sda-auth/.github/workflows/lint.yml b/sda-auth/.github/workflows/lint.yml
deleted file mode 100644
index fcb4d7326..000000000
--- a/sda-auth/.github/workflows/lint.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-name: Multilinters
-
-on:
- push:
-
-jobs:
- build:
- name: Check code
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- go-version: [1.19]
- steps:
- - name: Set up Go ${{ matrix.go-version }}
- uses: actions/setup-go@v4
- with:
- go-version: ${{ matrix.go-version }}
- - name: Check out code into the Go module directory
- uses: actions/checkout@v3
-
- - name: Run golangci-lint
- uses: golangci/golangci-lint-action@v3
- with:
- version: v1.50
- args: -E gosec,goconst,nestif,bodyclose,rowserrcheck
diff --git a/sda-auth/.github/workflows/tag_and_build.yaml b/sda-auth/.github/workflows/tag_and_build.yaml
deleted file mode 100644
index 2dc5767e2..000000000
--- a/sda-auth/.github/workflows/tag_and_build.yaml
+++ /dev/null
@@ -1,69 +0,0 @@
-name: Bump version
-on:
- push:
- branches:
- - main
- paths:
- - "Dockerfile"
- - "*.go"
- - "go.*"
- - "frontend/**"
-
-jobs:
- tag:
- name: bump tags
- outputs:
- part: ${{ steps.bump_tag.outputs.part }}
- tag: ${{ steps.bump_tag.outputs.tag }}
- new_tag: ${{ steps.bump_tag.outputs.new_tag }}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- with:
- fetch-depth: "1"
- - name: Bump version and push tag
- id: bump_tag
- uses: anothrNick/github-tag-action@1.67.0
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- WITH_V: true
- DEFAULT_BUMP: patch
-
- push_to_registry:
- needs: tag
- if: needs.tag.outputs.part != ''
- name: Push Docker image to Github Container registry
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- steps:
- - name: Check out the repo
- uses: actions/checkout@v3
-
- - name: Log in to the Github Container registry
- uses: docker/login-action@v2
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Extract metadata (tags, labels) for Docker
- id: meta
- uses: docker/metadata-action@v4
- with:
- images: ghcr.io/${{ github.repository }}
-
- - name: Build and push
- uses: docker/build-push-action@v4
- with:
- context: .
- file: ./Dockerfile
- push: true
- tags: |
- ghcr.io/${{ github.repository }}:${{ needs.tag.outputs.tag }}
- ghcr.io/${{ github.repository }}:latest
- labels: |
- org.opencontainers.image.source=${{ github.event.repository.clone_url }}
- org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- org.opencontainers.image.revision=${{ github.sha }}
diff --git a/sda-auth/.gitignore b/sda-auth/.gitignore
deleted file mode 100644
index c17924110..000000000
--- a/sda-auth/.gitignore
+++ /dev/null
@@ -1,25 +0,0 @@
-# MacOS specific
-*.DS_Store
-
-# vscode
-*.vscode
-
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-
-# Service binaries
-auth
-
-# Test binary, build with `go test -c`
-*.test
-
-# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
-
-# log dumps
-*.dump
-
diff --git a/sda-auth/Dockerfile b/sda-auth/Dockerfile
deleted file mode 100644
index 8d3d09904..000000000
--- a/sda-auth/Dockerfile
+++ /dev/null
@@ -1,20 +0,0 @@
-ARG GOLANG_VERSION=1.21
-FROM "golang:${GOLANG_VERSION}-alpine"
-RUN apk add --no-cache git
-COPY . .
-ENV GO111MODULE=on
-ENV GOPATH=$PWD
-ENV CGO_ENABLED=0
-ENV GOOS=linux
-RUN go build -ldflags "-extldflags -static" -o ./build/svc .
-RUN echo "nobody:x:65534:65534:nobody:/:/sbin/nologin" > passwd
-
-FROM scratch
-COPY --from=0 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
-COPY --from=0 /go/build/svc svc
-COPY --from=0 /go/frontend frontend/
-COPY --from=0 /go/passwd /etc/passwd
-USER 65534
-EXPOSE 8080
-ENTRYPOINT [ "/svc" ]
-
diff --git a/sda-auth/LICENSE b/sda-auth/LICENSE
deleted file mode 100644
index be3f7b28e..000000000
--- a/sda-auth/LICENSE
+++ /dev/null
@@ -1,661 +0,0 @@
- GNU AFFERO GENERAL PUBLIC LICENSE
- Version 3, 19 November 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU Affero General Public License is a free, copyleft license for
-software and other kinds of works, specifically designed to ensure
-cooperation with the community in the case of network server software.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-our General Public Licenses are intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- Developers that use our General Public Licenses protect your rights
-with two steps: (1) assert copyright on the software, and (2) offer
-you this License which gives you legal permission to copy, distribute
-and/or modify the software.
-
- A secondary benefit of defending all users' freedom is that
-improvements made in alternate versions of the program, if they
-receive widespread use, become available for other developers to
-incorporate. Many developers of free software are heartened and
-encouraged by the resulting cooperation. However, in the case of
-software used on network servers, this result may fail to come about.
-The GNU General Public License permits making a modified version and
-letting the public access it on a server without ever releasing its
-source code to the public.
-
- The GNU Affero General Public License is designed specifically to
-ensure that, in such cases, the modified source code becomes available
-to the community. It requires the operator of a network server to
-provide the source code of the modified version running there to the
-users of that server. Therefore, public use of a modified version, on
-a publicly accessible server, gives the public access to the source
-code of the modified version.
-
- An older license, called the Affero General Public License and
-published by Affero, was designed to accomplish similar goals. This is
-a different license, not a version of the Affero GPL, but Affero has
-released a new version of the Affero GPL which permits relicensing under
-this license.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU Affero General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Remote Network Interaction; Use with the GNU General Public License.
-
- Notwithstanding any other provision of this License, if you modify the
-Program, your modified version must prominently offer all users
-interacting with it remotely through a computer network (if your version
-supports such interaction) an opportunity to receive the Corresponding
-Source of your version by providing access to the Corresponding Source
-from a network server at no charge, through some standard or customary
-means of facilitating copying of software. This Corresponding Source
-shall include the Corresponding Source for any work covered by version 3
-of the GNU General Public License that is incorporated pursuant to the
-following paragraph.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the work with which it is combined will remain governed by version
-3 of the GNU General Public License.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU Affero General Public License from time to time. Such new versions
-will be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU Affero General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU Affero General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU Affero General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source. For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code. There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU AGPL, see
-.
diff --git a/sda-auth/README.md b/sda-auth/README.md
deleted file mode 100644
index 5aeb9048d..000000000
--- a/sda-auth/README.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# SDA authentication service
-
-This service allows users to log in both via Elixir AAI or EGA.
-
-## Configuration example for local testing
-
-The following settings can be configured for deploying the service, either by using environment variables or a YAML file.
-
-Parameter | Description | Defined value
---------- | ----------- | -------
-`LOG_LEVEL` | Log level | `info`
-`ELIXIR_ID` | Elixir authentication id | `XC56EL11xx`
-`ELIXIR_SECRET` | Elixir authentication secret | `wHPVQaYXmdDHg`
-`ELIXIR_PROVIDER` | Elixir issuer URL | `http://oidc:9090`
-`ELIXIR_JWKPATH` | JWK endpoint where the public key of the Elixir issuer can be retrieved from for token validation | `/jwks`
-`CEGA_AUTHURL` | CEGA server endpoint | `http://cega:8443/lega/v1/legas/users/`
-`CEGA_ID` | CEGA server authentication id | `dummy`
-`CEGA_SECRET` | CEGA server authentication secret | `dummy`
-`CORS_ORIGINS` | Allowed Cross-Origin Resource Sharing (CORS) origins | `""`
-`CORS_METHODS` | Allowed Cross-Origin Resource Sharing (CORS) methods | `""`
-`CORS_CREDENTIALS` | If cookies, authorization headers, and TLS client certificates are allowed over CORS | `false`
-`SERVER_CERT` | Certificate file path | `""`
-`SERVER_KEY` | Private key file path | `""`
-`S3INBOX` | S3 inbox host | `s3.example.com`
-`JWTISSUER` | Issuer of JWT tokens | `http://auth:8080`
-`JWTPRIVATEKEY` | Path to private key for signing the JWT token | `keys/sign-jwt.key`
-`JWTSIGNATUREALG` | Algorithm used to sign the JWT token. ES256 (ECDSA) or RS256 (RSA) are supported | `RS256`
-`RESIGNJWT` | Set to `false` to serve the raw OIDC JWT, i.e. without re-signing it | `""`
-
-## Running the development setup
-
-Start the full stack by running docker-compose in the `dev-server` folder:
-
-```bash
-docker-compose up --build
-```
-
-The current setup also requires that `127.0.0.1 oidc` is added to `/etc/hosts`, so that routing works properly.
-
-## Running with Cross-Origin Resource Sharing (CORS)
-
-This service can be run as a backend only, and in the case where the frontend
-is running somewhere else, CORS is needed.
-
-Recommended CORS settings for a given host are:
-
-```txt
-export CORS_ORIGINS="https://"
-export CORS_METHODS="GET,OPTIONS,POST"
-export CORS_CREDENTIALS="true"
-```
-
-There is a minimal CORS login testing site at `http://localhost:8000` of the
-dev-server.
-
-## Building a Docker container
-
-Using the provided Dockerfile, you may build a Docker image:
-
-```bash
-docker build -t neicnordic/sda-auth:mytag
-```
-
-## Choosing provider login
-
-The `sda-auth` allows for two different type of login providers: `EGA` and `Elixir` (LS-AAI). It is possible, however, to run the `sda-auth` using only one of the providers. In order to remove the `EGA` option, remove the `CEGA_ID` and `CEGA_SECRET` options for the configuration, while for removing the `Elixir` option, remove the `ELIXIR_ID` and `ELIXIR_SECRET` variables.
diff --git a/sda-auth/config.go b/sda-auth/config.go
deleted file mode 100644
index c582e094b..000000000
--- a/sda-auth/config.go
+++ /dev/null
@@ -1,199 +0,0 @@
-package main
-
-import (
- "errors"
- "fmt"
- "os"
- "path"
- "strings"
-
- log "github.com/sirupsen/logrus"
- "github.com/spf13/viper"
-)
-
-// ElixirConfig stores the config about the elixir oidc endpoint
-type ElixirConfig struct {
- ID string
- Provider string
- RedirectURL string
- RevocationURL string
- Secret string
- jwkURL string
-}
-
-// CegaConfig stores information about the cega endpoint
-type CegaConfig struct {
- AuthURL string
- ID string
- Secret string
-}
-
-// CORSConfig stores information about cross-origin resource sharing
-type CORSConfig struct {
- AllowOrigin string
- AllowMethods string
- AllowHeaders string
- AllowCredentials bool
-}
-
-// ServerConfig stores general server information
-type ServerConfig struct {
- Cert string
- Key string
- CORS CORSConfig
-}
-
-// Config is a parent object for all the different configuration parts
-type Config struct {
- Elixir ElixirConfig
- Cega CegaConfig
- JwtIssuer string
- JwtPrivateKey string
- JwtSignatureAlg string
- Server ServerConfig
- S3Inbox string
- ResignJwt bool
- InfoURL string
- InfoText string
- PublicFile string
-}
-
-// NewConfig initializes and parses the config file and/or environment using
-// the viper library.
-func NewConfig() (*Config, error) {
- viper.SetConfigName("config")
- viper.AddConfigPath(".")
- viper.AutomaticEnv()
- viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
- viper.SetConfigType("yaml")
- if viper.IsSet("server.confPath") {
- cp := viper.GetString("server.confPath")
- ss := strings.Split(strings.TrimLeft(cp, "/"), "/")
- viper.AddConfigPath(path.Join(ss...))
- }
- if viper.IsSet("server.confFile") {
- viper.SetConfigFile(viper.GetString("server.confFile"))
- }
-
- if err := viper.ReadInConfig(); err != nil {
- if _, ok := err.(viper.ConfigFileNotFoundError); ok {
- log.Infoln("No config file found, using ENVs only")
- } else {
- return nil, err
- }
- }
-
- c := &Config{}
- err := c.readConfig()
-
- return c, err
-}
-
-func (c *Config) readConfig() error {
- c.JwtPrivateKey = viper.GetString("JwtPrivateKey")
- c.JwtSignatureAlg = viper.GetString("JwtSignatureAlg")
- c.JwtIssuer = viper.GetString("jwtIssuer")
- c.InfoURL = viper.GetString("infoUrl")
- c.InfoText = viper.GetString("infoText")
- c.PublicFile = viper.GetString("publicFile")
-
- viper.SetDefault("ResignJwt", true)
- c.ResignJwt = viper.GetBool("resignJwt")
-
- // Setup elixir
- elixir := ElixirConfig{}
-
- elixir.ID = viper.GetString("elixir.id")
- elixir.Provider = viper.GetString("elixir.provider")
- elixir.RedirectURL = viper.GetString("elixir.redirectUrl")
- elixir.Secret = viper.GetString("elixir.secret")
- if viper.IsSet("elixir.jwkPath") {
- elixir.jwkURL = elixir.Provider + viper.GetString("elixir.jwkPath")
- }
-
- c.Elixir = elixir
-
- // Setup cega
- cega := CegaConfig{}
-
- cega.AuthURL = viper.GetString("cega.authUrl")
- cega.ID = viper.GetString("cega.id")
- cega.Secret = viper.GetString("cega.secret")
-
- c.Cega = cega
-
- // Check the either cega or Elixir config exists
- if (elixir.ID == "" || elixir.Secret == "") && (cega.ID == "" || cega.Secret == "") {
- return fmt.Errorf("neither cega or elixir login configured")
- }
-
- // Read CORS settings
- cors := CORSConfig{AllowCredentials: false}
- if viper.IsSet("cors.origins") {
- cors.AllowOrigin = viper.GetString("cors.origins")
- }
- if viper.IsSet("cors.methods") {
- cors.AllowMethods = viper.GetString("cors.methods")
- }
- if viper.IsSet("cors.headers") {
- cors.AllowHeaders = viper.GetString("cors.headers")
- }
- if viper.IsSet("cors.credentials") {
- cors.AllowCredentials = viper.GetBool("cors.credentials")
- }
-
- // Setup server
- s := ServerConfig{CORS: cors}
-
- if viper.IsSet("server.cert") {
- s.Cert = viper.GetString("server.cert")
- }
- if viper.IsSet("server.key") {
- s.Key = viper.GetString("server.key")
- }
-
- c.Server = s
-
- c.S3Inbox = viper.GetString("s3Inbox")
-
- if viper.IsSet("log.format") {
- if viper.GetString("log.format") == "json" {
- log.SetFormatter(&log.JSONFormatter{})
- log.Info("The logs format is set to JSON")
- }
- }
-
- if viper.IsSet("log.level") {
- stringLevel := viper.GetString("log.level")
- intLevel, err := log.ParseLevel(stringLevel)
- if err != nil {
- log.Printf("Log level '%s' not supported, setting to 'trace'", stringLevel)
- intLevel = log.TraceLevel
- }
- log.SetLevel(intLevel)
- log.Printf("Setting log level to '%s'", stringLevel)
- }
-
- for _, s := range []string{"s3Inbox", "publicFile"} {
- if viper.GetString(s) == "" {
- return fmt.Errorf("%s not set", s)
- }
- }
-
- // no need to check the variables for JWT generation if we won't use it
- if (cega.ID == "" && cega.Secret == "") && !c.ResignJwt {
- return nil
- }
-
- for _, s := range []string{"jwtIssuer", "JwtPrivateKey", "JwtSignatureAlg"} {
- if viper.GetString(s) == "" {
- return fmt.Errorf("%s not set", s)
- }
- }
-
- if _, err := os.Stat(c.JwtPrivateKey); errors.Is(err, os.ErrNotExist) {
- return fmt.Errorf("missing private key file, reason: '%s'", err.Error())
- }
-
- return nil
-}
diff --git a/sda-auth/config.yaml b/sda-auth/config.yaml
deleted file mode 100644
index fc7c1cec3..000000000
--- a/sda-auth/config.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
----
-log:
- level: "info"
- format: "json"
-elixir:
- id: "XC56EL11xx"
- provider: "http://oidc:9090"
- redirectUri: "http://oidc:31111/elixir/login"
- revocationUrl: "http://oidc:9090"
- secret: "wHPVQaYXmdDHg"
- jwkPath: "/jwks"
-cega:
- authUrl: "http://cega:8443/username/"
- id: "dummy"
- secret: "dummy"
-server:
- # do not use TLS until certs are fixed
- # cert: "keys/cert.pem"
- # key: "keys/key.pem"
-s3Inbox: "s3.example.com"
-jwtIssuer: "http://auth:8080"
-jwtPrivateKey: "keys/sign-jwt.key"
-jwtSignatureAlg: "ES256"
-resignJwt: true
-infoText: "About Federated EGA"
-infoUrl: "https://ega-archive.org/about/projects-and-funders/federated-ega/"
-publicFile: "/keys/c4gh.pub.pem"
diff --git a/sda-auth/config_test.go b/sda-auth/config_test.go
deleted file mode 100644
index ac5f36547..000000000
--- a/sda-auth/config_test.go
+++ /dev/null
@@ -1,259 +0,0 @@
-package main
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strconv"
- "testing"
-
- log "github.com/sirupsen/logrus"
- "github.com/spf13/viper"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/suite"
- "gopkg.in/yaml.v3"
-)
-
-// These are not complete tests of all functions in elixir. New tests should
-// be added as the code is updated.
-
-type ConfigTests struct {
- suite.Suite
- TempDir string
- ConfigFile *os.File
- ElixirConfig ElixirConfig
- CegaConfig CegaConfig
- ServerConfig ServerConfig
- S3Inbox string
- JwtIssuer string
- JwtPrivateKey string
- JwtPrivateKeyFile *os.File
- JwtSignatureAlg string
- ResignJwt bool
- InfoURL string
- InfoText string
- PublicFile string
-}
-
-func TestConfigTestSuite(t *testing.T) {
- suite.Run(t, new(ConfigTests))
-}
-
-func (suite *ConfigTests) SetupTest() {
-
- var err error
-
- // Create a temporary directory for our config file
- suite.TempDir, err = os.MkdirTemp("", "sda-auth-test-")
- if err != nil {
- log.Fatal("Couldn't create temporary test directory", err)
- }
- suite.ConfigFile, err = os.Create(filepath.Join(suite.TempDir, "config.yaml"))
- if err != nil {
- log.Fatal("Cannot create temporary config file", err)
- }
-
- // Create temporary dummy keys
- suite.JwtPrivateKeyFile, err = os.Create(filepath.Join(suite.TempDir, "jwt-dummy-sec.c4gh"))
- if err != nil {
- log.Fatal("Cannot create temporary private key file", err)
- }
- _, err = os.Create(filepath.Join(suite.TempDir, "jwt-dummy-sec.c4gh_env"))
- if err != nil {
- log.Fatal("Cannot create temporary private key file", err)
- }
-
- // config values to write to the config file
- suite.ElixirConfig = ElixirConfig{
- ID: "elixirTestID",
- Provider: "elixirTestIssuer",
- RedirectURL: "http://elixir/login",
- RevocationURL: "http://elixir/revoke",
- Secret: "elixirTestSecret",
- }
-
- suite.CegaConfig = CegaConfig{
- AuthURL: "http://cega/auth",
- ID: "cegaID",
- Secret: "cegaSecret",
- }
-
- suite.ServerConfig = ServerConfig{
- Cert: "serverCert.pem",
- Key: "serverKey.pem",
- }
-
- suite.S3Inbox = "s3://testInbox"
- suite.JwtIssuer = "JwtIssuer"
- suite.JwtPrivateKey = suite.JwtPrivateKeyFile.Name()
- suite.JwtSignatureAlg = "RS256"
- suite.ResignJwt = true
- suite.InfoURL = "https://test.info"
- suite.InfoText = "About LEGA"
- suite.PublicFile = "public.pem"
-
- // Write config to temp config file
- configYaml, err := yaml.Marshal(Config{
- Elixir: suite.ElixirConfig,
- Cega: suite.CegaConfig,
- Server: suite.ServerConfig,
- S3Inbox: suite.S3Inbox,
- JwtIssuer: suite.JwtIssuer,
- JwtPrivateKey: suite.JwtPrivateKey,
- JwtSignatureAlg: suite.JwtSignatureAlg,
- ResignJwt: suite.ResignJwt,
- InfoURL: suite.InfoURL,
- InfoText: suite.InfoText,
- PublicFile: suite.PublicFile,
- })
- if err != nil {
- log.Errorf("Error marshalling config yaml: %v", err)
- }
- _, err = suite.ConfigFile.Write(configYaml)
- if err != nil {
- log.Errorf("Error writing config file: %v", err)
- }
-
-}
-
-func (suite *ConfigTests) TearDownTest() {
- os.RemoveAll(suite.TempDir)
-}
-
-// Both readConfig and parseConfig is called when using NewConfig, so they are
-// both tested in this single test.
-func (suite *ConfigTests) TestConfig() {
- // change dir so that we read the right config
- err := os.Chdir(suite.TempDir)
- if err != nil {
- log.Errorf("Couldn't access temp directory: %v", err)
- }
-
- config, err := NewConfig()
- assert.NoError(suite.T(), err)
-
- // Check elixir values
- assert.Equal(suite.T(), suite.ElixirConfig.ID, config.Elixir.ID, "Elixir ID misread from config file")
- assert.Equal(suite.T(), suite.ElixirConfig.Provider, config.Elixir.Provider, "Elixir Issuer misread from config file")
- assert.Equal(suite.T(), suite.ElixirConfig.RedirectURL, config.Elixir.RedirectURL, "Elixir RedirectURL misread from config file")
- assert.Equal(suite.T(), suite.ElixirConfig.Secret, config.Elixir.Secret, "Elixir Secret misread from config file")
-
- // Check CEGA values
- assert.Equal(suite.T(), suite.CegaConfig.ID, config.Cega.ID, "CEGA ID misread from config file")
- assert.Equal(suite.T(), suite.CegaConfig.AuthURL, config.Cega.AuthURL, "CEGA AuthURL misread from config file")
- assert.Equal(suite.T(), suite.CegaConfig.Secret, config.Cega.Secret, "CEGA Secret misread from config file")
-
- // Check ServerConfig values
- assert.Equal(suite.T(), suite.ServerConfig.Cert, config.Server.Cert, "ServerConfig Cert misread from config file")
- assert.Equal(suite.T(), suite.ServerConfig.Key, config.Server.Key, "ServerConfig Key misread from config file")
-
- // Check S3Inbox value
- assert.Equal(suite.T(), suite.S3Inbox, config.S3Inbox, "S3Inbox misread from config file")
-
- // Check JWT values
- assert.Equal(suite.T(), suite.JwtIssuer, config.JwtIssuer, "JwtIssuer misread from config file")
- assert.Equal(suite.T(), suite.JwtPrivateKey, config.JwtPrivateKey, "JwtPrivateKey misread from config file")
- assert.Equal(suite.T(), suite.JwtSignatureAlg, config.JwtSignatureAlg, "JwtSignatureAlg misread from config file")
- assert.Equal(suite.T(), suite.ResignJwt, config.ResignJwt, "ResignJwt misread from config file")
-
- // Check project info values
- assert.Equal(suite.T(), suite.InfoText, config.InfoText, "Project info test misread from config file")
- assert.Equal(suite.T(), suite.InfoURL, config.InfoURL, "Project info URL misread from config file")
-
- // sanitycheck without config file or ENVs
- // this should fail
- os.Remove(suite.ConfigFile.Name())
- viper.Reset()
- _, e := NewConfig()
- assert.Error(suite.T(), e)
-
- // Set all values as environment variables
- os.Setenv("ELIXIR_ID", fmt.Sprintf("env_%v", suite.ElixirConfig.ID))
- os.Setenv("ELIXIR_PROVIDER", fmt.Sprintf("env_%v", suite.ElixirConfig.Provider))
- os.Setenv("ELIXIR_REDIRECTURL", fmt.Sprintf("env_%v", suite.ElixirConfig.RedirectURL))
- os.Setenv("ELIXIR_SECRET", fmt.Sprintf("env_%v", suite.ElixirConfig.Secret))
-
- os.Setenv("CEGA_ID", fmt.Sprintf("env_%v", suite.CegaConfig.ID))
- os.Setenv("CEGA_AUTHURL", fmt.Sprintf("env_%v", suite.CegaConfig.AuthURL))
- os.Setenv("CEGA_SECRET", fmt.Sprintf("env_%v", suite.CegaConfig.Secret))
-
- os.Setenv("SERVER_CERT", fmt.Sprintf("env_%v", suite.ServerConfig.Cert))
- os.Setenv("SERVER_KEY", fmt.Sprintf("env_%v", suite.ServerConfig.Key))
-
- os.Setenv("S3INBOX", fmt.Sprintf("env_%v", suite.S3Inbox))
-
- os.Setenv("JWTISSUER", fmt.Sprintf("env_%v", suite.JwtIssuer))
- os.Setenv("JWTPRIVATEKEY", fmt.Sprintf("%v_env", suite.JwtPrivateKey))
- os.Setenv("JWTSIGNATUREALG", fmt.Sprintf("env_%v", suite.JwtSignatureAlg))
- os.Setenv("RESIGNJWT", fmt.Sprintf("%t", suite.ResignJwt))
-
- os.Setenv("INFOTEXT", fmt.Sprintf("env_%v", suite.InfoText))
- os.Setenv("INFOURL", fmt.Sprintf("env_%v", suite.InfoURL))
- os.Setenv("PUBLICFILE", fmt.Sprintf("env_%v", suite.PublicFile))
-
- // re-read the config
- config, err = NewConfig()
- assert.NoError(suite.T(), err)
-
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.ElixirConfig.ID), config.Elixir.ID, "Elixir ID misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.ElixirConfig.Provider), config.Elixir.Provider, "Elixir Issuer misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.ElixirConfig.RedirectURL), config.Elixir.RedirectURL, "Elixir RedirectURL misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.ElixirConfig.Secret), config.Elixir.Secret, "Elixir Secret misread from environment variable")
-
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.CegaConfig.ID), config.Cega.ID, "CEGA ID misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.CegaConfig.AuthURL), config.Cega.AuthURL, "CEGA AuthURL misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.CegaConfig.Secret), config.Cega.Secret, "CEGA Secret misread from environment variable")
-
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.ServerConfig.Cert), config.Server.Cert, "ServerConfig Cert misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.ServerConfig.Key), config.Server.Key, "ServerConfig Key misread from environment variable")
-
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.S3Inbox), config.S3Inbox, "S3Inbox misread from environment variable")
-
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.JwtIssuer), config.JwtIssuer, "JwtIssuer misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("%v_env", suite.JwtPrivateKey), config.JwtPrivateKey, "JwtPrivateKey misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.JwtSignatureAlg), config.JwtSignatureAlg, "JwtSignatureAlg misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("%t", suite.ResignJwt), strconv.FormatBool(config.ResignJwt), "ResignJwt misread from environment variable")
-
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.InfoText), config.InfoText, "Project info text misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.InfoURL), config.InfoURL, "Project info text misread from environment variable")
- assert.Equal(suite.T(), fmt.Sprintf("env_%v", suite.PublicFile), config.PublicFile, "Public file misread from environment variable")
-
- // Check missing private key
- os.Setenv("JWTPRIVATEKEY", "nonexistent-key-file")
-
- // re-read the config
- _, err = NewConfig()
- assert.ErrorContains(suite.T(), err, "missing private key file")
-
- // Repeat check with CEGA login and JWT resigning disabled
- os.Setenv("CEGA_ID", "")
- os.Setenv("CEGA_SECRET", "")
- os.Setenv("RESIGNJWT", fmt.Sprintf("%t", false))
-
- // re-read the config
- _, err = NewConfig()
- assert.NoError(suite.T(), err)
-
- // Repeat with Elixir secret but no ID
- os.Setenv("ELIXIR_ID", "")
-
- // re-read the config
- _, err = NewConfig()
- assert.Equal(suite.T(), err.Error(), "neither cega or elixir login configured")
-
- // Repeat test without CEGA or Elixir login
- os.Setenv("ELIXIR_ID", "")
- os.Setenv("ELIXIR_SECRET", "")
-
- // re-read the config
- _, err = NewConfig()
- assert.Equal(suite.T(), err.Error(), "neither cega or elixir login configured")
-
- os.Setenv("CEGA_ID", fmt.Sprintf("env_%v", suite.CegaConfig.ID))
- os.Setenv("CEGA_SECRET", fmt.Sprintf("env_%v", suite.CegaConfig.Secret))
- os.Setenv("JWTPRIVATEKEY", fmt.Sprintf("%v_env", suite.JwtPrivateKey))
-
- // re-read the config
- _, err = NewConfig()
- assert.NoError(suite.T(), err)
-}
diff --git a/sda-auth/dev-server/cega-users/cega-mock.py b/sda-auth/dev-server/cega-users/cega-mock.py
deleted file mode 100644
index 0bf578fdd..000000000
--- a/sda-auth/dev-server/cega-users/cega-mock.py
+++ /dev/null
@@ -1,82 +0,0 @@
-import sys
-import os
-import logging
-import asyncio
-import json
-from base64 import b64decode
-from aiohttp import web
-
-#logging.basicConfig(format='[%(asctime)s][%(levelname)-8s] (L:%(lineno)s) %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
-logging.basicConfig(format='[%(levelname)-8s] (L:%(lineno)s) %(message)s')
-LOG = logging.getLogger(__name__)
-LOG.setLevel(logging.INFO)
-
-filepath = None
-instances = {}
-store = None
-usernames = {}
-uids = {}
-
-def fetch_user_info(identifier, query):
- LOG.info(f'Requesting User {identifier}')
- pos = usernames.get(identifier, None)
- return store[pos] if pos is not None else None
-
-async def user(request):
- # Authenticate
- auth_header = request.headers.get('AUTHORIZATION')
- if not auth_header:
- raise web.HTTPUnauthorized(text=f'Protected access\n')
- _, token = auth_header.split(None, 1) # Skipping the Basic keyword
- LOG.debug(f'Token is {token}')
- instance, passwd = b64decode(token).decode().split(':', 1)
- LOG.debug(f'I am instance {instance} and the password is {passwd}')
- info = instances.get(instance)
- if info is None or info != passwd:
- raise web.HTTPUnauthorized(text=f'Protected access\n')
-
- # Reload users list
- load_users()
-
- # Find user
- user_info = fetch_user_info(request.match_info['identifier'], request.rel_url.query)
- if user_info is None:
- raise web.HTTPBadRequest(text=f'No info for that user\n')
- LOG.info(f'user info {user_info}')
- return web.json_response(user_info)
-
-def main():
- print("Main is being run")
- if len(sys.argv) < 3:
- print('Usage: {sys.argv[0] }', file=sys.stderr)
- sys.exit(2)
-
- host = sys.argv[1]
- port = sys.argv[2]
-
- global filepath
- filepath = sys.argv[3]
-
- server = web.Application()
- load_users()
-
- # Registering the routes
- server.router.add_get('/username/{identifier}', user, name='user')
-
- # aaaand... cue music
- web.run_app(server, host=host, port=port, shutdown_timeout=0)
-
-
-def load_users():
- # Initialization
- global filepath, instances, store, usernames, uids
- instances[os.environ[f'CEGA_USERS_USER']] = os.environ[f'CEGA_USERS_PASSWORD']
- with open(filepath, 'rt') as f:
- store = json.load(f)
- for i, d in enumerate(store):
- usernames[d['username']] = i
- uids[d['uid']] = i
-
-
-if __name__ == '__main__':
- main()
diff --git a/sda-auth/dev-server/cega-users/users.json b/sda-auth/dev-server/cega-users/users.json
deleted file mode 100644
index 9ed6bbd06..000000000
--- a/sda-auth/dev-server/cega-users/users.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[{"username": "dummy@example.com",
- "uid": 1,
- "passwordHash": "$2b$12$1gyKIjBc9/cT0MYkXX24xe1LjEUjNwgL4rEk8fDoO.vDQZzWkqrn.",
- "gecos": "dummy user",
- "sshPublicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDiEcu2czBfbQh6+A3DplO2DRHG4LmdUKLRPX1vFOpC30TZusio0cFcgi8TEQv9TlMwu2ujF/wn/0D2VwXiDGk/Rbeq9jgTLpVbDWg/3ZGxGSqjPV3fzl0NzmaSgF0+IZQaSr6OjGVpTmpk5G4d4qqFg4Shjjm+AwlgmruThHNS9KmdJ7Vru+rQ8LwcjuSWtBdf6JM3bjlw1swQt6776p+wTK51YSKdtFEE5yVZjVwxlcPre7sRiem0XwSCFsu9sAfUTbHNTfwQ8lVXbvgRGu9SoW0wwb0Qele1WXZ8YFF10KLxGKpb1u0NsXSIZrJZhk0nxKb5tGBSnKXquoAvLZfVEKc+AXw1sDSaKvZaDw0/GORoAVSt3LDKYydAlzpMw6am4fgcEzm0vwCieWvSxd9uLY9IxV4sx0n0ZcuG55Le2TaQMnSm5XQ8zHBFYOb9ux8h6TY6JO+HmSjoHXkGhILKg8Y7zpq0PWy7HUvWzQVVfShAMN/N2gZ3a2T7amg17/S0wtgvjxxpNtnLc0HnHjr/mwtBjrN8C4n+IYI13rqZzPPU1wZu5qiacmHmeR15XAktEFKrpuvViJcylksjwyl6aY9psm+dwocON/yA3pdJGA8mPvrnDpPkGpzqvTqqIMxQkgel46jF2B7+lLzq6wQOsb7Ct66CKKppM6kpVVHRWQ==",
- "enabled": null
-}]
diff --git a/sda-auth/dev-server/docker-compose.yml b/sda-auth/dev-server/docker-compose.yml
deleted file mode 100644
index de51dbd48..000000000
--- a/sda-auth/dev-server/docker-compose.yml
+++ /dev/null
@@ -1,102 +0,0 @@
-services:
- oidc:
- container_name: oidc
- build:
- context: ./oidc
- dockerfile: Dockerfile
- image: mock-oidc-user-server
- environment:
- - PORT=9090
- - HOST=oidc
- - CLIENT_ID=XC56EL11xx
- - CLIENT_SECRET=wHPVQaYXmdDHg
- - CLIENT_REDIRECT_URI=http://localhost:8080/elixir/login
- - AUTH_ROUTE=/auth
- - INTROSPECTION_ROUTE=/token/introspection
- - JWKS_ROUTE=/jwks
- - REVOCATION_ROUTE=/token/revocation
- - TOKEN_ROUTE=/token
- - USERINFO_ROUTE=/userinfo
- ports:
- - 9090:9090
- healthcheck:
- test: ["CMD", "curl", "-f", "http://localhost:9090/.well-known/openid-configuration"]
- interval: 5s
- timeout: 10s
- retries: 4
- cega:
- container_name: cega
- image: egarchive/lega-base:release.v0.2.0
- volumes:
- - ./cega-users:/cega
- command:
- [
- "python",
- "/cega/cega-mock.py",
- "0.0.0.0",
- "8443",
- "/cega/users.json"
- ]
- environment:
- - LEGA_INSTANCES=dummy
- - CEGA_USERS_PASSWORD=dummy
- - CEGA_USERS_USER=dummy
- ports:
- - 8443:8443
- keygen:
- image: golang:alpine3.16
- container_name: keygen
- command:
- - "/bin/sh"
- - "-c"
- - if [ ! -f "/out/c4gh.sec.pem" ]; then wget -qO- "https://github.com/neicnordic/crypt4gh/releases/latest/download/crypt4gh_linux_x86_64.tar.gz" | tar zxf -;
- ./crypt4gh generate -n c4gh -p privatekeypass && mv *.pem /out/; fi
- volumes:
- - /tmp:/out
- auth:
- container_name: auth
- build:
- context: ../
- args:
- GOLANG_VERSION: ${GOLANG_VERSION-1.20}
- dockerfile: Dockerfile
- depends_on:
- oidc:
- condition: service_healthy
- cega:
- condition: service_started
- keygen:
- condition: service_completed_successfully
- environment:
- - ELIXIR_ID=XC56EL11xx
- - ELIXIR_PROVIDER=http://oidc:9090
- - ELIXIR_SECRET=wHPVQaYXmdDHg
- - ELIXIR_JWKPATH=/jwks
- - CEGA_AUTHURL=http://cega:8443/username/
- - CEGA_ID=dummy
- - CEGA_SECRET=dummy
- - CORS_ORIGINS=http://localhost:8080
- - CORS_METHODS=GET,POST, OPTIONS
- - CORS_CREDENTIALS=TRUE
- - LOG_LEVEL=info
- - S3INBOX=s3.example.com
- - JWTISSUER=http://auth:8080
- - JWTPRIVATEKEY=keys/sign-jwt.key
- - JWTSIGNATUREALG=ES256
- - INFOTEXT=About Federated EGA
- - INFOURL=https://ega-archive.org/about/projects-and-funders/federated-ega/
- - PUBLICFILE=/c4gh.pub.pem
- volumes:
- - ../keys:/keys
- - ../:/sda-auth
- - /tmp/c4gh.pub.pem:/c4gh.pub.pem
- image: sda-auth
- ports:
- - 8080:8080
- remote:
- container_name: remote
- image: nginx:1.21
- volumes:
- - ./remote:/usr/share/nginx/html
- ports:
- - 8000:80
diff --git a/sda-auth/dev-server/oidc/.dockerignore b/sda-auth/dev-server/oidc/.dockerignore
deleted file mode 100644
index 4819d0e8a..000000000
--- a/sda-auth/dev-server/oidc/.dockerignore
+++ /dev/null
@@ -1,3 +0,0 @@
-node_modules
-package-lock.json
-npm-debug.log
diff --git a/sda-auth/dev-server/oidc/Dockerfile b/sda-auth/dev-server/oidc/Dockerfile
deleted file mode 100644
index be231e034..000000000
--- a/sda-auth/dev-server/oidc/Dockerfile
+++ /dev/null
@@ -1,16 +0,0 @@
-FROM node:16.2.0-slim
-
-WORKDIR /app
-
-RUN apt update && apt upgrade -qy && apt install -qy curl
-
-COPY package.json ./
-
-RUN rm -rf node_modules
-
-RUN npm install -g npm@latest && \
- npm i camelcase oidc-provider
-
-COPY . .
-
-CMD [ "node", "server.js" ]
diff --git a/sda-auth/dev-server/oidc/package.json b/sda-auth/dev-server/oidc/package.json
deleted file mode 100644
index 4b4a1a554..000000000
--- a/sda-auth/dev-server/oidc/package.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "name": "mock-oidc",
- "version": "0.1.0",
- "main": "server.js",
- "engines": {
- "node": "12"
- },
- "scripts": {
- "start": "node server.js"
- },
- "dependencies": {
- "camelcase": "5.3.1",
- "oidc-provider": "5.5.2"
- }
-}
diff --git a/sda-auth/dev-server/oidc/server.js b/sda-auth/dev-server/oidc/server.js
deleted file mode 100644
index 04593b848..000000000
--- a/sda-auth/dev-server/oidc/server.js
+++ /dev/null
@@ -1,86 +0,0 @@
-const assert = require('assert');
-const camelCase = require('camelcase');
-const Provider = require('oidc-provider');
-
-const port = process.env.PORT || 3000;
-// External port can legally be an empty string
-const ext_port = process.env.EXTERNAL_PORT ?? process.env.PORT;
-const host = process.env.HOST || "oidc" ;
-
-const config = ['CLIENT_ID', 'CLIENT_SECRET', 'CLIENT_REDIRECT_URI'].reduce((acc, v) => {
- assert(process.env[v], `${v} config missing`);
- acc[camelCase(v)] = process.env[v];
- return acc;
-}, {});
-
-const oidcConfig = {
-
- features: {
- devInteractions: true,
- discovery: true,
- registration: false,
- revocation: true,
- sessionManagement: false
- },
- formats: {
- default: 'jwt',
- AccessToken: 'jwt',
- RefreshToken: 'jwt'
- },
- routes: {
- authorization: process.env.AUTH_ROUTE || '/auth',
- introspection: process.env.INTROSPECTION_ROUTE || '/token/introspection',
- certificates: process.env.JWKS_ROUTE || '/jwks',
- revocation: process.env.REVOCATION_ROUTE ||'/token/revocation',
- token: process.env.TOKEN_ROUTE || '/token',
- userinfo: process.env.USERINFO_ROUTE ||'/userinfo'
- },
- scopes: [
- 'openid',
- 'ga4gh_passport_v1',
- 'profile',
- 'email',
- 'offline_access'
- ],
- claims: {
- acr: null,
- sid: null,
- ga4gh_passport_v1: ['ga4gh_passport_v1'],
- auth_time: null,
- ss: null,
- openid: [ 'sub' ],
- profile: ['name', 'email']
- },
-
- findById: async function findById(ctx, sub, token) {
- return {
- accountId: sub,
- async claims(use, scope, claims, rejected) {
- return { name: 'Dummy Tester', email:'dummy.tester@gs.uu.se', sub, ga4gh_passport_v1: ['eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIwIiwibmFtZSI6InRlc3QiLCJnYTRnaF92aXNhX3YxIjp7ImFzc2VydGVkIjoxLCJieSI6InN5c3RlbSIsInNvdXJjZSI6Imh0dHA6Ly93d3cudXUuc2UvZW4vIiwidHlwZSI6IkFmZmlsaWF0aW9uQW5kUm9sZSIsInZhbHVlIjoic3RhZmZAdXUuc2UifSwiYWRtaW4iOnRydWUsImp0aSI6InRlc3QiLCJpYXQiOjE1ODQ4OTc4NDIsImV4cCI6MTU4NDkwMTQ0Mn0.RkAULuJEaExt0zVu3_uE2BSdkHLAHRD8owqhrsrTfLI'] };
- },
- };
- },
-
-};
-
-const oidc = new Provider(`http://${host}${ext_port ? ':' : ''}${ext_port}`, oidcConfig);
-
-const clients= [{
- client_id: config.clientId,
- client_secret: config.clientSecret,
- redirect_uris: config.clientRedirectUri.split(",")
- }];
-
-let server;
-(async () => {
-await oidc.initialize({ clients });
- server = oidc.listen(port, () => {
- console.log(
- `mock-oidc-user-server listening on port ${port}, check http://${host}:${port}/.well-known/openid-configuration`
- );
- });
-})().catch(err => {
- if (server && server.listening) server.close();
- console.error(err);
- process.exitCode = 1;
-});
diff --git a/sda-auth/dev-server/remote/index.html b/sda-auth/dev-server/remote/index.html
deleted file mode 100644
index 62c0fc367..000000000
--- a/sda-auth/dev-server/remote/index.html
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
- CORS login test page
-
-
-
- Log in
-
- Reset
-
-
-
-
-
-
-
diff --git a/sda-auth/go.mod b/sda-auth/go.mod
deleted file mode 100644
index 96f378829..000000000
--- a/sda-auth/go.mod
+++ /dev/null
@@ -1,90 +0,0 @@
-module auth
-
-go 1.21
-
-require (
- github.com/coreos/go-oidc v2.2.1+incompatible
- github.com/google/uuid v1.6.0
- github.com/iris-contrib/middleware/cors v0.0.0-20240111010557-e34016a4d6ee
- github.com/kataras/iris/v12 v12.2.10
- github.com/lestrrat-go/jwx/v2 v2.0.20
- github.com/neicnordic/crypt4gh v1.9.1
- github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282
- github.com/sirupsen/logrus v1.9.3
- github.com/spf13/viper v1.18.2
- github.com/stretchr/testify v1.8.4
- golang.org/x/crypto v0.20.0
- golang.org/x/oauth2 v0.17.0
- gopkg.in/yaml.v3 v3.0.1
-)
-
-require (
- filippo.io/edwards25519 v1.1.0 // indirect
- github.com/BurntSushi/toml v1.3.2 // indirect
- github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
- github.com/CloudyKit/jet/v6 v6.2.0 // indirect
- github.com/Joker/jade v1.1.3 // indirect
- github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
- github.com/andybalholm/brotli v1.1.0 // indirect
- github.com/aymerick/douceur v0.2.0 // indirect
- github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
- github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
- github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
- github.com/fatih/structs v1.1.0 // indirect
- github.com/flosch/pongo2/v4 v4.0.2 // indirect
- github.com/fsnotify/fsnotify v1.7.0 // indirect
- github.com/goccy/go-json v0.10.2 // indirect
- github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
- github.com/golang/protobuf v1.5.3 // indirect
- github.com/golang/snappy v0.0.4 // indirect
- github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 // indirect
- github.com/gorilla/css v1.0.1 // indirect
- github.com/hashicorp/hcl v1.0.0 // indirect
- github.com/iris-contrib/schema v0.0.6 // indirect
- github.com/josharian/intern v1.0.0 // indirect
- github.com/kataras/blocks v0.0.8 // indirect
- github.com/kataras/golog v0.1.11 // indirect
- github.com/kataras/pio v0.0.13 // indirect
- github.com/kataras/sitemap v0.0.6 // indirect
- github.com/kataras/tunnel v0.0.4 // indirect
- github.com/klauspost/compress v1.17.6 // indirect
- github.com/lestrrat-go/blackmagic v1.0.2 // indirect
- github.com/lestrrat-go/httpcc v1.0.1 // indirect
- github.com/lestrrat-go/httprc v1.0.4 // indirect
- github.com/lestrrat-go/iter v1.0.2 // indirect
- github.com/lestrrat-go/option v1.0.1 // indirect
- github.com/magiconair/properties v1.8.7 // indirect
- github.com/mailgun/raymond/v2 v2.0.48 // indirect
- github.com/mailru/easyjson v0.7.7 // indirect
- github.com/microcosm-cc/bluemonday v1.0.26 // indirect
- github.com/mitchellh/mapstructure v1.5.0 // indirect
- github.com/pelletier/go-toml/v2 v2.1.1 // indirect
- github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
- github.com/pquerna/cachecontrol v0.2.0 // indirect
- github.com/russross/blackfriday/v2 v2.1.0 // indirect
- github.com/sagikazarmark/locafero v0.4.0 // indirect
- github.com/sagikazarmark/slog-shim v0.1.0 // indirect
- github.com/schollz/closestmatch v2.1.0+incompatible // indirect
- github.com/segmentio/asm v1.2.0 // indirect
- github.com/sourcegraph/conc v0.3.0 // indirect
- github.com/spf13/afero v1.11.0 // indirect
- github.com/spf13/cast v1.6.0 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
- github.com/subosito/gotenv v1.6.0 // indirect
- github.com/tdewolff/minify/v2 v2.20.16 // indirect
- github.com/tdewolff/parse/v2 v2.7.11 // indirect
- github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
- github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
- github.com/yosssi/ace v0.0.5 // indirect
- go.uber.org/multierr v1.11.0 // indirect
- golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 // indirect
- golang.org/x/net v0.21.0 // indirect
- golang.org/x/sys v0.17.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/time v0.5.0 // indirect
- google.golang.org/appengine v1.6.8 // indirect
- google.golang.org/protobuf v1.32.0 // indirect
- gopkg.in/ini.v1 v1.67.0 // indirect
- gopkg.in/square/go-jose.v2 v2.6.0 // indirect
-)
diff --git a/sda-auth/go.sum b/sda-auth/go.sum
deleted file mode 100644
index f5b09c409..000000000
--- a/sda-auth/go.sum
+++ /dev/null
@@ -1,288 +0,0 @@
-filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
-filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
-github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
-github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
-github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
-github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
-github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME=
-github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
-github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc=
-github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
-github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=
-github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
-github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=
-github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM=
-github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
-github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
-github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
-github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
-github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
-github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
-github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
-github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
-github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a h1:saTgr5tMLFnmy/yg3qDTft4rE5DY2uJ/cCxCe3q0XTU=
-github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a/go.mod h1:Bw9BbhOJVNR+t0jCqx2GC6zv0TGBsShs56Y3gfSCvl0=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
-github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
-github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
-github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
-github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
-github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
-github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
-github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
-github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
-github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
-github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
-github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
-github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
-github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
-github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
-github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 h1:k4Tw0nt6lwro3Uin8eqoET7MDA4JnT8YgbCjc/g5E3k=
-github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
-github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
-github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
-github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
-github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
-github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
-github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
-github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
-github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
-github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
-github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
-github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go=
-github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE=
-github.com/iris-contrib/middleware/cors v0.0.0-20240111010557-e34016a4d6ee h1:srr0HUvI9IAximtqxhF0+WSy9cv9Dd5YlH8RMEkHtsw=
-github.com/iris-contrib/middleware/cors v0.0.0-20240111010557-e34016a4d6ee/go.mod h1:hAsE+pfCAz1M2cCfsEolTmaBwHCyzchRFyCk5I1+kDo=
-github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw=
-github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA=
-github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
-github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
-github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM=
-github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg=
-github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20=
-github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A=
-github.com/kataras/iris/v12 v12.2.10 h1:rEJVM7qMoyhv8wpgkA1yGxibFcONE0jkJ70LFLibTAA=
-github.com/kataras/iris/v12 v12.2.10/go.mod h1:z4+E+kLMqZ7U4WtDsYfFnG7BjMTXLkdzMAXLVMLnMNs=
-github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM=
-github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM=
-github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY=
-github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4=
-github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA=
-github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw=
-github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
-github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
-github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
-github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
-github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
-github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
-github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
-github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8=
-github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
-github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
-github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
-github.com/lestrrat-go/jwx/v2 v2.0.20 h1:sAgXuWS/t8ykxS9Bi2Qtn5Qhpakw1wrcjxChudjolCc=
-github.com/lestrrat-go/jwx/v2 v2.0.20/go.mod h1:UlCSmKqw+agm5BsOBfEAbTvKsEApaGNqHAEUTv5PJC4=
-github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
-github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
-github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
-github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
-github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
-github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
-github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
-github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
-github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
-github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
-github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
-github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
-github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/neicnordic/crypt4gh v1.9.1 h1:NKeOmsZ1/0xDpLvBDjN8Ltoh3ODbLB+NeKulDaNo4Oc=
-github.com/neicnordic/crypt4gh v1.9.1/go.mod h1:C8jHyUkt3bnQg0EwdRRswzvLXfu4dyLQOPARDIQTU24=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282 h1:TQMyrpijtkFyXpNI3rY5hsZQZw+paiH+BfAlsb81HBY=
-github.com/oauth2-proxy/mockoidc v0.0.0-20220308204021-b9169deeb282/go.mod h1:rW25Kyd08Wdn3UVn0YBsDTSvReu0jqpmJKzxITPSjks=
-github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
-github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
-github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k=
-github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
-github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
-github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
-github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
-github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
-github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
-github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
-github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
-github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
-github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
-github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=
-github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
-github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
-github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
-github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
-github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
-github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
-github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
-github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
-github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
-github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
-github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
-github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
-github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
-github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
-github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
-github.com/tdewolff/minify/v2 v2.20.16 h1:/C8dtRkxLTIyUlKlBz46gDiktCrE8a6+c1gTrnPFz+U=
-github.com/tdewolff/minify/v2 v2.20.16/go.mod h1:/FvxV9KaTrFu35J9I2FhRvWSBxcHj8sDSdwBFh5voxM=
-github.com/tdewolff/parse/v2 v2.7.11 h1:v+W45LnzmjndVlfqPCT5gGjAAZKd1GJGOPJveTIkBY8=
-github.com/tdewolff/parse/v2 v2.7.11/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
-github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
-github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
-github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
-github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
-github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
-github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
-github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
-github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
-github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
-github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
-github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
-github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
-github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
-github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
-github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=
-github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
-github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
-github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
-github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
-github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
-github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
-go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg=
-golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
-golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFcdWLGIKnZA4IXNFSrvo=
-golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
-golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
-golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
-golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
-golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
-golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
-google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
-google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
-gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
-gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
-gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs=
-moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=
diff --git a/sda-auth/hooks/build b/sda-auth/hooks/build
deleted file mode 100644
index 0c1346458..000000000
--- a/sda-auth/hooks/build
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-docker build \
- --cache-from neicnordic/sda-auth:latest \
- --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
- --build-arg SOURCE_COMMIT=$(git rev-parse --short HEAD) \
- --tag $IMAGE_NAME .
diff --git a/sda-auth/keys/cert.pem b/sda-auth/keys/cert.pem
deleted file mode 100644
index af8d81d57..000000000
--- a/sda-auth/keys/cert.pem
+++ /dev/null
@@ -1,34 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIF0zCCA7ugAwIBAgIULq1CtDtu0FwvgPWyLwwWIh8XZD0wDQYJKoZIhvcNAQEL
-BQAweTELMAkGA1UEBhMCU0UxEDAOBgNVBAgMB1VwcHNhbGExEDAOBgNVBAcMB1Vw
-cHNhbGExCzAJBgNVBAoMAlVVMQswCQYDVQQLDAJVVTEPMA0GA1UEAwwGc2RhdXRo
-MRswGQYJKoZIhvcNAQkBFgx0ZXN0QHRlc3Quc2UwHhcNMjAwOTE5MTA1NjQ0WhcN
-MjEwOTE5MTA1NjQ0WjB5MQswCQYDVQQGEwJTRTEQMA4GA1UECAwHVXBwc2FsYTEQ
-MA4GA1UEBwwHVXBwc2FsYTELMAkGA1UECgwCVVUxCzAJBgNVBAsMAlVVMQ8wDQYD
-VQQDDAZzZGF1dGgxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5zZTCCAiIwDQYJ
-KoZIhvcNAQEBBQADggIPADCCAgoCggIBALgtVLCyVUx65kgD4uECC7DxCighu++v
-F4xBPB2lhtfbGj2PZ3b1PXfOFMLiounf+doa6sIIgVHbtq59VO0Mfn5nosAJuQjf
-Hu8/F4NbAe5PZBw3xM8tNgIjQ6QEV9rI0Z5JXkL7/HCZBhgPiyHPZzm7HelvRgPe
-9KQHacWa6feOkdDbCVDtWwEYVP9JaieGFfy/5gbuc5M5aHNZO/p96DGzBJDISPR+
-5ZkOrLcLQ/t6r1Xu9/EuWHApW/ujbEn8mcy+LPvVKsNRBfUdTtrr33HKKKIp1MdR
-uXNLoJnMTVHyYkSK8mZhCshvuGWzloi7DWM3mYQgzjBoPhJHds+URlMOrhHEyzEA
-LU15rckYuQhMpiJyhPKAHzYcB420QWlYv0dJnFD/IUcRn7UQSbzlw6YtcNRxBLHr
-ANIWKeBZvcg0FmdsiRxznoVpCgrGrVT+0Jf5cotRV4dJA89TWi1CQuOMraUvwzU3
-qLBMpr6LcDOktFC6bIY8vjZxbVTkFRwwC1gvadiPZoGTYh0WuSMhJwZjeQXw0nJ3
-Unx8N5K6m77ciRFlZC6YHkjMesGu4VEy/nFERO4m6i/9qpXBBrIF8LAcCg6IWPwt
-Dq6n3dAaNDmymWzlwIQjXDjiBgPDuVOq/SQ55QUlG+UzgBbi2dFDCKGYaGl9Xu6x
-dekuOnZ9WxctAgMBAAGjUzBRMB0GA1UdDgQWBBR6nSQmWrlKMDj4OHIoG8jsjkrk
-ezAfBgNVHSMEGDAWgBR6nSQmWrlKMDj4OHIoG8jsjkrkezAPBgNVHRMBAf8EBTAD
-AQH/MA0GCSqGSIb3DQEBCwUAA4ICAQBfBwYKaFI902y+Y6fzvM8Id6i1inb6kMI0
-g/ssWZXXv/AAObcKfbCexdy611mrs+7z+KGWmU21qrTkcZIWocV1Qkq6XYW8n5uk
-AEiSMfkVRQnkiVjOiTSKq1/v0+KtTyU8Zq3Zged/n+aU/Kbt73lsnyOy0NKAW5pD
-TXZdm09wpk16kjTAII5HrC/X5R0PWlT7561A1KsTMygYhk2z4c+UnUTA2X/ggUVq
-GgfUL1iksFlv3i0Tq12ozTrl2qh6TJcVD4TWXLvkoOYwtoc1Iga78MkGodbdFAo3
-UkgOQt1vwxqNxJW/9TE15TLo5IEt6C7cG1IGhsCZfvKC624w9IFfu2gau2r2oXC5
-ngmJ9DKgBoClasRfv4hOclqyEl9Zug0rGQzwYxI0bP9EV0E0j2pu1Avo0kPvfOiE
-ytBcldufmZsDXSgeqZvNbQpmajKH807tdpz/rwrHow4qZ4C/bGWdYvQL9PO7sOKo
-iLRX5TYWN2MYlsvWYqLU3qTQ2UZFJt8QGdiXZzLY5kVItTPXk3BGvxYl6eZ+UJbS
-TP6qDFhyrvNZtBaSuWSofvg6VflqZrnV4X9sP7IycDSt1PrAUiyyYcOU1iCCjWDV
-BTa+r766YU4HGGjsrDafagllL2OoDou8ovPX7r4oLjCYZacTT8dVo5TW3CNu1ae9
-330dQ5Ow8A==
------END CERTIFICATE-----
diff --git a/sda-auth/keys/key.pem b/sda-auth/keys/key.pem
deleted file mode 100644
index 7bb3848b7..000000000
--- a/sda-auth/keys/key.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC4LVSwslVMeuZI
-A+LhAguw8QooIbvvrxeMQTwdpYbX2xo9j2d29T13zhTC4qLp3/naGurCCIFR27au
-fVTtDH5+Z6LACbkI3x7vPxeDWwHuT2QcN8TPLTYCI0OkBFfayNGeSV5C+/xwmQYY
-D4shz2c5ux3pb0YD3vSkB2nFmun3jpHQ2wlQ7VsBGFT/SWonhhX8v+YG7nOTOWhz
-WTv6fegxswSQyEj0fuWZDqy3C0P7eq9V7vfxLlhwKVv7o2xJ/JnMviz71SrDUQX1
-HU7a699xyiiiKdTHUblzS6CZzE1R8mJEivJmYQrIb7hls5aIuw1jN5mEIM4waD4S
-R3bPlEZTDq4RxMsxAC1Nea3JGLkITKYicoTygB82HAeNtEFpWL9HSZxQ/yFHEZ+1
-EEm85cOmLXDUcQSx6wDSFingWb3INBZnbIkcc56FaQoKxq1U/tCX+XKLUVeHSQPP
-U1otQkLjjK2lL8M1N6iwTKa+i3AzpLRQumyGPL42cW1U5BUcMAtYL2nYj2aBk2Id
-FrkjIScGY3kF8NJyd1J8fDeSupu+3IkRZWQumB5IzHrBruFRMv5xRETuJuov/aqV
-wQayBfCwHAoOiFj8LQ6up93QGjQ5spls5cCEI1w44gYDw7lTqv0kOeUFJRvlM4AW
-4tnRQwihmGhpfV7usXXpLjp2fVsXLQIDAQABAoICAQCPY4Nu+bhdDcXhRV1Kjrwp
-as/chL77kRbFNDioYCmGPmfEi7QisjXD42bYf3gUmzK7cn9YxyRfZa5pVNxcnYCR
-yv+zgR5U4NkFrNoSgzUSoy6upWCNZ4aHzYqo1FTN2dEQ6dAAWIyl4Q0UiG1qyj10
-fdCA4AfjlZ5jYf4gQUZsXMv7jbxIDDLwvE/YXQDPep39pC1jMhw6/9PpEg0XLRUs
-NFKWocfiyjTYn8spyxSHYnHFdoIEfG+QCzM4y3fQdmALPfhprAFaBOedeM7etArH
-XXubHPQypda7A6MqehusdAe7k2269Uxe1lP6ogHNu8tldnEHpD7DAzVoJ8lBPRAt
-4PyRLvexwJcEbt1vSGL4bcWlE8LTLJlwLX7FopuNcIhXUj/+lx+lh5OeG03FGqbJ
-4YGUswL8DUqWJcDc7Qm3PolgzwEZUglaTgkkezmBVlTc9QVysvxoxbYwu/7VxcPc
-6yEoVPUWSIOkJOjJy5t6nR4ew4sn19TwgNHC3+HjkFWjJpQlYgxDEr2ybthZGT9d
-VHl+nF7Gby5q5ODjTaojBncbM/D9Y3ccW8aWtbt5b1gQuEtWovxTvt6iGvwalwIC
-xsZmHm+qDE1ah12nqjxIjsIjAOdA4P7+mTUiBmYsxwvDwpImRRsviuLc5OiwSmCV
-xEvjUDz1O0aeqLldzC9TpQKCAQEA6EteRtz91EM13Mx8McFI6a1PxQi0Zqucilru
-6AgugOekIfQSvubBAZXu5bVSKplyp1zqaji+cPB/GCF+M3LRHIfp/vRgoDMt9Fdh
-N7I/ntk+E6fsaH6zqx94p8IymLh1jYDJw2csKo9EGvUZHoKCNj8IFdj583UnGhAQ
-smemgJ2UDu0O3OUAkGRRpil+ICdcgd/aipn/v1TxvaipQ83ag2/Bx2lwIFyAJ8EM
-f5BQTlRqrF3ZFDKr4+qn0jF4pEqFrpWH3eitPBtLLxqlgOcoZW3aCrMMy7VykRnS
-knI1vEhGUEg3je1S0Mgnb0RkGbjg44xBpozk/fpU5ihQgLTvwwKCAQEAyvjo2URP
-GL6KpBxZSnsDJvRAvwQz8nvZea006OgiX4R4dZhVfuOYS2heIIaOlTv4U982AFDc
-OFQNFsXyAJv+cO/+zGJaV9qQfbeC8r2g0+k508wY5ONDkCtxL59LrKDUJRsg5yRS
-UQJreU/Vo+RigrrDuZ1PT39583ZvVwm01RunoyhfCZ+ynj/P4eEC2GfyO29Moobs
-5rzc7U+bclTj5gKmOe14sweFTmWx5E+rBGqbL20bIeeQPyCGArXoc3uUX/kCcxQS
-c8fwb3lubIGmgITtwn3M9QVoqpV8eugFtSUSGe4Ucbha2nC69McEUEbgWLFuC9UW
-CZ8Kyhw9nF7eTwKCAQEA2Z3h0Fkvoi7kwtj+cE421FN8q4WgG58ho6vUrKMdjb10
-UiqpdRYQMkAX8jKPq0Dd3FR7ds95+awUJLMb227w392kJSkjbHEF2CYT+W2PlGzI
-bvmdy7cG8oUlL2QKqnAEEHBalCiPg797ehWrVp3FBrS+Clmer6lM3Gm4eqoHne4B
-yonipqYShTK2Gwg8FDtLuo/P2JC0urYFUjwzdkXfM8r6qqnoVSjTFmsQHmFAGmGT
-Ha89smJWDcrDNXMLJj56RjfndMiJogmfwZ0g90WW3o6u+d8LWbu+fJjIYFGGbcD3
-vjYpdVijgNxBtUdIz6AXbpTy2+iajiR6bLPP1wOqqQKCAQAqMPl+CFQEyb7aBEaP
-U+jA1S8MRdxigFohj96at35Fqqy7jRHgkYDb0/MVAcNrxA6HqLN591T/pIEgBb+b
-XtHSOiEV7S/oaTd12oqu2Lowsp9hpmBaW990fYNGqe86EChpGi2JvqQZ0M30ZqL7
-MYNEt3vt/oQ4+z+nWywjxJHBZsE/CipPPtILUSpuQq6ru1fAAQ/GDRP7lrC5571h
-U8IX0t8o1XMsi9irBjqnQeRDw8FEZ4KnVpJGfQU+VP/f2YVrOcDHmRmI1bvmADDy
-/zRULM2bizjqidhK9U3t4oMlN3J+z12SkgbYt2w1a5U69rC13xQIA6BUGapNfvdT
-pOjDAoIBAHbtTkcJw26AeKwhWsrL6U7pxLfWff0KE8YMJRukpvrGBS/HNYHSM4bh
-2Psq8FDPyfqsuRhInbPvgeAM8IQLW1LRYx4uIi97TvBzoIxwUZNiPISBHtZSL6R8
-XwRynwzCjYtorhay2w8gGvbPIw93crnfc6xh03xU++vx2Wq1cid0Akg9PxEcXuoo
-3tp1QEyuenzb1+4ADaoYFT+wkDdrCoj4I51Ljf3BEwbbfRtG9byw2AsS/4jA3cxg
-FXAX9JUbAn/crMZMJ0lt4+PWLCbWF4J3NR6NWFHBzLvKBAFLOIB60tzIkAhYC5OM
-h4bS/AwPLInvxr3d2Q8zXCbFqCJ4zBI=
------END PRIVATE KEY-----
diff --git a/sda-auth/keys/sign-jwt.key b/sda-auth/keys/sign-jwt.key
deleted file mode 100644
index 88a342896..000000000
--- a/sda-auth/keys/sign-jwt.key
+++ /dev/null
@@ -1,5 +0,0 @@
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEIOwU+SoxTKhL/btDfEQgArNGYOj6wu1wIMkL9pEpJaDAoAoGCCqGSM49
-AwEHoUQDQgAEOcK0xMvOLSdZYTzAEXVTDeEpXdTqh026D8RbX10vG9x7U2cED8Gf
-ikWwDVYNp0JldJOOxiqH/xJRJQ9Zhweqlg==
------END EC PRIVATE KEY-----
diff --git a/sda-auth/tests/integration/__init__.py b/sda-auth/tests/integration/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/sda-auth/tests/integration/__pycache__/__init__.cpython-37.pyc b/sda-auth/tests/integration/__pycache__/__init__.cpython-37.pyc
deleted file mode 100644
index 2e81fd44b..000000000
Binary files a/sda-auth/tests/integration/__pycache__/__init__.cpython-37.pyc and /dev/null differ
diff --git a/sda-auth/tests/integration/__pycache__/test_auth.cpython-37-pytest-6.0.1.pyc b/sda-auth/tests/integration/__pycache__/test_auth.cpython-37-pytest-6.0.1.pyc
deleted file mode 100644
index f683d3323..000000000
Binary files a/sda-auth/tests/integration/__pycache__/test_auth.cpython-37-pytest-6.0.1.pyc and /dev/null differ
diff --git a/sda-auth/tests/integration/test_auth.py b/sda-auth/tests/integration/test_auth.py
deleted file mode 100644
index df7a09dd4..000000000
--- a/sda-auth/tests/integration/test_auth.py
+++ /dev/null
@@ -1,91 +0,0 @@
-import unittest
-import requests
-
-
-class TestElixirAuth(unittest.TestCase):
- """ElixirAuth.
- Testing ElixirAuth."""
-
- def setUp(self):
- """Initialise authenticator."""
- self.backend_url = "http://localhost:8080/elixir/"
-
-
- def tearDown(self):
- """Finalise test."""
- print("Finishing test")
-
-
- def test_valid_elixir_login(self):
- """Test that the login endpoint is active."""
-
- grant_response = requests.get(self.backend_url,
- allow_redirects=True)
-
- print("Grant response")
- location = grant_response.url
- grant_id = location.split('/').pop()
- print(grant_id)
- print(location)
-
- self.assertEqual(grant_response.status_code, 200)
- self.assertIsNotNone(grant_id)
-
- oidc_url = f'http://oidc:9090/interaction/{grant_id}/submit'
- cookies = {"_grant": grant_id}
- creds_payload = {"view":'login',
- "login":'dummy@example.com',
- "password":'dummy',
- "submit": ''}
-
- oidc_response = requests.post(oidc_url,
- allow_redirects=True,
- data=creds_payload,
- cookies=cookies)
-
- location = oidc_response.url
- self.assertEqual(oidc_response.status_code, 200)
- self.assertIs(self.backend_url in location, True)
-
-class TestEGAAuth(unittest.TestCase):
- """EgaAuth.
- Testing EgaAuth."""
-
- def setUp(self):
- """Initialise authenticator."""
- self.backend_url = "http://localhost:8080/ega"
-
-
- def tearDown(self):
- """Finalise test."""
- print("Finishing test")
-
-
- def test_valid_ega_login(self):
- """Test that the login is successful."""
- creds_payload = { "username":'dummy@example.com',
- "password":'dummy',
- "submit": 'log+in' }
-
- login_response = requests.post(self.backend_url,
- allow_redirects=False,
- data=creds_payload,
- cookies=None)
-
-
- self.assertEqual(login_response.status_code, 200)
-
-
- def test_invalid_ega_login(self):
- """Test that the login is not successful."""
- creds_payload = { "username":'dummy@foo.bar',
- "password":'wrongpassword',
- "submit": 'log+in' }
-
- login_response = requests.post(self.backend_url,
- allow_redirects=False,
- data=creds_payload,
- cookies=None)
-
-
- self.assertEqual(login_response.status_code, 303)
diff --git a/sda/Dockerfile b/sda/Dockerfile
index b44d7bed2..597e8e712 100644
--- a/sda/Dockerfile
+++ b/sda/Dockerfile
@@ -19,6 +19,7 @@ LABEL org.label-schema.vcs-url="https://github.com/neicnordic/sensitive-data-arc
LABEL org.label-schema.vcs-ref=$SOURCE_COMMIT
COPY --from=Build /go/sda-* /usr/local/bin/
+COPY --from=Build /go/cmd/auth/frontend /frontend
COPY --from=Build /go/schemas /schemas
USER 65534
@@ -34,6 +35,7 @@ LABEL org.label-schema.vcs-url="https://github.com/neicnordic/sensitive-data-arc
LABEL org.label-schema.vcs-ref=$SOURCE_COMMIT
COPY --from=Build /go/sda-* /usr/local/bin/
+COPY --from=Build /go/cmd/auth/frontend /frontend
COPY --from=Build /go/schemas /schemas
USER 65534
diff --git a/sda/cmd/auth/auth.md b/sda/cmd/auth/auth.md
new file mode 100644
index 000000000..44bc4b366
--- /dev/null
+++ b/sda/cmd/auth/auth.md
@@ -0,0 +1,98 @@
+# SDA authentication service
+
+This service allows users to log in both via LS-AAI (OIDC) or EGA (NSS).
+
+After successful authentication users will be able to get the `access token` and download the `S3 config file` needed in order to be able to upload files to the [S3Inbox service](../s3inbox/s3inbox.md).
+
+## Choosing provider login
+
+The `auth` allows for two different types of login providers: `EGA` and `LS_AAI` (OIDC). It is possible, to run the service using both or only one of the providers.
+
+In order to remove the `EGA` option, remove the `CEGA_ID` and `CEGA_SECRET` options from the configuration, while for removing the `LS-AAI` option, remove the `OIDC_ID` and `OIDC_SECRET` variables.
+
+## Configuration example for local testing
+
+The following settings can be configured for deploying the service, either by using environment variables or a YAML file.
+
+| Parameter | Description | Defined value |
+| ----------------------- | ------------------------------------------------------------------------------------ | --------------------------------------- |
+| `AUTH_CEGA_AUTHURL` | CEGA server endpoint | `http://cega:8443/lega/v1/legas/users/` |
+| `AUTH_CEGA_ID` | CEGA server authentication id | `dummy` |
+| `AUTH_CEGA_SECRET` | CEGA server authentication secret | `dummy` |
+| `AUTH_CORS_CREDENTIALS` | If cookies, authorization headers, and TLS client certificates are allowed over CORS | `false` |
+| `AUTH_CORS_METHODS` | Allowed Cross-Origin Resource Sharing (CORS) methods | `""` |
+| `AUTH_CORS_ORIGINS` | Allowed Cross-Origin Resource Sharing (CORS) origins | `""` |
+| `AUTH_JWT_ISSUER` | Issuer of JWT tokens | `http://auth:8080` |
+| `AUTH_JWT_PRIVATEKEY` | Path to private key for signing the JWT token | `keys/sign-jwt.key` |
+| `AUTH_JWT_SIGNATUREALG` | Algorithm used to sign the JWT token. ES256 (ECDSA) or RS256 (RSA) are supported | `ES256` |
+| `AUTH_RESIGNJWT` | Set to `false` to serve the raw OIDC JWT, i.e. without re-signing it | `""` |
+| `AUTH_S3INBOX` | S3 inbox host | `http://s3.example.com` |
+| `LOG_LEVEL` | Log level | `info` |
+| `OIDC_ID` | OIDC authentication id | `XC56EL11xx` |
+| `OIDC_SECRET` | OIDC authentication secret | `wHPVQaYXmdDHg` |
+| `OIDC_PROVIDER` | OIDC issuer URL | `http://oidc:8080` |
+| `OIDC_JWKPATH` | JWK endpoint where the public key can be retrieved for token validation | `/jwks` |
+| `SERVER_CERT` | Certificate file path | `""` |
+| `SERVER_KEY` | Private key file path | `""` |
+
+## Running with Cross-Origin Resource Sharing (CORS)
+
+This service can be run as a backend only, and in the case where the frontend is running somewhere else, CORS is needed.
+
+Recommended CORS settings for a given host are:
+
+```txt
+AUTH_CORS_ORIGINS="https://"
+AUTH_CORS_METHODS="GET,OPTIONS,POST"
+AUTH_CORS_CREDENTIALS="true"
+```
+
+A minimal CORS login (for testing purposes) can look like this:
+
+```html
+
+
+
+
+
+
+ CORS login test page
+
+
+
+ Log in
+
+ Reset
+
+
+
+
+
+
+
+
+```
diff --git a/sda-auth/cega.go b/sda/cmd/auth/cega.go
similarity index 89%
rename from sda-auth/cega.go
rename to sda/cmd/auth/cega.go
index 8f9cabedb..54f2919bf 100644
--- a/sda-auth/cega.go
+++ b/sda/cmd/auth/cega.go
@@ -6,6 +6,7 @@ import (
"net/http"
"strings"
+ "github.com/neicnordic/sensitive-data-archive/internal/config"
log "github.com/sirupsen/logrus"
bcrypt "golang.org/x/crypto/bcrypt"
)
@@ -42,7 +43,7 @@ func verifyPassword(password, hash string) bool {
}
// Authenticate against CEGA
-func authenticateWithCEGA(conf CegaConfig, username string) (*http.Response, error) {
+func authenticateWithCEGA(conf config.CegaConfig, username string) (*http.Response, error) {
client := &http.Client{}
payload := strings.NewReader("")
req, err := http.NewRequest("GET", fmt.Sprintf("%s/%s", strings.TrimSuffix(conf.AuthURL, "/"), username), payload)
diff --git a/sda-auth/cega_test.go b/sda/cmd/auth/cega_test.go
similarity index 100%
rename from sda-auth/cega_test.go
rename to sda/cmd/auth/cega_test.go
diff --git a/sda-auth/frontend/static/EGA.png b/sda/cmd/auth/frontend/static/EGA.png
similarity index 100%
rename from sda-auth/frontend/static/EGA.png
rename to sda/cmd/auth/frontend/static/EGA.png
diff --git a/sda-auth/frontend/static/FEGA-logo-generic.svg b/sda/cmd/auth/frontend/static/FEGA-logo-generic.svg
similarity index 100%
rename from sda-auth/frontend/static/FEGA-logo-generic.svg
rename to sda/cmd/auth/frontend/static/FEGA-logo-generic.svg
diff --git a/sda-auth/frontend/static/Lifescience-RI.png b/sda/cmd/auth/frontend/static/Lifescience-RI.png
similarity index 100%
rename from sda-auth/frontend/static/Lifescience-RI.png
rename to sda/cmd/auth/frontend/static/Lifescience-RI.png
diff --git a/sda-auth/frontend/static/bootstrap.min.css b/sda/cmd/auth/frontend/static/bootstrap.min.css
similarity index 100%
rename from sda-auth/frontend/static/bootstrap.min.css
rename to sda/cmd/auth/frontend/static/bootstrap.min.css
diff --git a/sda-auth/frontend/static/bootstrap.min.js b/sda/cmd/auth/frontend/static/bootstrap.min.js
similarity index 100%
rename from sda-auth/frontend/static/bootstrap.min.js
rename to sda/cmd/auth/frontend/static/bootstrap.min.js
diff --git a/sda-auth/frontend/static/custom.css b/sda/cmd/auth/frontend/static/custom.css
similarity index 100%
rename from sda-auth/frontend/static/custom.css
rename to sda/cmd/auth/frontend/static/custom.css
diff --git a/sda-auth/frontend/static/jquery-3.5.1.min.js b/sda/cmd/auth/frontend/static/jquery-3.5.1.min.js
similarity index 100%
rename from sda-auth/frontend/static/jquery-3.5.1.min.js
rename to sda/cmd/auth/frontend/static/jquery-3.5.1.min.js
diff --git a/sda-auth/frontend/static/login.js b/sda/cmd/auth/frontend/static/login.js
similarity index 100%
rename from sda-auth/frontend/static/login.js
rename to sda/cmd/auth/frontend/static/login.js
diff --git a/sda-auth/frontend/templates/ega.html b/sda/cmd/auth/frontend/templates/ega.html
similarity index 100%
rename from sda-auth/frontend/templates/ega.html
rename to sda/cmd/auth/frontend/templates/ega.html
diff --git a/sda-auth/frontend/templates/elixir.html b/sda/cmd/auth/frontend/templates/elixir.html
similarity index 100%
rename from sda-auth/frontend/templates/elixir.html
rename to sda/cmd/auth/frontend/templates/elixir.html
diff --git a/sda-auth/frontend/templates/index.html b/sda/cmd/auth/frontend/templates/index.html
similarity index 100%
rename from sda-auth/frontend/templates/index.html
rename to sda/cmd/auth/frontend/templates/index.html
diff --git a/sda-auth/frontend/templates/loginform.html b/sda/cmd/auth/frontend/templates/loginform.html
similarity index 100%
rename from sda-auth/frontend/templates/loginform.html
rename to sda/cmd/auth/frontend/templates/loginform.html
diff --git a/sda-auth/info.go b/sda/cmd/auth/info.go
similarity index 92%
rename from sda-auth/info.go
rename to sda/cmd/auth/info.go
index 375bad2fe..ad7d75d15 100644
--- a/sda-auth/info.go
+++ b/sda/cmd/auth/info.go
@@ -34,7 +34,7 @@ func readPublicKeyFile(filename string) (key *[32]byte, err error) {
// getInfo returns information needed by the client to authenticate
func (auth AuthHandler) getInfo(ctx iris.Context) {
- info := Info{ClientID: auth.OAuth2Config.ClientID, OidcURI: auth.Config.Elixir.Provider, PublicKey: auth.pubKey, InboxURI: auth.Config.S3Inbox}
+ info := Info{ClientID: auth.OAuth2Config.ClientID, OidcURI: auth.Config.OIDC.Provider, PublicKey: auth.pubKey, InboxURI: auth.Config.S3Inbox}
err := ctx.JSON(info)
if err != nil {
diff --git a/sda-auth/jwt.go b/sda/cmd/auth/jwt.go
similarity index 100%
rename from sda-auth/jwt.go
rename to sda/cmd/auth/jwt.go
diff --git a/sda-auth/jwt_test.go b/sda/cmd/auth/jwt_test.go
similarity index 100%
rename from sda-auth/jwt_test.go
rename to sda/cmd/auth/jwt_test.go
diff --git a/sda-auth/main.go b/sda/cmd/auth/main.go
similarity index 84%
rename from sda-auth/main.go
rename to sda/cmd/auth/main.go
index 94f46e7cd..ff4f1a166 100644
--- a/sda-auth/main.go
+++ b/sda/cmd/auth/main.go
@@ -16,6 +16,7 @@ import (
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/sessions"
"github.com/lestrrat-go/jwx/v2/jwt"
+ "github.com/neicnordic/sensitive-data-archive/internal/config"
log "github.com/sirupsen/logrus"
"golang.org/x/oauth2"
)
@@ -26,12 +27,12 @@ type LoginOption struct {
}
type OIDCData struct {
- S3Conf map[string]string
- ElixirID ElixirIdentity
+ S3Conf map[string]string
+ OIDCID OIDCIdentity
}
type AuthHandler struct {
- Config *Config
+ Config config.AuthConf
OAuth2Config oauth2.Config
OIDCProvider *oidc.Provider
htmlDir string
@@ -84,9 +85,9 @@ func (auth AuthHandler) getMain(ctx iris.Context) {
func (auth AuthHandler) getLoginOptions(ctx iris.Context) {
var response []LoginOption
- // Only add the Elixir option if it has both id and secret
- if auth.Config.Elixir.ID != "" && auth.Config.Elixir.Secret != "" {
- response = append(response, LoginOption{Name: "Lifescience-RI", URL: "/elixir"})
+ // Only add the OIDC option if it has both id and secret
+ if auth.Config.OIDC.ID != "" && auth.Config.OIDC.Secret != "" {
+ response = append(response, LoginOption{Name: "Lifescience-RI", URL: "/oidc"})
}
// Only add the CEGA option if it has both id and secret
@@ -212,13 +213,13 @@ func (auth AuthHandler) getEGALogin(ctx iris.Context) {
}
}
-// getEGAConf returns an s3config file for an elixir login
+// getEGAConf returns an s3config file for an oidc login
func (auth AuthHandler) getEGAConf(ctx iris.Context) {
auth.getInboxConfig(ctx, "ega")
}
-// getElixir redirects to the elixir page defined in auth.Config
-func (auth AuthHandler) getElixir(ctx iris.Context) {
+// getOIDC redirects to the oidc page defined in auth.Config
+func (auth AuthHandler) getOIDC(ctx iris.Context) {
state := uuid.New()
ctx.SetCookie(&http.Cookie{Name: "state", Value: state.String(), Secure: true})
@@ -231,9 +232,9 @@ func (auth AuthHandler) getElixir(ctx iris.Context) {
}
}
-// elixirLogin authenticates the user with return values from the elixir
-// login page and returns the resulting data to the getElixirLogin page, or
-// getElixirCORSLogin endpoint.
+// elixirLogin authenticates the user with return values from the oidc
+// login page and returns the resulting data to the getOIDCLogin page, or
+// getOIDCCORSLogin endpoint.
func (auth AuthHandler) elixirLogin(ctx iris.Context) *OIDCData {
state := ctx.Request().URL.Query().Get("state")
sessionState := ctx.GetCookie("state")
@@ -251,9 +252,9 @@ func (auth AuthHandler) elixirLogin(ctx iris.Context) *OIDCData {
}
code := ctx.Request().URL.Query().Get("code")
- idStruct, err := authenticateWithOidc(auth.OAuth2Config, auth.OIDCProvider, code, auth.Config.Elixir.jwkURL)
+ idStruct, err := authenticateWithOidc(auth.OAuth2Config, auth.OIDCProvider, code, auth.Config.OIDC.JwkURL)
if err != nil {
- log.WithFields(log.Fields{"authType": "elixir"}).Errorf("authentication failed: %s", err)
+ log.WithFields(log.Fields{"authType": "oidc"}).Errorf("authentication failed: %s", err)
_, err := ctx.Writef("Authentication failed. You may need to clear your session cookies and try again.")
if err != nil {
log.Error("Failed to write response: ", err)
@@ -279,14 +280,14 @@ func (auth AuthHandler) elixirLogin(ctx iris.Context) *OIDCData {
idStruct.ExpDate = expDate
}
- log.WithFields(log.Fields{"authType": "elixir", "user": idStruct.User}).Infof("User was authenticated")
+ log.WithFields(log.Fields{"authType": "oidc", "user": idStruct.User}).Infof("User was authenticated")
s3conf := getS3ConfigMap(idStruct.Token, auth.Config.S3Inbox, idStruct.User)
- return &OIDCData{S3Conf: s3conf, ElixirID: idStruct}
+ return &OIDCData{S3Conf: s3conf, OIDCID: idStruct}
}
-// getElixirLogin renders the `elixir.html` template to the given iris context
-func (auth AuthHandler) getElixirLogin(ctx iris.Context) {
+// getOIDCLogin renders the `oidc.html` template to the given iris context
+func (auth AuthHandler) getOIDCLogin(ctx iris.Context) {
oidcData := auth.elixirLogin(ctx)
if oidcData == nil {
@@ -294,15 +295,15 @@ func (auth AuthHandler) getElixirLogin(ctx iris.Context) {
}
s := sessions.Get(ctx)
- s.SetFlash("elixir", oidcData.S3Conf)
+ s.SetFlash("oidc", oidcData.S3Conf)
ctx.ViewData("infoUrl", auth.Config.InfoURL)
ctx.ViewData("infoText", auth.Config.InfoText)
- ctx.ViewData("User", oidcData.ElixirID.User)
- ctx.ViewData("Passport", oidcData.ElixirID.Passport)
- ctx.ViewData("Token", oidcData.ElixirID.Token)
- ctx.ViewData("ExpDate", oidcData.ElixirID.ExpDate)
+ ctx.ViewData("User", oidcData.OIDCID.User)
+ ctx.ViewData("Passport", oidcData.OIDCID.Passport)
+ ctx.ViewData("Token", oidcData.OIDCID.Token)
+ ctx.ViewData("ExpDate", oidcData.OIDCID.ExpDate)
- err := ctx.View("elixir.html")
+ err := ctx.View("oidc.html")
if err != nil {
log.Error("Failed to view login form: ", err)
@@ -310,8 +311,8 @@ func (auth AuthHandler) getElixirLogin(ctx iris.Context) {
}
}
-// getElixirCORSLogin returns the oidc data as JSON to the given iris context
-func (auth AuthHandler) getElixirCORSLogin(ctx iris.Context) {
+// getOIDCCORSLogin returns the oidc data as JSON to the given iris context
+func (auth AuthHandler) getOIDCCORSLogin(ctx iris.Context) {
oidcData := auth.elixirLogin(ctx)
if oidcData == nil {
@@ -326,9 +327,9 @@ func (auth AuthHandler) getElixirCORSLogin(ctx iris.Context) {
}
}
-// getElixirConf returns an s3config file for an elixir login
-func (auth AuthHandler) getElixirConf(ctx iris.Context) {
- auth.getInboxConfig(ctx, "elixir")
+// getOIDCConf returns an s3config file for an oidc login
+func (auth AuthHandler) getOIDCConf(ctx iris.Context) {
+ auth.getInboxConfig(ctx, "oidc")
}
// globalHeaders presets common response headers
@@ -355,7 +356,7 @@ func addCSPheaders(ctx iris.Context) {
func main() {
// Initialise config
- config, err := NewConfig()
+ config, err := config.NewConfig("auth")
if err != nil {
log.Errorf("Failed to generate config, reason: %v", err)
os.Exit(1)
@@ -364,14 +365,14 @@ func main() {
var oauth2Config oauth2.Config
var provider *oidc.Provider
- if config.Elixir.ID != "" && config.Elixir.Secret != "" {
+ if config.Auth.OIDC.ID != "" && config.Auth.OIDC.Secret != "" {
// Initialise OIDC client
- oauth2Config, provider = getOidcClient(config.Elixir)
+ oauth2Config, provider = getOidcClient(config.Auth.OIDC)
}
// Create handler struct for the web server
authHandler := AuthHandler{
- Config: config,
+ Config: config.Auth,
OAuth2Config: oauth2Config,
OIDCProvider: provider,
htmlDir: "./frontend/templates",
@@ -408,11 +409,11 @@ func main() {
app.Get("/ega/s3conf", authHandler.getEGAConf)
app.Get("/ega/login", addCSPheaders, authHandler.getEGALogin)
- // Elixir endpoints
- app.Get("/elixir", authHandler.getElixir)
- app.Get("/elixir/s3conf", authHandler.getElixirConf)
- app.Get("/elixir/login", authHandler.getElixirLogin)
- app.Get("/elixir/cors_login", authHandler.getElixirCORSLogin)
+ // OIDC endpoints
+ app.Get("/oidc", authHandler.getOIDC)
+ app.Get("/oidc/s3conf", authHandler.getOIDCConf)
+ app.Get("/oidc/login", authHandler.getOIDCLogin)
+ app.Get("/oidc/cors_login", authHandler.getOIDCCORSLogin)
publicKey, err := readPublicKeyFile(authHandler.Config.PublicFile)
if err != nil {
diff --git a/sda-auth/elixir.go b/sda/cmd/auth/oidc.go
similarity index 88%
rename from sda-auth/elixir.go
rename to sda/cmd/auth/oidc.go
index 48a64c44a..19df6a136 100644
--- a/sda-auth/elixir.go
+++ b/sda/cmd/auth/oidc.go
@@ -9,12 +9,13 @@ import (
"github.com/lestrrat-go/jwx/v2/jwk"
"github.com/lestrrat-go/jwx/v2/jws"
"github.com/lestrrat-go/jwx/v2/jwt"
+ "github.com/neicnordic/sensitive-data-archive/internal/config"
log "github.com/sirupsen/logrus"
"golang.org/x/oauth2"
)
-// ElixirIdentity represents an Elixir user instance
-type ElixirIdentity struct {
+// OIDCIdentity represents an OIDC user instance
+type OIDCIdentity struct {
User string
Passport []string
Token string
@@ -25,7 +26,7 @@ type ElixirIdentity struct {
}
// Configure an OpenID Connect aware OAuth2 client.
-func getOidcClient(conf ElixirConfig) (oauth2.Config, *oidc.Provider) {
+func getOidcClient(conf config.OIDCConfig) (oauth2.Config, *oidc.Provider) {
contx := context.Background()
provider, err := oidc.NewProvider(contx, conf.Provider)
if err != nil {
@@ -43,11 +44,11 @@ func getOidcClient(conf ElixirConfig) (oauth2.Config, *oidc.Provider) {
return oauth2Config, provider
}
-// Authenticate with an Oidc client.against Elixir AAI
-func authenticateWithOidc(oauth2Config oauth2.Config, provider *oidc.Provider, code, jwkURL string) (ElixirIdentity, error) {
+// Authenticate with an Oidc client.against OIDC AAI
+func authenticateWithOidc(oauth2Config oauth2.Config, provider *oidc.Provider, code, jwkURL string) (OIDCIdentity, error) {
contx := context.Background()
defer contx.Done()
- var idStruct ElixirIdentity
+ var idStruct OIDCIdentity
oauth2Token, err := oauth2Config.Exchange(contx, code)
if err != nil {
@@ -101,7 +102,7 @@ func authenticateWithOidc(oauth2Config oauth2.Config, provider *oidc.Provider, c
return idStruct, err
}
- idStruct = ElixirIdentity{
+ idStruct = OIDCIdentity{
User: userInfo.Subject,
Token: rawAccessToken,
Passport: claims.PassportClaim,
@@ -114,7 +115,7 @@ func authenticateWithOidc(oauth2Config oauth2.Config, provider *oidc.Provider, c
return idStruct, err
}
-// Validate raw (Elixir) jwt against public key from jwk. Return parsed jwt and its expiration date.
+// Validate raw (OIDC) jwt against public key from jwk. Return parsed jwt and its expiration date.
func validateToken(rawJwt, jwksURL string) (*jwt.Token, string, error) {
set, err := jwk.Fetch(context.Background(), jwksURL)
if err != nil {
diff --git a/sda-auth/elixir_test.go b/sda/cmd/auth/oidc_test.go
similarity index 88%
rename from sda-auth/elixir_test.go
rename to sda/cmd/auth/oidc_test.go
index 84b993d8b..6a3d395cc 100644
--- a/sda-auth/elixir_test.go
+++ b/sda/cmd/auth/oidc_test.go
@@ -12,6 +12,7 @@ import (
"github.com/lestrrat-go/jwx/v2/jwa"
"github.com/lestrrat-go/jwx/v2/jwk"
"github.com/lestrrat-go/jwx/v2/jwt"
+ "github.com/neicnordic/sensitive-data-archive/internal/config"
"github.com/oauth2-proxy/mockoidc"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
@@ -19,26 +20,26 @@ import (
"golang.org/x/oauth2"
)
-type ElixirTests struct {
+type OIDCTests struct {
suite.Suite
- TempDir string
- ECKeyFile *os.File
- RSAKeyFile *os.File
- mockServer *mockoidc.MockOIDC
- ElixirConfig ElixirConfig
+ TempDir string
+ ECKeyFile *os.File
+ RSAKeyFile *os.File
+ mockServer *mockoidc.MockOIDC
+ OIDCConfig config.OIDCConfig
}
-func TestElixirTestSuite(t *testing.T) {
- suite.Run(t, new(ElixirTests))
+func TestOIDCTestSuite(t *testing.T) {
+ suite.Run(t, new(OIDCTests))
}
-func (suite *ElixirTests) SetupTest() {
+func (suite *OIDCTests) SetupTest() {
var err error
suite.mockServer, err = mockoidc.Run()
assert.NoError(suite.T(), err)
// create an elixir config that has the needed endpoints set
- suite.ElixirConfig = ElixirConfig{
+ suite.OIDCConfig = config.OIDCConfig{
ID: suite.mockServer.ClientID,
Provider: suite.mockServer.Issuer(),
RedirectURL: "http://redirect",
@@ -46,28 +47,28 @@ func (suite *ElixirTests) SetupTest() {
}
}
-func (suite *ElixirTests) TearDownTest() {
+func (suite *OIDCTests) TearDownTest() {
err := suite.mockServer.Shutdown()
assert.NoError(suite.T(), err)
}
-func (suite *ElixirTests) TestGetOidcClient() {
+func (suite *OIDCTests) TestGetOidcClient() {
expectedEndpoint := oauth2.Endpoint{
AuthURL: suite.mockServer.AuthorizationEndpoint(),
TokenURL: suite.mockServer.TokenEndpoint(),
AuthStyle: 0}
- oauth2Config, provider := getOidcClient(suite.ElixirConfig)
+ oauth2Config, provider := getOidcClient(suite.OIDCConfig)
assert.Equal(suite.T(), suite.mockServer.ClientID, oauth2Config.ClientID, "ClientID was modified when creating the oauth2Config")
assert.Equal(suite.T(), suite.mockServer.ClientSecret, oauth2Config.ClientSecret, "ClientSecret was modified when creating the oauth2Config")
- assert.Equal(suite.T(), suite.ElixirConfig.RedirectURL, oauth2Config.RedirectURL, "RedirectURL was modified when creating the oauth2Config")
+ assert.Equal(suite.T(), suite.OIDCConfig.RedirectURL, oauth2Config.RedirectURL, "RedirectURL was modified when creating the oauth2Config")
assert.Equal(suite.T(), expectedEndpoint, oauth2Config.Endpoint, "Issuer was modified when creating the oauth2Config")
assert.Equal(suite.T(), expectedEndpoint, provider.Endpoint(), "provider has the wrong endpoint")
assert.Equal(suite.T(), []string{"openid", "ga4gh_passport_v1 profile email eduperson_entitlement"}, oauth2Config.Scopes, "oauth2Config has the wrong scopes")
}
-func (suite *ElixirTests) TestAuthenticateWithOidc() {
+func (suite *OIDCTests) TestAuthenticateWithOidc() {
// Create a code to authenticate
@@ -79,17 +80,17 @@ func (suite *ElixirTests) TestAuthenticateWithOidc() {
code := session.SessionID
jwkURL := suite.mockServer.JWKSEndpoint()
- oauth2Config, provider := getOidcClient(suite.ElixirConfig)
+ oauth2Config, provider := getOidcClient(suite.OIDCConfig)
elixirIdentity, err := authenticateWithOidc(oauth2Config, provider, code, jwkURL)
assert.Nil(suite.T(), err, "Failed to authenticate with OIDC")
assert.NotEqual(suite.T(), "", elixirIdentity.Token, "Empty token returned from OIDC authentication")
}
-func (suite *ElixirTests) TestValidateJwt() {
+func (suite *OIDCTests) TestValidateJwt() {
session, err := suite.mockServer.SessionStore.NewSession("openid email profile", "nonce", mockoidc.DefaultUser(), "", "")
assert.NoError(suite.T(), err)
- oauth2Config, provider := getOidcClient(suite.ElixirConfig)
+ oauth2Config, provider := getOidcClient(suite.OIDCConfig)
jwkURL := suite.mockServer.JWKSEndpoint()
elixirIdentity, _ := authenticateWithOidc(oauth2Config, provider, session.SessionID, jwkURL)
elixirJWT := elixirIdentity.Token
diff --git a/sda-auth/s3conf.go b/sda/cmd/auth/s3conf.go
similarity index 100%
rename from sda-auth/s3conf.go
rename to sda/cmd/auth/s3conf.go
diff --git a/sda-auth/s3conf_test.go b/sda/cmd/auth/s3conf_test.go
similarity index 100%
rename from sda-auth/s3conf_test.go
rename to sda/cmd/auth/s3conf_test.go
diff --git a/sda/go.mod b/sda/go.mod
index 8559219d4..fa867ef33 100644
--- a/sda/go.mod
+++ b/sda/go.mod
@@ -10,15 +10,19 @@ require (
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.7
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.2
github.com/aws/smithy-go v1.20.1
+ github.com/coreos/go-oidc v2.2.1+incompatible
github.com/gin-gonic/gin v1.9.1
github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.1
github.com/heptiolabs/healthcheck v0.0.0-20211123025425-613501dd5deb
+ github.com/iris-contrib/middleware/cors v0.0.0-20240111010557-e34016a4d6ee
+ github.com/kataras/iris/v12 v12.2.10
github.com/lestrrat-go/jwx/v2 v2.0.20
github.com/lib/pq v1.10.9
github.com/minio/minio-go/v6 v6.0.57
github.com/mocktools/go-smtp-mock v1.10.0
github.com/neicnordic/crypt4gh v1.9.1
+ github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25
github.com/ory/dockertest v3.3.5+incompatible
github.com/ory/dockertest/v3 v3.10.0
github.com/pkg/errors v0.9.1
@@ -29,6 +33,7 @@ require (
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.21.0
+ golang.org/x/oauth2 v0.16.0
google.golang.org/grpc v1.62.1
google.golang.org/protobuf v1.32.0
)
@@ -36,8 +41,14 @@ require (
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
+ github.com/BurntSushi/toml v1.3.2 // indirect
+ github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
+ github.com/CloudyKit/jet/v6 v6.2.0 // indirect
+ github.com/Joker/jade v1.1.3 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
+ github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
+ github.com/andybalholm/brotli v1.1.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 // indirect
@@ -51,6 +62,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.2 // indirect
+ github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/sonic v1.10.2 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
@@ -66,21 +78,36 @@ require (
github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
+ github.com/fatih/structs v1.1.0 // indirect
+ github.com/flosch/pongo2/v4 v4.0.2 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
+ github.com/go-jose/go-jose/v3 v3.0.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.17.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
+ github.com/golang/snappy v0.0.4 // indirect
+ github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
+ github.com/gorilla/css v1.0.0 // indirect
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
+ github.com/iris-contrib/schema v0.0.6 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
+ github.com/kataras/blocks v0.0.8 // indirect
+ github.com/kataras/golog v0.1.11 // indirect
+ github.com/kataras/pio v0.0.13 // indirect
+ github.com/kataras/sitemap v0.0.6 // indirect
+ github.com/kataras/tunnel v0.0.4 // indirect
+ github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
@@ -90,7 +117,10 @@ require (
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/magiconair/properties v1.8.7 // indirect
+ github.com/mailgun/raymond/v2 v2.0.48 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/microcosm-cc/bluemonday v1.0.26 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect
@@ -101,23 +131,32 @@ require (
github.com/opencontainers/runc v1.1.12 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
+ github.com/pquerna/cachecontrol v0.2.0 // indirect
github.com/prometheus/client_golang v1.18.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.46.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
+ github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
+ github.com/schollz/closestmatch v2.1.0+incompatible // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
+ github.com/tdewolff/minify/v2 v2.20.14 // indirect
+ github.com/tdewolff/parse/v2 v2.7.8 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
+ github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
+ github.com/yosssi/ace v0.0.5 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.7.0 // indirect
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 // indirect
@@ -125,10 +164,13 @@ require (
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
+ golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.17.0 // indirect
+ google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
+ gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools v2.2.0+incompatible // indirect
diff --git a/sda/go.sum b/sda/go.sum
index 8fd4b9e34..caf6d29f7 100644
--- a/sda/go.sum
+++ b/sda/go.sum
@@ -3,12 +3,28 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
+github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
+github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
+github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME=
+github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
+github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc=
+github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
+github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=
+github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
+github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=
+github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM=
+github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
+github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
+github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
+github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/aws/aws-sdk-go-v2 v1.25.2 h1:/uiG1avJRgLGiQM9X3qJM8+Qa6KRGK5rRPuXE0HUM+w=
github.com/aws/aws-sdk-go-v2 v1.25.2/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU=
@@ -47,6 +63,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.28.2 h1:0YjXuWdYHvsm0HnT4vO8XpwG1D+i
github.com/aws/aws-sdk-go-v2/service/sts v1.28.2/go.mod h1:jI+FWmYkSMn+4APWmZiZTgt0oM0TrvymD51FMqCnWgA=
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
+github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
+github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
@@ -68,6 +86,8 @@ github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
+github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
+github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -87,6 +107,12 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
+github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
+github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
@@ -97,6 +123,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
+github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@@ -107,26 +135,42 @@ github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ
github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
+github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
+github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 h1:k4Tw0nt6lwro3Uin8eqoET7MDA4JnT8YgbCjc/g5E3k=
+github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
+github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
+github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
+github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
+github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
@@ -135,17 +179,41 @@ github.com/heptiolabs/healthcheck v0.0.0-20211123025425-613501dd5deb h1:tsEKRC3P
github.com/heptiolabs/healthcheck v0.0.0-20211123025425-613501dd5deb/go.mod h1:NtmN9h8vrTveVQRLHcX2HQ5wIPBDCsZ351TGbZWgg38=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
+github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
+github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk8iJJKokcJ3Go=
+github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE=
+github.com/iris-contrib/middleware/cors v0.0.0-20240111010557-e34016a4d6ee h1:srr0HUvI9IAximtqxhF0+WSy9cv9Dd5YlH8RMEkHtsw=
+github.com/iris-contrib/middleware/cors v0.0.0-20240111010557-e34016a4d6ee/go.mod h1:hAsE+pfCAz1M2cCfsEolTmaBwHCyzchRFyCk5I1+kDo=
+github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw=
+github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/kataras/blocks v0.0.8 h1:MrpVhoFTCR2v1iOOfGng5VJSILKeZZI+7NGfxEh3SUM=
+github.com/kataras/blocks v0.0.8/go.mod h1:9Jm5zx6BB+06NwA+OhTbHW1xkMOYxahnqTN5DveZ2Yg=
+github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20=
+github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A=
+github.com/kataras/iris/v12 v12.2.10 h1:rEJVM7qMoyhv8wpgkA1yGxibFcONE0jkJ70LFLibTAA=
+github.com/kataras/iris/v12 v12.2.10/go.mod h1:z4+E+kLMqZ7U4WtDsYfFnG7BjMTXLkdzMAXLVMLnMNs=
+github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM=
+github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM=
+github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY=
+github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4=
+github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA=
+github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
+github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
+github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
@@ -179,8 +247,16 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
+github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
+github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
github.com/minio/minio-go/v6 v6.0.57 h1:ixPkbKkyD7IhnluRgQpGSpHdpvNVaW6OD5R9IAO/9Tw=
github.com/minio/minio-go/v6 v6.0.57/go.mod h1:5+R/nM9Pwrh0vqF+HbYYDQ84wdUFPyXHkrdT4AIkifM=
@@ -188,6 +264,8 @@ github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
+github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk=
@@ -202,6 +280,9 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/neicnordic/crypt4gh v1.9.1 h1:NKeOmsZ1/0xDpLvBDjN8Ltoh3ODbLB+NeKulDaNo4Oc=
github.com/neicnordic/crypt4gh v1.9.1/go.mod h1:C8jHyUkt3bnQg0EwdRRswzvLXfu4dyLQOPARDIQTU24=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25 h1:9bCMuD3TcnjeqjPT2gSlha4asp8NvgcFRYExCaikCxk=
+github.com/oauth2-proxy/mockoidc v0.0.0-20240214162133-caebfff84d25/go.mod h1:eDjgYHYDJbPLBLsyZ6qRaugP0mX8vePOhZ5id1fdzJw=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
@@ -222,6 +303,8 @@ github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Q
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k=
+github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
@@ -234,15 +317,24 @@ github.com/rabbitmq/amqp091-go v1.9.0 h1:qrQtyzB4H8BQgEuJwhmVQqVHB9O4+MNDJCCAcpc
github.com/rabbitmq/amqp091-go v1.9.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
+github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
+github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
+github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=
+github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
+github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -275,18 +367,40 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
+github.com/tdewolff/minify/v2 v2.20.14 h1:sktSuVixRwk0ryQjqvKBu/uYS+MWmkwEFMEWtFZ+TdE=
+github.com/tdewolff/minify/v2 v2.20.14/go.mod h1:qnIJbnG2dSzk7LIa/UUwgN2OjS8ir6RRlqc0T/1q2xY=
+github.com/tdewolff/parse/v2 v2.7.8 h1:1cnVqa8L63xFkc2vfRsZTM6Qy35nJpTvQ2Uvdv3vbvs=
+github.com/tdewolff/parse/v2 v2.7.8/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
+github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
+github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
+github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
+github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
+github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
+github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
+github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
+github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
+github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=
+github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
+github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
+github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
+github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
+github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
@@ -297,6 +411,7 @@ golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -307,34 +422,43 @@ golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 h1:/RIbNt/Zr7rVhIkQhooTxCxFc
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
+golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -350,16 +474,21 @@ golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
@@ -367,6 +496,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
+google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
@@ -379,11 +510,14 @@ gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdr
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
+gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
@@ -396,5 +530,7 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
+moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs=
+moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/sda/internal/config/config.go b/sda/internal/config/config.go
index 74cd796bc..80b2e0434 100644
--- a/sda/internal/config/config.go
+++ b/sda/internal/config/config.go
@@ -32,6 +32,7 @@ type ServerConfig struct {
Key string
Jwtpubkeypath string
Jwtpubkeyurl string
+ CORS CORSConfig
}
// Config is a parent object for all the different configuration parts
@@ -48,6 +49,7 @@ type Config struct {
Sync Sync
SyncAPI SyncAPIConf
ReEncrypt ReEncConfig
+ Auth AuthConf
}
type ReEncConfig struct {
@@ -110,6 +112,42 @@ type OrchestratorConf struct {
ReleaseDelay time.Duration
}
+type AuthConf struct {
+ OIDC OIDCConfig
+ Cega CegaConfig
+ JwtIssuer string
+ JwtPrivateKey string
+ JwtSignatureAlg string
+ Server ServerConfig
+ S3Inbox string
+ ResignJwt bool
+ InfoURL string
+ InfoText string
+ PublicFile string
+}
+
+type OIDCConfig struct {
+ ID string
+ Provider string
+ RedirectURL string
+ RevocationURL string
+ Secret string
+ JwkURL string
+}
+
+type CegaConfig struct {
+ AuthURL string
+ ID string
+ Secret string
+}
+
+type CORSConfig struct {
+ AllowOrigin string
+ AllowMethods string
+ AllowHeaders string
+ AllowCredentials bool
+}
+
// NewConfig initializes and parses the config file and/or environment using
// the viper library.
func NewConfig(app string) (*Config, error) {
@@ -143,6 +181,24 @@ func NewConfig(app string) (*Config, error) {
}
}
+ if viper.IsSet("log.format") {
+ if viper.GetString("log.format") == "json" {
+ log.SetFormatter(&log.JSONFormatter{})
+ log.Info("The logs format is set to JSON")
+ }
+ }
+
+ if viper.IsSet("log.level") {
+ stringLevel := viper.GetString("log.level")
+ intLevel, err := log.ParseLevel(stringLevel)
+ if err != nil {
+ log.Infof("Log level '%s' not supported, setting to 'trace'", stringLevel)
+ intLevel = log.TraceLevel
+ }
+ log.SetLevel(intLevel)
+ log.Infof("Setting log level to '%s'", stringLevel)
+ }
+
switch app {
case "api":
requiredConfVars = []string{
@@ -157,6 +213,24 @@ func NewConfig(app string) (*Config, error) {
"db.password",
"db.database",
}
+ case "auth":
+ requiredConfVars = []string{
+ "auth.s3Inbox",
+ "auth.publicFile",
+ }
+
+ if viper.GetString("auth.cega.id") != "" && viper.GetString("auth.cega.secret") != "" {
+ requiredConfVars = append(requiredConfVars, []string{"auth.cega.authUrl"}...)
+ viper.Set("auth.resignJwt", true)
+ }
+
+ if viper.GetString("oidc.id") != "" && viper.GetString("oidc.secret") != "" {
+ requiredConfVars = append(requiredConfVars, []string{"oidc.provider", "oidc.redirectUrl"}...)
+ }
+
+ if viper.GetBool("auth.resignJwt") {
+ requiredConfVars = append(requiredConfVars, []string{"auth.jwt.issuer", "auth.jwt.privateKey", "auth.jwt.signatureAlg"}...)
+ }
case "ingest":
requiredConfVars = []string{
"broker.host",
@@ -370,24 +444,6 @@ func NewConfig(app string) (*Config, error) {
}
}
- if viper.IsSet("log.format") {
- if viper.GetString("log.format") == "json" {
- log.SetFormatter(&log.JSONFormatter{})
- log.Info("The logs format is set to JSON")
- }
- }
-
- if viper.IsSet("log.level") {
- stringLevel := viper.GetString("log.level")
- intLevel, err := log.ParseLevel(stringLevel)
- if err != nil {
- log.Infof("Log level '%s' not supported, setting to 'trace'", stringLevel)
- intLevel = log.TraceLevel
- }
- log.SetLevel(intLevel)
- log.Infof("Setting log level to '%s'", stringLevel)
- }
-
c := &Config{}
switch app {
case "api":
@@ -410,6 +466,64 @@ func NewConfig(app string) (*Config, error) {
if err != nil {
return nil, err
}
+ case "auth":
+ c.Auth.Cega.AuthURL = viper.GetString("auth.cega.authUrl")
+ c.Auth.Cega.ID = viper.GetString("auth.cega.id")
+ c.Auth.Cega.Secret = viper.GetString("auth.cega.secret")
+
+ c.Auth.OIDC.ID = viper.GetString("oidc.id")
+ c.Auth.OIDC.Provider = viper.GetString("oidc.provider")
+ c.Auth.OIDC.RedirectURL = viper.GetString("oidc.redirectUrl")
+ c.Auth.OIDC.Secret = viper.GetString("oidc.secret")
+ if viper.IsSet("oidc.jwkPath") {
+ c.Auth.OIDC.JwkURL = c.Auth.OIDC.Provider + viper.GetString("oidc.jwkPath")
+ }
+
+ if (c.Auth.OIDC.ID == "" || c.Auth.OIDC.Secret == "") && (c.Auth.Cega.ID == "" || c.Auth.Cega.Secret == "") {
+ return nil, fmt.Errorf("neither cega or oidc login configured")
+ }
+
+ c.Auth.InfoURL = viper.GetString("auth.infoUrl")
+ c.Auth.InfoText = viper.GetString("auth.infoText")
+ c.Auth.PublicFile = viper.GetString("auth.publicFile")
+ if _, err := os.Stat(c.Auth.PublicFile); err != nil {
+ return nil, err
+ }
+
+ if viper.GetBool("auth.resignJwt") {
+ c.Auth.ResignJwt = viper.GetBool("auth.resignJwt")
+ c.Auth.JwtPrivateKey = viper.GetString("auth.jwt.privateKey")
+ c.Auth.JwtSignatureAlg = viper.GetString("auth.jwt.signatureAlg")
+ c.Auth.JwtIssuer = viper.GetString("auth.jwt.issuer")
+
+ if _, err := os.Stat(c.Auth.JwtPrivateKey); err != nil {
+ return nil, err
+ }
+ }
+
+ cors := CORSConfig{AllowCredentials: false}
+ if viper.IsSet("cors.origins") {
+ cors.AllowOrigin = viper.GetString("cors.origins")
+ }
+ if viper.IsSet("cors.methods") {
+ cors.AllowMethods = viper.GetString("cors.methods")
+ }
+ if viper.IsSet("cors.headers") {
+ cors.AllowHeaders = viper.GetString("cors.headers")
+ }
+ if viper.IsSet("cors.credentials") {
+ cors.AllowCredentials = viper.GetBool("cors.credentials")
+ }
+ c.Server.CORS = cors
+
+ if viper.IsSet("server.cert") {
+ c.Server.Cert = viper.GetString("server.cert")
+ }
+ if viper.IsSet("server.key") {
+ c.Server.Key = viper.GetString("server.key")
+ }
+
+ c.Auth.S3Inbox = viper.GetString("auth.s3Inbox")
case "finalize":
if viper.GetString("archive.type") != "" && viper.GetString("backup.type") != "" {
c.configArchive()
diff --git a/sda/internal/config/config_test.go b/sda/internal/config/config_test.go
index 2cb6d30bd..253f68db5 100644
--- a/sda/internal/config/config_test.go
+++ b/sda/internal/config/config_test.go
@@ -392,3 +392,60 @@ func (suite *ConfigTestSuite) TestConfigReEncryptServer() {
assert.Equal(suite.T(), certPath+"/ca.crt", config.ReEncrypt.CACert)
assert.Equal(suite.T(), certPath+"/tls.crt", config.ReEncrypt.ServerCert)
}
+
+func (suite *ConfigTestSuite) TestConfigAuth_CEGA() {
+ suite.SetupTest()
+
+ ECPath, _ := os.MkdirTemp("", "EC")
+ if err := helper.CreateECkeys(ECPath, ECPath); err != nil {
+ suite.T().FailNow()
+ }
+ defer os.RemoveAll(ECPath)
+
+ noConfig, err := NewConfig("auth")
+ assert.Error(suite.T(), err)
+ assert.Nil(suite.T(), noConfig)
+
+ viper.Set("auth.s3Inbox", "http://inbox:8000")
+ viper.Set("auth.publicFile", "no-file")
+ viper.Set("auth.cega.authURL", "http://cega/auth")
+ viper.Set("auth.cega.id", "CegaID")
+ viper.Set("auth.cega.secret", "CegaSecret")
+ viper.Set("auth.jwt.Issuer", "http://auth:8080")
+ viper.Set("auth.Jwt.privateKey", "nonexistent-key-file")
+ viper.Set("auth.Jwt.signatureAlg", "ES256")
+ _, err = NewConfig("auth")
+ assert.ErrorContains(suite.T(), err, "no such file or directory")
+
+ viper.Set("auth.publicFile", ECPath+"/ec.pub")
+ viper.Set("auth.Jwt.privateKey", ECPath+"/ec")
+ c, err := NewConfig("auth")
+ assert.Equal(suite.T(), c.Auth.JwtPrivateKey, fmt.Sprintf("%s/ec", ECPath))
+ assert.NoError(suite.T(), err, "unexpected failure")
+}
+
+func (suite *ConfigTestSuite) TestConfigAuth_OIDC() {
+ suite.SetupTest()
+
+ ECPath, _ := os.MkdirTemp("", "EC")
+ if err := helper.CreateECkeys(ECPath, ECPath); err != nil {
+ suite.T().FailNow()
+ }
+ defer os.RemoveAll(ECPath)
+
+ noConfig, err := NewConfig("auth")
+ assert.Error(suite.T(), err)
+ assert.Nil(suite.T(), noConfig)
+
+ viper.Set("auth.s3Inbox", "http://inbox:8000")
+ viper.Set("auth.publicFile", ECPath+"/ec.pub")
+ viper.Set("oidc.id", "oidcTestID")
+ viper.Set("oidc.secret", "oidcTestIssuer")
+ _, err = NewConfig("auth")
+ assert.Error(suite.T(), err)
+
+ viper.Set("oidc.provider", "http://provider:9000")
+ viper.Set("oidc.redirectUrl", "http://auth/oidc/login")
+ _, err = NewConfig("auth")
+ assert.NoError(suite.T(), err, "unexpected failure")
+}
diff --git a/sda/sda.md b/sda/sda.md
index 909a56bb7..a9d1dec53 100644
--- a/sda/sda.md
+++ b/sda/sda.md
@@ -17,8 +17,9 @@ The SDA submission pipeline has four main steps:
There are also additional support services:
-1. [Intercept](cmd/intercept/intercept.md) relays messages from `CentralEGA` to the system.
-2. [ReEncrypt](cmd/reencrypt/reencrypt.md) reencrypts a given file header with a given public key.
-3. [s3inbox](cmd/s3inbox/s3inbox.md) proxies uploads to the an S3 compatible storage backend.
-4. [sync](cmd/sync/sync.md) mirrors ingested data between sites in the [Bigpicture](https://bigpicture.eu/) project.
-5. [syncapi](cmd/syncapi/syncapi.md) is used in the [Bigpicture](https://bigpicture.eu/) project for mirroring data between two installations of SDA.
+1. [Auth](cmd/auth/auth.md) authentication service used in conjunction with the [s3inbox](cmd/s3inbox/s3inbox.md).
+2. [Intercept](cmd/intercept/intercept.md) relays messages from `CentralEGA` to the system.
+3. [ReEncrypt](cmd/reencrypt/reencrypt.md) reencrypts a given file header with a given public key.
+4. [s3inbox](cmd/s3inbox/s3inbox.md) proxies uploads to the an S3 compatible storage backend.
+5. [sync](cmd/sync/sync.md) mirrors ingested data between sites in the [Bigpicture](https://bigpicture.eu/) project.
+6. [syncapi](cmd/syncapi/syncapi.md) is used in the [Bigpicture](https://bigpicture.eu/) project for mirroring data between two installations of SDA.