From c7a1ea9b7e9a4383d4e641b7dd896a88da2b8fc8 Mon Sep 17 00:00:00 2001 From: Simon Bergerfurth Date: Fri, 24 Jul 2026 13:49:25 +0200 Subject: [PATCH 1/3] feat(helm): add wallet and issuer-wallet charts --- NOTICE.md | 2 + helm/issuer-wallet/.helmignore | 23 + helm/issuer-wallet/Chart.lock | 9 + helm/issuer-wallet/Chart.yaml | 67 +++ helm/issuer-wallet/LICENSE | 201 +++++++++ helm/issuer-wallet/README.md | 179 ++++++++ helm/issuer-wallet/templates/NOTES.txt | 88 ++++ helm/issuer-wallet/templates/_helpers.tpl | 86 ++++ .../templates/configmap-datasource.yaml | 41 ++ .../templates/configmap-runtime.yaml | 80 ++++ .../templates/configmap-vault-init.yaml | 140 ++++++ helm/issuer-wallet/templates/deployment.yaml | 206 +++++++++ helm/issuer-wallet/templates/hpa.yaml | 50 +++ helm/issuer-wallet/templates/ingress.yaml | 98 +++++ .../templates/job-vault-init.yaml | 87 ++++ .../templates/secret-datasource.yaml | 42 ++ .../templates/secret-runtime.yaml | 38 ++ helm/issuer-wallet/templates/service.yaml | 60 +++ .../templates/serviceaccount.yaml | 33 ++ helm/issuer-wallet/templates/tests/test.yaml | 43 ++ helm/issuer-wallet/values.yaml | 402 ++++++++++++++++++ helm/wallet/.helmignore | 23 + helm/wallet/Chart.lock | 9 + helm/wallet/Chart.yaml | 67 +++ helm/wallet/LICENSE | 201 +++++++++ helm/wallet/README.md | 176 ++++++++ helm/wallet/templates/NOTES.txt | 88 ++++ helm/wallet/templates/_helpers.tpl | 86 ++++ .../templates/configmap-datasource.yaml | 41 ++ helm/wallet/templates/configmap-runtime.yaml | 73 ++++ .../templates/configmap-vault-init.yaml | 140 ++++++ helm/wallet/templates/deployment.yaml | 206 +++++++++ helm/wallet/templates/hpa.yaml | 50 +++ helm/wallet/templates/ingress.yaml | 98 +++++ helm/wallet/templates/job-vault-init.yaml | 87 ++++ helm/wallet/templates/secret-datasource.yaml | 42 ++ helm/wallet/templates/secret-runtime.yaml | 38 ++ helm/wallet/templates/service.yaml | 52 +++ helm/wallet/templates/serviceaccount.yaml | 33 ++ helm/wallet/templates/tests/test.yaml | 43 ++ helm/wallet/values.yaml | 388 +++++++++++++++++ 41 files changed, 3916 insertions(+) create mode 100644 helm/issuer-wallet/.helmignore create mode 100644 helm/issuer-wallet/Chart.lock create mode 100644 helm/issuer-wallet/Chart.yaml create mode 100644 helm/issuer-wallet/LICENSE create mode 100644 helm/issuer-wallet/README.md create mode 100644 helm/issuer-wallet/templates/NOTES.txt create mode 100644 helm/issuer-wallet/templates/_helpers.tpl create mode 100644 helm/issuer-wallet/templates/configmap-datasource.yaml create mode 100644 helm/issuer-wallet/templates/configmap-runtime.yaml create mode 100644 helm/issuer-wallet/templates/configmap-vault-init.yaml create mode 100644 helm/issuer-wallet/templates/deployment.yaml create mode 100644 helm/issuer-wallet/templates/hpa.yaml create mode 100644 helm/issuer-wallet/templates/ingress.yaml create mode 100644 helm/issuer-wallet/templates/job-vault-init.yaml create mode 100644 helm/issuer-wallet/templates/secret-datasource.yaml create mode 100644 helm/issuer-wallet/templates/secret-runtime.yaml create mode 100644 helm/issuer-wallet/templates/service.yaml create mode 100644 helm/issuer-wallet/templates/serviceaccount.yaml create mode 100644 helm/issuer-wallet/templates/tests/test.yaml create mode 100644 helm/issuer-wallet/values.yaml create mode 100644 helm/wallet/.helmignore create mode 100644 helm/wallet/Chart.lock create mode 100644 helm/wallet/Chart.yaml create mode 100644 helm/wallet/LICENSE create mode 100644 helm/wallet/README.md create mode 100644 helm/wallet/templates/NOTES.txt create mode 100644 helm/wallet/templates/_helpers.tpl create mode 100644 helm/wallet/templates/configmap-datasource.yaml create mode 100644 helm/wallet/templates/configmap-runtime.yaml create mode 100644 helm/wallet/templates/configmap-vault-init.yaml create mode 100644 helm/wallet/templates/deployment.yaml create mode 100644 helm/wallet/templates/hpa.yaml create mode 100644 helm/wallet/templates/ingress.yaml create mode 100644 helm/wallet/templates/job-vault-init.yaml create mode 100644 helm/wallet/templates/secret-datasource.yaml create mode 100644 helm/wallet/templates/secret-runtime.yaml create mode 100644 helm/wallet/templates/service.yaml create mode 100644 helm/wallet/templates/serviceaccount.yaml create mode 100644 helm/wallet/templates/tests/test.yaml create mode 100644 helm/wallet/values.yaml diff --git a/NOTICE.md b/NOTICE.md index 345a887..b07dfdb 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -10,6 +10,8 @@ All non-code files are distributed under the Creative Commons Attribution 4.0 In ## Third-Party Content There are third-party contents used by and shipped with this project with different licenses. +The Constuct-X wallet Helm charts are based on [Tractus-X IdentityHub Helm charts](https://github.com/eclipse-tractusx/tractusx-identityhub). + ### Code of Conduct The `CODE_OF_CONDUCT.md` is adapted from the Contributor Covenant, version 3.0, permanently available at [https://www.contributor-covenant.org/version/3/0/](https://www.contributor-covenant.org/version/3/0/). Contributor Covenant is stewarded by the Organization for Ethical Source and licensed under CC BY-SA 4.0. To view a copy of this license, visit [https://creativecommons.org/licenses/by-sa/4.0/](https://creativecommons.org/licenses/by-sa/4.0/). diff --git a/helm/issuer-wallet/.helmignore b/helm/issuer-wallet/.helmignore new file mode 100644 index 0000000..691fa13 --- /dev/null +++ b/helm/issuer-wallet/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ \ No newline at end of file diff --git a/helm/issuer-wallet/Chart.lock b/helm/issuer-wallet/Chart.lock new file mode 100644 index 0000000..6806a69 --- /dev/null +++ b/helm/issuer-wallet/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: postgres + repository: oci://registry-1.docker.io/cloudpirates + version: 0.19.5 +- name: vault + repository: https://helm.releases.hashicorp.com + version: 0.29.1 +digest: sha256:c730f7da67d2940512fb6cd112b9474968890ecd64c2e3a4101c16702b2b3a81 +generated: "2026-06-15T13:56:12.756876381+02:00" diff --git a/helm/issuer-wallet/Chart.yaml b/helm/issuer-wallet/Chart.yaml new file mode 100644 index 0000000..2117dd0 --- /dev/null +++ b/helm/issuer-wallet/Chart.yaml @@ -0,0 +1,67 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +apiVersion: v2 +name: issuer-wallet +description: A Helm chart for Construct-X Issuer-Wallet alongside Hashicorp Vault and PostgreSQL + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.17.0-1" +keywords: + - issuer-wallet + - issuer + - edc + - gaia-x +home: https://github.com/project-construct-x/wallet +sources: + - https://github.com/project-construct-x/wallet + - https://github.com/eclipse-tractusx/tractusx-identityhub +dependencies: + # PostgreSQL + - name: postgres + alias: postgresql + version: 0.19.5 + repository: oci://registry-1.docker.io/cloudpirates + condition: install.postgresql + # HashiCorp Vault + - name: vault + alias: vault + version: 0.29.1 + repository: https://helm.releases.hashicorp.com + condition: install.vault diff --git a/helm/issuer-wallet/LICENSE b/helm/issuer-wallet/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/helm/issuer-wallet/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/helm/issuer-wallet/README.md b/helm/issuer-wallet/README.md new file mode 100644 index 0000000..4500c78 --- /dev/null +++ b/helm/issuer-wallet/README.md @@ -0,0 +1,179 @@ +# Construct-X Issuer-Wallet + +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) +![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-informational?style=flat-square) + +Deploys the [Construct-X Wallet](https://github.com/project-construct-x/wallet) — an EDC IdentityHub runtime — together with a PostgreSQL database and a HashiCorp Vault instance and configures it to act as an dataspace issuer. + + +## Prerequisites + +| **Requirement** | **Version** | +|---|---| +| Kubernetes | 1.29+ | +| Helm | 3.14+ | + +- A Persistent Volume provisioner is required if `postgresql.primary.persistence.enabled: true` +- Cluster Internet connection is required if `vault.hashicorp.init.enabled: true` to pull required `apk` packages + +## Installation + +```bash +# Add dependencies +helm dependency build +# Install +helm install issuer . -f my-override-values.yaml +``` + +## Values + +### Top-level + +| Key | Type | Default | Description | +|---|---|---|---| +| `install.postgresql` | bool | `true` | Install the bundled PostgreSQL sub-chart. Set to `false` to use an external database. | +| `install.vault` | bool | `true` | Install the bundled Vault sub-chart. Set to `false` to use an external Vault. | +| `fullnameOverride` | string | `"issuer"` | Overrides the chart fullname used for all resource names. | +| `nameOverride` | string | `"issuer"` | Overrides the chart name used in labels. | +| `imagePullSecrets` | list | `[]` | Pull secrets for private image registries. | +| `customCaCerts` | object | `{}` | Custom CA certificates added to the Java truststore at startup. | + +### `wallet` + +| Key | Type | Default | Description | +|---|---|---|---| +| `wallet.image.repository` | string | `ghcr.io/project-construct-x/wallet` | Container image repository. | +| `wallet.image.tag` | string | `0.17.0-1` | Image tag. Defaults to `chart.appVersion` if left empty. | +| `wallet.image.pullPolicy` | string | `IfNotPresent` | Kubernetes image pull policy. | +| `wallet.initContainers` | list | `[]` | Additional init containers run before the wallet starts. | +| `wallet.podLabels` | object | `{}` | Extra labels applied to the wallet pod. | +| `wallet.podAnnotations` | object | `{}` | Extra annotations applied to the wallet pod. | +| `wallet.useSVE` | bool | `false` | Disables SVE CPU instructions via `JAVA_TOOL_OPTIONS`. Enable on SVE-capable nodes if the JVM crashes with illegal instruction errors. | +| `wallet.debug.enabled` | bool | `false` | Enables the JDWP remote debug socket. Never use in production. | +| `wallet.debug.port` | int | `1044` | JDWP listen port inside the container. | +| `wallet.debug.suspendOnStart` | bool | `false` | If `true`, the JVM suspends until a debugger connects. | +| `wallet.hostname` | string | `issuer.staging.construct-x.net` | Public hostname. Used in `did:web` URLs and ingress routing. | +| `wallet.superuser.createSecret` | bool | `true` | Creates a Kubernetes Secret from the values below and mounts it via `envFrom`. Set to `false` and reference an external secret via `envSecretNames` instead. | +| `wallet.superuser.id` | string | `admin` | Participant context ID of the super-user. | +| `wallet.superuser.apiKey` | string | `YWRtaW4.adminKey` | API key for the super-user. Format: `base64().`. **Change before production use.** | +| `wallet.superuser.publicKeyAlias` | string | `admin#pubkey` | Vault alias for the super-user RSA public key. Generated by the wallet on first start. | +| `wallet.superuser.privateKeyAlias` | string | `admin#privkey` | Vault alias for the super-user RSA private key. Generated by the wallet on first start. | +| `wallet.didweb.https` | bool | `true` | Use `https://` in `did:web` URLs. Set to `false` only for local testing. | +| `wallet.issuer.statuslist.callbackAddress`| string | `https://{ wallet.ingresses[0].hostname }{ wallet.endpoints.statuslist.path }` | Callback address for statuslist. | +| `wallet.env` | object | `{}` | Extra plain environment variables injected into the wallet pod. | +| `wallet.envValueFrom` | object | `{}` | Extra environment variables sourced from ConfigMaps or Secrets via `valueFrom`. | +| `wallet.envSecretNames` | list | `[]` | Names of existing Secrets whose keys are mounted as environment variables via `envFrom`. | +| `wallet.envConfigMapNames` | list | `[]` | Names of existing ConfigMaps whose keys are mounted as environment variables via `envFrom`. | +| `wallet.replicaCount` | int | `1` | Number of wallet pod replicas. | +| `wallet.resources.limits.cpu` | string | `500m` | CPU limit for the wallet container. | +| `wallet.resources.limits.memory` | string | `512Mi` | Memory limit for the wallet container. | +| `wallet.resources.requests.cpu` | string | `250m` | CPU request for the wallet container. | +| `wallet.resources.requests.memory` | string | `128Mi` | Memory request for the wallet container. | +| `wallet.autoscaling.enabled` | bool | `false` | Enables Horizontal Pod Autoscaling. | +| `wallet.autoscaling.minReplicas` | int | `1` | Minimum number of replicas under HPA. | +| `wallet.autoscaling.maxReplicas` | int | `100` | Maximum number of replicas under HPA. | +| `wallet.autoscaling.targetCPUUtilizationPercentage` | int | `80` | CPU utilisation target for HPA scale-out. | +| `wallet.autoscaling.targetMemoryUtilizationPercentage` | int | `80` | Memory utilisation target for HPA scale-out. | +| `wallet.nodeSelector` | object | `{}` | Node selector constraints for the wallet pod. | +| `wallet.tolerations` | list | `[]` | Tolerations for the wallet pod. | +| `wallet.affinity` | object | `{}` | Affinity rules for the wallet pod. | +| `wallet.volumeMounts` | list | `[]` | Additional volume mounts for the wallet container. | +| `wallet.volumes` | list | `[]` | Additional volumes for the wallet pod. | + +### `wallet.endpoints` + +Each endpoint creates a Kubernetes Service port and injects the corresponding `WEB_HTTP_*` environment variables into the issuer-wallet. Only endpoints listed under an ingress' `endpoints` array are exposed externally. + +| Key | Default port | Default path | Description | +|---|---|---|---| +| `wallet.endpoints.default` | `8181` | `/api` | Observability endpoint (health checks). Must not be added to public ingresses. | +| `wallet.endpoints.identity` | `15151` | `/api/identity` | Management API. Protected by `X-Api-Key`. Must not be internet-facing. | +| `wallet.endpoints.identity.authKeyAlias` | `sup3r$3cr3t` | — | Vault alias whose stored value is validated against the `X-Api-Key` request header. | +| `wallet.endpoints.issueradmin` | `15152` | `/api/issuer` | Issuer Admin API endpoint, must not be internet facing. | +| `wallet.endpoints.did` | `80` | `/` | DID document service. Resolves `did:web` documents. Must be publicly reachable. | +| `wallet.endpoints.sts` | `9292` | `/api/sts` | Secure Token Service. Issues self-signed ID tokens for DCP flows. Public-facing. | +| `wallet.endpoints.statuslist` | `9999` | `/statuslist` | StatusList API, used to check the status of verifiable credentials. Public-facing. | +| `wallet.endpoints.issuance` | `13132` | `/api/issuance` | DCP Issuance API. Public-facing. | + +### `wallet.livenessProbe` / `wallet.readinessProbe` + +Both probes call `GET /check/liveness` and `GET /check/readiness` on the `default` endpoint port. + +| Key | Type | Default | Description | +|---|---|---|---| +| `*.enabled` | bool | `true` | Whether the probe is active. | +| `*.initialDelaySeconds` | int | `5` | Seconds before the first probe fires. Increase to 30+ on slow cold starts. | +| `*.periodSeconds` | int | `5` | Interval between probes. | +| `*.timeoutSeconds` | int | `5` | Seconds before a probe attempt times out. | +| `*.failureThreshold` | int | `6` | Consecutive failures before the pod is restarted or marked not-ready. | +| `*.successThreshold` | int | `1` | Consecutive successes to transition back to healthy. | + +### `wallet.service` + +| Key | Type | Default | Description | +|---|---|---|---| +| `wallet.service.type` | string | `ClusterIP` | Kubernetes Service type. `ClusterIP` is recommended when an ingress or gateway is used. | +| `wallet.service.annotations` | object | `{}` | Annotations added to the Service resource. | + +### `wallet.ingresses` + +A list of Ingress definitions. Each entry creates one Ingress resource routing the listed endpoints. The chart ships two pre-configured entries (public and internal). Only entries with `enabled: true` are rendered. + +| Key | Type | Description | +|---|---|---| +| `*.enabled` | bool | Render this Ingress resource. | +| `*.hostname` | string | Hostname for all routes in this Ingress. | +| `*.annotations` | object | Annotations added to the Ingress (e.g. cert-manager, external-dns). | +| `*.endpoints` | list | Names of `wallet.endpoints` keys to expose via this Ingress. | +| `*.className` | string | Ingress class name (e.g. `nginx`, `traefik`). | +| `*.tls.enabled` | bool | Attach a TLS block to this Ingress. | +| `*.tls.secretName` | string | Name of the Secret holding the TLS certificate. | +| `*.certManager.issuer` | string | cert-manager namespace-scoped issuer. | +| `*.certManager.clusterIssuer` | string | cert-manager cluster-scoped issuer. | + +### `serviceAccount` + +| Key | Type | Default | Description | +|---|---|---|---| +| `serviceAccount.create` | bool | `true` | Create a dedicated ServiceAccount for the issuer-wallet and vault-init job. | +| `serviceAccount.automount` | bool | `true` | Automatically mount the ServiceAccount token into pods. | +| `serviceAccount.annotations` | object | `{}` | Annotations added to the ServiceAccount (e.g. for Vault Kubernetes auth). | +| `serviceAccount.name` | string | `""` | Override the generated ServiceAccount name. | + +### `postgresql` + +The chart uses the Cloudpirates PostgreSQL Chart. + +| Key | Type | Default | Description | +|---|---|---|---| +| `postgresql.jdbcUrl` | string | `jdbc:postgresql://issuer-postgresql:5432/wallet` | JDBC URL passed to the issuer-wallet. | +| `postgresql.auth.database` | string | `issuer` | Database name created on first start. | +| `postgresql.auth.username` | string | `user` | Database user the issuer-wallet connects as. | +| `postgresql.auth.password` | string | `password` | Database password. **Change before production use.** | +| `postgresql.persistence.enabled` | bool | `true` | Persist primary node data. Disable only for throwaway test environments. | +| `postgresql.persistence.size` | string | `10Gi` | Size of allocated Persistent Volume. | +| `postgresql.persistence.storageClass` | string | `""` | Storage Class of used Storage Provisioner. | +| `postgresql.initdb.scriptsConfigMap` | string | `""` | Name of ConfigMap for Database Initialization. | + +### `vault` + +| Key | Type | Default | Description | +|---|---|---|---| +| `vault.injector.enabled` | bool | `false` | Vault Agent Injector sidecar. Disabled — the issuer-wallet reads secrets directly via the Vault HTTP API. | +| `vault.server.dev.enabled` | bool | `true` | Run Vault in dev mode (in-memory, no persistence). **Disable for production.** | +| `vault.server.dev.devRootToken` | string | `root` | Root token for dev mode. Must match `vault.hashicorp.token`. | +| `vault.server.postStart` | string | `nil` | Optional post-start script executed inside the Vault container. Must be set externally. | +| `vault.hashicorp.url` | string | `http://issuer-vault:8200` | Vault address reachable from within the cluster. | +| `vault.hashicorp.token` | string | `root` | Vault token used by the issuer-wallet at runtime. **Change before production use.** | +| `vault.hashicorp.timeout` | int | `30` | Vault HTTP client timeout in seconds. | +| `vault.hashicorp.healthCheck.enabled` | bool | `true` | Whether the issuer-wallet checks Vault health on startup. | +| `vault.hashicorp.healthCheck.standbyOk` | bool | `true` | Treat Vault HA standby nodes as healthy. | +| `vault.hashicorp.paths.secret` | string | `/v1/secret` | Mount path for all issuer-wallet secrets. | +| `vault.hashicorp.paths.health` | string | `/v1/sys/health` | Vault health endpoint polled by the issuer-wallet and vault-init job. | +| `vault.hashicorp.init.enabled` | bool | `true` | Run the post-install vault-init job that seeds required Vault secrets. | +| `vault.hashicorp.init.aesKeyAlias` | string | `wallet-aes-key-alias` | Vault alias for the AES-256 encryption key. | + +## Sources + +- Code: [Construct-X Wallet](https://github.com/project-construct-x/wallet) +- Chart: [Tractus-X IdentityHub](https://github.com/eclipse-tractusx/tractusx-identityhub) \ No newline at end of file diff --git a/helm/issuer-wallet/templates/NOTES.txt b/helm/issuer-wallet/templates/NOTES.txt new file mode 100644 index 0000000..dc6831b --- /dev/null +++ b/helm/issuer-wallet/templates/NOTES.txt @@ -0,0 +1,88 @@ +{{- $fullName := include "issuer-wallet.fullname" . -}} +{{- $namespace := .Release.Namespace -}} +================================================================================ + Construct-X Issuer-Wallet "{{ .Release.Name }}" — installation complete +================================================================================ + + Chart version : {{ .Chart.Version }} + App version : {{ .Chart.AppVersion }} + Namespace : {{ $namespace }} + Release : {{ .Release.Name }} + +================================================================================ + Public endpoints +================================================================================ +{{- $ingressShown := false }} +{{- range .Values.wallet.ingresses }} + {{- if .enabled }} + {{- $ingressShown = true }} + {{- $proto := "http" }} + {{- if .tls.enabled }}{{ $proto = "https" }}{{ end }} + + Ingress on {{ .hostname }} (className: {{ .className | default "default" }}) + {{- range .endpoints }} + {{- $ep := index $.Values.wallet.endpoints . }} + {{- if $ep }} + {{ printf "%-15s" . }} {{ $proto }}://{{ index $.Values.wallet.ingresses 0 "hostname" }}{{ $ep.path }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- if not $ingressShown }} + No ingress is enabled. Endpoints are reachable inside the cluster only: + + kubectl port-forward -n {{ $namespace }} svc/{{ $fullName }} \ + {{- range $name, $ep := .Values.wallet.endpoints }} + {{ $ep.port }}:{{ $ep.port }} {{- end }} + + Then locally: + {{- range $name, $ep := .Values.wallet.endpoints }} + {{ printf "%-15s" $name }} http://localhost:{{ $ep.port }}{{ $ep.path }} + {{- end }} +{{- end }} + +{{- if eq .Values.wallet.superuser.createSecret true }} +================================================================================ + Super-User participant +================================================================================ + + The issuer-wallet auto-seeds a super-user on first start: + Participant ID : {{ .Values.wallet.superuser.id }} + API key : {{ .Values.wallet.superuser.apiKey }} + Public key alias: {{ .Values.wallet.superuser.publicKeyAlias }} + Private key alias: {{ .Values.wallet.superuser.privateKeyAlias }} + + If you reinstall while keeping PostgreSQL persistence, the participant context + remains and the seed is skipped. Wipe with: + kubectl exec -n {{ $namespace }} -it \ + $(kubectl get pod -n {{ $namespace }} -l app.kubernetes.io/name=postgresql -o name | head -1) -- \ + psql -U {{ .Values.postgresql.auth.username }} -d {{ .Values.postgresql.auth.database }} \ + -c "DELETE FROM participant_context WHERE participant_context_id = '{{ .Values.wallet.superuser.id }}';" + kubectl rollout restart -n {{ $namespace }} deploy/{{ $fullName }} + + {{- if eq (default "YWRtaW4.adminKey" .Values.wallet.superuser.apiKey) "YWRtaW4.adminKey" }} + + ⚠ WARNING: Super-User Extension is using the default API key. Change wallet.superuser.apiKey + before production use. + {{- end }} +{{- end }} +================================================================================ +{{- if not .Values.wallet.didweb.https }} + + ⚠ WARNING: didweb.https is set to false. did:web URLs will use HTTP. + This is only acceptable for local testing — switch to true before going public. +{{- end }} +{{- if eq .Values.vault.server.dev.enabled true }} + + ⚠ WARNING: Vault is running in dev mode. All secrets are lost on pod restart. + For production, set vault.server.dev.enabled=false and configure persistence. +{{- end }} +{{- if eq (default "root" .Values.vault.hashicorp.token) "root" }} + + ⚠ WARNING: vault.hashicorp.token is set to "root" (dev-mode default). Change vault.hashicorp.token before production use. +{{- end }} +{{- if eq (default "password" .Values.postgresql.auth.password) "password" }} + + ⚠ WARNING: PostgreSQL is using the default password. Change postgresql.auth.password + before production use. +{{- end }} diff --git a/helm/issuer-wallet/templates/_helpers.tpl b/helm/issuer-wallet/templates/_helpers.tpl new file mode 100644 index 0000000..c0b790b --- /dev/null +++ b/helm/issuer-wallet/templates/_helpers.tpl @@ -0,0 +1,86 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "issuer-wallet.name" -}} +{{- default .Chart.Name .Values.nameOverride | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "issuer-wallet.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "issuer-wallet.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Control Common labels +*/}} +{{- define "issuer-wallet.labels" -}} +helm.sh/chart: {{ include "issuer-wallet.chart" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Control Common Server labels +*/}} +{{- define "issuer-wallet.server.labels" -}} +helm.sh/chart: {{ include "issuer-wallet.chart" . }} +{{ include "issuer-wallet.server.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: wallet-server +app.kubernetes.io/part-of: wallet +{{- end }} + +{{/* +Control Selector labels +*/}} +{{- define "issuer-wallet.server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "issuer-wallet.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "issuer-wallet.server.serviceaccount.name" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "issuer-wallet.fullname" . ) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "issuer-wallet.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "issuer-wallet.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/issuer-wallet/templates/configmap-datasource.yaml b/helm/issuer-wallet/templates/configmap-datasource.yaml new file mode 100644 index 0000000..cee2636 --- /dev/null +++ b/helm/issuer-wallet/templates/configmap-datasource.yaml @@ -0,0 +1,41 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +# this configmap contains all database configuration that is required by the issuer-wallet runtime. + +{{ $fullName := .Values.fullnameOverride -}} +{{- $postgresql := index .Values "postgresql" | default dict }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $fullName }}-datasource-config + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "issuer-wallet.labels" . | nindent 4 }} +data: + + ################ + ## POSTGRESQL ## + ################ + + # default + EDC_SQL_SCHEMA_AUTOCREATE: {{ $postgresql.schemaAutocreate | default true | quote }} + EDC_DATASOURCE_DEFAULT_URL: {{ tpl .Values.postgresql.jdbcUrl . | quote }} \ No newline at end of file diff --git a/helm/issuer-wallet/templates/configmap-runtime.yaml b/helm/issuer-wallet/templates/configmap-runtime.yaml new file mode 100644 index 0000000..22ed58b --- /dev/null +++ b/helm/issuer-wallet/templates/configmap-runtime.yaml @@ -0,0 +1,80 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +# this configmap contains all application configuration that is required by the issuer-wallet runtime. + +{{ $fullName := .Values.fullnameOverride -}} +{{- $iam := index .Values "wallet" "iam" | default dict }} +{{- $issuer := index .Values "wallet" "issuer" | default dict }} +{{- $statuslist := index $issuer "statuslist" | default dict }} +{{- $defaultStlCallback := printf "https://%s%s" (index .Values.wallet.ingresses 0).hostname .Values.wallet.endpoints.statuslist.path }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $fullName }}-config + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "issuer-wallet.labels" . | nindent 4 }} +data: + ####### + # API # + ####### + EDC_HOSTNAME: {{ .Values.wallet.hostname | quote }} + WEB_HTTP_PORT: {{ .Values.wallet.endpoints.default.port | quote }} + WEB_HTTP_PATH: {{ .Values.wallet.endpoints.default.path | quote }} + WEB_HTTP_IDENTITY_PORT: {{ .Values.wallet.endpoints.identity.port | quote }} + WEB_HTTP_IDENTITY_PATH: {{ .Values.wallet.endpoints.identity.path | quote }} + WEB_HTTP_IDENTITY_AUTH_ALIAS: {{ .Values.wallet.endpoints.identity.authKeyAlias | required ".Values.wallet.endpoints.identity.authKeyAlias is required" | quote }} + WEB_HTTP_ISSUERADMIN_PORT: {{ .Values.wallet.endpoints.issueradmin.port | quote }} + WEB_HTTP_ISSUERADMIN_PATH: {{ .Values.wallet.endpoints.issueradmin.path | quote }} + WEB_HTTP_DID_PORT: {{ .Values.wallet.endpoints.did.port | quote }} + WEB_HTTP_DID_PATH: {{ .Values.wallet.endpoints.did.path | quote }} + WEB_HTTP_STS_PORT: {{ .Values.wallet.endpoints.sts.port | quote}} + WEB_HTTP_STS_PATH: {{ .Values.wallet.endpoints.sts.path | quote}} + WEB_HTTP_STATUSLIST_PORT: {{ .Values.wallet.endpoints.statuslist.port | quote }} + WEB_HTTP_STATUSLIST_PATH: {{ .Values.wallet.endpoints.statuslist.path | quote }} + WEB_HTTP_ISSUANCE_PORT: {{ .Values.wallet.endpoints.issuance.port | quote }} + WEB_HTTP_ISSUANCE_PATH: {{ .Values.wallet.endpoints.issuance.path | quote }} + + #################### + ## IAM/DID/Issuer ## + #################### + EDC_IAM_DID_WEB_USE_HTTPS: {{ .Values.wallet.didweb.https | quote }} + EDC_IAM_KEY_ALGORITHM: {{ $iam.keyAlgorithm | default "RSA" | quote }} + EDC_IAM_CREDENTIAL_RENEWAL_GRACEPERIOD: {{ $iam.renewalGraceperiod | default "172800" | quote }} + EDC_ISSUER_ISSUANCE_SEND_RETRY_LIMIT: {{ $issuer.sendRetryLimit | default "0" | quote }} + EDC_STATUSLIST_CALLBACK_ADDRESS: {{ $statuslist.callbackAddress | default $defaultStlCallback | quote }} + + ########### + ## VAULT ## + ########### + EDC_VAULT_HASHICORP_URL: {{ tpl .Values.vault.hashicorp.url . | quote }} + EDC_VAULT_HASHICORP_TIMEOUT_SECONDS: {{ .Values.vault.hashicorp.timeout | quote }} + EDC_VAULT_HASHICORP_HEALTH_CHECK_ENABLED: {{ .Values.vault.hashicorp.healthCheck.enabled | quote }} + EDC_VAULT_HASHICORP_HEALTH_CHECK_STANDBY_OK: {{ .Values.vault.hashicorp.healthCheck.standbyOk | quote }} + EDC_VAULT_HASHICORP_API_SECRET_PATH: {{ .Values.vault.hashicorp.paths.secret | quote }} + EDC_VAULT_HASHICORP_API_HEALTH_CHECK_PATH: {{ .Values.vault.hashicorp.paths.health | quote }} + + ################# + ## Encryption ## + ################# + EDC_ENCRYPTION_AES_KEY_ALIAS: {{ .Values.vault.hashicorp.init.aesKeyAlias | default "issuer-wallet-aes-key-alias" | quote }} + EDC_ISSUER_STATUSLIST_SIGNING_KEY_ALIAS: {{ $statuslist.signingKeyAlias | default "foo" | quote }} \ No newline at end of file diff --git a/helm/issuer-wallet/templates/configmap-vault-init.yaml b/helm/issuer-wallet/templates/configmap-vault-init.yaml new file mode 100644 index 0000000..6493287 --- /dev/null +++ b/helm/issuer-wallet/templates/configmap-vault-init.yaml @@ -0,0 +1,140 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +# this configmap contains the initialization script to generate and store aes and rsa keys into the vault. + +{{ if .Values.vault.hashicorp.init.enabled }} +{{- $fullName := .Values.fullnameOverride -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $fullName }}-vault-init + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "issuer-wallet.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +data: + init.sh: | + #!/usr/bin/env sh + set -eu + + VAULT="${VAULT_ADDR:?VAULT_ADDR is required}" + TOKEN="${VAULT_TOKEN:?VAULT_TOKEN is required}" + FORCE="${FORCE_REGENERATE:-false}" + SECRETS="${VAULT_SECRET_PATH:-/v1/secret}" + HEALTH="${VAULT_HEALTH_PATH:-/v1/sys/health}" + + AES_ALIAS="${AES_KEY_ALIAS:-}" + PRIV_ALIAS="${PRIVATE_KEY_ALIAS:-}" + PUB_ALIAS="${PUBLIC_KEY_ALIAS:-}" + + log() { echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*" >&2; } + + # Check provided Aliases for plausibility (AES or RSA pair must be requested) + if [ -z "$AES_ALIAS" ] && [ -z "$PRIV_ALIAS" ] && [ -z "$PUB_ALIAS" ]; then + log "ERROR: no alias provided. Set AES_KEY_ALIAS and/or PRIVATE_KEY_ALIAS+PUBLIC_KEY_ALIAS." + exit 1 + fi + if { [ -n "$PRIV_ALIAS" ] && [ -z "$PUB_ALIAS" ]; } || \ + { [ -z "$PRIV_ALIAS" ] && [ -n "$PUB_ALIAS" ]; }; then + log "ERROR: RSA generation requires BOTH PRIVATE_KEY_ALIAS and PUBLIC_KEY_ALIAS." + exit 1 + fi + + # Install required tools + if ! command -v openssl >/dev/null 2>&1 \ + || ! command -v curl >/dev/null 2>&1 \ + || ! command -v jq >/dev/null 2>&1; then + log "Installing curl, jq, openssl..." + apk add --no-cache curl jq openssl >/dev/null + fi + + log "Waiting for Vault at $VAULT$HEALTH..." + i=0 + until curl -fsS --connect-timeout 2 --max-time 5 "$VAULT$HEALTH" >/dev/null 2>&1; do + i=$((i+1)) + [ "$i" -gt 60 ] && { log "Vault not ready after 60 attempts."; exit 1; } + sleep 3 + done + log "Vault ready." + + # Check for existing Secret + secret_exists() { + [ "$(curl -sS -o /dev/null -w "%{http_code}" \ + -H "X-Vault-Token: $TOKEN" \ + "$VAULT$SECRETS/data/$1")" = "200" ] + } + + # Store Secret in Vault + put_secret() { + local alias="$1" payload="$2" + local code + code=$(printf '%s' "$payload" | curl -sS -o /dev/null -w "%{http_code}" \ + -H "X-Vault-Token: $TOKEN" \ + -H "Content-Type: application/json" \ + -X POST --data-binary @- \ + "$VAULT$SECRETS/data/$alias") + if [ "$code" != "200" ] && [ "$code" != "204" ]; then + log "Failed to store '$alias' (HTTP $code)" + exit 1 + fi + } + + # Generate AES Key + if [ -n "$AES_ALIAS" ]; then + if [ "$FORCE" != "true" ] && secret_exists "$AES_ALIAS"; then + log "AES key '$AES_ALIAS' already present — skipping." + else + log "Generating AES-256 key for '$AES_ALIAS'..." + key=$(openssl rand -base64 32 | tr -d '\n') + payload=$(jq -n --arg content "$key" '{data:{content:$content}}') + put_secret "$AES_ALIAS" "$payload" + log "AES key stored at $VAULT$SECRETS/data/$AES_ALIAS" + fi + fi + + # Generate RSA Keypair + if [ -n "$PRIV_ALIAS" ] && [ -n "$PUB_ALIAS" ]; then + if [ "$FORCE" != "true" ] \ + && secret_exists "$PRIV_ALIAS" \ + && secret_exists "$PUB_ALIAS"; then + log "RSA keypair ('$PRIV_ALIAS' / '$PUB_ALIAS') already present — skipping." + else + log "Generating RSA keypair ('$PRIV_ALIAS' / '$PUB_ALIAS')..." + umask 077 + dir=$(mktemp -d) + openssl genrsa -out "$dir/k.pem" 2048 2>/dev/null + openssl pkcs8 -topk8 -nocrypt -in "$dir/k.pem" -out "$dir/priv.pem" + openssl rsa -in "$dir/k.pem" -pubout -out "$dir/pub.pem" 2>/dev/null + + put_secret "$PRIV_ALIAS" \ + "$(jq -n --rawfile content "$dir/priv.pem" '{data:{content:$content}}')" + put_secret "$PUB_ALIAS" \ + "$(jq -n --rawfile content "$dir/pub.pem" '{data:{content:$content}}')" + + rm -rf "$dir" + log "RSA keypair stored at $VAULT$SECRETS/data/{$PRIV_ALIAS,$PUB_ALIAS}" + fi + fi + + log "Vault initialization complete." +{{- end }} diff --git a/helm/issuer-wallet/templates/deployment.yaml b/helm/issuer-wallet/templates/deployment.yaml new file mode 100644 index 0000000..8965f1d --- /dev/null +++ b/helm/issuer-wallet/templates/deployment.yaml @@ -0,0 +1,206 @@ +# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 LKS Next +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +{{ $fullName := .Values.fullnameOverride -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "issuer-wallet.fullname" . }} + labels: + {{- include "issuer-wallet.server.labels" . | nindent 4 }} +spec: + {{- if not .Values.wallet.autoscaling.enabled }} + replicas: {{ .Values.wallet.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "issuer-wallet.server.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.wallet.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "issuer-wallet.server.selectorLabels" . | nindent 8 }} + {{- with .Values.wallet.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "issuer-wallet.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.wallet.podSecurityContext | nindent 8 }} + {{- if or .Values.wallet.initContainers .Values.customCaCerts }} + initContainers: + {{- if .Values.wallet.initContainers }} + {{- toYaml .Values.wallet.initContainers | nindent 8 }} + {{- end }} + {{- if .Values.customCaCerts }} + - name: custom-cacerts + # either use the specified image, or use the default one + {{- if .Values.wallet.image.repository }} + image: "{{ .Values.wallet.image.repository }}:{{ .Values.wallet.image.tag | default .Chart.AppVersion }}" + {{- else }} + image: "ghcr.io/project-construct-x/wallet:{{ .Values.wallet.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.wallet.image.pullPolicy }} + command: + - /bin/sh + - -c + - | + cp /opt/java/openjdk/lib/security/cacerts /workdir/ + find /cacerts -type f \( -iname \*.crt -o -iname \*.pem \) -exec echo "{}" \; | while read PEM_FILE_PATH; do + PEM_FILE=${PEM_FILE_PATH##*/} + ALIAS=${PEM_FILE%.*} + echo "adding ${PEM_FILE} with alias ${ALIAS} to cacerts ..." + keytool -import -noprompt -trustcacerts -alias ${ALIAS} -file ${PEM_FILE_PATH} -keystore /workdir/cacerts -storepass changeit + done + securityContext: + {{- toYaml .Values.wallet.securityContext | nindent 12 }} + volumeMounts: + - name: custom-cacertificates + mountPath: /cacerts + - name: custom-cacerts + mountPath: /workdir + {{- end }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.wallet.securityContext | nindent 12 }} + # either use the specified image, or use the default one + {{- if .Values.wallet.image.repository }} + image: "{{ .Values.wallet.image.repository }}:{{ .Values.wallet.image.tag | default .Chart.AppVersion }}" + {{- else }} + image: "ghcr.io/project-construct-x/wallet:{{ .Values.wallet.image.tag | default .Chart.AppVersion }}" + {{- end }} + + imagePullPolicy: {{ .Values.wallet.image.pullPolicy }} + ports: + {{- range $key,$value := .Values.wallet.endpoints }} + - name: {{ $key }} + containerPort: {{ $value.port }} + protocol: TCP + {{- end }} + {{- if .Values.wallet.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.wallet.endpoints.default.path }}/check/liveness + port: {{ .Values.wallet.endpoints.default.port }} + initialDelaySeconds: {{ .Values.wallet.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.wallet.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.wallet.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.wallet.livenessProbe.failureThreshold }} + successThreshold: {{ .Values.wallet.livenessProbe.successThreshold }} + {{- end }} + {{- if .Values.wallet.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.wallet.endpoints.default.path }}/check/readiness + port: {{ .Values.wallet.endpoints.default.port }} + initialDelaySeconds: {{ .Values.wallet.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.wallet.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.wallet.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.wallet.readinessProbe.failureThreshold }} + successThreshold: {{ .Values.wallet.readinessProbe.successThreshold }} + {{- end }} + resources: + {{- toYaml .Values.wallet.resources | nindent 12 }} + env: + {{- if .Values.wallet.debug.enabled }} + - name: "JAVA_TOOL_OPTIONS" + {{- if .Values.wallet.debug.suspendOnStart }} + value: >- + {{ printf "%s-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=%v" (ternary "-XX:UseSVE=0 " "" .Values.wallet.useSVE) .Values.wallet.debug.port}} + {{- else }} + value: >- + {{ printf "%s-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=%v" (ternary "-XX:UseSVE=0 " "" .Values.wallet.useSVE) .Values.wallet.debug.port}} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.wallet.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 16 }} + {{- end }} + {{- range $key, $value := .Values.wallet.env }} + - name: {{ $key | quote }} + value: {{ $value | quote }} + {{- end }} + envFrom: + - configMapRef: + name: {{ $fullName }}-config + - configMapRef: + name: {{ $fullName }}-datasource-config + - secretRef: + name: {{ $fullName }}-datasource-credentials + {{- if .Values.wallet.superuser.createSecret }} + - secretRef: + name: {{ $fullName }}-superuser-credentials + {{- end }} + {{- if and (or .Values.wallet.envSecretNames .Values.wallet.envConfigMapNames) (or (gt (len .Values.wallet.envSecretNames) 0) (gt (len .Values.wallet.envConfigMapNames) 0)) }} + {{- range $value := .Values.wallet.envSecretNames }} + - secretRef: + name: {{ $value | quote }} + {{- end }} + {{- range $value := .Values.wallet.envConfigMapNames }} + - configMapRef: + name: {{ printf "%s-%s" $fullName $value | quote }} + {{- end }} + {{- end }} + volumeMounts: + {{- if .Values.customCaCerts }} + - name: custom-cacerts + mountPath: /opt/java/openjdk/lib/security/cacerts + subPath: cacerts + {{- end }} + - name: "tmp" + mountPath: "/tmp" + volumes: + - name: "configuration" + configMap: + {{- if .Values.customCaCerts }} + - name: custom-cacertificates + configMap: + name: {{ include "issuer-wallet.fullname" . }}-custom-cacerts + defaultMode: 0400 + - name: custom-cacerts + emptyDir: + sizeLimit: 1Mi + {{- end }} + - name: "tmp" + emptyDir: { } + {{- with .Values.wallet.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.wallet.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.wallet.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/issuer-wallet/templates/hpa.yaml b/helm/issuer-wallet/templates/hpa.yaml new file mode 100644 index 0000000..2ee252f --- /dev/null +++ b/helm/issuer-wallet/templates/hpa.yaml @@ -0,0 +1,50 @@ +################################################################################# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ if .Values.wallet.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "issuer-wallet.fullname" . }} + labels: + {{- include "issuer-wallet.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "issuer-wallet.fullname" . }} + minReplicas: {{ .Values.wallet.autoscaling.minReplicas }} + maxReplicas: {{ .Values.wallet.autoscaling.maxReplicas }} + metrics: + {{- if .Values.wallet.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + averageUtilization: {{ .Values.wallet.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.wallet.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + averageUtilization: {{ .Values.wallet.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/issuer-wallet/templates/ingress.yaml b/helm/issuer-wallet/templates/ingress.yaml new file mode 100644 index 0000000..b40ad5b --- /dev/null +++ b/helm/issuer-wallet/templates/ingress.yaml @@ -0,0 +1,98 @@ +################################################################################# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ $fullName := include "issuer-wallet.fullname" . }} +{{- $controlLabels := include "issuer-wallet.server.labels" . }} +{{- $controlEdcEndpoints := .Values.wallet.endpoints }} +{{- $gitVersion := .Capabilities.KubeVersion.GitVersion }} +{{- $namespace := .Release.Namespace }} + +{{- range .Values.wallet.ingresses }} +{{- if and .enabled .endpoints }} +{{- $controlIngressName := printf "%s-%s" $fullName .hostname }} +{{- $annotations := .annotations | default dict }} + +{{- if semverCompare ">=1.19-0" $gitVersion }} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" $gitVersion }} +apiVersion: networking.k8s.io/v1beta1 +{{- else }} +apiVersion: extensions/v1beta +{{- end }} +kind: Ingress +metadata: + name: {{ $controlIngressName }} + namespace: {{ $namespace | default "default" | quote }} + labels: + {{- $controlLabels | nindent 4 }} + annotations: + {{- if and .className (not (semverCompare ">=1.18-0" $gitVersion)) }} + {{- if not (hasKey $annotations "kubernetes.io/ingress.class") }} + {{- $_ := set $annotations "kubernetes.io/ingress.class" .className}} + {{- end }} + {{- end }} + {{- if .certManager }} + {{- if .certManager.issuer }} + {{- $_ := set $annotations "cert-manager.io/issuer" .certManager.issuer}} + {{- end }} + {{- if .certManager.clusterIssuer }} + {{- $_ := set $annotations "cert-manager.io/cluster-issuer" .certManager.clusterIssuer}} + {{- end }} + {{- end }} + {{- with $annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .className (semverCompare ">=1.18-0" $gitVersion) }} + ingressClassName: {{ .className }} + {{- end }} + {{- if .hostname }} + {{- if .tls.enabled }} + tls: + - hosts: + - {{ .hostname }} + {{- if .tls.secretName }} + secretName: {{ .tls.secretName }} + {{- else }} + secretName: {{ $controlIngressName }}-tls + {{- end }} + {{- end }} + rules: + - host: {{ .hostname }} + http: + paths: + {{- $ingressEdcEndpoints := .endpoints }} + {{- range $name, $mapping := $controlEdcEndpoints }} + {{- if (has $name $ingressEdcEndpoints) }} + - path: {{ $mapping.path }} + pathType: {{ $mapping.pathType | default "Prefix" }} + backend: + {{- if semverCompare ">=1.19-0" $gitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $mapping.port }} + {{- else }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} +{{- end }}{{- /* end: if .enabled */}} +{{- end }}{{- /* end: range .Values.ingresses */}} diff --git a/helm/issuer-wallet/templates/job-vault-init.yaml b/helm/issuer-wallet/templates/job-vault-init.yaml new file mode 100644 index 0000000..f468525 --- /dev/null +++ b/helm/issuer-wallet/templates/job-vault-init.yaml @@ -0,0 +1,87 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ if .Values.vault.hashicorp.init.enabled -}} +{{- $fullName := .Values.fullnameOverride -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ $fullName }}-vault-init + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "issuer-wallet.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "0" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + backoffLimit: 3 + ttlSecondsAfterFinished: 600 + activeDeadlineSeconds: 300 + template: + metadata: + labels: + {{- include "issuer-wallet.labels" . | nindent 8 }} + spec: + restartPolicy: OnFailure + serviceAccountName: {{ include "issuer-wallet.serviceAccountName" . }} + containers: + - name: vault-init + {{- $img := index .Values "vault" "hashicorp" "init" "image" | default dict }} + image: {{ $img.repository | default "alpine" }}:{{ $img.tag | default "3.20" }} + command: ["/bin/sh", "-c"] + args: + - | + tr -d '\r' < /scripts/init.sh > /tmp/init.sh + exec sh /tmp/init.sh + env: + - name: VAULT_ADDR + value: {{ tpl .Values.vault.hashicorp.url . | quote }} + - name: VAULT_TOKEN + value: {{ .Values.vault.hashicorp.token | required "vault.hashicorp.token is required" }} + - name: VAULT_SECRET_PATH + value: {{ .Values.vault.hashicorp.paths.secret | quote }} + - name: VAULT_HEALTH_PATH + value: {{ .Values.vault.hashicorp.paths.health | quote }} + {{- with .Values.vault.hashicorp.init.forceRegenerate }} + - name: FORCE_REGENERATE + value: {{ . | quote }} + {{- end }} + {{- with .Values.vault.hashicorp.init.aesKeyAlias }} + - name: AES_KEY_ALIAS + value: {{ . | quote }} + {{- end }} + {{- with .Values.vault.hashicorp.init.privateKeyAlias }} + - name: PRIVATE_KEY_ALIAS + value: {{ . | quote }} + {{- end }} + {{- with .Values.vault.hashicorp.init.publicKeyAlias }} + - name: PUBLIC_KEY_ALIAS + value: {{ . | quote }} + {{- end }} + volumeMounts: + - name: script + mountPath: /scripts + readOnly: true + volumes: + - name: script + configMap: + name: {{ $fullName }}-vault-init + defaultMode: 0555 +{{- end }} diff --git a/helm/issuer-wallet/templates/secret-datasource.yaml b/helm/issuer-wallet/templates/secret-datasource.yaml new file mode 100644 index 0000000..801b3b8 --- /dev/null +++ b/helm/issuer-wallet/templates/secret-datasource.yaml @@ -0,0 +1,42 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ $fullName := .Values.fullnameOverride -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $fullName }}-datasource-credentials + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "issuer-wallet.labels" . | nindent 4 }} +type: Opaque +stringData: + + ################ + ## POSTGRESQL ## + ################ + + # default + EDC_DATASOURCE_DEFAULT_USER: {{ .Values.postgresql.auth.username | quote }} + EDC_DATASOURCE_DEFAULT_PASSWORD: {{ .Values.postgresql.auth.password | quote }} + + ########### + ## VAULT ## + ########### + EDC_VAULT_HASHICORP_TOKEN: {{ .Values.vault.hashicorp.token | required ".Values.vault.hashicorp.token is required" | quote }} \ No newline at end of file diff --git a/helm/issuer-wallet/templates/secret-runtime.yaml b/helm/issuer-wallet/templates/secret-runtime.yaml new file mode 100644 index 0000000..9517354 --- /dev/null +++ b/helm/issuer-wallet/templates/secret-runtime.yaml @@ -0,0 +1,38 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ if .Values.wallet.superuser.createSecret -}} +{{- $fullName := .Values.fullnameOverride -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $fullName }}-superuser-credentials + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "issuer-wallet.labels" . | nindent 4 }} +type: Opaque +stringData: + ################ + ## Super-User ## + ################ + EDC_IH_API_SUPERUSER_ID: {{ .Values.wallet.superuser.id | quote }} + EDC_IH_API_KEY_SUPERUSER: {{ .Values.wallet.superuser.apiKey | quote }} + EDC_IH_API_SUPERUSER_PUBLIC_KEY_ALIAS: {{ .Values.wallet.superuser.publicKeyAlias | quote }} + EDC_IH_API_SUPERUSER_PRIVATE_KEY_ALIAS: {{ .Values.wallet.superuser.privateKeyAlias | quote }} +{{- end -}} \ No newline at end of file diff --git a/helm/issuer-wallet/templates/service.yaml b/helm/issuer-wallet/templates/service.yaml new file mode 100644 index 0000000..fbccd97 --- /dev/null +++ b/helm/issuer-wallet/templates/service.yaml @@ -0,0 +1,60 @@ +# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "issuer-wallet.fullname" . }} + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "issuer-wallet.server.labels" . | nindent 4 }} +spec: + type: {{ .Values.wallet.service.type }} + ports: + - port: {{ .Values.wallet.endpoints.default.port }} + targetPort: default + protocol: TCP + name: default + - port: {{ .Values.wallet.endpoints.identity.port }} + targetPort: identity + protocol: TCP + name: identity + - port: {{ .Values.wallet.endpoints.issueradmin.port }} + targetPort: issueradmin + protocol: TCP + name: issueradmin + - port: {{ .Values.wallet.endpoints.did.port }} + targetPort: did + protocol: TCP + name: did + - port: {{ .Values.wallet.endpoints.sts.port }} + targetPort: sts + protocol: TCP + name: sts + - port: {{ .Values.wallet.endpoints.statuslist.port }} + targetPort: statuslist + protocol: TCP + name: statuslist + - port: {{ .Values.wallet.endpoints.issuance.port }} + targetPort: issuance + protocol: TCP + name: issuance + selector: + {{- include "issuer-wallet.server.selectorLabels" . | nindent 4 }} diff --git a/helm/issuer-wallet/templates/serviceaccount.yaml b/helm/issuer-wallet/templates/serviceaccount.yaml new file mode 100644 index 0000000..0876ac6 --- /dev/null +++ b/helm/issuer-wallet/templates/serviceaccount.yaml @@ -0,0 +1,33 @@ +################################################################################# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "issuer-wallet.serviceAccountName" . }} + labels: + {{- include "issuer-wallet.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/issuer-wallet/templates/tests/test.yaml b/helm/issuer-wallet/templates/tests/test.yaml new file mode 100644 index 0000000..bf17f7e --- /dev/null +++ b/helm/issuer-wallet/templates/tests/test.yaml @@ -0,0 +1,43 @@ +# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "issuer-wallet.fullname" . }}-test" + labels: + {{- include "issuer-wallet.server.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": {{ .Values.tests.hookDeletePolicy }} +spec: + containers: + - name: readiness + image: curlimages/curl + command: [ 'curl', '--fail' ] + args: [ '{{- printf "http://%s:%v%s/check/readiness" (include "issuer-wallet.fullname" $ ) $.Values.wallet.endpoints.default.port $.Values.wallet.endpoints.default.path -}}' ] + restartPolicy: Never + securityContext: + fsGroup: 101 # curl_group + runAsGroup: 101 # curl_group + runAsNonRoot: true + runAsUser: 100 # curl_user + seccompProfile: + type: RuntimeDefault diff --git a/helm/issuer-wallet/values.yaml b/helm/issuer-wallet/values.yaml new file mode 100644 index 0000000..e5c8261 --- /dev/null +++ b/helm/issuer-wallet/values.yaml @@ -0,0 +1,402 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025,2026 LKS Next +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Controls whether the bundled sub-charts are installed alongside the issuer-wallet. +# Set to false to use externally managed PostgreSQL or Vault instances. +install: + postgresql: true + vault: true + +# This is to override the chart name. +fullnameOverride: "issuer" +nameOverride: "issuer" + +# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] + +# -- Add custom ca certificates to the truststore +customCaCerts: {} + +wallet: + # This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ + image: + repository: "ghcr.io/project-construct-x/wallet" + # This sets the pull policy for images. + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "0.17.0-1" + initContainers: [] + # This is for setting Kubernetes Labels to a Pod. + # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + podLabels: {} + + # This is for setting Kubernetes Annotations to a Pod. + # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + podAnnotations: {} + + # Disables SVE (Scalable Vector Extension) instructions via JAVA_TOOL_OPTIONS. + # Enable on nodes with SVE-capable CPUs if the JVM produces illegal instruction errors. + useSVE: false + + # Remote debugging via JDWP. Never enable in production environments. + debug: + enabled: false + # Port the JDWP agent listens on inside the container + port: 1044 + # If true, the JVM suspends on startup until a debugger connects + suspendOnStart: false + + # Public hostname of the issuer-wallet. Used to construct did:web URLs and ingress routing. + hostname: "issuer.staging.construct-x.net" + + # Super-user participant seeded on first startup by the super-user-seed-extension. + # The api key is stored in Vault under the alias derived from the participant id. + superuser: + # If true, a Kubernetes Secret is created from the values below and mounted via envFrom. + # Set to false to provide the secret externally and reference it via envSecretNames. + createSecret: true + id: admin + # API key for the super-user. Must follow the format base64().. + apiKey: YWRtaW4.adminKey + publicKeyAlias: admin#pubkey + privateKeyAlias: admin#privkey + # -- Whether web DIDs should be interpreted as HTTPS or HTTP + didweb: + https: true + + # Extra environment variables that will be pass onto deployment pods + env: {} + + # "valueFrom" environment variable references that will be added to deployment pods. Name is templated. + # ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core + envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + # secretKeyRef: + # name: secret-name + # key: value_key + + # [Kubernetes Secret Resource](https://kubernetes.io/docs/concepts/configuration/secret/) names to load environment variables from + envSecretNames: [] + # - first-secret + # - second-secret + + # [Kubernetes ConfigMap Resource](https://kubernetes.io/docs/concepts/configuration/configmap/) names to load environment variables from + envConfigMapNames: [] + # - first-config-map + # - second-config-map + + # This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + livenessProbe: + # -- Whether to enable kubernetes [liveness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) + enabled: true + # -- seconds to wait before performing the first liveness check + initialDelaySeconds: 5 + # -- this fields specifies that kubernetes should perform a liveness check every 5 seconds + periodSeconds: 5 + # -- number of seconds after which the probe times out + timeoutSeconds: 5 + # -- when a probe fails kubernetes will try 6 times before giving up + failureThreshold: 6 + # -- number of consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + + readinessProbe: + # -- Whether to enable kubernetes [readiness-probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) + enabled: true + # -- seconds to wait before performing the first readiness check + initialDelaySeconds: 5 + # -- this fields specifies that kubernetes should perform a readiness check every 5 seconds + periodSeconds: 5 + # -- number of seconds after which the probe times out + timeoutSeconds: 5 + # -- when a probe fails kubernetes will try 6 times before giving up + failureThreshold: 6 + # -- number of consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + + # -- endpoints of the issuer-wallet + endpoints: + # -- default api for health checks, should not be added to any ingress + default: + # -- port for incoming api calls + port: 8181 + # -- path for incoming api calls + path: /api + # -- management api, used by internal users, can be added to an ingress and must not be internet facing + identity: + # -- port for incoming api calls + port: 15151 + # -- path for incoming api calls + path: /api/identity + # -- authentication key, must be attached to each 'X-Api-Key' request header + authKeyAlias: "sup3r$3cr3t" + # -- Issuer Admin API endpoint, must not be internet facing + issueradmin: + # -- port for incoming api calls + port: 15152 + # -- path for incoming api calls + path: /api/issuer + # -- DID service endpoint. DID documents can be resolved from here. + did: + # -- port for incoming api calls + port: 80 + # -- path for incoming api calls + path: / + # -- STS Endpoint, used to obtain tokens + sts: + # -- port for incoming api calls + port: 9292 + # -- path for incoming api calls + path: /api/sts + # -- StatusList API, used to check the status of verifiable credentials. Must be internet-facing + statuslist: + # -- port for incoming api calls + port: 9999 + # -- path for incoming api calls + path: /statuslist + # -- DCP Issuance API. Must be internet-facing. + issuance: + # -- port for incoming api calls + port: 13132 + # -- path for incoming api calls + path: /api/issuance + + # This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ + service: + # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: ClusterIP + # Additional annotations to add to the Service resource + annotations: {} + + ## Ingress declaration to expose the network service. + ingresses: + ## Public / Internet facing Ingress for the Presentation API + - enabled: true + # -- The hostname to be used to precisely map incoming traffic onto the underlying network service + hostname: "issuer.staging.construct-x.net" + # -- Additional ingress annotations to add + annotations: + cert-manager.io/cluster-issuer: letsencrypt-staging + external-dns.alpha.kubernetes.io/hostname: "issuer.staging.construct-x.net" + external-dns.alpha.kubernetes.io/ttl: "300" + # -- EDC endpoints exposed by this ingress resource + endpoints: + - issuance + - sts + - did + - statuslist + # -- Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use + className: "nginx" + # -- TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource + tls: + # -- Enables TLS on the ingress resource + enabled: true + # -- If present overwrites the default secret name + secretName: "issuer-wallet-tls" + ## Adds [cert-manager](https://cert-manager.io/docs/) annotations to the ingress resource + certManager: + # -- If preset enables certificate generation via cert-manager namespace scoped issuer + issuer: "" + # -- If preset enables certificate generation via cert-manager cluster-wide issuer + clusterIssuer: "letsencrypt-staging" + ## Ingress for the Identity API, should not be internet facing + - enabled: false + # -- The hostname to be used to precisely map incoming traffic onto the underlying network service + hostname: "issuer.staging.construct-x.net" + # -- Additional ingress annotations to add + annotations: {} + # -- EDC endpoints exposed by this ingress resource + endpoints: + - issueradmin + - identity + # -- Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use + className: "nginx" + # -- TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource + tls: + # -- Enables TLS on the ingress resource + enabled: false + # -- If present overwrites the default secret name + secretName: "" + ## Adds [cert-manager](https://cert-manager.io/docs/) annotations to the ingress resource + certManager: + # -- If preset enables certificate generation via cert-manager namespace scoped issuer + issuer: "" + # -- If preset enables certificate generation via cert-manager cluster-wide issuer + clusterIssuer: "letsencrypt-staging" + + # Additional volumeMounts on the output Deployment definition. + volumeMounts: [] + # - name: foo + # mountPath: "/etc/foo" + # readOnly: true + + # Additional volumes on the output Deployment definition. + volumes: [] + # - name: foo + # secret: + # secretName: mysecret + # optional: false + + # -- [resource management](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the container + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 250m + memory: 128Mi + + # This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ + # This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ + replicaCount: 1 + autoscaling: + # -- Enables [horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) + enabled: false + # -- Minimal replicas if resource consumption falls below resource threshholds + minReplicas: 1 + # -- Maximum replicas if resource consumption exceeds resource threshholds + maxReplicas: 100 + # -- targetAverageUtilization of cpu provided to a pod + targetCPUUtilizationPercentage: 80 + # -- targetAverageUtilization of memory provided to a pod + targetMemoryUtilizationPercentage: 80 + + # [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) to constrain pods to nodes + nodeSelector: {} + # [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to configure preferred nodes + tolerations: [] + # [affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) to configure which nodes the pods can be scheduled on + affinity: {} + + # The [pod security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) defines privilege and access control settings for a Pod within the deployment + podSecurityContext: + seccompProfile: + # -- Restrict a Container's Syscalls with seccomp + type: RuntimeDefault + # -- Runs all processes within a pod with a special uid + runAsUser: 10100 + # -- Processes within a pod will belong to this guid + runAsGroup: 10100 + # -- The owner for volumes and any files created within volumes will belong to this guid + fsGroup: 10100 + + # The [container security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) defines privilege and access control settings for a Container within a pod + securityContext: + capabilities: + # -- Specifies which capabilities to drop to reduce syscall attack surface + drop: + - ALL + # -- Specifies which capabilities to add to issue specialized syscalls + add: [] + # -- Whether the root filesystem is mounted in read-only mode + readOnlyRootFilesystem: true + # -- Controls [Privilege Escalation](https://kubernetes.io/docs/concepts/security/pod-security-policy/#privilege-escalation) enabling setuid binaries changing the effective user ID + allowPrivilegeEscalation: false + # -- Requires the container to run without root privileges + runAsNonRoot: true + # -- The container's process will run with the specified uid + runAsUser: 10100 + +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +# -- Configurations for Helm tests +tests: + # -- Configure the hook-delete-policy for Helm tests + hookDeletePolicy: before-hook-creation,hook-succeeded + +postgresql: + # JDBC connection URL passed to the issuer-wallet runtime. + jdbcUrl: "jdbc:postgresql://{{ .Release.Name }}-postgresql:5432/issuer" + auth: + # Name of the PostgreSQL database created on first start. Must match with postgresql.jdbcUrl path. + database: "issuer" + # PostgreSQL user that the issuer-wallet connects as. + username: "user" + # Password for the PostgreSQL user. Change before production use. + password: "password" + persistence: + # Persist data across pod restarts. + enabled: true + size: 10Gi + storageClass: "" + # Initialization scripts ConfigMap + initdb: + scriptsConfigMap: "" # Optional: ConfigMap with init scripts + resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + +vault: + injector: + enabled: false + server: + dev: + # Run Vault in dev mode. All data is stored in memory and lost on pod restart. + # Disable for production and configure a persistent storage backend instead. + enabled: true + # Root token used when dev mode is active. Must match vault.hashicorp.token. + devRootToken: "root" + # Optional post-start hook script executed inside the Vault container after startup. + # Can be used to initialise the KV engine or apply policies. Must be set externally. + postStart: + hashicorp: + # URL of the Vault instance reachable from within the cluster. + url: "http://{{ .Release.Name }}-vault:8200" + # Vault token used by the issuer-wallet at runtime to read and write secrets. + # If vault.server.dev.enabled is true vault.hashicorp.token match with vault.server.dev.devRootToken. + token: "root" + # Timeout in seconds for Vault HTTP requests. + timeout: 30 + healthCheck: + enabled: true + standbyOk: true + paths: + # Mount path used for all issuer-wallet secrets + secret: /v1/secret + # Health endpoint polled by the issuer-wallet and the vault-init job + health: /v1/sys/health + init: + # Whether to run the post-install vault-init job that seeds required secrets + enabled: true + # Vault alias under which the AES-256 encryption key is stored. + aesKeyAlias: "issuer-wallet-aes-key-alias" diff --git a/helm/wallet/.helmignore b/helm/wallet/.helmignore new file mode 100644 index 0000000..691fa13 --- /dev/null +++ b/helm/wallet/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ \ No newline at end of file diff --git a/helm/wallet/Chart.lock b/helm/wallet/Chart.lock new file mode 100644 index 0000000..d5c366e --- /dev/null +++ b/helm/wallet/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: postgres + repository: oci://registry-1.docker.io/cloudpirates + version: 0.19.5 +- name: vault + repository: https://helm.releases.hashicorp.com + version: 0.29.1 +digest: sha256:c730f7da67d2940512fb6cd112b9474968890ecd64c2e3a4101c16702b2b3a81 +generated: "2026-06-15T14:23:22.466394659+02:00" diff --git a/helm/wallet/Chart.yaml b/helm/wallet/Chart.yaml new file mode 100644 index 0000000..f51b340 --- /dev/null +++ b/helm/wallet/Chart.yaml @@ -0,0 +1,67 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +apiVersion: v2 +name: wallet +description: A Helm chart for Construct-X Wallet alongside Hashicorp Vault and PostgreSQL + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.17.0-1" +keywords: + - wallet + - identityhub + - edc + - gaia-x +home: https://github.com/project-construct-x/wallet +sources: + - https://github.com/project-construct-x/wallet + - https://github.com/eclipse-tractusx/tractusx-identityhub +dependencies: + # PostgreSQL + - name: postgres + alias: postgresql + version: 0.19.5 + repository: oci://registry-1.docker.io/cloudpirates + condition: install.postgresql + # HashiCorp Vault + - name: vault + alias: vault + version: 0.29.1 + repository: https://helm.releases.hashicorp.com + condition: install.vault diff --git a/helm/wallet/LICENSE b/helm/wallet/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/helm/wallet/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/helm/wallet/README.md b/helm/wallet/README.md new file mode 100644 index 0000000..2bb0371 --- /dev/null +++ b/helm/wallet/README.md @@ -0,0 +1,176 @@ +# Construct-X Wallet + +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) +![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-informational?style=flat-square) + +Deploys the [Construct-X Wallet](https://github.com/project-construct-x/wallet) — an EDC IdentityHub runtime — together with a PostgreSQL database and a HashiCorp Vault instance. + + +## Prerequisites + +| **Requirement** | **Version** | +|---|---| +| Kubernetes | 1.29+ | +| Helm | 3.14+ | + +- A Persistent Volume provisioner is required if `postgresql.primary.persistence.enabled: true` +- Cluster Internet connection is required if `vault.hashicorp.init.enabled: true` to pull required `apk` packages + +## Installation + +```bash +# Add dependencies +helm dependency build +# Install +helm install wallet . -f my-override-values.yaml +``` + +## Values + +### Top-level + +| Key | Type | Default | Description | +|---|---|---|---| +| `install.postgresql` | bool | `true` | Install the bundled PostgreSQL sub-chart. Set to `false` to use an external database. | +| `install.vault` | bool | `true` | Install the bundled Vault sub-chart. Set to `false` to use an external Vault. | +| `fullnameOverride` | string | `"wallet"` | Overrides the chart fullname used for all resource names. | +| `nameOverride` | string | `"wallet"` | Overrides the chart name used in labels. | +| `imagePullSecrets` | list | `[]` | Pull secrets for private image registries. | +| `customCaCerts` | object | `{}` | Custom CA certificates added to the Java truststore at startup. | + +### `wallet` + +| Key | Type | Default | Description | +|---|---|---|---| +| `wallet.image.repository` | string | `ghcr.io/project-construct-x/wallet` | Container image repository. | +| `wallet.image.tag` | string | `0.17.0-1` | Image tag. Defaults to `chart.appVersion` if left empty. | +| `wallet.image.pullPolicy` | string | `IfNotPresent` | Kubernetes image pull policy. | +| `wallet.initContainers` | list | `[]` | Additional init containers run before the wallet starts. | +| `wallet.podLabels` | object | `{}` | Extra labels applied to the wallet pod. | +| `wallet.podAnnotations` | object | `{}` | Extra annotations applied to the wallet pod. | +| `wallet.useSVE` | bool | `false` | Disables SVE CPU instructions via `JAVA_TOOL_OPTIONS`. Enable on SVE-capable nodes if the JVM crashes with illegal instruction errors. | +| `wallet.debug.enabled` | bool | `false` | Enables the JDWP remote debug socket. Never use in production. | +| `wallet.debug.port` | int | `1045` | JDWP listen port inside the container. | +| `wallet.debug.suspendOnStart` | bool | `false` | If `true`, the JVM suspends until a debugger connects. | +| `wallet.hostname` | string | `wallet.staging.construct-x.net` | Public hostname. Used in `did:web` URLs and ingress routing. | +| `wallet.superuser.createSecret` | bool | `true` | Creates a Kubernetes Secret from the values below and mounts it via `envFrom`. Set to `false` and reference an external secret via `envSecretNames` instead. | +| `wallet.superuser.id` | string | `admin` | Participant context ID of the super-user. | +| `wallet.superuser.apiKey` | string | `YWRtaW4.adminKey` | API key for the super-user. Format: `base64().`. **Change before production use.** | +| `wallet.superuser.publicKeyAlias` | string | `admin#pubkey` | Vault alias for the super-user RSA public key. Generated by the wallet on first start. | +| `wallet.superuser.privateKeyAlias` | string | `admin#privkey` | Vault alias for the super-user RSA private key. Generated by the wallet on first start. | +| `wallet.didweb.https` | bool | `true` | Use `https://` in `did:web` URLs. Set to `false` only for local testing. | +| `wallet.env` | object | `{}` | Extra plain environment variables injected into the wallet pod. | +| `wallet.envValueFrom` | object | `{}` | Extra environment variables sourced from ConfigMaps or Secrets via `valueFrom`. | +| `wallet.envSecretNames` | list | `[]` | Names of existing Secrets whose keys are mounted as environment variables via `envFrom`. | +| `wallet.envConfigMapNames` | list | `[]` | Names of existing ConfigMaps whose keys are mounted as environment variables via `envFrom`. | +| `wallet.replicaCount` | int | `1` | Number of wallet pod replicas. | +| `wallet.resources.limits.cpu` | string | `500m` | CPU limit for the wallet container. | +| `wallet.resources.limits.memory` | string | `512Mi` | Memory limit for the wallet container. | +| `wallet.resources.requests.cpu` | string | `250m` | CPU request for the wallet container. | +| `wallet.resources.requests.memory` | string | `128Mi` | Memory request for the wallet container. | +| `wallet.autoscaling.enabled` | bool | `false` | Enables Horizontal Pod Autoscaling. | +| `wallet.autoscaling.minReplicas` | int | `1` | Minimum number of replicas under HPA. | +| `wallet.autoscaling.maxReplicas` | int | `100` | Maximum number of replicas under HPA. | +| `wallet.autoscaling.targetCPUUtilizationPercentage` | int | `80` | CPU utilisation target for HPA scale-out. | +| `wallet.autoscaling.targetMemoryUtilizationPercentage` | int | `80` | Memory utilisation target for HPA scale-out. | +| `wallet.nodeSelector` | object | `{}` | Node selector constraints for the wallet pod. | +| `wallet.tolerations` | list | `[]` | Tolerations for the wallet pod. | +| `wallet.affinity` | object | `{}` | Affinity rules for the wallet pod. | +| `wallet.volumeMounts` | list | `[]` | Additional volume mounts for the wallet container. | +| `wallet.volumes` | list | `[]` | Additional volumes for the wallet pod. | + +### `wallet.endpoints` + +Each endpoint creates a Kubernetes Service port and injects the corresponding `WEB_HTTP_*` environment variables into the wallet. Only endpoints listed under an ingress' `endpoints` array are exposed externally. + +| Key | Default port | Default path | Description | +|---|---|---|---| +| `wallet.endpoints.default` | `8181` | `/api` | Observability endpoint (health checks). Must not be added to public ingresses. | +| `wallet.endpoints.identity` | `15151` | `/api/identity` | Management API. Protected by `X-Api-Key`. Must not be internet-facing. | +| `wallet.endpoints.identity.authKeyAlias` | `sup3r$3cr3t` | — | Vault alias whose stored value is validated against the `X-Api-Key` request header. | +| `wallet.endpoints.credentials` | `13131` | `/api/credentials` | DCP Credential Offer and Presentation API. Public-facing in DCP flows. | +| `wallet.endpoints.did` | `80` | `/` | DID document service. Resolves `did:web` documents. Must be publicly reachable. | +| `wallet.endpoints.sts` | `9292` | `/api/sts` | Secure Token Service. Issues self-signed ID tokens for DCP flows. Public-facing. | + +### `wallet.livenessProbe` / `wallet.readinessProbe` + +Both probes call `GET /check/liveness` and `GET /check/readiness` on the `default` endpoint port. + +| Key | Type | Default | Description | +|---|---|---|---| +| `*.enabled` | bool | `true` | Whether the probe is active. | +| `*.initialDelaySeconds` | int | `5` | Seconds before the first probe fires. Increase to 30+ on slow cold starts. | +| `*.periodSeconds` | int | `5` | Interval between probes. | +| `*.timeoutSeconds` | int | `5` | Seconds before a probe attempt times out. | +| `*.failureThreshold` | int | `6` | Consecutive failures before the pod is restarted or marked not-ready. | +| `*.successThreshold` | int | `1` | Consecutive successes to transition back to healthy. | + +### `wallet.service` + +| Key | Type | Default | Description | +|---|---|---|---| +| `wallet.service.type` | string | `ClusterIP` | Kubernetes Service type. `ClusterIP` is recommended when an ingress or Istio gateway is used. | +| `wallet.service.annotations` | object | `{}` | Annotations added to the Service resource. | + +### `wallet.ingresses` + +A list of Ingress definitions. Each entry creates one Ingress resource routing the listed endpoints. The chart ships two pre-configured entries (public and internal). Only entries with `enabled: true` are rendered. + +| Key | Type | Description | +|---|---|---| +| `*.enabled` | bool | Render this Ingress resource. | +| `*.hostname` | string | Hostname for all routes in this Ingress. | +| `*.annotations` | object | Annotations added to the Ingress (e.g. cert-manager, external-dns). | +| `*.endpoints` | list | Names of `wallet.endpoints` keys to expose via this Ingress. | +| `*.className` | string | Ingress class name (e.g. `nginx`, `traefik`). | +| `*.tls.enabled` | bool | Attach a TLS block to this Ingress. | +| `*.tls.secretName` | string | Name of the Secret holding the TLS certificate. | +| `*.certManager.issuer` | string | cert-manager namespace-scoped issuer. | +| `*.certManager.clusterIssuer` | string | cert-manager cluster-scoped issuer. | + +### `serviceAccount` + +| Key | Type | Default | Description | +|---|---|---|---| +| `serviceAccount.create` | bool | `true` | Create a dedicated ServiceAccount for the wallet and vault-init job. | +| `serviceAccount.automount` | bool | `true` | Automatically mount the ServiceAccount token into pods. | +| `serviceAccount.annotations` | object | `{}` | Annotations added to the ServiceAccount (e.g. for Vault Kubernetes auth). | +| `serviceAccount.name` | string | `""` | Override the generated ServiceAccount name. | + +### `postgresql` + +The chart uses the Bitnami legacy PostgreSQL sub-chart. + +| Key | Type | Default | Description | +|---|---|---|---| +| `postgresql.jdbcUrl` | string | `jdbc:postgresql://wallet-postgresql:5432/wallet` | JDBC URL passed to the wallet. | +| `postgresql.auth.database` | string | `wallet` | Database name created on first start. | +| `postgresql.auth.username` | string | `user` | Database user the wallet connects as. | +| `postgresql.auth.password` | string | `password` | Database password. **Change before production use.** | +| `postgresql.persistence.enabled` | bool | `true` | Persist primary node data. Disable only for throwaway test environments. | +| `postgresql.persistence.size` | string | `10Gi` | Size of allocated Persistent Volume. | +| `postgresql.persistence.storageClass` | string | `""` | Storage Class of used Storage Provisioner. | +| `postgresql.initdb.scriptsConfigMap` | string | `""` | Name of ConfigMap for Database Initialization. | + +### `vault` + +| Key | Type | Default | Description | +|---|---|---|---| +| `vault.injector.enabled` | bool | `false` | Vault Agent Injector sidecar. Disabled — the wallet reads secrets directly via the Vault HTTP API. | +| `vault.server.dev.enabled` | bool | `true` | Run Vault in dev mode (in-memory, no persistence). **Disable for production.** | +| `vault.server.dev.devRootToken` | string | `root` | Root token for dev mode. Must match `vault.hashicorp.token`. | +| `vault.server.postStart` | string | `nil` | Optional post-start script executed inside the Vault container. Must be set externally. | +| `vault.hashicorp.url` | string | `http://wallet-vault:8200` | Vault address reachable from within the cluster. | +| `vault.hashicorp.token` | string | `root` | Vault token used by the wallet at runtime. **Change before production use.** | +| `vault.hashicorp.timeout` | int | `30` | Vault HTTP client timeout in seconds. | +| `vault.hashicorp.healthCheck.enabled` | bool | `true` | Whether the wallet checks Vault health on startup. | +| `vault.hashicorp.healthCheck.standbyOk` | bool | `true` | Treat Vault HA standby nodes as healthy. | +| `vault.hashicorp.paths.secret` | string | `/v1/secret` | Mount path for all wallet secrets. | +| `vault.hashicorp.paths.health` | string | `/v1/sys/health` | Vault health endpoint polled by the wallet and vault-init job. | +| `vault.hashicorp.init.enabled` | bool | `true` | Run the post-install vault-init job that seeds required Vault secrets. | +| `vault.hashicorp.init.aesKeyAlias` | string | `wallet-aes-key-alias` | Vault alias for the AES-256 encryption key. | + +## Sources + +- Code: [Construct-X Wallet](https://github.com/project-construct-x/wallet) +- Chart: [Tractus-X IdentityHub](https://github.com/eclipse-tractusx/tractusx-identityhub) \ No newline at end of file diff --git a/helm/wallet/templates/NOTES.txt b/helm/wallet/templates/NOTES.txt new file mode 100644 index 0000000..0c643f6 --- /dev/null +++ b/helm/wallet/templates/NOTES.txt @@ -0,0 +1,88 @@ +{{- $fullName := include "wallet.fullname" . -}} +{{- $namespace := .Release.Namespace -}} +================================================================================ + Construct-X Wallet "{{ .Release.Name }}" — installation complete +================================================================================ + + Chart version : {{ .Chart.Version }} + App version : {{ .Chart.AppVersion }} + Namespace : {{ $namespace }} + Release : {{ .Release.Name }} + +================================================================================ + Public endpoints +================================================================================ +{{- $ingressShown := false }} +{{- range .Values.wallet.ingresses }} + {{- if .enabled }} + {{- $ingressShown = true }} + {{- $proto := "http" }} + {{- if .tls.enabled }}{{ $proto = "https" }}{{ end }} + + Ingress on {{ .hostname }} (className: {{ .className | default "default" }}) + {{- range .endpoints }} + {{- $ep := index $.Values.wallet.endpoints . }} + {{- if $ep }} + {{ printf "%-15s" . }} {{ $proto }}://{{ index $.Values.wallet.ingresses 0 "hostname" }}{{ $ep.path }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- if not $ingressShown }} + No ingress is enabled. Endpoints are reachable inside the cluster only: + + kubectl port-forward -n {{ $namespace }} svc/{{ $fullName }} \ + {{- range $name, $ep := .Values.wallet.endpoints }} + {{ $ep.port }}:{{ $ep.port }} {{- end }} + + Then locally: + {{- range $name, $ep := .Values.wallet.endpoints }} + {{ printf "%-15s" $name }} http://localhost:{{ $ep.port }}{{ $ep.path }} + {{- end }} +{{- end }} + +{{- if eq .Values.wallet.superuser.createSecret true }} +================================================================================ + Super-User participant +================================================================================ + + The wallet auto-seeds a super-user on first start: + Participant ID : {{ .Values.wallet.superuser.id }} + API key : {{ .Values.wallet.superuser.apiKey }} + Public key alias: {{ .Values.wallet.superuser.publicKeyAlias }} + Private key alias: {{ .Values.wallet.superuser.privateKeyAlias }} + + If you reinstall while keeping PostgreSQL persistence, the participant context + remains and the seed is skipped. Wipe with: + kubectl exec -n {{ $namespace }} -it \ + $(kubectl get pod -n {{ $namespace }} -l app.kubernetes.io/name=postgresql -o name | head -1) -- \ + psql -U {{ .Values.postgresql.auth.username }} -d {{ .Values.postgresql.auth.database }} \ + -c "DELETE FROM participant_context WHERE participant_context_id = '{{ .Values.wallet.superuser.id }}';" + kubectl rollout restart -n {{ $namespace }} deploy/{{ $fullName }} + + {{- if eq (default "YWRtaW4.adminKey" .Values.wallet.superuser.apiKey) "YWRtaW4.adminKey" }} + + ⚠ WARNING: Super-User Extension is using the default API key. Change wallet.superuser.apiKey + before production use. + {{- end }} +{{- end }} +================================================================================ +{{- if not .Values.wallet.didweb.https }} + + ⚠ WARNING: didweb.https is set to false. did:web URLs will use HTTP. + This is only acceptable for local testing — switch to true before going public. +{{- end }} +{{- if eq .Values.vault.server.dev.enabled true }} + + ⚠ WARNING: Vault is running in dev mode. All secrets are lost on pod restart. + For production, set vault.server.dev.enabled=false and configure persistence. +{{- end }} +{{- if eq (default "root" .Values.vault.hashicorp.token) "root" }} + + ⚠ WARNING: vault.hashicorp.token is set to "root" (dev-mode default). Change vault.hashicorp.token before production use. +{{- end }} +{{- if eq (default "password" .Values.postgresql.auth.password) "password" }} + + ⚠ WARNING: PostgreSQL is using the default password. Change postgresql.auth.password + before production use. +{{- end }} diff --git a/helm/wallet/templates/_helpers.tpl b/helm/wallet/templates/_helpers.tpl new file mode 100644 index 0000000..9ef69aa --- /dev/null +++ b/helm/wallet/templates/_helpers.tpl @@ -0,0 +1,86 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "wallet.name" -}} +{{- default .Chart.Name .Values.nameOverride | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "wallet.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "wallet.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Control Common labels +*/}} +{{- define "wallet.labels" -}} +helm.sh/chart: {{ include "wallet.chart" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Control Common Server labels +*/}} +{{- define "wallet.server.labels" -}} +helm.sh/chart: {{ include "wallet.chart" . }} +{{ include "wallet.server.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: wallet-server +app.kubernetes.io/part-of: wallet +{{- end }} + +{{/* +Control Selector labels +*/}} +{{- define "wallet.server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "wallet.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "wallet.server.serviceaccount.name" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "wallet.fullname" . ) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "wallet.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "wallet.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/wallet/templates/configmap-datasource.yaml b/helm/wallet/templates/configmap-datasource.yaml new file mode 100644 index 0000000..55586b9 --- /dev/null +++ b/helm/wallet/templates/configmap-datasource.yaml @@ -0,0 +1,41 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +# this configmap contains all database configuration that is required by the wallet runtime. + +{{ $fullName := .Values.fullnameOverride -}} +{{- $postgresql := index .Values "postgresql" | default dict }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $fullName }}-datasource-config + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "wallet.labels" . | nindent 4 }} +data: + + ################ + ## POSTGRESQL ## + ################ + + # default + EDC_SQL_SCHEMA_AUTOCREATE: {{ $postgresql.schemaAutocreate | default true | quote }} + EDC_DATASOURCE_DEFAULT_URL: {{ tpl .Values.postgresql.jdbcUrl . | quote }} diff --git a/helm/wallet/templates/configmap-runtime.yaml b/helm/wallet/templates/configmap-runtime.yaml new file mode 100644 index 0000000..7399483 --- /dev/null +++ b/helm/wallet/templates/configmap-runtime.yaml @@ -0,0 +1,73 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +# this configmap contains all application configuration that is required by the wallet runtime. + +{{ $fullName := .Values.fullnameOverride -}} +{{- $iam := index .Values "wallet" "iam" | default dict }} +{{- $issuer := index .Values "wallet" "issuer" | default dict }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $fullName }}-config + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "wallet.labels" . | nindent 4 }} +data: + ####### + # API # + ####### + EDC_HOSTNAME: {{ .Values.wallet.hostname | quote }} + WEB_HTTP_PORT: {{ .Values.wallet.endpoints.default.port | quote }} + WEB_HTTP_PATH: {{ .Values.wallet.endpoints.default.path | quote }} + WEB_HTTP_IDENTITY_PORT: {{ .Values.wallet.endpoints.identity.port | quote }} + WEB_HTTP_IDENTITY_PATH: {{ .Values.wallet.endpoints.identity.path | quote }} + WEB_HTTP_IDENTITY_AUTH_ALIAS: {{ .Values.wallet.endpoints.identity.authKeyAlias | required ".Values.wallet.endpoints.identity.authKeyAlias is required" | quote }} + WEB_HTTP_CREDENTIALS_PORT: {{ .Values.wallet.endpoints.credentials.port | quote }} + WEB_HTTP_CREDENTIALS_PATH: {{ .Values.wallet.endpoints.credentials.path | quote }} + WEB_HTTP_DID_PORT: {{ .Values.wallet.endpoints.did.port | quote }} + WEB_HTTP_DID_PATH: {{ .Values.wallet.endpoints.did.path | quote }} + WEB_HTTP_STS_PORT: {{ .Values.wallet.endpoints.sts.port | quote}} + WEB_HTTP_STS_PATH: {{ .Values.wallet.endpoints.sts.path | quote}} + + #################### + ## IAM/DID/Issuer ## + #################### + EDC_IAM_DID_WEB_USE_HTTPS: {{ .Values.wallet.didweb.https | quote }} + EDC_IAM_KEY_ALGORITHM: {{ $iam.keyAlgorithm | default "RSA" | quote }} + EDC_IAM_CREDENTIAL_RENEWAL_GRACEPERIOD: {{ $iam.renewalGraceperiod | default "172800" | quote }} + EDC_ISSUER_ISSUANCE_SEND_RETRY_LIMIT: {{ $issuer.sendRetryLimit | default "0" | quote }} + + ########### + ## VAULT ## + ########### + EDC_VAULT_HASHICORP_URL: {{ tpl .Values.vault.hashicorp.url . | quote }} + EDC_VAULT_HASHICORP_TIMEOUT_SECONDS: {{ .Values.vault.hashicorp.timeout | quote }} + EDC_VAULT_HASHICORP_HEALTH_CHECK_ENABLED: {{ .Values.vault.hashicorp.healthCheck.enabled | quote }} + EDC_VAULT_HASHICORP_HEALTH_CHECK_STANDBY_OK: {{ .Values.vault.hashicorp.healthCheck.standbyOk | quote }} + EDC_VAULT_HASHICORP_API_SECRET_PATH: {{ .Values.vault.hashicorp.paths.secret | quote }} + EDC_VAULT_HASHICORP_API_HEALTH_CHECK_PATH: {{ .Values.vault.hashicorp.paths.health | quote }} + + ################# + ## Encryption ## + ################# + EDC_ENCRYPTION_AES_KEY_ALIAS: {{ .Values.vault.hashicorp.init.aesKeyAlias | default "wallet-aes-key-alias" | quote }} + EDC_ISSUER_STATUSLIST_SIGNING_KEY_ALIAS: {{ $issuer.statuslistSigningKeyAlias | default "foo" | quote }} \ No newline at end of file diff --git a/helm/wallet/templates/configmap-vault-init.yaml b/helm/wallet/templates/configmap-vault-init.yaml new file mode 100644 index 0000000..a2c9d9d --- /dev/null +++ b/helm/wallet/templates/configmap-vault-init.yaml @@ -0,0 +1,140 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +# this configmap contains the initialization script to generate and store aes and rsa keys into the vault. + +{{ if .Values.vault.hashicorp.init.enabled }} +{{- $fullName := .Values.fullnameOverride -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $fullName }}-vault-init + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "wallet.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +data: + init.sh: | + #!/usr/bin/env sh + set -eu + + VAULT="${VAULT_ADDR:?VAULT_ADDR is required}" + TOKEN="${VAULT_TOKEN:?VAULT_TOKEN is required}" + FORCE="${FORCE_REGENERATE:-false}" + SECRETS="${VAULT_SECRET_PATH:-/v1/secret}" + HEALTH="${VAULT_HEALTH_PATH:-/v1/sys/health}" + + AES_ALIAS="${AES_KEY_ALIAS:-}" + PRIV_ALIAS="${PRIVATE_KEY_ALIAS:-}" + PUB_ALIAS="${PUBLIC_KEY_ALIAS:-}" + + log() { echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*" >&2; } + + # Check provided Aliases for plausibility (AES or RSA pair must be requested) + if [ -z "$AES_ALIAS" ] && [ -z "$PRIV_ALIAS" ] && [ -z "$PUB_ALIAS" ]; then + log "ERROR: no alias provided. Set AES_KEY_ALIAS and/or PRIVATE_KEY_ALIAS+PUBLIC_KEY_ALIAS." + exit 1 + fi + if { [ -n "$PRIV_ALIAS" ] && [ -z "$PUB_ALIAS" ]; } || \ + { [ -z "$PRIV_ALIAS" ] && [ -n "$PUB_ALIAS" ]; }; then + log "ERROR: RSA generation requires BOTH PRIVATE_KEY_ALIAS and PUBLIC_KEY_ALIAS." + exit 1 + fi + + # Install required tools + if ! command -v openssl >/dev/null 2>&1 \ + || ! command -v curl >/dev/null 2>&1 \ + || ! command -v jq >/dev/null 2>&1; then + log "Installing curl, jq, openssl..." + apk add --no-cache curl jq openssl >/dev/null + fi + + log "Waiting for Vault at $VAULT$HEALTH..." + i=0 + until curl -fsS --connect-timeout 2 --max-time 5 "$VAULT$HEALTH" >/dev/null 2>&1; do + i=$((i+1)) + [ "$i" -gt 60 ] && { log "Vault not ready after 60 attempts."; exit 1; } + sleep 3 + done + log "Vault ready." + + # Check for existing Secret + secret_exists() { + [ "$(curl -sS -o /dev/null -w "%{http_code}" \ + -H "X-Vault-Token: $TOKEN" \ + "$VAULT$SECRETS/data/$1")" = "200" ] + } + + # Store Secret in Vault + put_secret() { + local alias="$1" payload="$2" + local code + code=$(printf '%s' "$payload" | curl -sS -o /dev/null -w "%{http_code}" \ + -H "X-Vault-Token: $TOKEN" \ + -H "Content-Type: application/json" \ + -X POST --data-binary @- \ + "$VAULT$SECRETS/data/$alias") + if [ "$code" != "200" ] && [ "$code" != "204" ]; then + log "Failed to store '$alias' (HTTP $code)" + exit 1 + fi + } + + # Generate AES Key + if [ -n "$AES_ALIAS" ]; then + if [ "$FORCE" != "true" ] && secret_exists "$AES_ALIAS"; then + log "AES key '$AES_ALIAS' already present — skipping." + else + log "Generating AES-256 key for '$AES_ALIAS'..." + key=$(openssl rand -base64 32 | tr -d '\n') + payload=$(jq -n --arg content "$key" '{data:{content:$content}}') + put_secret "$AES_ALIAS" "$payload" + log "AES key stored at $VAULT$SECRETS/data/$AES_ALIAS" + fi + fi + + # Generate RSA Keypair + if [ -n "$PRIV_ALIAS" ] && [ -n "$PUB_ALIAS" ]; then + if [ "$FORCE" != "true" ] \ + && secret_exists "$PRIV_ALIAS" \ + && secret_exists "$PUB_ALIAS"; then + log "RSA keypair ('$PRIV_ALIAS' / '$PUB_ALIAS') already present — skipping." + else + log "Generating RSA keypair ('$PRIV_ALIAS' / '$PUB_ALIAS')..." + umask 077 + dir=$(mktemp -d) + openssl genrsa -out "$dir/k.pem" 2048 2>/dev/null + openssl pkcs8 -topk8 -nocrypt -in "$dir/k.pem" -out "$dir/priv.pem" + openssl rsa -in "$dir/k.pem" -pubout -out "$dir/pub.pem" 2>/dev/null + + put_secret "$PRIV_ALIAS" \ + "$(jq -n --rawfile content "$dir/priv.pem" '{data:{content:$content}}')" + put_secret "$PUB_ALIAS" \ + "$(jq -n --rawfile content "$dir/pub.pem" '{data:{content:$content}}')" + + rm -rf "$dir" + log "RSA keypair stored at $VAULT$SECRETS/data/{$PRIV_ALIAS,$PUB_ALIAS}" + fi + fi + + log "Vault initialization complete." +{{- end }} diff --git a/helm/wallet/templates/deployment.yaml b/helm/wallet/templates/deployment.yaml new file mode 100644 index 0000000..7d086f4 --- /dev/null +++ b/helm/wallet/templates/deployment.yaml @@ -0,0 +1,206 @@ +# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 LKS Next +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +{{ $fullName := .Values.fullnameOverride -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "wallet.fullname" . }} + labels: + {{- include "wallet.server.labels" . | nindent 4 }} +spec: + {{- if not .Values.wallet.autoscaling.enabled }} + replicas: {{ .Values.wallet.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "wallet.server.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.wallet.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "wallet.server.selectorLabels" . | nindent 8 }} + {{- with .Values.wallet.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "wallet.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.wallet.podSecurityContext | nindent 8 }} + {{- if or .Values.wallet.initContainers .Values.customCaCerts }} + initContainers: + {{- if .Values.wallet.initContainers }} + {{- toYaml .Values.wallet.initContainers | nindent 8 }} + {{- end }} + {{- if .Values.customCaCerts }} + - name: custom-cacerts + # either use the specified image, or use the default one + {{- if .Values.wallet.image.repository }} + image: "{{ .Values.wallet.image.repository }}:{{ .Values.wallet.image.tag | default .Chart.AppVersion }}" + {{- else }} + image: "ghcr.io/project-construct-x/wallet:{{ .Values.wallet.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.wallet.image.pullPolicy }} + command: + - /bin/sh + - -c + - | + cp /opt/java/openjdk/lib/security/cacerts /workdir/ + find /cacerts -type f \( -iname \*.crt -o -iname \*.pem \) -exec echo "{}" \; | while read PEM_FILE_PATH; do + PEM_FILE=${PEM_FILE_PATH##*/} + ALIAS=${PEM_FILE%.*} + echo "adding ${PEM_FILE} with alias ${ALIAS} to cacerts ..." + keytool -import -noprompt -trustcacerts -alias ${ALIAS} -file ${PEM_FILE_PATH} -keystore /workdir/cacerts -storepass changeit + done + securityContext: + {{- toYaml .Values.wallet.securityContext | nindent 12 }} + volumeMounts: + - name: custom-cacertificates + mountPath: /cacerts + - name: custom-cacerts + mountPath: /workdir + {{- end }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.wallet.securityContext | nindent 12 }} + # either use the specified image, or use the default one + {{- if .Values.wallet.image.repository }} + image: "{{ .Values.wallet.image.repository }}:{{ .Values.wallet.image.tag | default .Chart.AppVersion }}" + {{- else }} + image: "ghcr.io/project-construct-x/wallet:{{ .Values.wallet.image.tag | default .Chart.AppVersion }}" + {{- end }} + + imagePullPolicy: {{ .Values.wallet.image.pullPolicy }} + ports: + {{- range $key,$value := .Values.wallet.endpoints }} + - name: {{ $key }} + containerPort: {{ $value.port }} + protocol: TCP + {{- end }} + {{- if .Values.wallet.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.wallet.endpoints.default.path }}/check/liveness + port: {{ .Values.wallet.endpoints.default.port }} + initialDelaySeconds: {{ .Values.wallet.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.wallet.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.wallet.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.wallet.livenessProbe.failureThreshold }} + successThreshold: {{ .Values.wallet.livenessProbe.successThreshold }} + {{- end }} + {{- if .Values.wallet.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.wallet.endpoints.default.path }}/check/readiness + port: {{ .Values.wallet.endpoints.default.port }} + initialDelaySeconds: {{ .Values.wallet.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.wallet.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.wallet.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.wallet.readinessProbe.failureThreshold }} + successThreshold: {{ .Values.wallet.readinessProbe.successThreshold }} + {{- end }} + resources: + {{- toYaml .Values.wallet.resources | nindent 12 }} + env: + {{- if .Values.wallet.debug.enabled }} + - name: "JAVA_TOOL_OPTIONS" + {{- if .Values.wallet.debug.suspendOnStart }} + value: >- + {{ printf "%s-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=%v" (ternary "-XX:UseSVE=0 " "" .Values.wallet.useSVE) .Values.wallet.debug.port}} + {{- else }} + value: >- + {{ printf "%s-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=%v" (ternary "-XX:UseSVE=0 " "" .Values.wallet.useSVE) .Values.wallet.debug.port}} + {{- end }} + {{- end }} + {{- range $key, $value := .Values.wallet.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 16 }} + {{- end }} + {{- range $key, $value := .Values.wallet.env }} + - name: {{ $key | quote }} + value: {{ $value | quote }} + {{- end }} + envFrom: + - configMapRef: + name: {{ $fullName }}-config + - configMapRef: + name: {{ $fullName }}-datasource-config + - secretRef: + name: {{ $fullName }}-datasource-credentials + {{- if .Values.wallet.superuser.createSecret }} + - secretRef: + name: {{ $fullName }}-superuser-credentials + {{- end }} + {{- if and (or .Values.wallet.envSecretNames .Values.wallet.envConfigMapNames) (or (gt (len .Values.wallet.envSecretNames) 0) (gt (len .Values.wallet.envConfigMapNames) 0)) }} + {{- range $value := .Values.wallet.envSecretNames }} + - secretRef: + name: {{ $value | quote }} + {{- end }} + {{- range $value := .Values.wallet.envConfigMapNames }} + - configMapRef: + name: {{ printf "%s-%s" $fullName $value | quote }} + {{- end }} + {{- end }} + volumeMounts: + {{- if .Values.customCaCerts }} + - name: custom-cacerts + mountPath: /opt/java/openjdk/lib/security/cacerts + subPath: cacerts + {{- end }} + - name: "tmp" + mountPath: "/tmp" + volumes: + - name: "configuration" + configMap: + {{- if .Values.customCaCerts }} + - name: custom-cacertificates + configMap: + name: {{ include "wallet.fullname" . }}-custom-cacerts + defaultMode: 0400 + - name: custom-cacerts + emptyDir: + sizeLimit: 1Mi + {{- end }} + - name: "tmp" + emptyDir: { } + {{- with .Values.wallet.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.wallet.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.wallet.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/wallet/templates/hpa.yaml b/helm/wallet/templates/hpa.yaml new file mode 100644 index 0000000..fbb75d1 --- /dev/null +++ b/helm/wallet/templates/hpa.yaml @@ -0,0 +1,50 @@ +################################################################################# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ if .Values.wallet.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "wallet.fullname" . }} + labels: + {{- include "wallet.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "wallet.fullname" . }} + minReplicas: {{ .Values.wallet.autoscaling.minReplicas }} + maxReplicas: {{ .Values.wallet.autoscaling.maxReplicas }} + metrics: + {{- if .Values.wallet.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + averageUtilization: {{ .Values.wallet.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.wallet.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + averageUtilization: {{ .Values.wallet.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/wallet/templates/ingress.yaml b/helm/wallet/templates/ingress.yaml new file mode 100644 index 0000000..0822306 --- /dev/null +++ b/helm/wallet/templates/ingress.yaml @@ -0,0 +1,98 @@ +################################################################################# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ $fullName := include "wallet.fullname" . }} +{{- $controlLabels := include "wallet.server.labels" . }} +{{- $controlEdcEndpoints := .Values.wallet.endpoints }} +{{- $gitVersion := .Capabilities.KubeVersion.GitVersion }} +{{- $namespace := .Release.Namespace }} + +{{- range .Values.wallet.ingresses }} +{{- if and .enabled .endpoints }} +{{- $controlIngressName := printf "%s-%s" $fullName .hostname }} +{{- $annotations := .annotations | default dict }} + +{{- if semverCompare ">=1.19-0" $gitVersion }} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" $gitVersion }} +apiVersion: networking.k8s.io/v1beta1 +{{- else }} +apiVersion: extensions/v1beta +{{- end }} +kind: Ingress +metadata: + name: {{ $controlIngressName }} + namespace: {{ $namespace | default "default" | quote }} + labels: + {{- $controlLabels | nindent 4 }} + annotations: + {{- if and .className (not (semverCompare ">=1.18-0" $gitVersion)) }} + {{- if not (hasKey $annotations "kubernetes.io/ingress.class") }} + {{- $_ := set $annotations "kubernetes.io/ingress.class" .className}} + {{- end }} + {{- end }} + {{- if .certManager }} + {{- if .certManager.issuer }} + {{- $_ := set $annotations "cert-manager.io/issuer" .certManager.issuer}} + {{- end }} + {{- if .certManager.clusterIssuer }} + {{- $_ := set $annotations "cert-manager.io/cluster-issuer" .certManager.clusterIssuer}} + {{- end }} + {{- end }} + {{- with $annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .className (semverCompare ">=1.18-0" $gitVersion) }} + ingressClassName: {{ .className }} + {{- end }} + {{- if .hostname }} + {{- if .tls.enabled }} + tls: + - hosts: + - {{ .hostname }} + {{- if .tls.secretName }} + secretName: {{ .tls.secretName }} + {{- else }} + secretName: {{ $controlIngressName }}-tls + {{- end }} + {{- end }} + rules: + - host: {{ .hostname }} + http: + paths: + {{- $ingressEdcEndpoints := .endpoints }} + {{- range $name, $mapping := $controlEdcEndpoints }} + {{- if (has $name $ingressEdcEndpoints) }} + - path: {{ $mapping.path }} + pathType: {{ $mapping.pathType | default "Prefix" }} + backend: + {{- if semverCompare ">=1.19-0" $gitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $mapping.port }} + {{- else }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} +{{- end }}{{- /* end: if .enabled */}} +{{- end }}{{- /* end: range .Values.ingresses */}} diff --git a/helm/wallet/templates/job-vault-init.yaml b/helm/wallet/templates/job-vault-init.yaml new file mode 100644 index 0000000..59d7a6d --- /dev/null +++ b/helm/wallet/templates/job-vault-init.yaml @@ -0,0 +1,87 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ if .Values.vault.hashicorp.init.enabled -}} +{{- $fullName := .Values.fullnameOverride -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ $fullName }}-vault-init + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "wallet.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "0" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + backoffLimit: 3 + ttlSecondsAfterFinished: 600 + activeDeadlineSeconds: 300 + template: + metadata: + labels: + {{- include "wallet.labels" . | nindent 8 }} + spec: + restartPolicy: OnFailure + serviceAccountName: {{ include "wallet.serviceAccountName" . }} + containers: + - name: vault-init + {{- $img := index .Values "vault" "hashicorp" "init" "image" | default dict }} + image: {{ $img.repository | default "alpine" }}:{{ $img.tag | default "3.20" }} + command: ["/bin/sh", "-c"] + args: + - | + tr -d '\r' < /scripts/init.sh > /tmp/init.sh + exec sh /tmp/init.sh + env: + - name: VAULT_ADDR + value: {{ tpl .Values.vault.hashicorp.url . | quote }} + - name: VAULT_TOKEN + value: {{ .Values.vault.hashicorp.token | required "vault.hashicorp.token is required" }} + - name: VAULT_SECRET_PATH + value: {{ .Values.vault.hashicorp.paths.secret | quote }} + - name: VAULT_HEALTH_PATH + value: {{ .Values.vault.hashicorp.paths.health | quote }} + {{- with .Values.vault.hashicorp.init.forceRegenerate }} + - name: FORCE_REGENERATE + value: {{ . | quote }} + {{- end }} + {{- with .Values.vault.hashicorp.init.aesKeyAlias }} + - name: AES_KEY_ALIAS + value: {{ . | quote }} + {{- end }} + {{- with .Values.vault.hashicorp.init.privateKeyAlias }} + - name: PRIVATE_KEY_ALIAS + value: {{ . | quote }} + {{- end }} + {{- with .Values.vault.hashicorp.init.publicKeyAlias }} + - name: PUBLIC_KEY_ALIAS + value: {{ . | quote }} + {{- end }} + volumeMounts: + - name: script + mountPath: /scripts + readOnly: true + volumes: + - name: script + configMap: + name: {{ $fullName }}-vault-init + defaultMode: 0555 +{{- end }} diff --git a/helm/wallet/templates/secret-datasource.yaml b/helm/wallet/templates/secret-datasource.yaml new file mode 100644 index 0000000..cb17f23 --- /dev/null +++ b/helm/wallet/templates/secret-datasource.yaml @@ -0,0 +1,42 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ $fullName := .Values.fullnameOverride -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $fullName }}-datasource-credentials + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "wallet.labels" . | nindent 4 }} +type: Opaque +stringData: + + ################ + ## POSTGRESQL ## + ################ + + # default + EDC_DATASOURCE_DEFAULT_USER: {{ .Values.postgresql.auth.username | quote }} + EDC_DATASOURCE_DEFAULT_PASSWORD: {{ .Values.postgresql.auth.password | quote }} + + ########### + ## VAULT ## + ########### + EDC_VAULT_HASHICORP_TOKEN: {{ .Values.vault.hashicorp.token | required ".Values.vault.hashicorp.token is required" | quote }} diff --git a/helm/wallet/templates/secret-runtime.yaml b/helm/wallet/templates/secret-runtime.yaml new file mode 100644 index 0000000..46a080b --- /dev/null +++ b/helm/wallet/templates/secret-runtime.yaml @@ -0,0 +1,38 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ if .Values.wallet.superuser.createSecret -}} +{{- $fullName := .Values.fullnameOverride -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $fullName }}-superuser-credentials + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "wallet.labels" . | nindent 4 }} +type: Opaque +stringData: + ################ + ## Super-User ## + ################ + EDC_IH_API_SUPERUSER_ID: {{ .Values.wallet.superuser.id | quote }} + EDC_IH_API_KEY_SUPERUSER: {{ .Values.wallet.superuser.apiKey | quote }} + EDC_IH_API_SUPERUSER_PUBLIC_KEY_ALIAS: {{ .Values.wallet.superuser.publicKeyAlias | quote }} + EDC_IH_API_SUPERUSER_PRIVATE_KEY_ALIAS: {{ .Values.wallet.superuser.privateKeyAlias | quote }} +{{- end -}} \ No newline at end of file diff --git a/helm/wallet/templates/service.yaml b/helm/wallet/templates/service.yaml new file mode 100644 index 0000000..bbc5143 --- /dev/null +++ b/helm/wallet/templates/service.yaml @@ -0,0 +1,52 @@ +# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "wallet.fullname" . }} + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "wallet.server.labels" . | nindent 4 }} +spec: + type: {{ .Values.wallet.service.type }} + ports: + - port: {{ .Values.wallet.endpoints.default.port }} + targetPort: default + protocol: TCP + name: default + - port: {{ .Values.wallet.endpoints.identity.port }} + targetPort: identity + protocol: TCP + name: identity + - port: {{ .Values.wallet.endpoints.credentials.port }} + targetPort: credentials + protocol: TCP + name: credentials + - port: {{ .Values.wallet.endpoints.did.port }} + targetPort: did + protocol: TCP + name: did + - port: {{ .Values.wallet.endpoints.sts.port }} + targetPort: sts + protocol: TCP + name: sts + selector: + {{- include "wallet.server.selectorLabels" . | nindent 4 }} diff --git a/helm/wallet/templates/serviceaccount.yaml b/helm/wallet/templates/serviceaccount.yaml new file mode 100644 index 0000000..d58012b --- /dev/null +++ b/helm/wallet/templates/serviceaccount.yaml @@ -0,0 +1,33 @@ +################################################################################# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "wallet.serviceAccountName" . }} + labels: + {{- include "wallet.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/wallet/templates/tests/test.yaml b/helm/wallet/templates/tests/test.yaml new file mode 100644 index 0000000..66d5f82 --- /dev/null +++ b/helm/wallet/templates/tests/test.yaml @@ -0,0 +1,43 @@ +# +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "wallet.fullname" . }}-test" + labels: + {{- include "wallet.server.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": {{ .Values.tests.hookDeletePolicy }} +spec: + containers: + - name: readiness + image: curlimages/curl + command: [ 'curl', '--fail' ] + args: [ '{{- printf "http://%s:%v%s/check/readiness" (include "wallet.fullname" $ ) $.Values.wallet.endpoints.default.port $.Values.wallet.endpoints.default.path -}}' ] + restartPolicy: Never + securityContext: + fsGroup: 101 # curl_group + runAsGroup: 101 # curl_group + runAsNonRoot: true + runAsUser: 100 # curl_user + seccompProfile: + type: RuntimeDefault diff --git a/helm/wallet/values.yaml b/helm/wallet/values.yaml new file mode 100644 index 0000000..5f56785 --- /dev/null +++ b/helm/wallet/values.yaml @@ -0,0 +1,388 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# Copyright (c) 2025 Cofinity-X +# Copyright (c) 2025,2026 LKS Next +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Controls whether the bundled sub-charts are installed alongside the wallet. +# Set to false to use externally managed PostgreSQL or Vault instances. +install: + postgresql: true + vault: true + +# This is to override the chart name. +fullnameOverride: "wallet" +nameOverride: "wallet" + +# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] + +# -- Add custom ca certificates to the truststore +customCaCerts: {} + +wallet: + # This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ + image: + repository: "ghcr.io/project-construct-x/wallet" + # This sets the pull policy for images. + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "0.17.0-1" + initContainers: [] + # This is for setting Kubernetes Labels to a Pod. + # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ + podLabels: {} + + # This is for setting Kubernetes Annotations to a Pod. + # For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + podAnnotations: {} + + # Disables SVE (Scalable Vector Extension) instructions via JAVA_TOOL_OPTIONS. + # Enable on nodes with SVE-capable CPUs if the JVM produces illegal instruction errors. + useSVE: false + + # Remote debugging via JDWP. Never enable in production environments. + debug: + enabled: false + # Port the JDWP agent listens on inside the container + port: 1045 + # If true, the JVM suspends on startup until a debugger connects + suspendOnStart: false + + # Public hostname of the wallet. Used to construct did:web URLs and ingress routing. + hostname: "wallet.staging.construct-x.net" + + # Super-user participant seeded on first startup by the super-user-seed-extension. + # The api key is stored in Vault under the alias derived from the participant id. + superuser: + # If true, a Kubernetes Secret is created from the values below and mounted via envFrom. + # Set to false to provide the secret externally and reference it via envSecretNames. + createSecret: true + id: admin + # API key for the super-user. Must follow the format base64().. + apiKey: YWRtaW4.adminKey + publicKeyAlias: admin#pubkey + privateKeyAlias: admin#privkey + # -- Whether web DIDs should be interpreted as HTTPS or HTTP + didweb: + https: true + + # Extra environment variables that will be pass onto deployment pods + env: {} + + # "valueFrom" environment variable references that will be added to deployment pods. Name is templated. + # ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core + envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + # secretKeyRef: + # name: secret-name + # key: value_key + + # [Kubernetes Secret Resource](https://kubernetes.io/docs/concepts/configuration/secret/) names to load environment variables from + envSecretNames: [] + # - first-secret + # - second-secret + + # [Kubernetes ConfigMap Resource](https://kubernetes.io/docs/concepts/configuration/configmap/) names to load environment variables from + envConfigMapNames: [] + # - first-config-map + # - second-config-map + + # This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + livenessProbe: + # -- Whether to enable kubernetes [liveness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) + enabled: true + # -- seconds to wait before performing the first liveness check + initialDelaySeconds: 5 + # -- this fields specifies that kubernetes should perform a liveness check every 5 seconds + periodSeconds: 5 + # -- number of seconds after which the probe times out + timeoutSeconds: 5 + # -- when a probe fails kubernetes will try 6 times before giving up + failureThreshold: 6 + # -- number of consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + + readinessProbe: + # -- Whether to enable kubernetes [readiness-probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) + enabled: true + # -- seconds to wait before performing the first readiness check + initialDelaySeconds: 5 + # -- this fields specifies that kubernetes should perform a readiness check every 5 seconds + periodSeconds: 5 + # -- number of seconds after which the probe times out + timeoutSeconds: 5 + # -- when a probe fails kubernetes will try 6 times before giving up + failureThreshold: 6 + # -- number of consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + + # -- endpoints of the wallet + endpoints: + # -- default api for health checks, should not be added to any ingress + default: + # -- port for incoming api calls + port: 8181 + # -- path for incoming api calls + path: /api + # -- management api, used by internal users, can be added to an ingress and must not be internet facing + identity: + # -- port for incoming api calls + port: 15151 + # -- path for incoming api calls + path: /api/identity + # -- authentication key, must be attached to each 'X-Api-Key' request header + authKeyAlias: "sup3r$3cr3t" + # -- DCP Presentation API endpoint + credentials: + # -- port for incoming api calls + port: 13131 + # -- path for incoming api calls + path: /api/credentials + # -- DID service endpoint. DID documents can be resolved from here. + did: + # -- port for incoming api calls + port: 80 + # -- path for incoming api calls + path: / + # -- STS Endpoint, used to obtain tokens + sts: + # -- port for incoming api calls + port: 9292 + # -- path for incoming api calls + path: /api/sts + + # This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ + service: + # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: ClusterIP + # Additional annotations to add to the Service resource + annotations: {} + + ## Ingress declaration to expose the network service. + ingresses: + ## Public / Internet facing Ingress for the Presentation API + - enabled: true + # -- The hostname to be used to precisely map incoming traffic onto the underlying network service + hostname: "wallet.staging.construct-x.net" + # -- Additional ingress annotations to add + annotations: + cert-manager.io/cluster-issuer: letsencrypt-staging + external-dns.alpha.kubernetes.io/hostname: "wallet.staging.construct-x.net" + external-dns.alpha.kubernetes.io/ttl: "300" + # -- EDC endpoints exposed by this ingress resource + endpoints: + - credentials + - did + - sts + # -- Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use + className: "nginx" + # -- TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource + tls: + # -- Enables TLS on the ingress resource + enabled: true + # -- If present overwrites the default secret name + secretName: "wallet-tls" + ## Adds [cert-manager](https://cert-manager.io/docs/) annotations to the ingress resource + certManager: + # -- If preset enables certificate generation via cert-manager namespace scoped issuer + issuer: "" + # -- If preset enables certificate generation via cert-manager cluster-wide issuer + clusterIssuer: "letsencrypt-staging" + ## Ingress for the Identity API, should not be internet facing + - enabled: false + # -- The hostname to be used to precisely map incoming traffic onto the underlying network service + hostname: "wallet.staging.construct-x.net" + # -- Additional ingress annotations to add + annotations: {} + # -- EDC endpoints exposed by this ingress resource + endpoints: + - identity + # -- Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use + className: "nginx" + # -- TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource + tls: + # -- Enables TLS on the ingress resource + enabled: false + # -- If present overwrites the default secret name + secretName: "" + ## Adds [cert-manager](https://cert-manager.io/docs/) annotations to the ingress resource + certManager: + # -- If preset enables certificate generation via cert-manager namespace scoped issuer + issuer: "" + # -- If preset enables certificate generation via cert-manager cluster-wide issuer + clusterIssuer: "letsencrypt-staging" + + # Additional volumeMounts on the output Deployment definition. + volumeMounts: [] + # - name: foo + # mountPath: "/etc/foo" + # readOnly: true + + # Additional volumes on the output Deployment definition. + volumes: [] + # - name: foo + # secret: + # secretName: mysecret + # optional: false + + # -- [resource management](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the container + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 250m + memory: 128Mi + + # This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ + # This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ + replicaCount: 1 + autoscaling: + # -- Enables [horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) + enabled: false + # -- Minimal replicas if resource consumption falls below resource threshholds + minReplicas: 1 + # -- Maximum replicas if resource consumption exceeds resource threshholds + maxReplicas: 100 + # -- targetAverageUtilization of cpu provided to a pod + targetCPUUtilizationPercentage: 80 + # -- targetAverageUtilization of memory provided to a pod + targetMemoryUtilizationPercentage: 80 + + # [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) to constrain pods to nodes + nodeSelector: {} + # [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to configure preferred nodes + tolerations: [] + # [affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) to configure which nodes the pods can be scheduled on + affinity: {} + + # The [pod security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) defines privilege and access control settings for a Pod within the deployment + podSecurityContext: + seccompProfile: + # -- Restrict a Container's Syscalls with seccomp + type: RuntimeDefault + # -- Runs all processes within a pod with a special uid + runAsUser: 10100 + # -- Processes within a pod will belong to this guid + runAsGroup: 10100 + # -- The owner for volumes and any files created within volumes will belong to this guid + fsGroup: 10100 + + # The [container security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) defines privilege and access control settings for a Container within a pod + securityContext: + capabilities: + # -- Specifies which capabilities to drop to reduce syscall attack surface + drop: + - ALL + # -- Specifies which capabilities to add to issue specialized syscalls + add: [] + # -- Whether the root filesystem is mounted in read-only mode + readOnlyRootFilesystem: true + # -- Controls [Privilege Escalation](https://kubernetes.io/docs/concepts/security/pod-security-policy/#privilege-escalation) enabling setuid binaries changing the effective user ID + allowPrivilegeEscalation: false + # -- Requires the container to run without root privileges + runAsNonRoot: true + # -- The container's process will run with the specified uid + runAsUser: 10100 + +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +# -- Configurations for Helm tests +tests: + # -- Configure the hook-delete-policy for Helm tests + hookDeletePolicy: before-hook-creation,hook-succeeded + +postgresql: + # JDBC connection URL passed to the wallet runtime. + jdbcUrl: "jdbc:postgresql://{{ .Release.Name }}-postgresql:5432/wallet" + auth: + # Name of the PostgreSQL database created on first start. Must match with postgresql.jdbcUrl path. + database: "wallet" + # PostgreSQL user that the issuer-wallet connects as. + username: "user" + # Password for the PostgreSQL user. Change before production use. + password: "password" + persistence: + # Persist data across pod restarts. + enabled: true + size: 10Gi + storageClass: "" + # Initialization scripts ConfigMap + initdb: + scriptsConfigMap: "" # Optional: ConfigMap with init scripts + resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + +vault: + injector: + enabled: false + server: + dev: + # Run Vault in dev mode. All data is stored in memory and lost on pod restart. + # Disable for production and configure a persistent storage backend instead. + enabled: true + # Root token used when dev mode is active. Must match vault.hashicorp.token. + devRootToken: "root" + # Optional post-start hook script executed inside the Vault container after startup. + # Can be used to initialise the KV engine or apply policies. Must be set externally. + postStart: + hashicorp: + # URL of the Vault instance reachable from within the cluster. + url: "http://{{ .Release.Name }}-vault:8200" + # Vault token used by the wallet at runtime to read and write secrets. + # If vault.server.dev.enabled is true vault.hashicorp.token match with vault.server.dev.devRootToken. + token: "root" + # Timeout in seconds for Vault HTTP requests. + timeout: 30 + healthCheck: + enabled: true + standbyOk: true + paths: + # Mount path used for all wallet secrets + secret: /v1/secret + # Health endpoint polled by the wallet and the vault-init job + health: /v1/sys/health + init: + # Whether to run the post-install vault-init job that seeds required secrets + enabled: true + # Vault alias under which the AES-256 encryption key is stored. + aesKeyAlias: "wallet-aes-key-alias" From 9bb70589ee7e4c2443e86cc3bfca980dd1c2d387 Mon Sep 17 00:00:00 2001 From: Simon Bergerfurth Date: Fri, 24 Jul 2026 13:56:22 +0200 Subject: [PATCH 2/3] feat(helm): add con-x edc chart --- helm/tractusx-connector/Chart.lock | 9 + helm/tractusx-connector/Chart.yaml | 65 ++ helm/tractusx-connector/LICENSE | 201 +++++ helm/tractusx-connector/README.md | 312 +++++++ helm/tractusx-connector/README.md.gotmpl | 60 ++ helm/tractusx-connector/templates/NOTES.txt | 61 ++ .../tractusx-connector/templates/_helpers.tpl | 182 ++++ .../templates/configmap-controlplane.yaml | 35 + .../templates/configmap-customcacerts.yaml | 31 + .../templates/configmap-dataplane.yaml | 35 + .../templates/configmap-log4j2.yaml | 34 + .../templates/configmap-vault-init.yaml | 140 ++++ .../templates/deployment-controlplane.yaml | 378 +++++++++ .../templates/deployment-dataplane.yaml | 374 +++++++++ .../templates/hpa-controlplane.yaml | 52 ++ .../templates/hpa-dataplane.yaml | 52 ++ .../templates/ingress-controlplane.yaml | 86 ++ .../templates/ingress-dataplane.yaml | 86 ++ .../templates/job-vault-init.yaml | 87 ++ .../templates/networkpolicy.yaml | 46 ++ .../templates/service-controlplane.yaml | 63 ++ .../templates/service-dataplane.yaml | 64 ++ .../templates/serviceaccount.yaml | 40 + .../tests/test-dataplane-readiness.yaml | 43 + .../test-mgmt-api-fails-without-auth.yaml | 44 + .../tests/test-mgmt-api-with-token-auth.yaml | 56 ++ helm/tractusx-connector/values-consumer.yaml | 124 +++ helm/tractusx-connector/values-provider.yaml | 124 +++ helm/tractusx-connector/values.yaml | 778 ++++++++++++++++++ 29 files changed, 3662 insertions(+) create mode 100644 helm/tractusx-connector/Chart.lock create mode 100644 helm/tractusx-connector/Chart.yaml create mode 100644 helm/tractusx-connector/LICENSE create mode 100644 helm/tractusx-connector/README.md create mode 100644 helm/tractusx-connector/README.md.gotmpl create mode 100644 helm/tractusx-connector/templates/NOTES.txt create mode 100644 helm/tractusx-connector/templates/_helpers.tpl create mode 100644 helm/tractusx-connector/templates/configmap-controlplane.yaml create mode 100644 helm/tractusx-connector/templates/configmap-customcacerts.yaml create mode 100644 helm/tractusx-connector/templates/configmap-dataplane.yaml create mode 100644 helm/tractusx-connector/templates/configmap-log4j2.yaml create mode 100644 helm/tractusx-connector/templates/configmap-vault-init.yaml create mode 100644 helm/tractusx-connector/templates/deployment-controlplane.yaml create mode 100644 helm/tractusx-connector/templates/deployment-dataplane.yaml create mode 100644 helm/tractusx-connector/templates/hpa-controlplane.yaml create mode 100644 helm/tractusx-connector/templates/hpa-dataplane.yaml create mode 100644 helm/tractusx-connector/templates/ingress-controlplane.yaml create mode 100644 helm/tractusx-connector/templates/ingress-dataplane.yaml create mode 100644 helm/tractusx-connector/templates/job-vault-init.yaml create mode 100644 helm/tractusx-connector/templates/networkpolicy.yaml create mode 100644 helm/tractusx-connector/templates/service-controlplane.yaml create mode 100644 helm/tractusx-connector/templates/service-dataplane.yaml create mode 100644 helm/tractusx-connector/templates/serviceaccount.yaml create mode 100644 helm/tractusx-connector/templates/tests/test-dataplane-readiness.yaml create mode 100644 helm/tractusx-connector/templates/tests/test-mgmt-api-fails-without-auth.yaml create mode 100644 helm/tractusx-connector/templates/tests/test-mgmt-api-with-token-auth.yaml create mode 100644 helm/tractusx-connector/values-consumer.yaml create mode 100644 helm/tractusx-connector/values-provider.yaml create mode 100644 helm/tractusx-connector/values.yaml diff --git a/helm/tractusx-connector/Chart.lock b/helm/tractusx-connector/Chart.lock new file mode 100644 index 0000000..bcf7fdc --- /dev/null +++ b/helm/tractusx-connector/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: vault + repository: https://helm.releases.hashicorp.com + version: 0.27.0 +- name: postgres + repository: oci://registry-1.docker.io/cloudpirates + version: 0.19.5 +digest: sha256:1ba6ada6ac0e5f1a5b5d01d8f9a1a7a6fe4d690f5bb007de116eb11eed49e80b +generated: "2026-06-16T13:50:25.043091293+02:00" diff --git a/helm/tractusx-connector/Chart.yaml b/helm/tractusx-connector/Chart.yaml new file mode 100644 index 0000000..7a4d895 --- /dev/null +++ b/helm/tractusx-connector/Chart.yaml @@ -0,0 +1,65 @@ +################################################################################# +# Copyright (c) 2023 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +--- +apiVersion: v2 +name: tractusx-connector +description: | + A Helm chart for Tractus-X Eclipse Data Space Connector. The connector deployment consists of two runtime consists of a + Control Plane and a Data Plane. Note that _no_ external dependencies such as a PostgreSQL database and HashiCorp Vault are included. + + This chart is intended for use with an _existing_ PostgreSQL database and an _existing_ HashiCorp Vault. +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.13.0-SNAPSHOT +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.13.0-SNAPSHOT" +home: https://github.com/eclipse-tractusx/tractusx-edc/tree/main/charts/tractusx-connector +sources: + - https://github.com/eclipse-tractusx/tractusx-edc/tree/main/charts/tractusx-connector +dependencies: + # HashiCorp Vault + - name: vault + alias: vault + version: "0.27.0" + repository: https://helm.releases.hashicorp.com + condition: install.vault + # PostgreSQL + - name: postgres + alias: postgresql + version: 0.19.5 + repository: oci://registry-1.docker.io/cloudpirates + condition: install.postgresql diff --git a/helm/tractusx-connector/LICENSE b/helm/tractusx-connector/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/helm/tractusx-connector/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/helm/tractusx-connector/README.md b/helm/tractusx-connector/README.md new file mode 100644 index 0000000..8ee56f9 --- /dev/null +++ b/helm/tractusx-connector/README.md @@ -0,0 +1,312 @@ +# tractusx-connector + +![Version: 0.13.0-SNAPSHOT](https://img.shields.io/badge/Version-0.13.0--SNAPSHOT-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.13.0-SNAPSHOT](https://img.shields.io/badge/AppVersion-0.13.0--SNAPSHOT-informational?style=flat-square) + +A Helm chart for Tractus-X Eclipse Data Space Connector. The connector deployment consists of two runtime consists of a +Control Plane and a Data Plane. Note that _no_ external dependencies such as a PostgreSQL database and HashiCorp Vault are included. + +This chart is intended for use with an _existing_ PostgreSQL database and an _existing_ HashiCorp Vault. + +**Homepage:** + +## Setting up IATP + +### Preconditions + +- You'll need an account with DIV, the wallet for VerifiableCredentials +- the necessary set of VerifiableCredentials for this participant must already be issued to your DIV tenant. This is typically done by the + Portal during participant onboarding +- the client ID and client secret corresponding to that account must be known + +### Preparatory work + +- store client secret in the HashiCorp vault using an alias. The exact procedure will depend on your deployment of HashiCorp Vault and + is out of scope of this document. But by default, Tractus-X EDC expects to find the secret under `secret/client-secret`. The alias must be configured + using the `iatp.sts.oauth.client.secret_alias` Helm value. + +### Configure the chart + +Be sure to provide the following configuration entries to your Tractus-X EDC Helm chart: +- `iatp.sts.oauth.token_url`: the token endpoint of DIV +- `iatp.sts.oauth.client.id`: the client ID of your tenant in DIV +- `iatp.sts.oauth.client.secret_alias`: alias under which you saved your DIV client secret in the vault +- `iatp.sts.div.url`: the base URL for DIV + +In addition, in order to map BPNs to DIDs, a new service is required, called the BPN-DID Resolution Service, which +must be configured: +- `controlplane.bdrs.server.url`: base URL of the BPN-DID Resolution Service ("BDRS") + +### Launching the application + +As an easy starting point, please consider using [this example configuration](https://github.com/eclipse-tractusx/tractusx-edc/blob/main/edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml) +to launch the application. The configuration values mentioned above (`controlplane.ssi.*`) will have to be adapted manually. +Combined, run this shell command to start the in-memory Tractus-X EDC runtime: + +```shell +helm repo add tractusx-edc https://eclipse-tractusx.github.io/charts/dev +helm install my-release tractusx-edc/tractusx-connector --version 0.13.0-SNAPSHOT \ + -f /tractusx-connector-test.yaml +``` + +## Source Code + +* + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| https://charts.bitnami.com/bitnami | postgresql(postgresql) | 15.2.1 | +| https://helm.releases.hashicorp.com | vault(vault) | 0.27.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| controlplane.affinity | object | `{}` | [affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) to configure which nodes the pods can be scheduled on | +| controlplane.autoscaling.enabled | bool | `false` | Enables [horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) | +| controlplane.autoscaling.maxReplicas | int | `100` | Maximum replicas if resource consumption exceeds resource threshholds | +| controlplane.autoscaling.minReplicas | int | `1` | Minimal replicas if resource consumption falls below resource threshholds | +| controlplane.autoscaling.targetCPUUtilizationPercentage | int | `80` | targetAverageUtilization of cpu provided to a pod | +| controlplane.autoscaling.targetMemoryUtilizationPercentage | int | `80` | targetAverageUtilization of memory provided to a pod | +| controlplane.bdrs.cache_validity_seconds | int | `600` | Time that a cached BPN/DID resolution map is valid in seconds, default is 600 seconds (10 min) | +| controlplane.bdrs.server.url | string | `nil` | URL of the BPN/DID Resolution Service | +| controlplane.debug.enabled | bool | `false` | Enables java debugging mode. | +| controlplane.debug.port | int | `1044` | Port where the debuggee can connect to. | +| controlplane.debug.suspendOnStart | bool | `false` | Defines if the JVM should wait with starting the application until someone connected to the debugging port. | +| controlplane.endpoints | object | `{"control":{"path":"/control","port":8083},"default":{"path":"/api","port":8080},"management":{"authKey":"password","jwksUrl":null,"path":"/management","port":8081},"metrics":{"path":"/metrics","port":9090},"protocol":{"path":"/api/v1/dsp","port":8084}}` | endpoints of the control plane | +| controlplane.endpoints.control | object | `{"path":"/control","port":8083}` | control api, used for internal control calls. can be added to the internal ingress, but should probably not | +| controlplane.endpoints.control.path | string | `"/control"` | path for incoming api calls | +| controlplane.endpoints.control.port | int | `8083` | port for incoming api calls | +| controlplane.endpoints.default | object | `{"path":"/api","port":8080}` | default api for health checks, should not be added to any ingress | +| controlplane.endpoints.default.path | string | `"/api"` | path for incoming api calls | +| controlplane.endpoints.default.port | int | `8080` | port for incoming api calls | +| controlplane.endpoints.management | object | `{"authKey":"password","jwksUrl":null,"path":"/management","port":8081}` | data management api, used by internal users, can be added to an ingress and must not be internet facing | +| controlplane.endpoints.management.authKey | string | `"password"` | authentication key, must be attached to each request as `X-Api-Key` header | +| controlplane.endpoints.management.jwksUrl | string | `nil` | if the JWKS url is set, the DelegatedAuth service will be engaged | +| controlplane.endpoints.management.path | string | `"/management"` | path for incoming api calls | +| controlplane.endpoints.management.port | int | `8081` | port for incoming api calls | +| controlplane.endpoints.metrics | object | `{"path":"/metrics","port":9090}` | metrics api, used for application metrics, must not be internet facing | +| controlplane.endpoints.metrics.path | string | `"/metrics"` | path for incoming api calls | +| controlplane.endpoints.metrics.port | int | `9090` | port for incoming api calls | +| controlplane.endpoints.protocol | object | `{"path":"/api/v1/dsp","port":8084}` | dsp api, used for inter connector communication and must be internet facing | +| controlplane.endpoints.protocol.path | string | `"/api/v1/dsp"` | path for incoming api calls | +| controlplane.endpoints.protocol.port | int | `8084` | port for incoming api calls | +| controlplane.env | object | `{}` | Extra environment variables that will be pass onto deployment pods | +| controlplane.envConfigMapNames | list | `[]` | [Kubernetes ConfigMap Resource](https://kubernetes.io/docs/concepts/configuration/configmap/) names to load environment variables from | +| controlplane.envSecretNames | list | `[]` | [Kubernetes Secret Resource](https://kubernetes.io/docs/concepts/configuration/secret/) names to load environment variables from | +| controlplane.envValueFrom | object | `{}` | "valueFrom" environment variable references that will be added to deployment pods. Name is templated. ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core | +| controlplane.image.pullPolicy | string | `"IfNotPresent"` | [Kubernetes image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy) to use | +| controlplane.image.repository | string | `""` | Which derivate of the control plane to use. When left empty the deployment will select the correct image automatically | +| controlplane.image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion | +| controlplane.ingresses[0].annotations | object | `{}` | Additional ingress annotations to add | +| controlplane.ingresses[0].certManager.clusterIssuer | string | `""` | If preset enables certificate generation via cert-manager cluster-wide issuer | +| controlplane.ingresses[0].certManager.issuer | string | `""` | If preset enables certificate generation via cert-manager namespace scoped issuer | +| controlplane.ingresses[0].className | string | `""` | Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use | +| controlplane.ingresses[0].enabled | bool | `false` | | +| controlplane.ingresses[0].endpoints | list | `["protocol"]` | EDC endpoints exposed by this ingress resource | +| controlplane.ingresses[0].hostname | string | `"edc-control.local"` | The hostname to be used to precisely map incoming traffic onto the underlying network service | +| controlplane.ingresses[0].tls | object | `{"enabled":false,"secretName":""}` | TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource | +| controlplane.ingresses[0].tls.enabled | bool | `false` | Enables TLS on the ingress resource | +| controlplane.ingresses[0].tls.secretName | string | `""` | If present overwrites the default secret name | +| controlplane.ingresses[1].annotations | object | `{}` | Additional ingress annotations to add | +| controlplane.ingresses[1].certManager.clusterIssuer | string | `""` | If preset enables certificate generation via cert-manager cluster-wide issuer | +| controlplane.ingresses[1].certManager.issuer | string | `""` | If preset enables certificate generation via cert-manager namespace scoped issuer | +| controlplane.ingresses[1].className | string | `""` | Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use | +| controlplane.ingresses[1].enabled | bool | `false` | | +| controlplane.ingresses[1].endpoints | list | `["management","control"]` | EDC endpoints exposed by this ingress resource | +| controlplane.ingresses[1].hostname | string | `"edc-control.intranet"` | The hostname to be used to precisely map incoming traffic onto the underlying network service | +| controlplane.ingresses[1].tls | object | `{"enabled":false,"secretName":""}` | TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource | +| controlplane.ingresses[1].tls.enabled | bool | `false` | Enables TLS on the ingress resource | +| controlplane.ingresses[1].tls.secretName | string | `""` | If present overwrites the default secret name | +| controlplane.initContainers | list | `[]` | | +| controlplane.livenessProbe.enabled | bool | `true` | Whether to enable kubernetes [liveness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) | +| controlplane.livenessProbe.failureThreshold | int | `6` | when a probe fails kubernetes will try 6 times before giving up | +| controlplane.livenessProbe.initialDelaySeconds | int | `30` | seconds to wait before performing the first liveness check | +| controlplane.livenessProbe.periodSeconds | int | `10` | this fields specifies that kubernetes should perform a liveness check every 10 seconds | +| controlplane.livenessProbe.successThreshold | int | `1` | number of consecutive successes for the probe to be considered successful after having failed | +| controlplane.livenessProbe.timeoutSeconds | int | `5` | number of seconds after which the probe times out | +| controlplane.logs.level | string | `"DEBUG"` | Defines the log granularity of the default Console Monitor. | +| controlplane.nodeSelector | object | `{}` | [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) to constrain pods to nodes | +| controlplane.opentelemetry | string | `"otel.javaagent.enabled=false\notel.javaagent.debug=false"` | configuration of the [Open Telemetry Agent](https://opentelemetry.io/docs/instrumentation/java/automatic/agent-config/) to collect and expose metrics | +| controlplane.podAnnotations | object | `{}` | additional annotations for the pod | +| controlplane.podLabels | object | `{}` | additional labels for the pod | +| controlplane.podSecurityContext | object | `{"fsGroup":10001,"runAsGroup":10001,"runAsUser":10001,"seccompProfile":{"type":"RuntimeDefault"}}` | The [pod security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) defines privilege and access control settings for a Pod within the deployment | +| controlplane.podSecurityContext.fsGroup | int | `10001` | The owner for volumes and any files created within volumes will belong to this guid | +| controlplane.podSecurityContext.runAsGroup | int | `10001` | Processes within a pod will belong to this guid | +| controlplane.podSecurityContext.runAsUser | int | `10001` | Runs all processes within a pod with a special uid | +| controlplane.podSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | Restrict a Container's Syscalls with seccomp | +| controlplane.policy | object | `{"validation":{"enabled":true}}` | configuration for policy engine | +| controlplane.readinessProbe.enabled | bool | `true` | Whether to enable kubernetes [readiness-probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) | +| controlplane.readinessProbe.failureThreshold | int | `6` | when a probe fails kubernetes will try 6 times before giving up | +| controlplane.readinessProbe.initialDelaySeconds | int | `30` | seconds to wait before performing the first readiness check | +| controlplane.readinessProbe.periodSeconds | int | `10` | this fields specifies that kubernetes should perform a readiness check every 10 seconds | +| controlplane.readinessProbe.successThreshold | int | `1` | number of consecutive successes for the probe to be considered successful after having failed | +| controlplane.readinessProbe.timeoutSeconds | int | `5` | number of seconds after which the probe times out | +| controlplane.replicaCount | int | `1` | | +| controlplane.resources | object | `{"limits":{"cpu":1.5,"memory":"1024Mi"},"requests":{"cpu":"500m","memory":"1024Mi"}}` | [resource management](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the container | +| controlplane.resources.limits.cpu | float | `1.5` | Maximum CPU limit | +| controlplane.resources.limits.memory | string | `"1024Mi"` | Maximum memory limit | +| controlplane.resources.requests.cpu | string | `"500m"` | Initial CPU request | +| controlplane.resources.requests.memory | string | `"1024Mi"` | Initial memory request | +| controlplane.securityContext.allowPrivilegeEscalation | bool | `false` | Controls [Privilege Escalation](https://kubernetes.io/docs/concepts/security/pod-security-policy/#privilege-escalation) enabling setuid binaries changing the effective user ID | +| controlplane.securityContext.capabilities.add | list | `[]` | Specifies which capabilities to add to issue specialized syscalls | +| controlplane.securityContext.capabilities.drop | list | `["ALL"]` | Specifies which capabilities to drop to reduce syscall attack surface | +| controlplane.securityContext.readOnlyRootFilesystem | bool | `true` | Whether the root filesystem is mounted in read-only mode | +| controlplane.securityContext.runAsNonRoot | bool | `true` | Requires the container to run without root privileges | +| controlplane.securityContext.runAsUser | int | `10001` | The container's process will run with the specified uid | +| controlplane.service.annotations | object | `{}` | additional annotations for the service | +| controlplane.service.labels | object | `{}` | additional labels for the service | +| controlplane.service.type | string | `"ClusterIP"` | [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. | +| controlplane.tolerations | list | `[]` | [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to configure preferred nodes | +| controlplane.url.protocol | string | `""` | Explicitly declared url for reaching the dsp api (e.g. if ingresses not used) | +| controlplane.volumeMounts | string | `nil` | declare where to mount [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) into the container | +| controlplane.volumes | string | `nil` | [volume](https://kubernetes.io/docs/concepts/storage/volumes/) directories | +| customCaCerts | object | `{}` | Add custom ca certificates to the truststore | +| customLabels | object | `{}` | Add some custom labels | +| dataplane.affinity | object | `{}` | [affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) to configure which nodes the pods can be scheduled on | +| dataplane.autoscaling.enabled | bool | `false` | Enables [horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) | +| dataplane.autoscaling.maxReplicas | int | `100` | Maximum replicas if resource consumption exceeds resource threshholds | +| dataplane.autoscaling.minReplicas | int | `1` | Minimal replicas if resource consumption falls below resource threshholds | +| dataplane.autoscaling.targetCPUUtilizationPercentage | int | `80` | targetAverageUtilization of cpu provided to a pod | +| dataplane.autoscaling.targetMemoryUtilizationPercentage | int | `80` | targetAverageUtilization of memory provided to a pod | +| dataplane.aws.accessKeyId | string | `""` | | +| dataplane.aws.endpointOverride | string | `""` | | +| dataplane.aws.secretAccessKey | string | `""` | | +| dataplane.debug.enabled | bool | `false` | Enables java debugging mode. | +| dataplane.debug.port | int | `1044` | Port where the debuggee can connect to. | +| dataplane.debug.suspendOnStart | bool | `false` | Defines if the JVM should wait with starting the application until someone connected to the debugging port. | +| dataplane.endpoints | object | `{"control":{"path":"/api/control","port":8084},"default":{"path":"/api","port":8080},"metrics":{"path":"/metrics","port":9090},"proxy":{"authKey":"password","path":"/proxy","port":8186},"public":{"path":"/api/public","port":8081}}` | endpoints of the dataplane | +| dataplane.endpoints.control | object | `{"path":"/api/control","port":8084}` | control api, used for internal control calls. can be added to the internal ingress, but should probably not | +| dataplane.endpoints.control.path | string | `"/api/control"` | path for incoming api calls | +| dataplane.endpoints.control.port | int | `8084` | port for incoming api calls | +| dataplane.endpoints.default | object | `{"path":"/api","port":8080}` | default api for health checks, should not be added to any ingress | +| dataplane.endpoints.default.path | string | `"/api"` | path for incoming api calls | +| dataplane.endpoints.default.port | int | `8080` | port for incoming api calls | +| dataplane.endpoints.metrics | object | `{"path":"/metrics","port":9090}` | metrics api, used for application metrics, must not be internet facing | +| dataplane.endpoints.metrics.path | string | `"/metrics"` | path for incoming api calls | +| dataplane.endpoints.metrics.port | int | `9090` | port for incoming api calls | +| dataplane.endpoints.proxy.authKey | string | `"password"` | authentication key, must be attached to each request as `X-Api-Key` header | +| dataplane.endpoints.proxy.path | string | `"/proxy"` | path for incoming api calls | +| dataplane.endpoints.proxy.port | int | `8186` | port for incoming api calls | +| dataplane.endpoints.public | object | `{"path":"/api/public","port":8081}` | public endpoint where the data can be fetched from if HttpPull was used. Must be internet facing. | +| dataplane.endpoints.public.path | string | `"/api/public"` | path for incoming api calls | +| dataplane.endpoints.public.port | int | `8081` | port for incoming api calls | +| dataplane.env | object | `{}` | Extra environment variables that will be pass onto deployment pods | +| dataplane.envConfigMapNames | list | `[]` | [Kubernetes ConfigMap Resource](https://kubernetes.io/docs/concepts/configuration/configmap/) names to load environment variables from | +| dataplane.envSecretNames | list | `[]` | [Kubernetes Secret Resource](https://kubernetes.io/docs/concepts/configuration/secret/) names to load environment variables from | +| dataplane.envValueFrom | object | `{}` | "valueFrom" environment variable references that will be added to deployment pods. Name is templated. ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core | +| dataplane.image.pullPolicy | string | `"IfNotPresent"` | [Kubernetes image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy) to use | +| dataplane.image.repository | string | `""` | Which derivate of the data plane to use. when left empty the deployment will select the correct image automatically | +| dataplane.image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion | +| dataplane.ingresses[0].annotations | object | `{}` | Additional ingress annotations to add | +| dataplane.ingresses[0].certManager.clusterIssuer | string | `""` | If preset enables certificate generation via cert-manager cluster-wide issuer | +| dataplane.ingresses[0].certManager.issuer | string | `""` | If preset enables certificate generation via cert-manager namespace scoped issuer | +| dataplane.ingresses[0].className | string | `""` | Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use | +| dataplane.ingresses[0].enabled | bool | `false` | | +| dataplane.ingresses[0].endpoints | list | `["public"]` | EDC endpoints exposed by this ingress resource | +| dataplane.ingresses[0].hostname | string | `"edc-data.local"` | The hostname to be used to precisely map incoming traffic onto the underlying network service | +| dataplane.ingresses[0].tls | object | `{"enabled":false,"secretName":""}` | TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource | +| dataplane.ingresses[0].tls.enabled | bool | `false` | Enables TLS on the ingress resource | +| dataplane.ingresses[0].tls.secretName | string | `""` | If present overwrites the default secret name | +| dataplane.initContainers | list | `[]` | | +| dataplane.livenessProbe.enabled | bool | `true` | Whether to enable kubernetes [liveness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) | +| dataplane.livenessProbe.failureThreshold | int | `6` | when a probe fails kubernetes will try 6 times before giving up | +| dataplane.livenessProbe.initialDelaySeconds | int | `30` | seconds to wait before performing the first liveness check | +| dataplane.livenessProbe.periodSeconds | int | `10` | this fields specifies that kubernetes should perform a liveness check every 10 seconds | +| dataplane.livenessProbe.successThreshold | int | `1` | number of consecutive successes for the probe to be considered successful after having failed | +| dataplane.livenessProbe.timeoutSeconds | int | `5` | number of seconds after which the probe times out | +| dataplane.logs.level | string | `"DEBUG"` | Defines the log granularity of the default Console Monitor. | +| dataplane.nodeSelector | object | `{}` | [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) to constrain pods to nodes | +| dataplane.opentelemetry | string | `"otel.javaagent.enabled=false\notel.javaagent.debug=false"` | configuration of the [Open Telemetry Agent](https://opentelemetry.io/docs/instrumentation/java/automatic/agent-config/) to collect and expose metrics | +| dataplane.podAnnotations | object | `{}` | additional annotations for the pod | +| dataplane.podLabels | object | `{}` | additional labels for the pod | +| dataplane.podSecurityContext | object | `{"fsGroup":10001,"runAsGroup":10001,"runAsUser":10001,"seccompProfile":{"type":"RuntimeDefault"}}` | The [pod security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) defines privilege and access control settings for a Pod within the deployment | +| dataplane.podSecurityContext.fsGroup | int | `10001` | The owner for volumes and any files created within volumes will belong to this guid | +| dataplane.podSecurityContext.runAsGroup | int | `10001` | Processes within a pod will belong to this guid | +| dataplane.podSecurityContext.runAsUser | int | `10001` | Runs all processes within a pod with a special uid | +| dataplane.podSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | Restrict a Container's Syscalls with seccomp | +| dataplane.readinessProbe.enabled | bool | `true` | Whether to enable kubernetes [readiness-probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) | +| dataplane.readinessProbe.failureThreshold | int | `6` | when a probe fails kubernetes will try 6 times before giving up | +| dataplane.readinessProbe.initialDelaySeconds | int | `30` | seconds to wait before performing the first readiness check | +| dataplane.readinessProbe.periodSeconds | int | `10` | this fields specifies that kubernetes should perform a liveness check every 10 seconds | +| dataplane.readinessProbe.successThreshold | int | `1` | number of consecutive successes for the probe to be considered successful after having failed | +| dataplane.readinessProbe.timeoutSeconds | int | `5` | number of seconds after which the probe times out | +| dataplane.replicaCount | int | `1` | | +| dataplane.resources | object | `{"limits":{"cpu":1.5,"memory":"1024Mi"},"requests":{"cpu":"500m","memory":"1024Mi"}}` | [resource management](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the container | +| dataplane.resources.limits.cpu | float | `1.5` | Maximum CPU limit | +| dataplane.resources.limits.memory | string | `"1024Mi"` | Maximum memory limit | +| dataplane.resources.requests.cpu | string | `"500m"` | Initial CPU request | +| dataplane.resources.requests.memory | string | `"1024Mi"` | Initial memory request | +| dataplane.securityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"add":[],"drop":["ALL"]},"readOnlyRootFilesystem":true,"runAsNonRoot":true,"runAsUser":10001}` | The [container security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) defines privilege and access control settings for a Container within a pod | +| dataplane.securityContext.allowPrivilegeEscalation | bool | `false` | Controls [Privilege Escalation](https://kubernetes.io/docs/concepts/security/pod-security-policy/#privilege-escalation) enabling setuid binaries changing the effective user ID | +| dataplane.securityContext.capabilities.add | list | `[]` | Specifies which capabilities to add to issue specialized syscalls | +| dataplane.securityContext.capabilities.drop | list | `["ALL"]` | Specifies which capabilities to drop to reduce syscall attack surface | +| dataplane.securityContext.readOnlyRootFilesystem | bool | `true` | Whether the root filesystem is mounted in read-only mode | +| dataplane.securityContext.runAsNonRoot | bool | `true` | Requires the container to run without root privileges | +| dataplane.securityContext.runAsUser | int | `10001` | The container's process will run with the specified uid | +| dataplane.service.annotations | object | `{}` | additional annotations for the service | +| dataplane.service.labels | object | `{}` | additional labels for the service | +| dataplane.service.type | string | `"ClusterIP"` | [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. | +| dataplane.token.refresh.expiry_seconds | int | `300` | TTL in seconds for access tokens (also known as EDR token) | +| dataplane.token.refresh.expiry_tolerance_seconds | int | `10` | Tolerance for token expiry in seconds | +| dataplane.token.refresh.refresh_endpoint | string | `nil` | Optional endpoint for an OAuth2 token refresh. Default endpoint is `/token` | +| dataplane.token.signer.privatekey_alias | string | `nil` | Alias under which the private key (JWK or PEM format) is stored in the vault | +| dataplane.token.verifier.publickey_alias | string | `nil` | Alias under which the public key (JWK or PEM format) is stored in the vault, that belongs to the private key which was referred to at `dataplane.token.signer.privatekey_alias` | +| dataplane.tolerations | list | `[]` | [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to configure preferred nodes | +| dataplane.url.public | string | `""` | Explicitly declared url for reaching the public api (e.g. if ingresses not used) | +| dataplane.volumeMounts | string | `nil` | declare where to mount [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) into the container | +| dataplane.volumes | string | `nil` | [volume](https://kubernetes.io/docs/concepts/storage/volumes/) directories | +| fullnameOverride | string | `""` | | +| iatp.cache.enabled | bool | `true` | Whether the Verifiable Presentation cache is enabled | +| iatp.cache.validity | int | `86400` | Validity of the Verifiable Presentation cache in seconds | +| iatp.didService.selfRegistration.enabled | bool | `false` | Whether Service Self Registration is enabled | +| iatp.didService.selfRegistration.id | string | `"did:web:changeme"` | Unique id of connector to be used for register / unregister service inside did document (must be valid URI) | +| iatp.id | string | `"did:web:changeme"` | Decentralized IDentifier (DID) of the connector | +| iatp.sts.div.url | string | `nil` | URL where connectors can request SI tokens | +| iatp.sts.oauth.client.id | string | `nil` | Client ID for requesting OAuth2 access token for DIV access | +| iatp.sts.oauth.client.secret_alias | string | `nil` | Alias under which the client secret is stored in the vault for requesting OAuth2 access token for DIV access | +| iatp.sts.oauth.token_url | string | `nil` | URL where connectors can request OAuth2 access tokens for DIV access | +| iatp.trustedIssuers | list | `[]` | Configures the trusted issuers for this runtime. If no supportedTypes are specified, the value defaults to "*" for that issuer | +| imagePullSecrets | list | `[]` | Existing image pull secret to use to [obtain the container image from private registries](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) | +| install.postgresql | bool | `true` | Deploying a PostgreSQL instance | +| install.vault | bool | `true` | Deploying a HashiCorp Vault instance | +| log4j2.config | string | `"Appenders:\n Console:\n name: CONSOLE\n JsonTemplateLayout:\n eventTemplate: |-\n {\n \"timestamp\": {\n \"$resolver\": \"timestamp\",\n \"pattern\": {\n \"format\": \"yyyy-MM-dd'T'HH:mm:ss.SSSSSSS\",\n \"timeZone\": \"UTC\"\n }\n },\n \"level\": {\n \"$resolver\": \"level\",\n \"field\": \"severity\",\n \"severity\": {\n \"field\": \"keyword\"\n }\n },\n \"message\": {\n \"$resolver\": \"message\"\n }\n }\nLoggers:\n Root:\n level: \"OFF\"\n Logger:\n name: org.eclipse.edc.monitor.logger\n level: DEBUG\n AppenderRef:\n ref: CONSOLE"` | Log4j2 configuration for json log formatting. | +| log4j2.enableJsonLogs | bool | `true` | Whether to enable the json log config in log4j2.config | +| nameOverride | string | `""` | | +| networkPolicy.controlplane | object | `{"from":[{"namespaceSelector":{}}]}` | Configuration of the controlplane component | +| networkPolicy.controlplane.from | list | `[{"namespaceSelector":{}}]` | Specify from rule network policy for cp (defaults to all namespaces) | +| networkPolicy.dataplane | object | `{"from":[{"namespaceSelector":{}}]}` | Configuration of the dataplane component | +| networkPolicy.dataplane.from | list | `[{"namespaceSelector":{}}]` | Specify from rule network policy for dp (defaults to all namespaces) | +| networkPolicy.enabled | bool | `false` | If `true` network policy will be created to restrict access to control- and dataplane | +| participant.contextId | string | `"UUID CHANGEME"` | Participant Context Id - Newly introduced id for a connector instance (needed for multitenancy) | +| participant.id | string | `"BPNLCHANGEME"` | BPN Number | +| postgresql.auth.database | string | `"edc"` | | +| postgresql.auth.password | string | `"password"` | | +| postgresql.auth.username | string | `"user"` | | +| postgresql.image.repository | string | `"bitnamilegacy/postgresql"` | | +| postgresql.image.tag | string | `"16.2.0-debian-12-r10"` | | +| postgresql.jdbcUrl | string | `"jdbc:postgresql://{{ .Release.Name }}-postgresql:5432/edc"` | | +| postgresql.primary.persistence.enabled | bool | `false` | | +| postgresql.readReplicas.persistence.enabled | bool | `false` | | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| serviceAccount.imagePullSecrets | list | `[]` | Existing image pull secret bound to the service account to use to [obtain the container image from private registries](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| tests | object | `{"hookDeletePolicy":"before-hook-creation,hook-succeeded"}` | Configurations for Helm tests | +| tests.hookDeletePolicy | string | `"before-hook-creation,hook-succeeded"` | Configure the hook-delete-policy for Helm tests | +| vault.hashicorp.healthCheck.enabled | bool | `true` | | +| vault.hashicorp.healthCheck.standbyOk | bool | `true` | | +| vault.hashicorp.paths.folder | string | `""` | | +| vault.hashicorp.paths.health | string | `"/v1/sys/health"` | | +| vault.hashicorp.paths.secret | string | `"/v1/secret"` | | +| vault.hashicorp.timeout | int | `30` | | +| vault.hashicorp.token | string | `"root"` | | +| vault.hashicorp.url | string | `"http://{{ .Release.Name }}-vault:8200"` | | +| vault.injector.enabled | bool | `false` | | +| vault.server.dev.devRootToken | string | `"root"` | | +| vault.server.dev.enabled | bool | `true` | | +| vault.server.postStart | string | `nil` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs](https://github.com/norwoodj/helm-docs/) diff --git a/helm/tractusx-connector/README.md.gotmpl b/helm/tractusx-connector/README.md.gotmpl new file mode 100644 index 0000000..9e9a12b --- /dev/null +++ b/helm/tractusx-connector/README.md.gotmpl @@ -0,0 +1,60 @@ +{{ template "chart.header" . }} + +{{ template "chart.deprecationWarning" . }} + +{{ template "chart.badgesSection" . }} + +{{ template "chart.description" . }} + +{{ template "chart.homepageLine" . }} + +## Setting up IATP + +### Preconditions + +- You'll need an account with DIV, the wallet for VerifiableCredentials +- the necessary set of VerifiableCredentials for this participant must already be issued to your DIV tenant. This is typically done by the + Portal during participant onboarding +- the client ID and client secret corresponding to that account must be known + +### Preparatory work + +- store client secret in the HashiCorp vault using an alias. The exact procedure will depend on your deployment of HashiCorp Vault and + is out of scope of this document. But by default, Tractus-X EDC expects to find the secret under `secret/client-secret`. The alias must be configured + using the `iatp.sts.oauth.client.secret_alias` Helm value. + + +### Configure the chart + +Be sure to provide the following configuration entries to your Tractus-X EDC Helm chart: +- `iatp.sts.oauth.token_url`: the token endpoint of DIV +- `iatp.sts.oauth.client.id`: the client ID of your tenant in DIV +- `iatp.sts.oauth.client.secret_alias`: alias under which you saved your DIV client secret in the vault +- `iatp.sts.div.url`: the base URL for DIV + +In addition, in order to map BPNs to DIDs, a new service is required, called the BPN-DID Resolution Service, which +must be configured: +- `controlplane.bdrs.server.url`: base URL of the BPN-DID Resolution Service ("BDRS") + +### Launching the application + +As an easy starting point, please consider using [this example configuration](https://github.com/eclipse-tractusx/tractusx-edc/blob/main/edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml) +to launch the application. The configuration values mentioned above (`controlplane.ssi.*`) will have to be adapted manually. +Combined, run this shell command to start the in-memory Tractus-X EDC runtime: + +```shell +helm repo add tractusx-edc https://eclipse-tractusx.github.io/charts/dev +helm install my-release tractusx-edc/tractusx-connector --version {{ .Version }} \ + -f /tractusx-connector-test.yaml +``` + +{{ template "chart.maintainersSection" . }} + +{{ template "chart.sourcesSection" . }} + +{{ template "chart.requirementsSection" . }} + +{{ template "chart.valuesSection" . }} + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs](https://github.com/norwoodj/helm-docs/) diff --git a/helm/tractusx-connector/templates/NOTES.txt b/helm/tractusx-connector/templates/NOTES.txt new file mode 100644 index 0000000..2847002 --- /dev/null +++ b/helm/tractusx-connector/templates/NOTES.txt @@ -0,0 +1,61 @@ +{{- range $.Values.controlplane.ingresses }} + {{- if .enabled }} + {{- if (has "management" .endpoints) }} + +Your Control Plane's Management API is running here: + http{{ if .tls.enabled }}s{{ end }}://{{ .hostname }}{{ $.Values.controlplane.endpoints.management.path }} + + {{- end }} + {{- end }} +{{- end }} +{{- if contains "NodePort" $.Values.controlplane.service.type }} +Run these commands to learn where your application is exposed via NodePort: + export NODE_PORT=$(kubectl get --namespace {{ $.Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "txdc.fullname" $ }}-controlplane) + export NODE_IP=$(kubectl get nodes --namespace {{ $.Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT + +{{- else if contains "LoadBalancer" $.Values.controlplane.service.type }} +NOTE: It may take a few minutes for the LoadBalancer IP to be available. +You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "txdc.fullname" . }}-controlplane' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "txdc.fullname" . }}-controlplane --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ $.Values.controlplane.service.port }} + +{{- else if contains "ClusterIP" $.Values.controlplane.service.type }} +If no ingress is configured, you can forward the Control Plane's ClusterIP by running these commands: + export CONTAINER_PORT=$(kubectl get pod --namespace {{ $.Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + kubectl --namespace {{ $.Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT + echo "Visit http://127.0.0.1:8080 to use your application" + +{{- end }} + + +{{- range $.Values.dataplane.ingresses }} + {{- if .enabled }} + {{- if (has "public" .endpoints) }} +Your Data Plane's public API is running here: + http{{ if .tls.enabled }}s{{ end }}://{{ .hostname }}{{ $.Values.dataplane.endpoints.public.path }} + + {{- end }} + {{- end }} +{{- end }} +{{- if contains "NodePort" $.Values.dataplane.service.type }} +Run these commands to learn where your application is exposed via NodePort: + export NODE_PORT=$(kubectl get --namespace {{ $.Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "txdc.fullname" $ }}-dataplane) + export NODE_IP=$(kubectl get nodes --namespace {{ $.Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT + +{{- else if contains "LoadBalancer" $.Values.dataplane.service.type }} +NOTE: It may take a few minutes for the LoadBalancer IP to be available. +You can watch the status of by running 'kubectl get --namespace {{ $.Release.Namespace }} svc -w {{ include "txdc.fullname" $ }}-dataplane' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "txdc.fullname" $ }}-dataplane --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} + +{{- else if contains "ClusterIP" $.Values.dataplane.service.type }} +If no ingress is configured, you can also forward the Dataplane's ClusterIP by running these commands. Note that this API should be publically exposed: + export CONTAINER_PORT=$(kubectl get pod --namespace {{ $.Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + kubectl --namespace {{ $.Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT + echo "Visit http://127.0.0.1:8080 to use your application" + +{{- end }} + + diff --git a/helm/tractusx-connector/templates/_helpers.tpl b/helm/tractusx-connector/templates/_helpers.tpl new file mode 100644 index 0000000..a115b22 --- /dev/null +++ b/helm/tractusx-connector/templates/_helpers.tpl @@ -0,0 +1,182 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "txdc.name" -}} +{{- default .Chart.Name .Values.nameOverride | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "txdc.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "txdc.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Control Common labels +*/}} +{{- define "txdc.labels" -}} +helm.sh/chart: {{ include "txdc.chart" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Control Common labels +*/}} +{{- define "txdc.controlplane.labels" -}} +helm.sh/chart: {{ include "txdc.chart" . }} +{{ include "txdc.controlplane.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: edc-controlplane +app.kubernetes.io/part-of: edc +{{- end }} + +{{/* +Data Common labels +*/}} +{{- define "txdc.dataplane.labels" -}} +helm.sh/chart: {{ include "txdc.chart" . }} +{{ include "txdc.dataplane.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: edc-dataplane +app.kubernetes.io/part-of: edc +{{- end }} + +{{/* +Control Selector labels +*/}} +{{- define "txdc.controlplane.selectorLabels" -}} +app.kubernetes.io/name: {{ include "txdc.name" . }}-controlplane +app.kubernetes.io/instance: {{ .Release.Name }}-controlplane +{{- end }} + +{{/* +Data Selector labels +*/}} +{{- define "txdc.dataplane.selectorLabels" -}} +app.kubernetes.io/name: {{ include "txdc.name" . }}-dataplane +app.kubernetes.io/instance: {{ .Release.Name }}-dataplane +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "txdc.controlplane.serviceaccount.name" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "txdc.fullname" . ) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "txdc.dataplane.serviceaccount.name" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "txdc.fullname" . ) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Control DSP URL +*/}} +{{- define "txdc.controlplane.url.protocol" -}} +{{- if .Values.controlplane.url.protocol }}{{/* if dsp api url has been specified explicitly */}} +{{- .Values.controlplane.url.protocol }} +{{- else }}{{/* else when dsp api url has not been specified explicitly */}} +{{- with (index .Values.controlplane.ingresses 0) }} +{{- if .enabled }}{{/* if ingress enabled */}} +{{- if .tls.enabled }}{{/* if TLS enabled */}} +{{- printf "https://%s" .hostname -}} +{{- else }}{{/* else when TLS not enabled */}} +{{- printf "http://%s" .hostname -}} +{{- end }}{{/* end if tls */}} +{{- else }}{{/* else when ingress not enabled */}} +{{- printf "http://%s-controlplane:%v" ( include "txdc.fullname" $ ) $.Values.controlplane.endpoints.protocol.port -}} +{{- end }}{{/* end if ingress */}} +{{- end }}{{/* end with ingress */}} +{{- end }}{{/* end if .Values.controlplane.url.protocol */}} +{{- end }} + +{{/* +Validation URL +*/}} +{{- define "txdc.controlplane.url.validation" -}} +{{- printf "%s/token" ( include "txdc.controlplane.url.control" $ ) -}} +{{- end }} + +{{/* +Control Plane Control URL +*/}} +{{- define "txdc.controlplane.url.control" -}} +{{- printf "http://%s-controlplane:%v%s" ( include "txdc.fullname" $ ) $.Values.controlplane.endpoints.control.port $.Values.controlplane.endpoints.control.path -}} +{{- end }} + +{{/* +Data Plane Control URL +*/}} +{{- define "txdc.dataplane.url.control" -}} +{{- printf "http://%s-dataplane:%v%s" ( include "txdc.fullname" $ ) $.Values.dataplane.endpoints.control.port $.Values.dataplane.endpoints.control.path -}} +{{- end }} + +{{/* +Data Public URL +*/}} +{{- define "txdc.dataplane.url.public" -}} +{{- if .Values.dataplane.url.public }}{{/* if public api url has been specified explicitly */}} +{{- .Values.dataplane.url.public }} +{{- else }}{{/* else when public api url has not been specified explicitly */}} +{{- with (index .Values.dataplane.ingresses 0) }} +{{- if .enabled }}{{/* if ingress enabled */}} +{{- if .tls.enabled }}{{/* if TLS enabled */}} +{{- printf "https://%s%s" .hostname $.Values.dataplane.endpoints.public.path -}} +{{- else }}{{/* else when TLS not enabled */}} +{{- printf "http://%s%s" .hostname $.Values.dataplane.endpoints.public.path -}} +{{- end }}{{/* end if tls */}} +{{- else }}{{/* else when ingress not enabled */}} +{{- printf "http://%s-dataplane:%v%s" (include "txdc.fullname" $ ) $.Values.dataplane.endpoints.public.port $.Values.dataplane.endpoints.public.path -}} +{{- end }}{{/* end if ingress */}} +{{- end }}{{/* end with ingress */}} +{{- end }}{{/* end if .Values.dataplane.url.public */}} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "txdc.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "txdc.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/tractusx-connector/templates/configmap-controlplane.yaml b/helm/tractusx-connector/templates/configmap-controlplane.yaml new file mode 100644 index 0000000..644bb1d --- /dev/null +++ b/helm/tractusx-connector/templates/configmap-controlplane.yaml @@ -0,0 +1,35 @@ +################################################################################# +# Copyright (c) 2023 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "txdc.fullname" . }}-controlplane + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "txdc.controlplane.labels" . | nindent 4 }} +data: + opentelemetry.properties: |- + {{- .Values.controlplane.opentelemetry | nindent 4 }} + diff --git a/helm/tractusx-connector/templates/configmap-customcacerts.yaml b/helm/tractusx-connector/templates/configmap-customcacerts.yaml new file mode 100644 index 0000000..3d1eff0 --- /dev/null +++ b/helm/tractusx-connector/templates/configmap-customcacerts.yaml @@ -0,0 +1,31 @@ +################################################################################# +# Copyright (c) 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{- if .Values.customCaCerts }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "txdc.fullname" . }}-custom-cacerts + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "txdc.labels" . | nindent 4 }} +data: + {{- .Values.customCaCerts | toYaml | nindent 2 }} +{{- end }} diff --git a/helm/tractusx-connector/templates/configmap-dataplane.yaml b/helm/tractusx-connector/templates/configmap-dataplane.yaml new file mode 100644 index 0000000..fa179c8 --- /dev/null +++ b/helm/tractusx-connector/templates/configmap-dataplane.yaml @@ -0,0 +1,35 @@ +################################################################################# +# Copyright (c) 2023 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "txdc.fullname" . }}-dataplane + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "txdc.dataplane.labels" . | nindent 4 }} +data: + opentelemetry.properties: |- + {{- .Values.dataplane.opentelemetry | nindent 4 }} + diff --git a/helm/tractusx-connector/templates/configmap-log4j2.yaml b/helm/tractusx-connector/templates/configmap-log4j2.yaml new file mode 100644 index 0000000..50919f8 --- /dev/null +++ b/helm/tractusx-connector/templates/configmap-log4j2.yaml @@ -0,0 +1,34 @@ +################################################################################# + # Copyright (c) 2023 ZF Friedrichshafen AG + # Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH + # Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0. + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + ################################################################################# + + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "txdc.fullname" . }}-log4j2 + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "txdc.labels" . | nindent 4 }} +data: + log4j2.yaml: |- + {{- .Values.log4j2.config | nindent 4 }} \ No newline at end of file diff --git a/helm/tractusx-connector/templates/configmap-vault-init.yaml b/helm/tractusx-connector/templates/configmap-vault-init.yaml new file mode 100644 index 0000000..ed687da --- /dev/null +++ b/helm/tractusx-connector/templates/configmap-vault-init.yaml @@ -0,0 +1,140 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +# this configmap contains the initialization script to generate and store aes and rsa keys into the vault. + +{{ if .Values.vault.hashicorp.init.enabled }} +{{- $fullName := .Values.fullnameOverride -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $fullName }}-vault-init + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "txdc.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +data: + init.sh: | + #!/usr/bin/env sh + set -eu + + VAULT="${VAULT_ADDR:?VAULT_ADDR is required}" + TOKEN="${VAULT_TOKEN:?VAULT_TOKEN is required}" + FORCE="${FORCE_REGENERATE:-false}" + SECRETS="${VAULT_SECRET_PATH:-/v1/secret}" + HEALTH="${VAULT_HEALTH_PATH:-/v1/sys/health}" + + AES_ALIAS="${AES_KEY_ALIAS:-}" + PRIV_ALIAS="${PRIVATE_KEY_ALIAS:-}" + PUB_ALIAS="${PUBLIC_KEY_ALIAS:-}" + + log() { echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*" >&2; } + + # Check provided Aliases for plausibility (AES or RSA pair must be requested) + if [ -z "$AES_ALIAS" ] && [ -z "$PRIV_ALIAS" ] && [ -z "$PUB_ALIAS" ]; then + log "ERROR: no alias provided. Set AES_KEY_ALIAS and/or PRIVATE_KEY_ALIAS+PUBLIC_KEY_ALIAS." + exit 1 + fi + if { [ -n "$PRIV_ALIAS" ] && [ -z "$PUB_ALIAS" ]; } || \ + { [ -z "$PRIV_ALIAS" ] && [ -n "$PUB_ALIAS" ]; }; then + log "ERROR: RSA generation requires BOTH PRIVATE_KEY_ALIAS and PUBLIC_KEY_ALIAS." + exit 1 + fi + + # Install required tools + if ! command -v openssl >/dev/null 2>&1 \ + || ! command -v curl >/dev/null 2>&1 \ + || ! command -v jq >/dev/null 2>&1; then + log "Installing curl, jq, openssl..." + apk add --no-cache curl jq openssl >/dev/null + fi + + log "Waiting for Vault at $VAULT$HEALTH..." + i=0 + until curl -fsS --connect-timeout 2 --max-time 5 "$VAULT$HEALTH" >/dev/null 2>&1; do + i=$((i+1)) + [ "$i" -gt 60 ] && { log "Vault not ready after 60 attempts."; exit 1; } + sleep 3 + done + log "Vault ready." + + # Check for existing Secret + secret_exists() { + [ "$(curl -sS -o /dev/null -w "%{http_code}" \ + -H "X-Vault-Token: $TOKEN" \ + "$VAULT$SECRETS/data/$1")" = "200" ] + } + + # Store Secret in Vault + put_secret() { + local alias="$1" payload="$2" + local code + code=$(printf '%s' "$payload" | curl -sS -o /dev/null -w "%{http_code}" \ + -H "X-Vault-Token: $TOKEN" \ + -H "Content-Type: application/json" \ + -X POST --data-binary @- \ + "$VAULT$SECRETS/data/$alias") + if [ "$code" != "200" ] && [ "$code" != "204" ]; then + log "Failed to store '$alias' (HTTP $code)" + exit 1 + fi + } + + # Generate AES Key + if [ -n "$AES_ALIAS" ]; then + if [ "$FORCE" != "true" ] && secret_exists "$AES_ALIAS"; then + log "AES key '$AES_ALIAS' already present — skipping." + else + log "Generating AES-256 key for '$AES_ALIAS'..." + key=$(openssl rand -base64 32 | tr -d '\n') + payload=$(jq -n --arg content "$key" '{data:{content:$content}}') + put_secret "$AES_ALIAS" "$payload" + log "AES key stored at $VAULT$SECRETS/data/$AES_ALIAS" + fi + fi + + # Generate RSA Keypair + if [ -n "$PRIV_ALIAS" ] && [ -n "$PUB_ALIAS" ]; then + if [ "$FORCE" != "true" ] \ + && secret_exists "$PRIV_ALIAS" \ + && secret_exists "$PUB_ALIAS"; then + log "RSA keypair ('$PRIV_ALIAS' / '$PUB_ALIAS') already present — skipping." + else + log "Generating RSA keypair ('$PRIV_ALIAS' / '$PUB_ALIAS')..." + umask 077 + dir=$(mktemp -d) + openssl genrsa -out "$dir/k.pem" 2048 2>/dev/null + openssl pkcs8 -topk8 -nocrypt -in "$dir/k.pem" -out "$dir/priv.pem" + openssl rsa -in "$dir/k.pem" -pubout -out "$dir/pub.pem" 2>/dev/null + + put_secret "$PRIV_ALIAS" \ + "$(jq -n --rawfile content "$dir/priv.pem" '{data:{content:$content}}')" + put_secret "$PUB_ALIAS" \ + "$(jq -n --rawfile content "$dir/pub.pem" '{data:{content:$content}}')" + + rm -rf "$dir" + log "RSA keypair stored at $VAULT$SECRETS/data/{$PRIV_ALIAS,$PUB_ALIAS}" + fi + fi + + log "Vault initialization complete." +{{- end }} diff --git a/helm/tractusx-connector/templates/deployment-controlplane.yaml b/helm/tractusx-connector/templates/deployment-controlplane.yaml new file mode 100644 index 0000000..29c619c --- /dev/null +++ b/helm/tractusx-connector/templates/deployment-controlplane.yaml @@ -0,0 +1,378 @@ +################################################################################# + + # Copyright (c) 2026 ARENA2036 e.V. + # Copyright (c) 2023 ZF Friedrichshafen AG + # Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH + # Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + ################################################################################# + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "txdc.fullname" . }}-controlplane + labels: + {{- include "txdc.controlplane.labels" . | nindent 4 }} +spec: + {{- if not .Values.controlplane.autoscaling.enabled }} + replicas: {{ .Values.controlplane.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "txdc.controlplane.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.controlplane.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "txdc.controlplane.selectorLabels" . | nindent 8 }} + {{- with .Values.controlplane.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.controlplane.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "txdc.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.controlplane.podSecurityContext | nindent 8 }} + {{- if or .Values.controlplane.initContainers .Values.customCaCerts }} + initContainers: + {{- if .Values.controlplane.initContainers }} + {{- toYaml .Values.controlplane.initContainers | nindent 8 }} + {{- end }} + {{- if .Values.customCaCerts }} + - name: custom-cacerts + # either use the specified image, or use the default one + {{- if .Values.controlplane.image.repository }} + image: "{{ .Values.controlplane.image.repository }}:{{ .Values.controlplane.image.tag | default .Chart.AppVersion }}" + {{- else }} + image: "tractusx/edc-controlplane-postgresql-hashicorp-vault:{{ .Values.controlplane.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.controlplane.image.pullPolicy }} + command: + - /bin/sh + - -c + - | + cp /opt/java/openjdk/lib/security/cacerts /workdir/ + find /cacerts -type f \( -iname \*.crt -o -iname \*.pem \) -exec echo "{}" \; | while read PEM_FILE_PATH; do + PEM_FILE=${PEM_FILE_PATH##*/} + ALIAS=${PEM_FILE%.*} + echo "adding ${PEM_FILE} with alias ${ALIAS} to cacerts ..." + keytool -import -noprompt -trustcacerts -alias ${ALIAS} -file ${PEM_FILE_PATH} -keystore /workdir/cacerts -storepass changeit + done + securityContext: + {{- toYaml .Values.controlplane.securityContext | nindent 12 }} + volumeMounts: + - name: custom-cacertificates + mountPath: /cacerts + - name: custom-cacerts + mountPath: /workdir + {{- end }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.controlplane.securityContext | nindent 12 }} + + # either use the specified image, or use the default one + {{- if .Values.controlplane.image.repository }} + image: "{{ .Values.controlplane.image.repository }}:{{ .Values.controlplane.image.tag | default .Chart.AppVersion }}" + {{- else }} + image: "tractusx/edc-controlplane-postgresql-hashicorp-vault:{{ .Values.controlplane.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.controlplane.image.pullPolicy }} + args: [ --log-level={{ .Values.controlplane.logs.level | required ".Values.controlplane.logs.level is required" }} ] + ports: + {{- range $key,$value := .Values.controlplane.endpoints }} + - name: {{ $key }} + containerPort: {{ $value.port }} + protocol: TCP + {{- end }} + {{- if .Values.controlplane.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.controlplane.endpoints.default.path }}/check/liveness + port: {{ .Values.controlplane.endpoints.default.port }} + initialDelaySeconds: {{ .Values.controlplane.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.controlplane.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.controlplane.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.controlplane.livenessProbe.failureThreshold }} + successThreshold: {{ .Values.controlplane.livenessProbe.successThreshold }} + {{- end }} + {{- if .Values.controlplane.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.controlplane.endpoints.default.path }}/check/readiness + port: {{ .Values.controlplane.endpoints.default.port }} + initialDelaySeconds: {{ .Values.controlplane.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.controlplane.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.controlplane.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.controlplane.readinessProbe.failureThreshold }} + successThreshold: {{ .Values.controlplane.readinessProbe.successThreshold }} + {{- end }} + resources: + {{- toYaml .Values.controlplane.resources | nindent 12 }} + env: + {{- if .Values.controlplane.debug.enabled }} + - name: "JAVA_TOOL_OPTIONS" + {{- if .Values.controlplane.debug.suspendOnStart }} + value: >- + {{ printf "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=%v" .Values.controlplane.debug.port }} + {{- else }} + value: >- + {{ printf "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=%v" .Values.controlplane.debug.port }} + {{- end }} + {{- end }} + + - name: EDC_HOSTNAME + value: {{ .Values.controlplane.hostname | quote }} + - name: "EDC_SQL_SCHEMA_AUTOCREATE" + value: {{ .Values.controlplane.schema.autocreate | quote }} + + ######################## + ## ID CONFIGURATION ## + ######################## + - name: EDC_PARTICIPANT_ID + value: {{ .Values.iatp.id | required ".Values.iatp.id is required" | quote }} + - name: "EDC_IAM_ISSUER_ID" + value: {{ .Values.iatp.id | required ".Values.iatp.id is required" | quote }} + - name: "EDC_IAM_TRUSTED-ISSUER_EXAMPLE_ID" + value: {{ .Values.iatp.trustedIssuerId | required ".Values.iatp.trustedIssuerId is required" | quote }} + + ########################### + ## LOGGING CONFIGURATION ## + ########################### + {{ if .Values.log4j2.enableJsonLogs}} + - name: LOG4J_CONFIGURATION_FILE + value: "/app/log4j2.yaml" + {{ end }} + + ####### + # API # + ####### + {{- if .Values.controlplane.endpoints.management.jwksUrl }} + - name: "WEB_HTTP_MANAGEMENT_AUTH_DAC_KEY_URL" + value: {{ .Values.controlplane.endpoints.management.jwksUrl | quote}} + - name: "WEB_HTTP_MANAGEMENT_AUTH_TYPE" + value: "delegated" + {{- else }} + - name: "WEB_HTTP_MANAGEMENT_AUTH_KEY" + value: {{ .Values.controlplane.endpoints.management.authKey | required ".Values.controlplane.endpoints.management.authKey is required" | quote }} + - name: "WEB_HTTP_MANAGEMENT_AUTH_TYPE" + value: "tokenbased" + {{- end }} + + - name: "WEB_HTTP_PORT" + value: {{ .Values.controlplane.endpoints.default.port | quote }} + - name: "WEB_HTTP_PATH" + value: {{ .Values.controlplane.endpoints.default.path | quote }} + - name: "WEB_HTTP_MANAGEMENT_PORT" + value: {{ .Values.controlplane.endpoints.management.port | quote }} + - name: "WEB_HTTP_MANAGEMENT_PATH" + value: {{ .Values.controlplane.endpoints.management.path | quote }} + - name: "WEB_HTTP_CONTROL_PORT" + value: {{ .Values.controlplane.endpoints.control.port | quote }} + - name: "WEB_HTTP_CONTROL_PATH" + value: {{ .Values.controlplane.endpoints.control.path | quote }} + - name: "WEB_HTTP_PROTOCOL_PORT" + value: {{ .Values.controlplane.endpoints.protocol.port | quote }} + - name: "WEB_HTTP_PROTOCOL_PATH" + value: {{ .Values.controlplane.endpoints.protocol.path | quote }} + - name: "WEB_HTTP_VALIDATION_PORT" + value: {{ .Values.controlplane.endpoints.validation.port | quote }} + - name: "WEB_HTTP_VALIDATION_PATH" + value: {{ .Values.controlplane.endpoints.validation.path | quote }} + + ######### + ## DSP ## + ######### + + - name: "EDC_DSP_CALLBACK_ADDRESS" + value: {{ printf "%s%s" (include "txdc.controlplane.url.protocol" .) .Values.controlplane.endpoints.protocol.path | quote }} + - name: "EDC_OAUTH_PROVIDER_AUDIENCE" + value: "idsc:IDS_CONNECTORS_ALL" + - name: "EDC_OAUTH_ENDPOINT_AUDIENCE" + value: {{ printf "%s%s" (include "txdc.controlplane.url.protocol" . ) .Values.controlplane.endpoints.protocol.path | quote }} + + ################ + ## POSTGRESQL ## + ################ + + # default datasource + - name: "EDC_DATASOURCE_DEFAULT_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_DEFAULT_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_DEFAULT_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + + + ############################# + ## IATP / STS / DIV CONFIG ## + ############################# + - name: "EDC_IAM_STS_OAUTH_TOKEN_URL" + value: {{ .Values.iatp.sts.oauth.token_url | required ".Values.iatp.sts.oauth.token_url is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_ID" + value: {{ .Values.iatp.sts.oauth.client.id | required ".Values.iatp.sts.oauth.client.id is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS" + value: {{ .Values.iatp.sts.oauth.client.secret_alias | required ".Values.iatp.sts.oauth.client.secret_alias is required" | quote}} + {{- if .Values.iatp.sts.div.url }} + - name: "TX_EDC_IAM_STS_DIV_URL" + value: {{ .Values.iatp.sts.div.url | quote }} + {{- end }} + {{- range $index, $issuer := .Values.iatp.trustedIssuers }} + {{- if eq (kindOf $issuer) "string" }} + - name: "EDC_IAM_TRUSTED-ISSUER_{{$index}}-ISSUER_ID" + value: {{ $issuer | quote }} + {{- else }} + - name: "EDC_IAM_TRUSTED-ISSUER_{{$index}}-ISSUER_ID" + value: {{ $issuer.id | quote }} + {{- if $issuer.supportedTypes }} + - name: "EDC_IAM_TRUSTED-ISSUER_{{$index}}-ISSUER_SUPPORTEDTYPES" + value: {{ $issuer.supportedTypes | toJson | quote }} + {{- end }} + {{- end }} + {{- end }} + - name: "TX_EDC_DID_SERVICE_SELF_REGISTRATION_ENABLED" + value: {{ .Values.iatp.didService.selfRegistration.enabled | quote}} + - name: "TX_EDC_DID_SERVICE_SELF_DEREGISTRATION_ENABLED" + value: {{ and (eq (int .Values.controlplane.replicaCount) 1) (not .Values.controlplane.autoscaling.enabled) | quote }} + - name: "TX_EDC_DID_SERVICE_SELF_REGISTRATION_ID" + value: {{ .Values.iatp.didService.selfRegistration.id | quote }} + - name: "TX_EDC_DCP_CACHE_ENABLED" + value: {{ .Values.iatp.cache.enabled | quote }} + - name: "TX_EDC_DCP_CACHE_VALIDITY_SECONDS" + value: {{ .Values.iatp.cache.validity | quote }} + + ########### + ## VAULT ## + ########### + + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/common/vault/vault-hashicorp + - name: "EDC_VAULT_HASHICORP_URL" + value: {{ tpl .Values.vault.hashicorp.url . | quote }} + - name: "EDC_VAULT_HASHICORP_TOKEN" + value: {{ .Values.vault.hashicorp.token | required ".Values.vault.hashicorp.token is required" | quote }} + - name: "EDC_VAULT_HASHICORP_TIMEOUT_SECONDS" + value: {{ .Values.vault.hashicorp.timeout | quote }} + - name: "EDC_VAULT_HASHICORP_HEALTH_CHECK_ENABLED" + value: {{ .Values.vault.hashicorp.healthCheck.enabled | quote }} + - name: "EDC_VAULT_HASHICORP_HEALTH_CHECK_STANDBY_OK" + value: {{ .Values.vault.hashicorp.healthCheck.standbyOk | quote }} + - name: "EDC_VAULT_HASHICORP_API_SECRET_PATH" + value: {{ .Values.vault.hashicorp.paths.secret | quote }} + - name: "EDC_VAULT_HASHICORP_API_HEALTH_CHECK_PATH" + value: {{ .Values.vault.hashicorp.paths.health | quote }} + {{- if .Values.vault.hashicorp.paths.folder }} + - name: "EDC_VAULT_HASHICORP_FOLDER" + value: {{ .Values.vault.hashicorp.paths.folder | quote }} + {{- end }} + + ################### + ## POLICY ENGINE ## + ################### + - name: "EDC_POLICY_VALIDATION_ENABLED" + value: {{ .Values.controlplane.policy.validation.enabled | quote }} + + ###################################### + ## Additional environment variables ## + ###################################### + + - name: "EDC_RUNTIME_ID" + value: {{ include "txdc.fullname" .}}-controlplane + {{- range $key, $value := .Values.controlplane.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 16 }} + {{- end }} + {{- range $key, $value := .Values.controlplane.env }} + - name: {{ $key | quote }} + value: {{ $value | quote }} + {{- end }} + {{- if and (or .Values.controlplane.envSecretNames .Values.controlplane.envConfigMapNames) (or (gt (len .Values.controlplane.envSecretNames) 0) (gt (len .Values.controlplane.envConfigMapNames) 0)) }} + envFrom: + {{- range $value := .Values.controlplane.envSecretNames }} + - secretRef: + name: {{ $value | quote }} + {{- end }} + {{- range $value := .Values.controlplane.envConfigMapNames }} + - configMapRef: + name: {{ $value | quote }} + {{- end }} + {{- end }} + volumeMounts: + {{- if .Values.controlplane.volumeMounts }} + {{- toYaml .Values.controlplane.volumeMounts | nindent 12 }} + {{- end}} + - name: "configuration" + mountPath: "/app/opentelemetry.properties" + subPath: "opentelemetry.properties" + - name: log4j2-config + mountPath: /app/log4j2.yaml + subPath: log4j2.yaml + {{- if .Values.customCaCerts }} + - name: custom-cacerts + mountPath: /opt/java/openjdk/lib/security/cacerts + subPath: cacerts + {{- end }} + - name: "tmp" + mountPath: "/tmp" + volumes: + {{- if .Values.controlplane.volumeMounts }} + {{- toYaml .Values.controlplane.volumes | nindent 8 }} + {{- end}} + - name: "configuration" + configMap: + name: {{ include "txdc.fullname" . }}-controlplane + items: + - key: "opentelemetry.properties" + path: "opentelemetry.properties" + - name: "log4j2-config" + configMap: + name: {{ include "txdc.fullname" . }}-log4j2 + items: + - key: "log4j2.yaml" + path: "log4j2.yaml" + {{- if .Values.customCaCerts }} + - name: custom-cacertificates + configMap: + name: {{ include "txdc.fullname" . }}-custom-cacerts + defaultMode: 0400 + - name: custom-cacerts + emptyDir: + sizeLimit: 1Mi + {{- end }} + - name: "tmp" + emptyDir: { } + {{- with .Values.controlplane.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controlplane.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controlplane.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/tractusx-connector/templates/deployment-dataplane.yaml b/helm/tractusx-connector/templates/deployment-dataplane.yaml new file mode 100644 index 0000000..9f7d234 --- /dev/null +++ b/helm/tractusx-connector/templates/deployment-dataplane.yaml @@ -0,0 +1,374 @@ +################################################################################# + + # Copyright (c) 2026 ARENA2036 e.V. + # Copyright (c) 2023 ZF Friedrichshafen AG + # Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH + # Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0. + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + ################################################################################# + + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "txdc.fullname" . }}-dataplane + labels: + {{- include "txdc.dataplane.labels" . | nindent 4 }} +spec: + {{- if not .Values.dataplane.autoscaling.enabled }} + replicas: {{ .Values.dataplane.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "txdc.dataplane.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.dataplane.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "txdc.dataplane.selectorLabels" . | nindent 8 }} + {{- with .Values.dataplane.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.dataplane.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "txdc.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.dataplane.podSecurityContext | nindent 8 }} + {{- if or .Values.dataplane.initContainers .Values.customCaCerts }} + initContainers: + {{- if .Values.dataplane.initContainers }} + {{- toYaml .Values.dataplane.initContainers | nindent 8 }} + {{- end }} + {{- if .Values.customCaCerts }} + - name: custom-cacerts + # either use the specified image, or use the default one + {{- if .Values.dataplane.image.repository }} + image: "{{ .Values.dataplane.image.repository }}:{{ .Values.dataplane.image.tag | default .Chart.AppVersion }}" + {{- else }} + image: "tractusx/edc-dataplane-hashicorp-vault:{{ .Values.dataplane.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.dataplane.image.pullPolicy }} + command: + - /bin/sh + - -c + - | + cp /opt/java/openjdk/lib/security/cacerts /workdir/ + find /cacerts -type f \( -iname \*.crt -o -iname \*.pem \) -exec echo "{}" \; | while read PEM_FILE_PATH; do + PEM_FILE=${PEM_FILE_PATH##*/} + ALIAS=${PEM_FILE%.*} + echo "adding ${PEM_FILE} with alias ${ALIAS} to cacerts ..." + keytool -import -noprompt -trustcacerts -alias ${ALIAS} -file ${PEM_FILE_PATH} -keystore /workdir/cacerts -storepass changeit + done + securityContext: + {{- toYaml .Values.dataplane.securityContext | nindent 12 }} + volumeMounts: + - name: custom-cacertificates + mountPath: /cacerts + - name: custom-cacerts + mountPath: /workdir + {{- end }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.dataplane.securityContext | nindent 12 }} + {{- if .Values.dataplane.image.repository }} + image: "{{ .Values.dataplane.image.repository }}:{{ .Values.dataplane.image.tag | default .Chart.AppVersion }}" + {{- else }} + image: "tractusx/edc-dataplane-hashicorp-vault:{{ .Values.dataplane.image.tag | default .Chart.AppVersion }}" + {{- end }} + imagePullPolicy: {{ .Values.dataplane.image.pullPolicy }} + args: [ --log-level={{ .Values.dataplane.logs.level | required ".Values.dataplane.logs.level is required" }} ] + ports: + {{- range $key,$value := .Values.dataplane.endpoints }} + - name: {{ $key }} + containerPort: {{ $value.port }} + protocol: TCP + {{- end }} + {{- if .Values.dataplane.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.dataplane.endpoints.default.path }}/check/liveness + port: {{ .Values.dataplane.endpoints.default.port }} + initialDelaySeconds: {{ .Values.dataplane.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.dataplane.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.dataplane.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.dataplane.livenessProbe.failureThreshold }} + successThreshold: {{ .Values.dataplane.livenessProbe.successThreshold }} + {{- end }} + {{- if .Values.dataplane.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: {{ .Values.dataplane.endpoints.default.path }}/check/readiness + port: {{ .Values.dataplane.endpoints.default.port }} + initialDelaySeconds: {{ .Values.dataplane.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.dataplane.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.dataplane.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.dataplane.readinessProbe.failureThreshold }} + successThreshold: {{ .Values.dataplane.readinessProbe.successThreshold }} + {{- end }} + resources: + {{- toYaml .Values.dataplane.resources | nindent 12 }} + env: + {{- if .Values.dataplane.debug.enabled }} + - name: "JAVA_TOOL_OPTIONS" + {{- if .Values.dataplane.debug.suspendOnStart }} + value: >- + {{ printf "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=%v" .Values.dataplane.debug.port }} + {{- else }} + value: >- + {{ printf "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=%v" .Values.dataplane.debug.port }} + {{- end }} + {{- end }} + - name: EDC_HOSTNAME + value: {{ .Values.dataplane.hostname | quote }} + - name: "EDC_SQL_SCHEMA_AUTOCREATE" + value: {{ .Values.dataplane.schema.autocreate | quote }} + + ######################## + ## ID CONFIGURATION ## + ######################## + - name: EDC_PARTICIPANT_ID + value: {{ .Values.participant.id | required ".Values.participant.id is required" | quote }} + - name: "EDC_IAM_ISSUER_ID" + value: {{ .Values.iatp.id | required ".Values.iatp.id is required" | quote}} + - name: "EDC_IAM_TRUSTED-ISSUER_EXAMPLE_ID" + value: {{ .Values.iatp.trustedIssuerId | required ".Values.iatp.trustedIssuerId is required" | quote}} + + ########################### + ## LOGGING CONFIGURATION ## + ########################### + {{ if .Values.log4j2.enableJsonLogs}} + - name: LOG4J_CONFIGURATION_FILE + value: "/app/log4j2.yaml" + {{ end }} + + ####### + # API # + ####### + - name: "WEB_HTTP_MANAGEMENT_PORT" + value: {{ .Values.dataplane.endpoints.management.port | quote }} + - name: "WEB_HTTP_MANAGEMENT_PATH" + value: {{ .Values.dataplane.endpoints.management.path | quote }} + - name: "TX_EDC_DPF_CONSUMER_PROXY_AUTH_APIKEY" + value: {{ .Values.dataplane.endpoints.proxy.authKey | required ".Values.dataplane.endpoints.proxy.authKey is required" | quote }} + - name: "WEB_HTTP_PORT" + value: {{ .Values.dataplane.endpoints.default.port | quote }} + - name: "WEB_HTTP_PATH" + value: {{ .Values.dataplane.endpoints.default.path | quote }} + - name: "WEB_HTTP_CONTROL_PORT" + value: {{ .Values.dataplane.endpoints.control.port | quote }} + - name: "WEB_HTTP_CONTROL_PATH" + value: {{ .Values.dataplane.endpoints.control.path | quote }} + - name: "WEB_HTTP_PUBLIC_PORT" + value: {{ .Values.dataplane.endpoints.public.port | quote }} + - name: "WEB_HTTP_PUBLIC_PATH" + value: {{ .Values.dataplane.endpoints.public.path | quote }} + - name: "EDC_CONTROL_ENDPOINT" + value: {{ include "txdc.dataplane.url.control" . }} + - name: "EDC_DPF_SELECTOR_URL" + value: {{ include "txdc.controlplane.url.control" . }}/v1/dataplanes + + ####### + # AWS # + ####### + {{- if .Values.dataplane.aws.endpointOverride }} + - name: "EDC_AWS_ENDPOINT_OVERRIDE" + value: {{ .Values.dataplane.aws.endpointOverride | quote }} + {{- end }} + {{- if .Values.dataplane.aws.secretAccessKey }} + - name: "AWS_SECRET_ACCESS_KEY" + value: {{ .Values.dataplane.aws.secretAccessKey | quote }} + {{- end }} + {{- if .Values.dataplane.aws.accessKeyId }} + - name: "AWS_ACCESS_KEY_ID" + value: {{ .Values.dataplane.aws.accessKeyId | quote }} + {{- end }} + + ########### + ## VAULT ## + ########### + + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/common/vault/vault-hashicorp + - name: "EDC_VAULT_HASHICORP_URL" + value: {{ tpl .Values.vault.hashicorp.url . | quote }} + - name: "EDC_VAULT_HASHICORP_TOKEN" + value: {{ .Values.vault.hashicorp.token | required ".Values.vault.hashicorp.token is required" | quote }} + - name: "EDC_VAULT_HASHICORP_TIMEOUT_SECONDS" + value: {{ .Values.vault.hashicorp.timeout | quote }} + - name: "EDC_VAULT_HASHICORP_HEALTH_CHECK_ENABLED" + value: {{ .Values.vault.hashicorp.healthCheck.enabled | quote }} + - name: "EDC_VAULT_HASHICORP_HEALTH_CHECK_STANDBY_OK" + value: {{ .Values.vault.hashicorp.healthCheck.standbyOk | quote }} + - name: "EDC_VAULT_HASHICORP_API_SECRET_PATH" + value: {{ .Values.vault.hashicorp.paths.secret | quote }} + - name: "EDC_VAULT_HASHICORP_API_HEALTH_CHECK_PATH" + value: {{ .Values.vault.hashicorp.paths.health | quote }} + {{- if .Values.vault.hashicorp.paths.folder }} + - name: "EDC_VAULT_HASHICORP_FOLDER" + value: {{ .Values.vault.hashicorp.paths.folder | quote }} + {{ end }} + + ############################# + ## IATP / STS / DIV CONFIG ## + ############################# + - name: "EDC_IAM_STS_OAUTH_TOKEN_URL" + value: {{ .Values.iatp.sts.oauth.token_url | required ".Values.iatp.sts.oauth.token_url is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_ID" + value: {{ .Values.iatp.sts.oauth.client.id | required ".Values.iatp.sts.oauth.client.id is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS" + value: {{ .Values.iatp.sts.oauth.client.secret_alias | required ".Values.iatp.sts.oauth.client.secret_alias is required" | quote}} + {{- if .Values.iatp.sts.div.url }} + - name: "TX_EDC_IAM_STS_DIV_URL" + value: {{ .Values.iatp.sts.div.url | quote }} + {{- end }} + + ################ + ## POSTGRESQL ## + ################ + + # default datasource + - name: "EDC_DATASOURCE_DEFAULT_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_DEFAULT_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_DEFAULT_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + + ######################### + ## DATA PLANE PUBLIC API + ######################## + - name: "EDC_DATAPLANE_API_PUBLIC_BASEURL" + value: {{ include "txdc.dataplane.url.public" . }} + + + ################## + ## TOKEN REFRESH + ################## + {{- if .Values.dataplane.token.refresh.expiry_seconds }} + - name: "TX_EDC_DATAPLANE_TOKEN_EXPIRY" + value: {{ .Values.dataplane.token.refresh.expiry_seconds | quote}} + {{- end}} + + {{- if .Values.dataplane.token.refresh.expiry_tolerance_seconds }} + - name: "TX_EDC_DATAPLANE_TOKEN_EXPIRY_TOLERANCE" + value: {{ .Values.dataplane.token.refresh.expiry_tolerance_seconds | quote }} + {{- end}} + + {{- if .Values.dataplane.token.refresh.refresh_endpoint }} + - name: "TX_EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" + value: {{ .Values.dataplane.token.refresh.refresh_endpoint }} + {{- else}} + - name: "TX_EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" + value: {{ include "txdc.dataplane.url.public" . }}/token + {{- end}} + + - name: "EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS" + value: {{ .Values.dataplane.token.signer.privatekey_alias | required ".Values.dataplane.token.signer.privatekey_alias is required" | quote}} + + - name: "EDC_TRANSFER_PROXY_TOKEN_VERIFIER_PUBLICKEY_ALIAS" + value: {{ .Values.dataplane.token.verifier.publickey_alias | required ".Values.dataplane.token.verifier.publickey_alias" | quote }} + + ###################################### + ## Additional environment variables ## + ###################################### + - name: "EDC_RUNTIME_ID" + value: {{ include "txdc.fullname" .}}-dataplane + {{- range $key, $value := .Values.dataplane.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 16 }} + {{- end }} + {{- range $key, $value := .Values.dataplane.env }} + - name: {{ $key | quote }} + value: {{ $value | quote }} + {{- end }} + {{- if and (or .Values.dataplane.envSecretNames .Values.dataplane.envConfigMapNames) (or (gt (len .Values.dataplane.envSecretNames) 0) (gt (len .Values.dataplane.envConfigMapNames) 0)) }} + envFrom: + {{- range $value := .Values.dataplane.envSecretNames }} + - secretRef: + name: {{ $value | quote }} + {{- end }} + {{- range $value := .Values.dataplane.envConfigMapNames }} + - configMapRef: + name: {{ $value | quote }} + {{- end }} + {{- end }} + volumeMounts: + {{- if .Values.dataplane.volumeMounts }} + {{- toYaml .Values.dataplane.volumeMounts | nindent 12 }} + {{- end}} + - name: "configuration" + mountPath: "/app/opentelemetry.properties" + subPath: "opentelemetry.properties" + - name: log4j2-config + mountPath: /app/log4j2.yaml + subPath: log4j2.yaml + {{- if .Values.customCaCerts }} + - name: custom-cacerts + mountPath: /opt/java/openjdk/lib/security/cacerts + subPath: cacerts + {{- end }} + - name: "tmp" + mountPath: "/tmp" + volumes: + {{- if .Values.dataplane.volumeMounts }} + {{- toYaml .Values.dataplane.volumes | nindent 8 }} + {{- end}} + - name: "configuration" + configMap: + name: {{ include "txdc.fullname" . }}-dataplane + items: + - key: "opentelemetry.properties" + path: "opentelemetry.properties" + - name: "log4j2-config" + configMap: + name: {{ include "txdc.fullname" . }}-log4j2 + items: + - key: "log4j2.yaml" + path: "log4j2.yaml" + {{- if .Values.customCaCerts }} + - name: custom-cacertificates + configMap: + name: {{ include "txdc.fullname" . }}-custom-cacerts + defaultMode: 0400 + - name: custom-cacerts + emptyDir: + sizeLimit: 1Mi + {{- end }} + - name: "tmp" + emptyDir: { } + {{- with .Values.dataplane.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.dataplane.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.dataplane.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/tractusx-connector/templates/hpa-controlplane.yaml b/helm/tractusx-connector/templates/hpa-controlplane.yaml new file mode 100644 index 0000000..3195a12 --- /dev/null +++ b/helm/tractusx-connector/templates/hpa-controlplane.yaml @@ -0,0 +1,52 @@ +################################################################################# +# Copyright (c) 2023 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +{{- if .Values.controlplane.autoscaling.enabled }} +--- +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "txdc.fullname" . }}-controlplane + labels: + {{- include "txdc.controlplane.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "txdc.fullname" . }}-controlplane + minReplicas: {{ .Values.controlplane.autoscaling.minReplicas }} + maxReplicas: {{ .Values.controlplane.autoscaling.maxReplicas }} + metrics: + {{- if .Values.controlplane.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.controlplane.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.controlplane.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.controlplane.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/tractusx-connector/templates/hpa-dataplane.yaml b/helm/tractusx-connector/templates/hpa-dataplane.yaml new file mode 100644 index 0000000..9e3f769 --- /dev/null +++ b/helm/tractusx-connector/templates/hpa-dataplane.yaml @@ -0,0 +1,52 @@ +################################################################################# +# Copyright (c) 2023 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +{{- if .Values.controlplane.autoscaling.enabled }} +--- +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "txdc.fullname" . }}-dataplane + labels: + {{- include "txdc.dataplane.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "txdc.fullname" . }}-dataplane + minReplicas: {{ .Values.dataplane.autoscaling.minReplicas }} + maxReplicas: {{ .Values.dataplane.autoscaling.maxReplicas }} + metrics: + {{- if .Values.dataplane.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.dataplane.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.dataplane.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.dataplane.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/tractusx-connector/templates/ingress-controlplane.yaml b/helm/tractusx-connector/templates/ingress-controlplane.yaml new file mode 100644 index 0000000..624eac3 --- /dev/null +++ b/helm/tractusx-connector/templates/ingress-controlplane.yaml @@ -0,0 +1,86 @@ +################################################################################# +# Copyright (c) 2023 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +{{- $fullName := include "txdc.fullname" . }} +{{- $controlLabels := include "txdc.controlplane.labels" . }} +{{- $controlEdcEndpoints := .Values.controlplane.endpoints }} +{{- $namespace := .Release.Namespace }} + +{{- range .Values.controlplane.ingresses }} +{{- if and .enabled .endpoints }} +{{- $controlIngressName := printf "%s-controlplane-%s" $fullName .hostname }} +{{- $annotations := .annotations | default dict }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $controlIngressName }} + namespace: {{ $namespace | default "default" | quote }} + labels: + {{- $controlLabels | nindent 4 }} + annotations: + {{- if .certManager }} + {{- if .certManager.issuer }} + {{- $_ := set $annotations "cert-manager.io/issuer" .certManager.issuer}} + {{- end }} + {{- if .certManager.clusterIssuer }} + {{- $_ := set $annotations "cert-manager.io/cluster-issuer" .certManager.clusterIssuer}} + {{- end }} + {{- end }} + {{- with $annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .className }} + ingressClassName: {{ .className }} + {{- end }} + {{- if .hostname }} + {{- if .tls.enabled }} + tls: + - hosts: + - {{ .hostname }} + {{- if .tls.secretName }} + secretName: {{ .tls.secretName }} + {{- else }} + secretName: {{ $controlIngressName }}-tls + {{- end }} + {{- end }} + rules: + - host: {{ .hostname }} + http: + paths: + {{- $ingressEdcEndpoints := .endpoints }} + {{- range $name, $mapping := $controlEdcEndpoints }} + {{- if (has $name $ingressEdcEndpoints) }} + - path: {{ $mapping.path }} + pathType: Prefix + backend: + service: + name: {{ $fullName }}-controlplane + port: + number: {{ $mapping.port }} + {{- end }} + {{- end }} + {{- end }} +{{- end }}{{- /* end: if .enabled */}} +{{- end }}{{- /* end: range .Values.ingresses */}} diff --git a/helm/tractusx-connector/templates/ingress-dataplane.yaml b/helm/tractusx-connector/templates/ingress-dataplane.yaml new file mode 100644 index 0000000..9d5653f --- /dev/null +++ b/helm/tractusx-connector/templates/ingress-dataplane.yaml @@ -0,0 +1,86 @@ +################################################################################# +# Copyright (c) 2023 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +{{- $fullName := include "txdc.fullname" . }} +{{- $dataLabels := include "txdc.dataplane.labels" . }} +{{- $dataEdcEndpoints := .Values.dataplane.endpoints }} +{{- $namespace := .Release.Namespace }} + +{{- range .Values.dataplane.ingresses }} +{{- if and .enabled .endpoints }} +{{- $dataIngressName := printf "%s-dataplane-%s" $fullName .hostname }} +{{- $annotations := .annotations | default dict }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $dataIngressName }} + namespace: {{ $namespace | default "default" | quote }} + labels: + {{- $dataLabels | nindent 4 }} + annotations: + {{- if .certManager }} + {{- if .certManager.issuer }} + {{- $_ := set $annotations "cert-manager.io/issuer" .certManager.issuer}} + {{- end }} + {{- if .certManager.clusterIssuer }} + {{- $_ := set $annotations "cert-manager.io/cluster-issuer" .certManager.clusterIssuer}} + {{- end }} + {{- end }} + {{- with $annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .className }} + ingressClassName: {{ .className }} + {{- end }} + {{- if .hostname }} + {{- if .tls.enabled }} + tls: + - hosts: + - {{ .hostname }} + {{- if .tls.secretName }} + secretName: {{ .tls.secretName }} + {{- else }} + secretName: {{ $dataIngressName }}-tls + {{- end }} + {{- end }} + rules: + - host: {{ .hostname }} + http: + paths: + {{- $ingressEdcEndpoints := .endpoints }} + {{- range $name, $mapping := $dataEdcEndpoints }} + {{- if (has $name $ingressEdcEndpoints) }} + - path: {{ $mapping.path }} + pathType: Prefix + backend: + service: + name: {{ $fullName }}-dataplane + port: + number: {{ $mapping.port }} + {{- end }} + {{- end }} + {{- end }} +{{- end }}{{- /* end: if .enabled */}} +{{- end }}{{- /* end: range .Values.ingresses */}} diff --git a/helm/tractusx-connector/templates/job-vault-init.yaml b/helm/tractusx-connector/templates/job-vault-init.yaml new file mode 100644 index 0000000..f284147 --- /dev/null +++ b/helm/tractusx-connector/templates/job-vault-init.yaml @@ -0,0 +1,87 @@ +################################################################################# +# Copyright (c) 2026 Zentralverband der Deutschen Elektro- und Informationstechnischen Handwerke (ZVEH) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +{{ if .Values.vault.hashicorp.init.enabled -}} +{{- $fullName := .Values.fullnameOverride -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ $fullName }}-vault-init + namespace: {{ .Release.Namespace | default "default" | quote }} + labels: + {{- include "txdc.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "0" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + backoffLimit: 3 + ttlSecondsAfterFinished: 600 + activeDeadlineSeconds: 300 + template: + metadata: + labels: + {{- include "txdc.labels" . | nindent 8 }} + spec: + restartPolicy: OnFailure + serviceAccountName: {{ include "txdc.serviceAccountName" . }} + containers: + - name: vault-init + {{- $img := index .Values "vault" "hashicorp" "init" "image" | default dict }} + image: {{ $img.repository | default "alpine" }}:{{ $img.tag | default "3.20" }} + command: ["/bin/sh", "-c"] + args: + - | + tr -d '\r' < /scripts/init.sh > /tmp/init.sh + exec sh /tmp/init.sh + env: + - name: VAULT_ADDR + value: {{ tpl .Values.vault.hashicorp.url . | quote }} + - name: VAULT_TOKEN + value: {{ .Values.vault.hashicorp.token | required "vault.hashicorp.token is required" }} + - name: VAULT_SECRET_PATH + value: {{ .Values.vault.hashicorp.paths.secret | quote }} + - name: VAULT_HEALTH_PATH + value: {{ .Values.vault.hashicorp.paths.health | quote }} + {{- with .Values.vault.hashicorp.init.forceRegenerate }} + - name: FORCE_REGENERATE + value: {{ . | quote }} + {{- end }} + {{- with .Values.vault.hashicorp.init.aesKeyAlias }} + - name: AES_KEY_ALIAS + value: {{ . | quote }} + {{- end }} + {{- with .Values.dataplane.token.signer.privatekey_alias }} + - name: PRIVATE_KEY_ALIAS + value: {{ . | quote }} + {{- end }} + {{- with .Values.dataplane.token.verifier.publickey_alias }} + - name: PUBLIC_KEY_ALIAS + value: {{ . | quote }} + {{- end }} + volumeMounts: + - name: script + mountPath: /scripts + readOnly: true + volumes: + - name: script + configMap: + name: {{ $fullName }}-vault-init + defaultMode: 0555 +{{- end }} diff --git a/helm/tractusx-connector/templates/networkpolicy.yaml b/helm/tractusx-connector/templates/networkpolicy.yaml new file mode 100644 index 0000000..8904146 --- /dev/null +++ b/helm/tractusx-connector/templates/networkpolicy.yaml @@ -0,0 +1,46 @@ +################################################################################# +# Copyright (c) 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +{{- if eq (.Values.networkPolicy.enabled | toString) "true" }} +{{- range tuple "controlplane" "dataplane" }} +{{- $name := . }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "txdc.fullname" $ }}-{{ $name }} + labels: + {{- include (printf "txdc.%s.labels" $name) $ | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include (printf "txdc.%s.selectorLabels" $name) $ | nindent 6 }} + ingress: + - from: + {{- toYaml (index $.Values.networkPolicy $name "from") | nindent 6 }} + ports: + {{- range $key,$value := (index $.Values $name "endpoints") }} + - port: {{ $value.port }} + protocol: TCP + {{- end }} + policyTypes: + - Ingress +--- +{{- end }} +{{- end }} diff --git a/helm/tractusx-connector/templates/service-controlplane.yaml b/helm/tractusx-connector/templates/service-controlplane.yaml new file mode 100644 index 0000000..400a5d8 --- /dev/null +++ b/helm/tractusx-connector/templates/service-controlplane.yaml @@ -0,0 +1,63 @@ +################################################################################# +# Copyright (c) 2023.2024 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2024 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "txdc.fullname" . }}-controlplane + namespace: {{ .Release.Namespace }} + {{- with .Values.controlplane.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "txdc.controlplane.labels" . | nindent 4 }} + {{- with .Values.controlplane.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.controlplane.service.type }} + ports: + - port: {{ .Values.controlplane.endpoints.default.port }} + targetPort: default + protocol: TCP + name: default + - port: {{ .Values.controlplane.endpoints.control.port }} + targetPort: control + protocol: TCP + name: control + - port: {{ .Values.controlplane.endpoints.management.port }} + targetPort: management + protocol: TCP + name: management + - port: {{ .Values.controlplane.endpoints.protocol.port }} + targetPort: protocol + protocol: TCP + name: protocol + - port: {{ .Values.controlplane.endpoints.metrics.port }} + targetPort: metrics + protocol: TCP + name: metrics + selector: + {{- include "txdc.controlplane.selectorLabels" . | nindent 4 }} diff --git a/helm/tractusx-connector/templates/service-dataplane.yaml b/helm/tractusx-connector/templates/service-dataplane.yaml new file mode 100644 index 0000000..6b6e35a --- /dev/null +++ b/helm/tractusx-connector/templates/service-dataplane.yaml @@ -0,0 +1,64 @@ +################################################################################# +# Copyright (c) 2023,2024 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2024 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "txdc.fullname" . }}-dataplane + namespace: {{ .Release.Namespace }} + {{- with .Values.dataplane.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "txdc.dataplane.labels" . | nindent 4 }} + {{- with .Values.dataplane.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.dataplane.service.type }} + ports: + - port: {{ .Values.dataplane.endpoints.default.port }} + targetPort: default + protocol: TCP + name: default + - port: {{ .Values.dataplane.endpoints.control.port }} + targetPort: control + protocol: TCP + name: control + - port: {{ .Values.dataplane.endpoints.public.port }} + targetPort: public + protocol: TCP + name: public + - port: {{ .Values.dataplane.endpoints.metrics.port }} + targetPort: metrics + protocol: TCP + name: metrics + - port: {{ .Values.dataplane.endpoints.proxy.port }} + targetPort: proxy + protocol: TCP + name: proxy + + selector: + {{- include "txdc.dataplane.selectorLabels" . | nindent 4 }} diff --git a/helm/tractusx-connector/templates/serviceaccount.yaml b/helm/tractusx-connector/templates/serviceaccount.yaml new file mode 100644 index 0000000..ae9ac61 --- /dev/null +++ b/helm/tractusx-connector/templates/serviceaccount.yaml @@ -0,0 +1,40 @@ +################################################################################# +# Copyright (c) 2023 ZF Friedrichshafen AG +# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +{{- if .Values.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "txdc.serviceAccountName" . }} + labels: + {{- include "txdc.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.serviceAccount.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} diff --git a/helm/tractusx-connector/templates/tests/test-dataplane-readiness.yaml b/helm/tractusx-connector/templates/tests/test-dataplane-readiness.yaml new file mode 100644 index 0000000..fa58c7d --- /dev/null +++ b/helm/tractusx-connector/templates/tests/test-dataplane-readiness.yaml @@ -0,0 +1,43 @@ +# + # Copyright (c) 2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + # + +--- +apiVersion: v1 +kind: Pod +metadata: + name: "{{include "txdc.fullname" .}}test-dataplane-readiness" + labels: + {{- include "txdc.dataplane.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": {{ .Values.tests.hookDeletePolicy }} +spec: + containers: + - name: wget + image: curlimages/curl + command: [ 'curl', '--fail' ] + args: [ '{{- printf "http://%s-dataplane:%v%s/check/readiness" (include "txdc.fullname" $ ) $.Values.dataplane.endpoints.default.port $.Values.dataplane.endpoints.default.path -}}' ] + restartPolicy: Never + securityContext: + fsGroup: 101 # curl_group + runAsGroup: 101 # curl_group + runAsNonRoot: true + runAsUser: 100 # curl_user + seccompProfile: + type: RuntimeDefault diff --git a/helm/tractusx-connector/templates/tests/test-mgmt-api-fails-without-auth.yaml b/helm/tractusx-connector/templates/tests/test-mgmt-api-fails-without-auth.yaml new file mode 100644 index 0000000..a37fc60 --- /dev/null +++ b/helm/tractusx-connector/templates/tests/test-mgmt-api-fails-without-auth.yaml @@ -0,0 +1,44 @@ +# +# Copyright (c) 2025 Cofinity-X GmbH +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +--- +apiVersion: v1 +kind: Pod +metadata: + name: "controlplane-without-token-auth-test" + labels: + {{- include "txdc.controlplane.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test-failure + "helm.sh/hook-delete-policy": {{ .Values.tests.hookDeletePolicy }} +spec: + containers: + {{/* Try calling a management API endpoint without authorization header */}} + - name: management-api-call-without-auth + image: curlimages/curl + command: [ 'curl', '-X', 'GET', '--fail' ] + args: [ '{{- printf "http://%s-controlplane:%v%s/v3/business-partner-groups/groups" (include "txdc.fullname" $ ) $.Values.controlplane.endpoints.management.port $.Values.controlplane.endpoints.management.path -}}' ] + restartPolicy: Never + securityContext: + fsGroup: 101 # curl_group + runAsGroup: 101 # curl_group + runAsNonRoot: true + runAsUser: 100 # curl_user + seccompProfile: + type: RuntimeDefault diff --git a/helm/tractusx-connector/templates/tests/test-mgmt-api-with-token-auth.yaml b/helm/tractusx-connector/templates/tests/test-mgmt-api-with-token-auth.yaml new file mode 100644 index 0000000..7ee31cd --- /dev/null +++ b/helm/tractusx-connector/templates/tests/test-mgmt-api-with-token-auth.yaml @@ -0,0 +1,56 @@ +# + # Copyright (c) 2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + # License for the specific language governing permissions and limitations + # under the License. + # + # SPDX-License-Identifier: Apache-2.0 + # + +--- +apiVersion: v1 +kind: Pod +metadata: + name: "controlplane-with-token-auth-test" + labels: + {{- include "txdc.controlplane.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test + "helm.sh/hook-delete-policy": {{ .Values.tests.hookDeletePolicy }} +spec: + containers: + {{/* Poke the pod's management API */}} + - name: readiness + image: curlimages/curl + command: [ 'curl', '--fail' ] + args: [ '{{- printf "http://%s-controlplane:%v%s/check/readiness" (include "txdc.fullname" $ ) $.Values.controlplane.endpoints.default.port $.Values.controlplane.endpoints.default.path -}}' ] + + {{/* Try adding a BPN Group to the store via the management API */}} + - name: bpn-store + image: curlimages/curl + command: [ 'curl', '-X', 'POST', '--fail','-H','Content-Type: application/json', '-H', '{{- printf "x-api-key: %s" $.Values.controlplane.endpoints.management.authKey }}', '-d', '{ + "@context": { + "tx": "https://w3id.org/tractusx/v0.0.1/ns/" + }, + "@id": "tx:BPN000001234", + "tx:groups": ["group1", "group2", "group3"] + }' ] + args: [ '{{- printf "http://%s-controlplane:%v%s/v3/business-partner-groups" (include "txdc.fullname" $ ) $.Values.controlplane.endpoints.management.port $.Values.controlplane.endpoints.management.path -}}' ] + restartPolicy: Never + securityContext: + fsGroup: 101 # curl_group + runAsGroup: 101 # curl_group + runAsNonRoot: true + runAsUser: 100 # curl_user + seccompProfile: + type: RuntimeDefault diff --git a/helm/tractusx-connector/values-consumer.yaml b/helm/tractusx-connector/values-consumer.yaml new file mode 100644 index 0000000..40f950c --- /dev/null +++ b/helm/tractusx-connector/values-consumer.yaml @@ -0,0 +1,124 @@ +shared: + connectorId: &connectorId did:web:consumer-wallet.staging.construct-x.net:consumer + secretAlias: &secretAlias consumersecret + trustedIssuerId: &trustedIssuerId did:web:issuer.staging.construct-x.net:issuer + clusterIssuer: &clusterIssuer letsencrypt-staging + ingressClass: &ingressClass nginx + imagePullSecret: &imagePullSecret registry-creds + controlplaneFqdn: &controlplaneFqdn consumer-edc-controlplane.staging.construct-x.net + dataplaneFqdn: &dataplaneFqdn consumer-edc-dataplane.staging.construct-x.net + +nameOverride: consumer-edc +fullnameOverride: consumer-edc + +participant: + id: *connectorId + +iatp: + id: *connectorId + trustedIssuerId: *trustedIssuerId + trustedIssuers: + - id: *trustedIssuerId + sts: + oauth: + token_url: https://consumer-wallet.staging.construct-x.net/api/sts/token + client: + id: *connectorId + secret_alias: *secretAlias + didService: + selfRegistration: + id: *connectorId + +controlplane: + hostname: consumer-edc-controlplane + imagePullSecrets: + - name: *imagePullSecret + ingresses: + ## Public / Internet facing Ingress + - enabled: true + hostname: *controlplaneFqdn + annotations: + cert-manager.io/cluster-issuer: *clusterIssuer + external-dns.alpha.kubernetes.io/hostname: *controlplaneFqdn + external-dns.alpha.kubernetes.io/ttl: "300" + endpoints: + - protocol + className: *ingressClass + tls: + enabled: true + secretName: consumer-edc-cp-tls + certManager: + clusterIssuer: *clusterIssuer + ## Private / Intranet facing Ingress + - enabled: false + hostname: *controlplaneFqdn + annotations: + cert-manager.io/cluster-issuer: *clusterIssuer + external-dns.alpha.kubernetes.io/hostname: *controlplaneFqdn + external-dns.alpha.kubernetes.io/ttl: "300" + endpoints: + - management + - control + - validation + - metrics + className: *ingressClass + tls: + enabled: true + secretName: consumer-edc-cp-int-tls + certManager: + clusterIssuer: *clusterIssuer + +dataplane: + hostname: consumer-edc-dataplane + imagePullSecrets: + - name: *imagePullSecret + token: + signer: + privatekey_alias: cons_priv + verifier: + publickey_alias: cons_pub + ingresses: + ## Public / Internet facing Ingress + - enabled: true + hostname: *dataplaneFqdn + annotations: + cert-manager.io/cluster-issuer: *clusterIssuer + external-dns.alpha.kubernetes.io/hostname: *dataplaneFqdn + external-dns.alpha.kubernetes.io/ttl: "300" + endpoints: + - public + - proxy + className: *ingressClass + tls: + enabled: true + secretName: consumer-edc-dp-tls + certManager: + clusterIssuer: *clusterIssuer + ## Private / Intranet facing Ingress + - enabled: false + hostname: *dataplaneFqdn + annotations: + cert-manager.io/cluster-issuer: *clusterIssuer + external-dns.alpha.kubernetes.io/hostname: *dataplaneFqdn + external-dns.alpha.kubernetes.io/ttl: "300" + endpoints: + - management + - control + - metrics + className: *ingressClass + tls: + enabled: true + secretName: consumer-edc-dp-int-tls + certManager: + clusterIssuer: *clusterIssuer + +postgresql: + persistence: + enabled: true + size: 10Gi + storageClass: "" + +vault: + hashicorp: + init: + enabled: true \ No newline at end of file diff --git a/helm/tractusx-connector/values-provider.yaml b/helm/tractusx-connector/values-provider.yaml new file mode 100644 index 0000000..937f669 --- /dev/null +++ b/helm/tractusx-connector/values-provider.yaml @@ -0,0 +1,124 @@ +shared: + connectorId: &connectorId did:web:provider-wallet.staging.construct-x.net:provider + secretAlias: &secretAlias providersecret + trustedIssuerId: &trustedIssuerId did:web:issuer.staging.construct-x.net:issuer + clusterIssuer: &clusterIssuer letsencrypt-staging + ingressClass: &ingressClass nginx + imagePullSecret: &imagePullSecret registry-creds + controlplaneFqdn: &controlplaneFqdn provider-edc-controlplane.staging.construct-x.net + dataplaneFqdn: &dataplaneFqdn provider-edc-dataplane.staging.construct-x.net + +nameOverride: provider-edc +fullnameOverride: provider-edc + +participant: + id: *connectorId + +iatp: + id: *connectorId + trustedIssuerId: *trustedIssuerId + trustedIssuers: + - id: *trustedIssuerId + sts: + oauth: + token_url: https://provider-wallet.staging.construct-x.net/api/sts/token + client: + id: *connectorId + secret_alias: *secretAlias + didService: + selfRegistration: + id: *connectorId + +controlplane: + hostname: provider-edc-controlplane + imagePullSecrets: + - name: *imagePullSecret + ingresses: + ## Public / Internet facing Ingress + - enabled: true + hostname: *controlplaneFqdn + annotations: + cert-manager.io/cluster-issuer: *clusterIssuer + external-dns.alpha.kubernetes.io/hostname: *controlplaneFqdn + external-dns.alpha.kubernetes.io/ttl: "300" + endpoints: + - protocol + className: *ingressClass + tls: + enabled: true + secretName: provider-edc-cp-tls + certManager: + clusterIssuer: *clusterIssuer + ## Private / Intranet facing Ingress + - enabled: false + hostname: *controlplaneFqdn + annotations: + cert-manager.io/cluster-issuer: *clusterIssuer + external-dns.alpha.kubernetes.io/hostname: *controlplaneFqdn + external-dns.alpha.kubernetes.io/ttl: "300" + endpoints: + - management + - control + - validation + - metrics + className: *ingressClass + tls: + enabled: true + secretName: provider-edc-cp-int-tls + certManager: + clusterIssuer: *clusterIssuer + +dataplane: + hostname: provider-edc-dataplane + imagePullSecrets: + - name: *imagePullSecret + token: + signer: + privatekey_alias: prov_priv + verifier: + publickey_alias: prov_pub + ingresses: + ## Public / Internet facing Ingress + - enabled: true + hostname: *dataplaneFqdn + annotations: + cert-manager.io/cluster-issuer: *clusterIssuer + external-dns.alpha.kubernetes.io/hostname: *dataplaneFqdn + external-dns.alpha.kubernetes.io/ttl: "300" + endpoints: + - public + - proxy + className: *ingressClass + tls: + enabled: true + secretName: provider-edc-dp-tls + certManager: + clusterIssuer: *clusterIssuer + ## Private / Intranet facing Ingress + - enabled: false + hostname: *dataplaneFqdn + annotations: + cert-manager.io/cluster-issuer: *clusterIssuer + external-dns.alpha.kubernetes.io/hostname: *dataplaneFqdn + external-dns.alpha.kubernetes.io/ttl: "300" + endpoints: + - management + - control + - metrics + className: *ingressClass + tls: + enabled: true + secretName: provider-edc-dp-int-tls + certManager: + clusterIssuer: *clusterIssuer + +postgresql: + persistence: + enabled: true + size: 10Gi + storageClass: "" + +vault: + hashicorp: + init: + enabled: true \ No newline at end of file diff --git a/helm/tractusx-connector/values.yaml b/helm/tractusx-connector/values.yaml new file mode 100644 index 0000000..6c0c72c --- /dev/null +++ b/helm/tractusx-connector/values.yaml @@ -0,0 +1,778 @@ +################################################################################# +# Copyright (c) 2026 ARENA2036 e.V. +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +--- +# Default values for eclipse-dataspace-connector. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +install: + # -- Deploying a PostgreSQL instance + postgresql: true + # -- Deploying a HashiCorp Vault instance + vault: true + +fullnameOverride: "" +nameOverride: "" + +# -- Existing image pull secret to use to [obtain the container image from private registries](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) +imagePullSecrets: [] +# -- Add some custom labels +customLabels: {} + +participant: + id: "did:web:changeme" + +iatp: + # -- Decentralized IDentifier (DID) of the connector + id: "did:web:changeme" + # -- ID of the trusted issuer that is used for SI token validation (maps to EDC_IAM_TRUSTED-ISSUER_EXAMPLE_ID) + trustedIssuerId: "change-me" + # -- Configures the trusted issuers for this runtime. If no supportedTypes are specified, the value defaults to "*" for that issuer + trustedIssuers: [] + # - id: "did:web:example1.com" + # supportedTypes: + # - "MembershipCredential" + # - "did:web:example2.com" + sts: + div: + # -- URL where connectors can request SI tokens + url: + oauth: + # -- URL where connectors can request OAuth2 access tokens for DIV access + token_url: "https://change-me" + client: + # -- Client ID for requesting OAuth2 access token for DIV access + id: "change-me" + # -- Alias under which the client secret is stored in the vault for requesting OAuth2 access token for DIV access + secret_alias: "change-me" + didService: + selfRegistration: + # -- Whether Service Self Registration is enabled + enabled: false + # -- Unique id of connector to be used for register / unregister service inside did document (must be valid URI) + id: "did:web:changeme" + # - Configures the Verifiable Presentation cache + cache: + # -- Whether the Verifiable Presentation cache is enabled + enabled: true + # -- Validity of the Verifiable Presentation cache in seconds + validity: 86400 + +# -- Add custom ca certificates to the truststore +customCaCerts: {} + +log4j2: + # -- Whether to enable the json log config in log4j2.config + enableJsonLogs: true + # -- Log4j2 configuration for json log formatting. + config: |- + Appenders: + Console: + name: CONSOLE + JsonTemplateLayout: + eventTemplate: |- + { + "timestamp": { + "$resolver": "timestamp", + "pattern": { + "format": "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS", + "timeZone": "UTC" + } + }, + "level": { + "$resolver": "level", + "field": "severity", + "severity": { + "field": "keyword" + } + }, + "message": { + "$resolver": "message" + } + } + Loggers: + Root: + level: "OFF" + Logger: + name: org.eclipse.edc.monitor.logger + level: DEBUG + AppenderRef: + ref: CONSOLE + +controlplane: + nameOverride: "" + fullnameOverride: "" + # -- hostname where the controlplane is reachable + hostname: "" + image: + # -- Which derivate of the control plane to use. When left empty the deployment will select the correct image automatically + repository: "ghcr.io/project-construct-x/con-x-controlplane-postgresql-hashicorp-vault" + # -- [Kubernetes image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy) to use + pullPolicy: IfNotPresent + # -- Overrides the image tag whose default is the chart appVersion + tag: "latest" + # -- Configure ghcr credentials to pull the control plane image + imagePullSecrets: + - name: ghcr-creds + initContainers: [] + debug: + # -- Enables java debugging mode. + enabled: false + # -- Port where the debuggee can connect to. + port: 1044 + # -- Defines if the JVM should wait with starting the application until someone connected to the debugging port. + suspendOnStart: false + + logs: + # -- Defines the log granularity of the default Console Monitor. + level: DEBUG + + livenessProbe: + # -- Whether to enable kubernetes [liveness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) + enabled: true + # -- seconds to wait before performing the first liveness check + initialDelaySeconds: 30 + # -- this fields specifies that kubernetes should perform a liveness check every 10 seconds + periodSeconds: 10 + # -- number of seconds after which the probe times out + timeoutSeconds: 5 + # -- when a probe fails kubernetes will try 6 times before giving up + failureThreshold: 6 + # -- number of consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + readinessProbe: + # -- Whether to enable kubernetes [readiness-probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) + enabled: true + # -- seconds to wait before performing the first readiness check + initialDelaySeconds: 30 + # -- this fields specifies that kubernetes should perform a readiness check every 10 seconds + periodSeconds: 10 + # -- number of seconds after which the probe times out + timeoutSeconds: 5 + # -- when a probe fails kubernetes will try 6 times before giving up + failureThreshold: 6 + # -- number of consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + + # -- endpoints of the control plane + endpoints: + # -- default api for health checks, should not be added to any ingress + default: + # -- port for incoming api calls + port: 9000 + # -- path for incoming api calls + path: /api + # -- data management api, used by internal users, can be added to an ingress and must not be internet facing + management: + # -- port for incoming api calls + port: 9010 + # -- path for incoming api calls + path: /management + # -- authentication key, must be attached to each request as `X-Api-Key` header + authKey: "password" + # -- if the JWKS url is set, the DelegatedAuth service will be engaged + jwksUrl: + + # -- control api, used for internal control calls. can be added to the internal ingress, but should probably not + control: + # -- port for incoming api calls + port: 9050 + # -- path for incoming api calls + path: /control + # -- dsp api, used for inter connector communication and must be internet facing + protocol: + # -- port for incoming api calls + port: 9020 + # -- path for incoming api calls + path: /dsp + # -- validation api + validation: + # -- port for incoming api calls + port: 9030 + # -- path for incoming api calls + path: /validation + # -- metrics api, used for application metrics, must not be internet facing + metrics: + # -- port for incoming api calls + port: 9090 + # -- path for incoming api calls + path: /metrics + + bdrs: + # -- Time that a cached BPN/DID resolution map is valid in seconds, default is 600 seconds (10 min) + cache_validity_seconds: 600 + server: + # -- URL of the BPN/DID Resolution Service + url: + + # -- configuration for policy engine + policy: + validation: + enabled: true + + service: + # -- [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. + type: ClusterIP + # -- additional labels for the service + labels: {} + # -- additional annotations for the service + annotations: {} + + # -- additional labels for the pod + podLabels: {} + # -- additional annotations for the pod + podAnnotations: {} + # -- The [pod security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) defines privilege and access control settings for a Pod within the deployment + podSecurityContext: + seccompProfile: + # -- Restrict a Container's Syscalls with seccomp + type: RuntimeDefault + # -- Runs all processes within a pod with a special uid + runAsUser: 10001 + # -- Processes within a pod will belong to this guid + runAsGroup: 10001 + # -- The owner for volumes and any files created within volumes will belong to this guid + fsGroup: 10001 + # The [container security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) defines privilege and access control settings for a Container within a pod + securityContext: + capabilities: + # -- Specifies which capabilities to drop to reduce syscall attack surface + drop: + - ALL + # -- Specifies which capabilities to add to issue specialized syscalls + add: [] + # -- Whether the root filesystem is mounted in read-only mode + readOnlyRootFilesystem: true + # -- Controls [Privilege Escalation](https://kubernetes.io/docs/concepts/security/pod-security-policy/#privilege-escalation) enabling setuid binaries changing the effective user ID + allowPrivilegeEscalation: false + # -- Requires the container to run without root privileges + runAsNonRoot: true + # -- The container's process will run with the specified uid + runAsUser: 10001 + + # -- Extra environment variables that will be passed onto deployment pods + env: + EDC_IAM_DID_WEB_USE_HTTPS: true + TX_EDC_POSTGRESQL_MIGRATION_ASSET_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_AGREEMENTBPNS_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_BPN_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_CONTRACTDEFINITION_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_CONTRACTNEGOTIATION_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_DATAPLANEINSTANCE_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_EDR_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_FEDERATEDCATALOG_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_JTI-VALIDATION_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_POLICY-MONITOR_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_POLICY_ENABLED: false + TX_EDC_POSTGRESQL_MIGRATION_TRANSFERPROCESS_ENABLED: false + EDC_IAM_CREDENTIAL_REVOCATION_MIMETYPE: application/json + TX_EDC_IAM_IATP_DEFAULT-SCOPES_TEST_ALIAS: org.eclipse.dspace.dcp.vc.type + TX_EDC_IAM_IATP_DEFAULT-SCOPES_TEST_TYPE: MembershipCredential + TX_EDC_IAM_IATP_DEFAULT-SCOPES_TEST_OPERATION: read + + # -- "valueFrom" environment variable references that will be added to deployment pods. Name is templated. + # ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core + envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + # secretKeyRef: + # name: secret-name + # key: value_key + + # -- [Kubernetes Secret Resource](https://kubernetes.io/docs/concepts/configuration/secret/) names to load environment variables from + envSecretNames: [] + # - first-secret + # - second-secret + + # -- [Kubernetes ConfigMap Resource](https://kubernetes.io/docs/concepts/configuration/configmap/) names to load environment variables from + envConfigMapNames: [] + # - first-config-map + # - second-config-map + + # Database schema auto-creation + schema: + autocreate: true + + ## Ingress declaration to expose the network service. + ingresses: + ## Public / Internet facing Ingress + - enabled: true + # -- The hostname to be used to precisely map incoming traffic onto the underlying network service + hostname: "edc-control.local" + # -- Additional ingress annotations to add + annotations: {} + # -- EDC endpoints exposed by this ingress resource + endpoints: + - protocol + # -- Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use + className: "" + # -- TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource + tls: + # -- Enables TLS on the ingress resource + enabled: false + # -- If present overwrites the default secret name + secretName: "" + ## Adds [cert-manager](https://cert-manager.io/docs/) annotations to the ingress resource + certManager: + # -- If preset enables certificate generation via cert-manager namespace scoped issuer + issuer: "" + # -- If preset enables certificate generation via cert-manager cluster-wide issuer + clusterIssuer: "" + ## Private / Intranet facing Ingress + - enabled: true + # -- The hostname to be used to precisely map incoming traffic onto the underlying network service + hostname: "edc-control.intranet" + # -- Additional ingress annotations to add + annotations: {} + # -- EDC endpoints exposed by this ingress resource + endpoints: + - management + - control + - validation + - metrics + # -- Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use + className: "" + # -- TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource + tls: + # -- Enables TLS on the ingress resource + enabled: false + # -- If present overwrites the default secret name + secretName: "" + ## Adds [cert-manager](https://cert-manager.io/docs/) annotations to the ingress resource + certManager: + # -- If preset enables certificate generation via cert-manager namespace scoped issuer + issuer: "" + # -- If preset enables certificate generation via cert-manager cluster-wide issuer + clusterIssuer: "" + + # -- declare where to mount [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) into the container + volumeMounts: + # -- [volume](https://kubernetes.io/docs/concepts/storage/volumes/) directories + volumes: + + # -- [resource management](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the container + resources: + limits: + # -- Maximum CPU limit + cpu: 1.5 + # -- Maximum memory limit + memory: 1024Mi + requests: + # -- Initial CPU request + cpu: 500m + # -- Initial memory request + memory: 1024Mi + + replicaCount: 1 + + autoscaling: + # -- Enables [horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) + enabled: false + # -- Minimal replicas if resource consumption falls below resource threshholds + minReplicas: 1 + # -- Maximum replicas if resource consumption exceeds resource threshholds + maxReplicas: 100 + # -- targetAverageUtilization of cpu provided to a pod + targetCPUUtilizationPercentage: 80 + # -- targetAverageUtilization of memory provided to a pod + targetMemoryUtilizationPercentage: 80 + + # -- configuration of the [Open Telemetry Agent](https://opentelemetry.io/docs/instrumentation/java/automatic/agent-config/) to collect and expose metrics + opentelemetry: |- + otel.javaagent.enabled=false + otel.javaagent.debug=false + + # -- [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) to constrain pods to nodes + nodeSelector: {} + # -- [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to configure preferred nodes + tolerations: [] + # -- [affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) to configure which nodes the pods can be scheduled on + affinity: {} + + url: + # -- Explicitly declared url for reaching the dsp api (e.g. if ingresses not used) + protocol: "" + +dataplane: + nameOverride: "" + fullnameOverride: "" + # -- hostname where the dataplane is reachable + hostname: "" + image: + # -- Which derivate of the data plane to use. when left empty the deployment will select the correct image automatically + repository: "ghcr.io/project-construct-x/con-x-dataplane-postgresql-hashicorp-vault" + # -- [Kubernetes image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy) to use + pullPolicy: IfNotPresent + # -- Overrides the image tag whose default is the chart appVersion + tag: "latest" + # -- Configure ghcr credentials to pull the control plane image + imagePullSecrets: + - name: ghcr-creds + initContainers: [] + debug: + # -- Enables java debugging mode. + enabled: false + # -- Port where the debuggee can connect to. + port: 1044 + # -- Defines if the JVM should wait with starting the application until someone connected to the debugging port. + suspendOnStart: false + + logs: + # -- Defines the log granularity of the default Console Monitor. + level: DEBUG + + livenessProbe: + # -- Whether to enable kubernetes [liveness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) + enabled: true + # -- seconds to wait before performing the first liveness check + initialDelaySeconds: 30 + # -- this fields specifies that kubernetes should perform a liveness check every 10 seconds + periodSeconds: 10 + # -- number of seconds after which the probe times out + timeoutSeconds: 5 + # -- when a probe fails kubernetes will try 6 times before giving up + failureThreshold: 6 + # -- number of consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + readinessProbe: + # -- Whether to enable kubernetes [readiness-probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) + enabled: true + # -- seconds to wait before performing the first readiness check + initialDelaySeconds: 30 + # -- this fields specifies that kubernetes should perform a liveness check every 10 seconds + periodSeconds: 10 + # -- number of seconds after which the probe times out + timeoutSeconds: 5 + # -- when a probe fails kubernetes will try 6 times before giving up + failureThreshold: 6 + # -- number of consecutive successes for the probe to be considered successful after having failed + successThreshold: 1 + + service: + # -- [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. + type: ClusterIP + # -- additional labels for the service + labels: {} + # -- additional annotations for the service + annotations: {} + + # -- endpoints of the dataplane + endpoints: + # -- default api for health checks, should not be added to any ingress + default: + # -- port for incoming api calls + port: 8181 + # -- path for incoming api calls + path: /api + # -- public endpoint where the data can be fetched from if HttpPull was used. Must be internet facing. + public: + # -- port for incoming api calls + port: 9500 + # -- path for incoming api calls + path: /public + # -- control api, used for internal control calls. can be added to the internal ingress, but should probably not + control: + # -- port for incoming api calls + port: 9550 + # -- path for incoming api calls + path: /control + # -- data management api + management: + # -- port for incoming api calls + port: 9510 + # -- path for incoming api calls + path: /management + # -- proxy api for consumer data transfer + proxy: + # -- port for incoming api calls + port: 9511 + # -- path for incoming api calls + path: /proxy + # -- authentication key, must be attached to each request as `X-Api-Key` header + authKey: "password" + # -- metrics api, used for application metrics, must not be internet facing + metrics: + # -- port for incoming api calls + port: 9090 + # -- path for incoming api calls + path: /metrics + + token: + refresh: + # -- TTL in seconds for access tokens (also known as EDR token) + expiry_seconds: 300 + # -- Tolerance for token expiry in seconds + expiry_tolerance_seconds: 10 + # -- Optional endpoint for an OAuth2 token refresh. Default endpoint is `/token` + refresh_endpoint: + signer: + # -- Alias under which the private key (JWK or PEM format) is stored in the vault + privatekey_alias: priv + verifier: + # -- Alias under which the public key (JWK or PEM format) is stored in the vault, that belongs to the private key which was referred to at `dataplane.token.signer.privatekey_alias` + publickey_alias: pub + + # Database schema auto-creation + schema: + autocreate: true + + aws: + endpointOverride: "" + accessKeyId: "" + secretAccessKey: "" + + # -- additional labels for the pod + podLabels: {} + # -- additional annotations for the pod + podAnnotations: {} + # -- The [pod security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) defines privilege and access control settings for a Pod within the deployment + podSecurityContext: + seccompProfile: + # -- Restrict a Container's Syscalls with seccomp + type: RuntimeDefault + # -- Runs all processes within a pod with a special uid + runAsUser: 10001 + # -- Processes within a pod will belong to this guid + runAsGroup: 10001 + # -- The owner for volumes and any files created within volumes will belong to this guid + fsGroup: 10001 + # -- The [container security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) defines privilege and access control settings for a Container within a pod + securityContext: + capabilities: + # -- Specifies which capabilities to drop to reduce syscall attack surface + drop: + - ALL + # -- Specifies which capabilities to add to issue specialized syscalls + add: [] + # -- Whether the root filesystem is mounted in read-only mode + readOnlyRootFilesystem: true + # -- Controls [Privilege Escalation](https://kubernetes.io/docs/concepts/security/pod-security-policy/#privilege-escalation) enabling setuid binaries changing the effective user ID + allowPrivilegeEscalation: false + # -- Requires the container to run without root privileges + runAsNonRoot: true + # -- The container's process will run with the specified uid + runAsUser: 10001 + + # -- Extra environment variables that will be passed onto deployment pods + env: + EDC_IAM_DID_WEB_USE_HTTPS: true + EDC_DATA_PLANE_SELF_UNREGISTRATION: true + EDC_IAM_CREDENTIAL_REVOCATION_MIMETYPE: application/json + + # -- "valueFrom" environment variable references that will be added to deployment pods. Name is templated. + # ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core + envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + # secretKeyRef: + # name: secret-name + # key: value_key + + # -- [Kubernetes Secret Resource](https://kubernetes.io/docs/concepts/configuration/secret/) names to load environment variables from + envSecretNames: [] + # - first-secret + # - second-secret + + # -- [Kubernetes ConfigMap Resource](https://kubernetes.io/docs/concepts/configuration/configmap/) names to load environment variables from + envConfigMapNames: [] + # - first-config-map + # - second-config-map + + ## Ingress declaration to expose the network service. + ingresses: + ## Public / Internet facing Ingress + - enabled: true + # -- The hostname to be used to precisely map incoming traffic onto the underlying network service + hostname: "edc-data.local" + # -- Additional ingress annotations to add + annotations: {} + # -- EDC endpoints exposed by this ingress resource + endpoints: + - public + - proxy + # -- Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use + className: "" + # -- TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource + tls: + # -- Enables TLS on the ingress resource + enabled: false + # -- If present overwrites the default secret name + secretName: "" + ## Adds [cert-manager](https://cert-manager.io/docs/) annotations to the ingress resource + certManager: + # -- If preset enables certificate generation via cert-manager namespace scoped issuer + issuer: "" + # -- If preset enables certificate generation via cert-manager cluster-wide issuer + clusterIssuer: "" + ## Private / Intranet facing Ingress + - enabled: true + # -- The hostname to be used to precisely map incoming traffic onto the underlying network service + hostname: "edc-data.intranet" + # -- Additional ingress annotations to add + annotations: {} + # -- EDC endpoints exposed by this ingress resource + endpoints: + - management + - control + - metrics + # -- Defines the [ingress class](https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class) to use + className: "" + # -- TLS [tls class](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls) applied to the ingress resource + tls: + # -- Enables TLS on the ingress resource + enabled: false + # -- If present overwrites the default secret name + secretName: "" + ## Adds [cert-manager](https://cert-manager.io/docs/) annotations to the ingress resource + certManager: + # -- If preset enables certificate generation via cert-manager namespace scoped issuer + issuer: "" + # -- If preset enables certificate generation via cert-manager cluster-wide issuer + clusterIssuer: "" + + # -- declare where to mount [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) into the container + volumeMounts: + # -- [volume](https://kubernetes.io/docs/concepts/storage/volumes/) directories + volumes: + + # -- [resource management](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the container + resources: + limits: + # -- Maximum CPU limit + cpu: 1.5 + # -- Maximum memory limit + memory: 1024Mi + requests: + # -- Initial CPU request + cpu: 500m + # -- Initial memory request + memory: 1024Mi + + replicaCount: 1 + + autoscaling: + # -- Enables [horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) + enabled: false + # -- Minimal replicas if resource consumption falls below resource threshholds + minReplicas: 1 + # -- Maximum replicas if resource consumption exceeds resource threshholds + maxReplicas: 100 + # -- targetAverageUtilization of cpu provided to a pod + targetCPUUtilizationPercentage: 80 + # -- targetAverageUtilization of memory provided to a pod + targetMemoryUtilizationPercentage: 80 + + # -- configuration of the [Open Telemetry Agent](https://opentelemetry.io/docs/instrumentation/java/automatic/agent-config/) to collect and expose metrics + opentelemetry: |- + otel.javaagent.enabled=false + otel.javaagent.debug=false + + # -- [node selector](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) to constrain pods to nodes + nodeSelector: {} + # -- [tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) to configure preferred nodes + tolerations: [] + # -- [affinity](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) to configure which nodes the pods can be scheduled on + affinity: {} + url: + # -- Explicitly declared url for reaching the public api (e.g. if ingresses not used) + public: "" + +postgresql: + # JDBC connection URL passed to the edc runtime. + jdbcUrl: "jdbc:postgresql://{{ .Release.Name }}-postgresql:5432/edc" + auth: + # Name of the PostgreSQL database created on first start. Must match with postgresql.jdbcUrl path. + database: "edc" + # PostgreSQL user that the issuer-wallet connects as. + username: "user" + # Password for the PostgreSQL user. Change before production use. + password: "password" + persistence: + # Persist data across pod restarts. + enabled: true + size: 10Gi + storageClass: "" + # Initialization scripts ConfigMap + initdb: + scriptsConfigMap: "" # Optional: ConfigMap with init scripts + resources: + limits: + cpu: 500m + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + +vault: + injector: + enabled: false + server: + dev: + enabled: true + devRootToken: "root" + postStart: # must be set externally! + hashicorp: + url: "http://{{ .Release.Name }}-vault:8200" + token: "root" + timeout: 30 + healthCheck: + enabled: true + standbyOk: true + paths: + secret: /v1/secret + health: /v1/sys/health + folder: "" + init: + # Whether to run the post-install vault-init job that seeds required secrets. Creates RSA Keys for dataplane.token.signer and dataplane.token.verifier. + enabled: false + +networkPolicy: + # -- If `true` network policy will be created to restrict access to control- and dataplane + enabled: false + # -- Configuration of the controlplane component + controlplane: + # -- Specify from rule network policy for cp (defaults to all namespaces) + from: + - namespaceSelector: {} + # -- Configuration of the dataplane component + dataplane: + # -- Specify from rule network policy for dp (defaults to all namespaces) + from: + - namespaceSelector: {} + +serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + # -- Existing image pull secret bound to the service account to use to [obtain the container image from private registries](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) + imagePullSecrets: [] + +# -- Configurations for Helm tests +tests: + # -- Configure the hook-delete-policy for Helm tests + hookDeletePolicy: before-hook-creation,hook-succeeded From d5f260508f91d0272e59760eab724d734079c357 Mon Sep 17 00:00:00 2001 From: Simon Bergerfurth Date: Wed, 2 Sep 2026 11:38:40 +0200 Subject: [PATCH 3/3] docs: add edc third party content to notice file --- NOTICE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NOTICE.md b/NOTICE.md index b07dfdb..9c19c90 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -12,6 +12,8 @@ There are third-party contents used by and shipped with this project with differ The Constuct-X wallet Helm charts are based on [Tractus-X IdentityHub Helm charts](https://github.com/eclipse-tractusx/tractusx-identityhub). +The Constuct-X EDC Helm charts are based on [Tractus-X EDC Helm charts](https://github.com/eclipse-tractusx/tractusx-edc). + ### Code of Conduct The `CODE_OF_CONDUCT.md` is adapted from the Contributor Covenant, version 3.0, permanently available at [https://www.contributor-covenant.org/version/3/0/](https://www.contributor-covenant.org/version/3/0/). Contributor Covenant is stewarded by the Organization for Ethical Source and licensed under CC BY-SA 4.0. To view a copy of this license, visit [https://creativecommons.org/licenses/by-sa/4.0/](https://creativecommons.org/licenses/by-sa/4.0/).