From 72a57da8b4f771526637963d0c75b31170366e58 Mon Sep 17 00:00:00 2001 From: Phil Schneider Date: Tue, 26 Mar 2024 18:38:39 +0100 Subject: [PATCH 01/30] adjust dim creation --- src/clients/Dim.Clients/Api/Cf/CfClient.cs | 35 +++++++++++++++++-- src/clients/Dim.Clients/Api/Cf/ICfClient.cs | 1 + .../Dim.Clients/Api/Cf/ServicePlanResponse.cs | 7 +++- .../Dim.Clients/Api/Cf/SpaceResponse.cs | 31 ++++++++++++++++ .../DimProcess.Library/DimProcessHandler.cs | 11 ++---- 5 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 src/clients/Dim.Clients/Api/Cf/SpaceResponse.cs diff --git a/src/clients/Dim.Clients/Api/Cf/CfClient.cs b/src/clients/Dim.Clients/Api/Cf/CfClient.cs index 140f84a..721ebcc 100644 --- a/src/clients/Dim.Clients/Api/Cf/CfClient.cs +++ b/src/clients/Dim.Clients/Api/Cf/CfClient.cs @@ -119,7 +119,7 @@ public async Task GetServicePlan(string servicePlanName, string servicePla var servicePlans = response.Resources.Where(x => x.Name == servicePlanType && x.BrokerCatalog?.BrokerCatalogMetadata?.AutoSubscription?.AppName == servicePlanName); - if (response == null || servicePlans.Count() != 1) + if (servicePlans.Count() != 1) { throw new ServiceException($"There must be exactly one service plan with name {servicePlanName} and type {servicePlanType}"); } @@ -132,6 +132,37 @@ public async Task GetServicePlan(string servicePlanName, string servicePla } } + public async Task GetSpace(string tenantName, CancellationToken cancellationToken) + { + var spaceName = $"{tenantName}-space"; + var client = await _basicAuthTokenService.GetBasicAuthorizedLegacyClient(_settings, cancellationToken).ConfigureAwait(false); + var result = await client.GetAsync("/v3/spaces", cancellationToken) + .CatchingIntoServiceExceptionFor("get-space", HttpAsyncResponseMessageExtension.RecoverOptions.ALLWAYS).ConfigureAwait(false); + try + { + var response = await result.Content + .ReadFromJsonAsync(JsonSerializerExtensions.Options, cancellationToken) + .ConfigureAwait(false); + + if (response == null) + { + throw new ServiceException("response should never be null here"); + } + + var spaces = response.Resources.Where(x => x.Name == spaceName); + if (spaces.Count() != 1) + { + throw new ServiceException($"There must be exactly one space with name {spaceName}"); + } + + return spaces.Single().Id; + } + catch (JsonException je) + { + throw new ServiceException(je.Message); + } + } + public async Task CreateDimServiceInstance(string tenantName, Guid spaceId, Guid servicePlanId, CancellationToken cancellationToken) { var client = await _basicAuthTokenService.GetBasicAuthorizedLegacyClient(_settings, cancellationToken).ConfigureAwait(false); @@ -163,7 +194,7 @@ private async Task GetServiceInstances(string tenantName, Guid? spaceId, C } var name = $"{tenantName}-dim-instance"; - var resources = response.Resources.Where(x => x.Name == name && x.Type == "managed" && (spaceId == null || x.Relationships.Space.Data.Id == spaceId.Value)); + var resources = response.Resources.Where(x => x.Name == name && x.Type == "managed" && (spaceId == null || x.Relationships.Space.Data.Id == spaceId.Value) && x.LastOperation.State == "succeeded"); if (resources.Count() != 1) { throw new ServiceException($"There must be exactly one service instance"); diff --git a/src/clients/Dim.Clients/Api/Cf/ICfClient.cs b/src/clients/Dim.Clients/Api/Cf/ICfClient.cs index 603392b..3e41e0f 100644 --- a/src/clients/Dim.Clients/Api/Cf/ICfClient.cs +++ b/src/clients/Dim.Clients/Api/Cf/ICfClient.cs @@ -24,6 +24,7 @@ public interface ICfClient Task CreateCloudFoundrySpace(string tenantName, CancellationToken cancellationToken); Task AddSpaceRoleToUser(string type, string user, Guid spaceId, CancellationToken cancellationToken); Task GetServicePlan(string servicePlanName, string servicePlanType, CancellationToken cancellationToken); + Task GetSpace(string tenantName, CancellationToken cancellationToken); Task CreateDimServiceInstance(string tenantName, Guid spaceId, Guid servicePlanId, CancellationToken cancellationToken); Task CreateServiceInstanceBindings(string tenantName, Guid spaceId, CancellationToken cancellationToken); Task GetServiceBinding(string tenantName, Guid spaceId, string bindingName, CancellationToken cancellationToken); diff --git a/src/clients/Dim.Clients/Api/Cf/ServicePlanResponse.cs b/src/clients/Dim.Clients/Api/Cf/ServicePlanResponse.cs index 248a339..cbdb758 100644 --- a/src/clients/Dim.Clients/Api/Cf/ServicePlanResponse.cs +++ b/src/clients/Dim.Clients/Api/Cf/ServicePlanResponse.cs @@ -52,13 +52,18 @@ public record ServiceInstanceResource( [property: JsonPropertyName("guid")] Guid Id, [property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("type")] string Type, - [property: JsonPropertyName("relationships")] ServiceInstanceRelationship Relationships + [property: JsonPropertyName("relationships")] ServiceInstanceRelationship Relationships, + [property: JsonPropertyName("last_operation")] LastOperation LastOperation ); public record ServiceInstanceRelationship( [property: JsonPropertyName("space")] ServiceInstanceRelationshipSpace Space ); +public record LastOperation( + [property: JsonPropertyName("state")] string State +); + public record ServiceInstanceRelationshipSpace( [property: JsonPropertyName("data")] DimData Data ); diff --git a/src/clients/Dim.Clients/Api/Cf/SpaceResponse.cs b/src/clients/Dim.Clients/Api/Cf/SpaceResponse.cs new file mode 100644 index 0000000..21f9234 --- /dev/null +++ b/src/clients/Dim.Clients/Api/Cf/SpaceResponse.cs @@ -0,0 +1,31 @@ +/******************************************************************************** + * Copyright (c) 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 + ********************************************************************************/ + +using System.Text.Json.Serialization; + +namespace Dim.Clients.Api.Cf; + +public record SpaceResponse( + [property: JsonPropertyName("resources")] IEnumerable Resources +); + +public record Space( + [property: JsonPropertyName("guid")] Guid Id, + [property: JsonPropertyName("name")] string Name +); diff --git a/src/processes/DimProcess.Library/DimProcessHandler.cs b/src/processes/DimProcess.Library/DimProcessHandler.cs index e69912b..fc7d0df 100644 --- a/src/processes/DimProcess.Library/DimProcessHandler.cs +++ b/src/processes/DimProcess.Library/DimProcessHandler.cs @@ -335,14 +335,9 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateDimServiceInstance(string tenantName, Guid tenantId, CancellationToken cancellationToken) { - var spaceId = await _dimRepositories.GetInstance().GetSpaceId(tenantId).ConfigureAwait(false); - if (spaceId == null) - { - throw new ConflictException("SpaceId must not be null."); - } - var servicePlanId = await _cfClient.GetServicePlan("decentralized-identity-management", "standard", cancellationToken).ConfigureAwait(false); - await _cfClient.CreateDimServiceInstance(tenantName, spaceId.Value, servicePlanId, cancellationToken).ConfigureAwait(false); + var spaceId = await _cfClient.GetSpace(tenantName, cancellationToken).ConfigureAwait(false); + await _cfClient.CreateDimServiceInstance(tenantName, spaceId, servicePlanId, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.CREATE_SERVICE_INSTANCE_BINDING, 1), @@ -358,7 +353,7 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe { throw new ConflictException("SpaceId must not be null."); } - + await _cfClient.CreateServiceInstanceBindings(tenantName, spaceId.Value, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( From 1c21f65bd715832e43b204767b4d8b30765b48c9 Mon Sep 17 00:00:00 2001 From: Evelyn Gurschler Date: Thu, 28 Mar 2024 17:09:17 +0100 Subject: [PATCH 02/30] chore: enable workflows, docker images and helm chart (#1) * add helm chart * add dockerfiles * add workflows * change header * remove eclipse code of conduct --------- Reviewed-by: Phil Schneider --- .github/dependabot.yml | 57 ++++ .github/pull_request_template.md | 22 ++ .github/workflows/chart-release.yaml | 86 ++++++ .github/workflows/chart-test.yml | 128 +++++++++ .github/workflows/codeql.yml | 105 ++++++++ .github/workflows/kics.yml | 75 ++++++ .github/workflows/lint-pull-request.yml | 61 +++++ .github/workflows/migrations-docker.yml | 84 ++++++ .github/workflows/owasp-zap.yml | 142 ++++++++++ .github/workflows/processes-worker-docker.yml | 83 ++++++ .github/workflows/release-please.yml | 41 +++ .github/workflows/release.yml | 151 +++++++++++ .github/workflows/service-docker.yml | 83 ++++++ .github/workflows/sonarcloud.yml | 79 ++++++ .github/workflows/trivy.yml | 170 ++++++++++++ .github/workflows/unit.tests-formatting.yml | 56 ++++ CHANGELOG.md | 0 CODE_OF_CONDUCT.md | 93 ------- README.md | 49 ++++ charts/chart-testing-config.yaml | 22 ++ charts/dim/.helmignore | 27 ++ charts/dim/Chart.yaml | 31 +++ charts/dim/LICENSE | 201 ++++++++++++++ charts/dim/README.md | 134 +++++++++ charts/dim/README.md.gotmpl | 37 +++ charts/dim/templates/_helpers.tpl | 128 +++++++++ .../templates/configmap-postgres-init.yaml | 35 +++ charts/dim/templates/cronjob-processes.yaml | 123 +++++++++ charts/dim/templates/deployment.yaml | 131 +++++++++ charts/dim/templates/ingress.yaml | 80 ++++++ charts/dim/templates/job-migrations.yaml | 77 ++++++ charts/dim/templates/secret-external-db.yaml | 39 +++ charts/dim/templates/secret-postgres.yaml | 45 ++++ charts/dim/templates/secret.yaml | 47 ++++ charts/dim/templates/service.yaml | 33 +++ charts/dim/values.yaml | 255 ++++++++++++++++++ .../argocd-app-templates/appsetup-dev.yaml | 41 +++ .../argocd-app-templates/appsetup-int.yaml | 38 +++ consortia/environments/values-dev.yaml | 93 +++++++ consortia/environments/values-int.yaml | 84 ++++++ docker/Dockerfile-dim-migrations | 36 +++ docker/Dockerfile-dim-processes-worker | 36 +++ docker/Dockerfile-dim-service | 37 +++ .../Api/Cf/AddSpaceRoleToUserRequest.cs | 2 +- src/clients/Dim.Clients/Api/Cf/CfClient.cs | 2 +- .../Dim.Clients/Api/Cf/CreateCfeRequest.cs | 2 +- .../CfClientServiceExtensions.cs | 2 +- .../Api/Cf/DependencyInjection/CfSettings.cs | 2 +- src/clients/Dim.Clients/Api/Cf/ICfClient.cs | 2 +- .../Dim.Clients/Api/Cf/ServicePlanResponse.cs | 2 +- .../Api/Dim/ApplicationResponse.cs | 2 +- .../Api/Dim/CompanyIdentityPatch.cs | 2 +- .../Api/Dim/CreateApplicationRequest.cs | 2 +- .../Api/Dim/CreateCompanyIdentityRequest.cs | 2 +- .../DimClientServiceExtensions.cs | 2 +- src/clients/Dim.Clients/Api/Dim/DimClient.cs | 2 +- src/clients/Dim.Clients/Api/Dim/IDimClient.cs | 2 +- .../DirectoryClientServiceExtensions.cs | 2 +- .../DependencyInjection/DirectorySettings.cs | 2 +- .../Api/Directories/DirectoryClient.cs | 2 +- .../Api/Directories/DirectoryRequest.cs | 2 +- .../Api/Directories/IDirectoryClient.cs | 2 +- .../Entitlements/CreateSubAccountRequest.cs | 2 +- .../EntitlementClientServiceExtensions.cs | 2 +- .../EntitlementSettings.cs | 2 +- .../Api/Entitlements/EntitlementClient.cs | 2 +- .../Api/Entitlements/IEntitlementClient.cs | 2 +- .../Api/Provisioning/CreateCfeRequest.cs | 2 +- .../ProvisioningClientServiceExtensions.cs | 2 +- .../ProvisioningSettings.cs | 2 +- .../Api/Provisioning/IProvisioningClient.cs | 2 +- .../Api/Provisioning/ProvisioningClient.cs | 2 +- .../Services/CreateServiceInstanceRequest.cs | 2 +- .../ServiceClientServiceExtensions.cs | 2 +- .../Api/Services/IServiceClient.cs | 2 +- .../Dim.Clients/Api/Services/ServiceClient.cs | 2 +- .../SubAccounts/CreateSubAccountRequest.cs | 2 +- .../SubAccountClientServiceExtensions.cs | 2 +- .../DependencyInjection/SubAccountSettings.cs | 2 +- .../Api/SubAccounts/ISubAccountClient.cs | 2 +- .../Api/SubAccounts/SubAccountClient.cs | 2 +- .../Api/SubAccounts/UsedForProduction.cs | 2 +- .../SubscriptionClientServiceExtensions.cs | 2 +- .../Api/Subscriptions/ISubscriptionClient.cs | 2 +- .../Api/Subscriptions/SubscriptionClient.cs | 2 +- src/clients/Dim.Clients/Dim.Clients.csproj | 2 +- .../Extensions/HttpClientExtensions.cs | 2 +- .../Extensions/JsonSerializerExtensions.cs | 2 +- src/clients/Dim.Clients/Token/AuthResponse.cs | 2 +- .../Dim.Clients/Token/BasicAuthSettings.cs | 2 +- .../Token/BasicAuthTokenService.cs | 2 +- .../Token/GetBasicTokenSettings.cs | 2 +- .../Token/IBasicAuthTokenService.cs | 2 +- .../DimRepositoriesServiceExtensions.cs | 2 +- src/database/Dim.DbAccess/Dim.DbAccess.csproj | 2 +- src/database/Dim.DbAccess/DimRepositories.cs | 2 +- src/database/Dim.DbAccess/IDimRepositories.cs | 2 +- .../Repositories/IProcessStepRepository.cs | 2 +- .../Repositories/ITenantRepository.cs | 2 +- .../Repositories/ProcessStepRepository.cs | 2 +- .../Repositories/TenantRepository.cs | 2 +- src/database/Dim.Entities/Dim.Entities.csproj | 2 +- src/database/Dim.Entities/DimDbContext.cs | 2 +- src/database/Dim.Entities/Entities/Process.cs | 2 +- .../Dim.Entities/Entities/ProcessStep.cs | 2 +- .../Entities/ProcessStepStatus.cs | 2 +- .../Dim.Entities/Entities/ProcessStepType.cs | 2 +- .../Dim.Entities/Entities/ProcessType.cs | 2 +- src/database/Dim.Entities/Entities/Tenant.cs | 2 +- .../Entities/VerifyProcessData.cs | 2 +- .../Dim.Entities/Enums/ProcessStepStatusId.cs | 2 +- .../Dim.Entities/Enums/ProcessStepTypeId.cs | 2 +- .../Dim.Entities/Enums/ProcessTypeId.cs | 2 +- .../Dim.Migrations/Dim.Migrations.csproj | 2 +- .../20240307101150_initial.Designer.cs | 2 +- .../Migrations/20240307101150_initial.cs | 2 +- .../Migrations/DimDbContextModelSnapshot.cs | 2 +- src/database/Dim.Migrations/Program.cs | 2 +- .../DimProcessCollectionExtensions.cs | 2 +- .../DimProcess.Executor.csproj | 2 +- .../DimProcessTypeExecutor.cs | 2 +- .../Callback/CallbackDataModel.cs | 2 +- .../Callback/CallbackService.cs | 2 +- .../CallbackServiceExtensions.cs | 2 +- .../DependencyInjection/CallbackSettings.cs | 2 +- .../Callback/ICallbackService.cs | 2 +- .../DimHandlerExtensions.cs | 2 +- .../DependencyInjection/DimHandlerSettings.cs | 2 +- .../DimProcess.Library.csproj | 2 +- .../DimProcess.Library/DimProcessHandler.cs | 2 +- .../DimProcess.Library/IDimProcessHandler.cs | 2 +- .../ManualProcessStepData.cs | 2 +- .../ManualProcessStepDataExtensions.cs | 2 +- .../Processes.Library.csproj | 2 +- .../IProcessExecutor.cs | 2 +- .../IProcessTypeExecutor.cs | 2 +- .../ProcessExecutionService.cs | 2 +- .../ProcessExecutionServiceExtensions.cs | 2 +- .../ProcessExecutionServiceSettings.cs | 2 +- .../ProcessExecutor.cs | 2 +- .../Processes.Worker.Library.csproj | 2 +- .../Processes.Worker/Processes.Worker.csproj | 2 +- src/processes/Processes.Worker/Program.cs | 2 +- .../Dim.Web/BusinessLogic/DimBusinessLogic.cs | 2 +- src/web/Dim.Web/BusinessLogic/DimSettings.cs | 2 +- .../BusinessLogic/IDimBusinessLogic.cs | 2 +- src/web/Dim.Web/Controllers/DimController.cs | 2 +- .../RouteHandlerBuilderExtensions.cs | 2 +- .../Extensions/ServiceCollectionExtensions.cs | 2 +- src/web/Dim.Web/Models/Constants.cs | 2 +- src/web/Dim.Web/Program.cs | 2 +- .../DimProcessTypeExecutorTests.cs | 2 +- .../DimProcess.Executor.Tests/Usings.cs | 2 +- .../DimProcessHandlerTests.cs | 2 +- .../DimProcess.Library.Tests/Usings.cs | 2 +- .../ManualProcessDataExtensionsTests.cs | 2 +- .../Processes.Library.Tests.csproj | 2 +- .../Processes.Library.Tests/Usings.cs | 2 +- .../ProcessExecutionServiceTests.cs | 2 +- .../ProcessExecutorTests.cs | 2 +- .../Processes.Worker.Library.Tests.csproj | 2 +- .../Processes.Worker.Library.Tests/Usings.cs | 2 +- tests/shared/Tests.Shared/MockLogger.cs | 2 +- tests/shared/Tests.Shared/Tests.Shared.csproj | 2 +- 164 files changed, 3403 insertions(+), 214 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/chart-release.yaml create mode 100644 .github/workflows/chart-test.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/kics.yml create mode 100644 .github/workflows/lint-pull-request.yml create mode 100644 .github/workflows/migrations-docker.yml create mode 100644 .github/workflows/owasp-zap.yml create mode 100644 .github/workflows/processes-worker-docker.yml create mode 100644 .github/workflows/release-please.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/service-docker.yml create mode 100644 .github/workflows/sonarcloud.yml create mode 100644 .github/workflows/trivy.yml create mode 100644 .github/workflows/unit.tests-formatting.yml create mode 100644 CHANGELOG.md delete mode 100644 CODE_OF_CONDUCT.md create mode 100644 README.md create mode 100644 charts/chart-testing-config.yaml create mode 100644 charts/dim/.helmignore create mode 100644 charts/dim/Chart.yaml create mode 100644 charts/dim/LICENSE create mode 100644 charts/dim/README.md create mode 100644 charts/dim/README.md.gotmpl create mode 100644 charts/dim/templates/_helpers.tpl create mode 100644 charts/dim/templates/configmap-postgres-init.yaml create mode 100644 charts/dim/templates/cronjob-processes.yaml create mode 100644 charts/dim/templates/deployment.yaml create mode 100644 charts/dim/templates/ingress.yaml create mode 100644 charts/dim/templates/job-migrations.yaml create mode 100644 charts/dim/templates/secret-external-db.yaml create mode 100644 charts/dim/templates/secret-postgres.yaml create mode 100644 charts/dim/templates/secret.yaml create mode 100644 charts/dim/templates/service.yaml create mode 100644 charts/dim/values.yaml create mode 100644 consortia/argocd-app-templates/appsetup-dev.yaml create mode 100644 consortia/argocd-app-templates/appsetup-int.yaml create mode 100644 consortia/environments/values-dev.yaml create mode 100644 consortia/environments/values-int.yaml create mode 100644 docker/Dockerfile-dim-migrations create mode 100644 docker/Dockerfile-dim-processes-worker create mode 100644 docker/Dockerfile-dim-service diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6ac1ec9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,57 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +--- +version: 2 +updates: + # NuGet + - + package-ecosystem: "nuget" + directory: / + labels: + - "dependabot" + - "dependencies" + schedule: + interval: "weekly" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] + + # Github Actions + - + package-ecosystem: "github-actions" + directory: / + labels: + - "dependabot" + - "github-actions" + schedule: + interval: "weekly" + + # Docker + - + package-ecosystem: "docker" + directory: ./docker/ + labels: + - "dependabot" + - "docker" + schedule: + interval: "weekly" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..459f9b7 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,22 @@ +## Description + +Please include a summary of the change. + +## Why + +Please include an explanation of why this change is necessary as well as relevant motivation and context. List any dependencies that are required for this change. + +## Issue + +Link to Github issue. + +## Checklist + +Please delete options that are not relevant. + +- [ ] I have performed a self-review of my own code +- [ ] I have successfully tested my changes locally +- [ ] I have added tests that prove my changes work +- [ ] I have checked that new and existing tests pass locally with my changes +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have added copyright and license headers, footers (for .md files) or files (for images) diff --git a/.github/workflows/chart-release.yaml b/.github/workflows/chart-release.yaml new file mode 100644 index 0000000..4e397f4 --- /dev/null +++ b/.github/workflows/chart-release.yaml @@ -0,0 +1,86 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: Release Chart + +on: + workflow_dispatch: + push: + paths: + - 'charts/**' + branches: + - main + +jobs: + release: + # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions + # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Install Helm + uses: azure/setup-helm@b7246b12e77f7134dc2d460a3d5bad15bbe29390 # v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Update helm dependencies for dim + run: | + cd charts/dim + helm repo add bitnami https://charts.bitnami.com/bitnami + helm dependency update + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.4.1 + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + CR_SKIP_EXISTING: "true" + + - name: Get current helm chart version + id: chart-version + run: | + current=$(cat ./charts/dim/Chart.yaml | grep "version:" | head -1 | cut -d ":" -d " " -f2) + echo "current=$current" >> $GITHUB_OUTPUT + echo "Exported $current helm chart version" + + - name: Check for previous version + id: version-check + run: | + exists=$(git tag -l "v${{ steps.chart-version.outputs.current }}") + if [[ -n "$exists" ]]; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Create and push git tag for release workflow to be triggered + run: | + git tag v${{ steps.chart-version.outputs.current }} + git push origin v${{ steps.chart-version.outputs.current }} + if: steps.version-check.outputs.exists == 'false' \ No newline at end of file diff --git a/.github/workflows/chart-test.yml b/.github/workflows/chart-test.yml new file mode 100644 index 0000000..7d992b7 --- /dev/null +++ b/.github/workflows/chart-test.yml @@ -0,0 +1,128 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: Lint and Test Chart + +on: + push: + paths: + - 'charts/dim/**' + branches: [main] + pull_request: + paths: + - 'charts/dim/**' + workflow_dispatch: + inputs: + node_image: + description: 'kindest/node image for k8s kind cluster' + # k8s version + default: 'kindest/node:v1.27.3' + required: false + type: string + upgrade_from: + description: 'dim chart version to upgrade from' + # tbd + default: 'tbd' + required: false + type: string + +jobs: + + lint-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + + - name: Kubernetes KinD Cluster + uses: container-tools/kind-action@0ad70e2299366b0e1552c7240f4e4567148f723e # v2.0.4 + with: + # upgrade version, default (v0.17.0) uses node image v1.21.1 and doesn't work with more recent node image versions + version: v0.20.0 + # default value for event_name != workflow_dispatch + node_image: ${{ github.event.inputs.node_image || 'kindest/node:v1.27.3' }} + + - name: Build migration image + id: build-migration-image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: docker/Dockerfile-dim-migrations + push: true + tags: kind-registry:5000/dim-migrations:testing + + - name: Build service image + id: build-service-image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: docker/Dockerfile-dim-service + push: true + tags: kind-registry:5000/dim-service:testing + + - name: Build processes worker + id: build-processes-worker-image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: docker/Dockerfile-dim-processes-worker + push: true + tags: kind-registry:5000/dim-processes-worker:testing + + - name: Set up Helm + uses: azure/setup-helm@b7246b12e77f7134dc2d460a3d5bad15bbe29390 # v4 + with: + version: v3.9.3 + + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + with: + python-version: '3.9' + check-latest: true + + - name: Set up chart-testing + uses: helm/chart-testing-action@e6669bcd63d7cb57cb4380c33043eebe5d111992 # v2.6.1 + + - name: Run chart-testing (list-changed) + id: list-changed + run: | + changed=$(ct list-changed --target-branch ${{ github.event.repository.default_branch }}) + if [[ -n "$changed" ]]; then + echo "changed=true" >> $GITHUB_OUTPUT + fi + + - name: Run chart-testing (lint) + run: ct lint --validate-maintainers=false --check-version-increment=false --target-branch ${{ github.event.repository.default_branch }} + + - name: Run chart-testing (install) + run: ct install --charts charts/dim --config charts/chart-testing-config.yaml --helm-extra-set-args "--set dim.image.name=kind-registry:5000/dim-service --set dim.image.tag=testing --set migrations.image.name=kind-registry:5000/dim-migrations --set migrations.image.tag=testing --set processesworker.image.name=kind-registry:5000/dim-processes-worker --set processesworker.image.tag=testing" + if: github.event_name != 'pull_request' || steps.list-changed.outputs.changed == 'true' + + # TODO: re-add the step after the first version release + # Upgrade the released chart version with the locally available chart + # default value for event_name != workflow_dispatch + # - name: Run helm upgrade + # run: | + # helm repo add bitnami https://charts.bitnami.com/bitnami + # helm repo add tractusx-dev https://eclipse-tractusx.github.io/charts/dev + # helm install dim tractusx-dev/dim --version ${{ github.event.inputs.upgrade_from || 'tbd' }} --namespace upgrade --create-namespace + # helm dependency update charts/dim + # helm upgrade dim charts/dim --set dim.image.name=kind-registry:5000/dim-service --set dim.image.tag=testing --set migrations.image.name=kind-registry:5000/dim-migrations --set migrations.image.tag=testing --set processesworker.image.name=kind-registry:5000/dim-processes-worker --set processesworker.image.tag=testing --namespace upgrade + # if: github.event_name != 'pull_request' || steps.list-changed.outputs.changed == 'true' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..d7a59ed --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,105 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# + +name: "CodeQL" + +on: + push: + branches: [main] + paths: + - 'src/**' + pull_request: + paths: + - 'src/**' + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + analyze: + name: Analyze + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners + # Consider using larger runners for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ["csharp"] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@1b1aada464948af03b950897e5eb522f92603cc2 # v2.227 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + queries: +security-extended,security-and-quality + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # Automates dependency installation for Python, Ruby, and JavaScript, optimizing the CodeQL analysis setup. + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@1b1aada464948af03b950897e5eb522f92603cc2 # v2.227 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@1b1aada464948af03b950897e5eb522f92603cc2 # v2.227 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/kics.yml b/.github/workflows/kics.yml new file mode 100644 index 0000000..5c56d58 --- /dev/null +++ b/.github/workflows/kics.yml @@ -0,0 +1,75 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: "KICS" + +on: + push: + branches: [main] + # pull_request: + # The branches below must be a subset of the branches above + # branches: [main, dev] + # paths-ignore: + # - "**/*.md" + # - "**/*.txt" + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: KICS scan + uses: checkmarx/kics-github-action@8a44970e3d2eca668be41abe9d4e06709c3b3609 # v1.7.0 + with: + # Scanning directory . + path: "." + # Fail on HIGH severity results + fail_on: high + # Disable secrets detection - we use GitGuardian + disable_secrets: true + # when provided with a directory on output_path + # it will generate the specified reports file named 'results.{extension}' + # in this example it will generate: + # - results-dir/results.json + # - results-dir/results.sarif + output_path: kicsResults/ + output_formats: "json,sarif" + # If you want KICS to ignore the results and return exit status code 0 unless a KICS engine error happens + # ignore_on_exit: results + # GITHUB_TOKEN enables this github action to access github API and post comments in a pull request + # token: ${{ secrets.GITHUB_TOKEN }} + # enable_comments: true + + # Upload findings to GitHub Advanced Security Dashboard + - name: Upload SARIF file for GitHub Advanced Security Dashboard + if: always() + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + with: + sarif_file: kicsResults/results.sarif + diff --git a/.github/workflows/lint-pull-request.yml b/.github/workflows/lint-pull-request.yml new file mode 100644 index 0000000..397b46d --- /dev/null +++ b/.github/workflows/lint-pull-request.yml @@ -0,0 +1,61 @@ +# ############################################################################# +# Copyright (c) 2024 BMW Group AG +# +# 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 +# ############################################################################# + +name: "Lint PullRequest" + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@e9fabac35e210fea40ca5b14c0da95a099eff26f # v5.4.0 + id: lint_pr_title + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2.9.0 + # When the previous steps fail, the workflow would stop. By adding this + # condition you can continue the execution with the populated error message. + if: always() && (steps.lint_pr_title.outputs.error_message != null) + with: + header: pr-title-lint-error + message: | + Hey there and thank you for opening this pull request! 👋đŸŧ + + We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted. + + Details: + + ``` + ${{ steps.lint_pr_title.outputs.error_message }} + ``` + + # Delete a previous comment when the issue has been resolved + - if: ${{ steps.lint_pr_title.outputs.error_message == null }} + uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2.9.0 + with: + header: pr-title-lint-error + delete: true diff --git a/.github/workflows/migrations-docker.yml b/.github/workflows/migrations-docker.yml new file mode 100644 index 0000000..5fd83c7 --- /dev/null +++ b/.github/workflows/migrations-docker.yml @@ -0,0 +1,84 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: Build Migrations Image + +on: + push: + paths: + # service and transitive paths + - 'src/database/Dim.Migrations/**' + - 'src/database/Dim.Entities/**' + # workflow file + - '.github/workflows/migrations-docker.yml' + # dockerfile + - 'docker/Dockerfile-dim-migrations' + + branches: + - 'main' + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }}_dim-migrations + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Login to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0 + + - name: Set up QEMU + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 + + - name: Docker meta + id: meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=dev + type=raw,value=${{ github.sha }} + + - name: Build and push Docker image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: docker/Dockerfile-dim-migrations + platforms: linux/amd64, linux/arm64 + pull: true + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/owasp-zap.yml b/.github/workflows/owasp-zap.yml new file mode 100644 index 0000000..c262cff --- /dev/null +++ b/.github/workflows/owasp-zap.yml @@ -0,0 +1,142 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: "OWASP ZAP (DAST Scan)" + +on: + push: + branches: [main] + paths: + - 'src/**' + pull_request: + paths: + - 'src/**' + schedule: + # Once a day + - cron: "0 0 * * *" + workflow_dispatch: + # Trigger manually + inputs: + node_image: + description: 'kindest/node image for k8s kind cluster' + # k8s version + default: 'kindest/node:v1.27.3' + required: false + type: string + +jobs: + owasp-zap-scan: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + + - name: Kubernetes KinD Cluster + uses: container-tools/kind-action@0fc957b58d9a5bc9ca57a1b419324a2074c7653b # v2.0.3 + with: + node_image: ${{ github.event.inputs.node_image || 'kindest/node:v1.27.3' }} + version: v0.20.0 + + - name: Set up Helm + uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3.5 + with: + version: v3.5.0 + + - name: Build migration image + id: build-migration-image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: docker/Dockerfile-dim-migrations + push: true + tags: kind-registry:5000/dim-migrations:testing + + - name: Build service image + id: build-service-image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: docker/Dockerfile-dim-service + push: true + tags: kind-registry:5000/dim-service:testing + + - name: Build Worker image + id: build-worker-image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: docker/Dockerfile-dim-processes-worker + push: true + tags: kind-registry:5000/dim-processes-worker:testing + + - name: Add bitnami repo + run: | + helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo update + + - name: Update Helm dependencies + run: | + cd charts/dim + helm dependency build + + - name: Install the chart on KinD cluster + run: helm install testing -n apps --create-namespace --wait --set dim.image.name=kind-registry:5000/dim-service --set dim.image.tag=testing --set migrations.image.name=kind-registry:5000/dim-migrations --set migrations.image.tag=testing --set processesworker.image.name=kind-registry:5000/dim-processes-worker --set processesworker.image.tag=testing --set dim.swaggerEnabled=true charts/dim + + - name: Configure port forward to app in KinD + run: | + echo "Getting Agent IP..." + IP_ADDR=$(hostname -i) + echo "-> IP: $IP_ADDR" + echo "IP_ADDR=$IP_ADDR" >> $GITHUB_ENV + + POD_NAME=$(kubectl get pods --namespace apps -l "app.kubernetes.io/name=dim,app.kubernetes.io/instance=testing" -o jsonpath="{.items[0].metadata.name}") + CONTAINER_PORT=$(kubectl get pod --namespace apps $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + + echo "Port-forwarding 0.0.0.0:8080 to $POD_NAME:$CONTAINER_PORT..." + + kubectl --namespace apps port-forward $POD_NAME 8080:$CONTAINER_PORT --address 0.0.0.0 & + + - name: Generating report skeletons + if: success() || failure() + run: | + touch report_md.md report_html.html + chmod a+w report_md.md report_html.html + ls -lrt + + - name: Run ZAP scan + run: | + set +e + + echo "Pulling ZAP image..." + docker pull ghcr.io/zaproxy/zaproxy:stable -q + + echo "Starting ZAP Docker container..." + docker run -v ${GITHUB_WORKSPACE}:/zap/wrk/:rw ghcr.io/zaproxy/zaproxy:stable zap-api-scan.py -t http://$IP_ADDR:8080/api/swagger/v1/swagger.json -f openapi -w report_md.md -r report_html.html -T 1 + + echo "... done." + + - name: Upload HTML report + if: success() || failure() + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + name: ZAP scan report + path: ./report_html.html + retention-days: 1 diff --git a/.github/workflows/processes-worker-docker.yml b/.github/workflows/processes-worker-docker.yml new file mode 100644 index 0000000..b5a9816 --- /dev/null +++ b/.github/workflows/processes-worker-docker.yml @@ -0,0 +1,83 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: Build Processes Worker Image + +on: + push: + paths: + # service and transitive paths + - 'src/**' + # workflow file + - '.github/workflows/processes-worker-docker.yml' + # dockerfile + - 'docker/Dockerfile-dim-processes-worker' + + branches: + - 'main' + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }}_dim-processes-worker + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Login to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0 + + - name: Set up QEMU + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 + + - name: Docker meta + id: meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.REGISTRY}}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=dev + type=raw,value=${{ github.sha }} + + - name: Build and push Docker image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: docker/Dockerfile-dim-processes-worker + platforms: linux/amd64, linux/arm64 + pull: true + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..9abce54 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,41 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: Release Please + +on: + push: + branches: + - 'v*.*.*' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + prepare-release: + runs-on: ubuntu-latest + steps: + - uses: google-github-actions/release-please-action@v4 + name: Prepare release + with: + target-branch: ${{ github.ref_name }} + release-type: simple + skip-github-release: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..53de006 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,151 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: Release + +on: + workflow_dispatch: + push: + paths: + - 'charts/**' + branches: + - main + +jobs: + release-helm-chart: + # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions + # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Install Helm + uses: azure/setup-helm@b7246b12e77f7134dc2d460a3d5bad15bbe29390 # v4 + + - name: Update helm dependencies for dim + run: | + cd charts/dim + helm repo add bitnami https://charts.bitnami.com/bitnami + helm dependency update + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.4.1 + with: + pages_branch: "main" + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + CR_SKIP_EXISTING: "true" + + release-images: + needs: release-helm-chart + permissions: + packages: write + runs-on: ubuntu-latest + strategy: + matrix: + include: + - image: ghcr.io/${{ github.repository }}_dim-service + dockerfile: docker/Dockerfile-dim-service + - image: ghcr.io/${{ github.repository }}_dim-migrations + dockerfile: docker/Dockerfile-dim-migrations + - image: ghcr.io/${{ github.repository }}_dim-processes-worker + dockerfile: docker/Dockerfile-dim-processes-worker + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + + - name: Get current helm chart version + id: chart-version + run: | + current=$(cat ./charts/dim/Chart.yaml | grep "version:" | head -1 | cut -d ":" -d " " -f2) + echo "current=$current" >> $GITHUB_OUTPUT + echo "Exported $current helm chart version" + + - name: Check for previous version + id: version-check + run: | + exists=$(git tag -l "v${{ steps.chart-version.outputs.current }}") + if [[ -n "$exists" ]]; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Login to GitHub Container Registry + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + if: steps.version-check.outputs.exists == 'false' + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0 + if: steps.version-check.outputs.exists == 'false' + + - name: Set up QEMU + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 + if: steps.version-check.outputs.exists == 'false' + + # Create SemVer or ref tags dependent of trigger event + - name: Docker meta + id: meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ matrix.image }} + # Automatically prepare image tags; See action docs for more examples. + # semver patter will generate tags like these for example :1 :1.2 :1.2.3 + tags: | + type=ref,event=branch + type=ref,event=pr + type=raw,value=latest + type=semver,pattern={{version}},value=${{ steps.chart-version.outputs.current }} + type=semver,pattern={{major}},value=${{ steps.chart-version.outputs.current }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.chart-version.outputs.current }} + if: steps.version-check.outputs.exists == 'false' + + - name: Build and push Docker images + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: ${{ matrix.dockerfile }} + platforms: linux/amd64, linux/arm64 + pull: true + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + if: steps.version-check.outputs.exists == 'false' + + - name: Create and push git tag + run: | + git tag v${{ steps.chart-version.outputs.current }} + git push origin v${{ steps.chart-version.outputs.current }} + if: steps.version-check.outputs.exists == 'false' diff --git a/.github/workflows/service-docker.yml b/.github/workflows/service-docker.yml new file mode 100644 index 0000000..261e9f0 --- /dev/null +++ b/.github/workflows/service-docker.yml @@ -0,0 +1,83 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: Build Service Image + +on: + push: + paths: + # service and transitive paths + - 'src/**' + # workflow file + - '.github/workflows/service-docker.yml' + # dockerfile + - 'docker/Dockerfile-dim-service' + + branches: + - 'main' + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }}_dim-service + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Login to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0 + + - name: Set up QEMU + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 + + - name: Docker meta + id: meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.REGISTRY}}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=dev + type=raw,value=${{ github.sha }} + + - name: Build and push Docker image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: docker/Dockerfile-dim-service + platforms: linux/amd64, linux/arm64 + pull: true + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 0000000..ebec24e --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,79 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: Sonarcloud +on: + push: + branches: [main] + paths: + - 'src/**' + pull_request: + types: [opened, synchronize, reopened] + paths: + - 'src/**' + workflow_dispatch: + +jobs: + build: + name: Build + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + strategy: + matrix: + dotnet-version: ['7.0'] + + steps: + - name: Set up JDK 17 + uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + with: + distribution: 'temurin' + java-version: '17' + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Cache SonarCloud packages + uses: actions/cache@v3 + with: + path: ~/sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache SonarCloud scanner + id: cache-sonar-scanner + uses: actions/cache@v3 + with: + path: ./.sonar/scanner + key: ${{ runner.os }}-sonar-scanner + restore-keys: ${{ runner.os }}-sonar-scanner + - name: Install SonarCloud scanner + if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' + run: | + mkdir -p ./.sonar/scanner + dotnet tool update dotnet-sonarscanner --tool-path ./.sonar/scanner + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + dotnet tool install --global dotnet-coverage + ./.sonar/scanner/dotnet-sonarscanner begin /k:"${{ vars.SONAR_PROJECT_KEY }}" /o:"${{ vars.SONAR_ORGANIZATION }}" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=src/coverage.xml + dotnet build src + cd src + dotnet-coverage collect 'dotnet test --no-restore --verbosity normal' -s 'settings-coverage.xml' -f xml -o 'coverage.xml' + cd .. + ./.sonar/scanner/dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml new file mode 100644 index 0000000..d59e056 --- /dev/null +++ b/.github/workflows/trivy.yml @@ -0,0 +1,170 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +# Depending on the location of your Docker container +# you need to change the path to the specific Docker registry. +# +name: "Trivy" + +on: + push: + branches: [main] + # pull_request: + # The branches below must be a subset of the branches above + # branches: [ main, master ] + # paths-ignore: + # - "**/*.md" + # - "**/*.txt" + schedule: + # Once a day + - cron: "0 0 * * *" + workflow_dispatch: + # Trigger manually + +env: + REGISTRY: ghcr.io + IMAGE_NAME_SERVICE: ${{ github.repository }}_dim-service + IMAGE_NAME_MIGRATIONS: ${{ github.repository }}_dim-migrations + IMAGE_NAME_WORKER: ${{ github.repository }}_dim-processes-worker + +jobs: + analyze-config: + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Run Trivy vulnerability scanner in repo mode + uses: aquasecurity/trivy-action@062f2592684a31eb3aa050cc61e7ca1451cecd3d # v0.18.0 + with: + scan-type: "config" + hide-progress: false + format: "sarif" + output: "trivy-results1.sarif" + vuln-type: "os,library" + skip-dirs: "docs/" + timeout: "3600s" + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + if: always() + with: + sarif_file: "trivy-results1.sarif" + + analyze-service: + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + # It's also possible to scan your private registry with Trivy's built-in image scan. + # All you have to do is set ENV vars. + # Docker Hub needs TRIVY_USERNAME and TRIVY_PASSWORD. + # You don't need to set ENV vars when downloading from a public repository. + # For public images, no ENV vars must be set. + - name: Run Trivy vulnerability scanner + if: always() + uses: aquasecurity/trivy-action@062f2592684a31eb3aa050cc61e7ca1451cecd3d # v0.18.0 + with: + # Path to Docker image + image-ref: "${{ env.REGISTRY}}/${{ env.IMAGE_NAME_SERVICE}}:dev" + format: "sarif" + output: "trivy-results2.sarif" + vuln-type: "os,library" + + - name: Upload Trivy scan results to GitHub Security tab + if: always() + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + with: + sarif_file: "trivy-results2.sarif" + + analyze-migrations: + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + # It's also possible to scan your private registry with Trivy's built-in image scan. + # All you have to do is set ENV vars. + # Docker Hub needs TRIVY_USERNAME and TRIVY_PASSWORD. + # You don't need to set ENV vars when downloading from a public repository. + # For public images, no ENV vars must be set. + - name: Run Trivy vulnerability scanner + if: always() + uses: aquasecurity/trivy-action@062f2592684a31eb3aa050cc61e7ca1451cecd3d # v0.18.0 + with: + # Path to Docker image + image-ref: "${{ env.REGISTRY}}/${{ env.IMAGE_NAME_MIGRATIONS}}:dev" + format: "sarif" + output: "trivy-results3.sarif" + vuln-type: "os,library" + + - name: Upload Trivy scan results to GitHub Security tab + if: always() + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + with: + sarif_file: "trivy-results4.sarif" + + analyze-processes-worker: + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + # It's also possible to scan your private registry with Trivy's built-in image scan. + # All you have to do is set ENV vars. + # Docker Hub needs TRIVY_USERNAME and TRIVY_PASSWORD. + # You don't need to set ENV vars when downloading from a public repository. + # For public images, no ENV vars must be set. + - name: Run Trivy vulnerability scanner + if: always() + uses: aquasecurity/trivy-action@062f2592684a31eb3aa050cc61e7ca1451cecd3d # v0.18.0 + with: + # Path to Docker image + image-ref: "${{ env.REGISTRY}}/${{ env.IMAGE_NAME_WORKER}}:dev" + format: "sarif" + output: "trivy-results4.sarif" + vuln-type: "os,library" + + - name: Upload Trivy scan results to GitHub Security tab + if: always() + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + with: + sarif_file: "trivy-results4.sarif" + \ No newline at end of file diff --git a/.github/workflows/unit.tests-formatting.yml b/.github/workflows/unit.tests-formatting.yml new file mode 100644 index 0000000..3695ac7 --- /dev/null +++ b/.github/workflows/unit.tests-formatting.yml @@ -0,0 +1,56 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +name: Unit-Tests and Formatting + +on: + push: + branches: [main] + paths: + - 'src/**' + pull_request: + types: [opened, synchronize, reopened] + paths: + - 'src/**' + workflow_dispatch: + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + dotnet-version: ['7.0'] + + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} + uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 + with: + dotnet-version: ${{ matrix.dotnet-version }} + - name: Install dotnet-format + run: dotnet tool install -g dotnet-format + - name: Install dependencies + run: dotnet restore src + - name: Build + run: dotnet build src --configuration Release --no-restore + - name: Check Format + run: dotnet format src --verify-no-changes --no-restore + - name: Test + run: dotnet test src --no-restore --verbosity normal diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index faa735b..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,93 +0,0 @@ -# Community Code of Conduct - -**Version 2.0 -January 1, 2023** - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as community members, contributors, Committers[^1], and Project Leads (collectively "Contributors") pledge to make participation in our projects and our community a harassment-free and inclusive experience for everyone. - -This Community Code of Conduct ("Code") outlines our behavior expectations as members of our community in all Eclipse Foundation activities, both offline and online. It is not intended to govern scenarios or behaviors outside of the scope of Eclipse Foundation activities. Nor is it intended to replace or supersede the protections offered to all our community members under the law. Please follow both the spirit and letter of this Code and encourage other Contributors to follow these principles into our work. Failure to read or acknowledge this Code does not excuse a Contributor from compliance with the Code. - -## Our Standards - -Examples of behavior that contribute to creating a positive and professional environment include: - -- Using welcoming and inclusive language; -- Actively encouraging all voices; -- Helping others bring their perspectives and listening actively. If you find yourself dominating a discussion, it is especially important to encourage other voices to join in; -- Being respectful of differing viewpoints and experiences; -- Gracefully accepting constructive criticism; -- Focusing on what is best for the community; -- Showing empathy towards other community members; -- Being direct but professional; and -- Leading by example by holding yourself and others accountable - -Examples of unacceptable behavior by Contributors include: - -- The use of sexualized language or imagery; -- Unwelcome sexual attention or advances; -- Trolling, insulting/derogatory comments, and personal or political attacks; -- Public or private harassment, repeated harassment; -- Publishing others' private information, such as a physical or electronic address, without explicit permission; -- Violent threats or language directed against another person; -- Sexist, racist, or otherwise discriminatory jokes and language; -- Posting sexually explicit or violent material; -- Sharing private content, such as emails sent privately or non-publicly, or unlogged forums such as IRC channel history; -- Personal insults, especially those using racist or sexist terms; -- Excessive or unnecessary profanity; -- Advocating for, or encouraging, any of the above behavior; and -- Other conduct which could reasonably be considered inappropriate in a professional setting - -## Our Responsibilities - -With the support of the Eclipse Foundation employees, consultants, officers, and directors (collectively, the "Staff"), Committers, and Project Leads, the Eclipse Foundation Conduct Committee (the "Conduct Committee") is responsible for clarifying the standards of acceptable behavior. The Conduct Committee takes appropriate and fair corrective action in response to any instances of unacceptable behavior. - -## Scope - -This Code applies within all Project, Working Group, and Interest Group spaces and communication channels of the Eclipse Foundation (collectively, "Eclipse spaces"), within any Eclipse-organized event or meeting, and in public spaces when an individual is representing an Eclipse Foundation Project, Working Group, Interest Group, or their communities. Examples of representing a Project or community include posting via an official social media account, personal accounts, or acting as an appointed representative at an online or offline event. Representation of Projects, Working Groups, and Interest Groups may be further defined and clarified by Committers, Project Leads, or the Staff. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Conduct Committee via conduct@eclipse-foundation.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Without the explicit consent of the reporter, the Conduct Committee is obligated to maintain confidentiality with regard to the reporter of an incident. The Conduct Committee is further obligated to ensure that the respondent is provided with sufficient information about the complaint to reply. If such details cannot be provided while maintaining confidentiality, the Conduct Committee will take the respondent‘s inability to provide a defense into account in its deliberations and decisions. Further details of enforcement guidelines may be posted separately. - -Staff, Committers and Project Leads have the right to report, remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code, or to block temporarily or permanently any Contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. Any such actions will be reported to the Conduct Committee for transparency and record keeping. - -Any Staff (including officers and directors of the Eclipse Foundation), Committers, Project Leads, or Conduct Committee members who are the subject of a complaint to the Conduct Committee will be recused from the process of resolving any such complaint. - -## Responsibility - -The responsibility for administering this Code rests with the Conduct Committee, with oversight by the Executive Director and the Board of Directors. For additional information on the Conduct Committee and its process, please write to . - -## Investigation of Potential Code Violations - -All conflict is not bad as a healthy debate may sometimes be necessary to push us to do our best. It is, however, unacceptable to be disrespectful or offensive, or violate this Code. If you see someone engaging in objectionable behavior violating this Code, we encourage you to address the behavior directly with those involved. If for some reason, you are unable to resolve the matter or feel uncomfortable doing so, or if the behavior is threatening or harassing, please report it following the procedure laid out below. - -Reports should be directed to . It is the Conduct Committee’s role to receive and address reported violations of this Code and to ensure a fair and speedy resolution. - -The Eclipse Foundation takes all reports of potential Code violations seriously and is committed to confidentiality and a full investigation of all allegations. The identity of the reporter will be omitted from the details of the report supplied to the accused. Contributors who are being investigated for a potential Code violation will have an opportunity to be heard prior to any final determination. Those found to have violated the Code can seek reconsideration of the violation and disciplinary action decisions. Every effort will be made to have all matters disposed of within 60 days of the receipt of the complaint. - -## Actions -Contributors who do not follow this Code in good faith may face temporary or permanent repercussions as determined by the Conduct Committee. - -This Code does not address all conduct. It works in conjunction with our [Communication Channel Guidelines](https://www.eclipse.org/org/documents/communication-channel-guidelines/), [Social Media Guidelines](https://www.eclipse.org/org/documents/social_media_guidelines.php), [Bylaws](https://www.eclipse.org/org/documents/eclipse-foundation-be-bylaws-en.pdf), and [Internal Rules](https://www.eclipse.org/org/documents/ef-be-internal-rules.pdf) which set out additional protections for, and obligations of, all contributors. The Foundation has additional policies that provide further guidance on other matters. - -It’s impossible to spell out every possible scenario that might be deemed a violation of this Code. Instead, we rely on one another’s good judgment to uphold a high standard of integrity within all Eclipse Spaces. Sometimes, identifying the right thing to do isn’t an easy call. In such a scenario, raise the issue as early as possible. - -## No Retaliation - -The Eclipse community relies upon and values the help of Contributors who identify potential problems that may need to be addressed within an Eclipse Space. Any retaliation against a Contributor who raises an issue honestly is a violation of this Code. That a Contributor has raised a concern honestly or participated in an investigation, cannot be the basis for any adverse action, including threats, harassment, or discrimination. If you work with someone who has raised a concern or provided information in an investigation, you should continue to treat the person with courtesy and respect. If you believe someone has retaliated against you, report the matter as described by this Code. Honest reporting does not mean that you have to be right when you raise a concern; you just have to believe that the information you are providing is accurate. - -False reporting, especially when intended to retaliate or exclude, is itself a violation of this Code and will not be accepted or tolerated. - -Everyone is encouraged to ask questions about this Code. Your feedback is welcome, and you will get a response within three business days. Write to . - -## Amendments - -The Eclipse Foundation Board of Directors may amend this Code from time to time and may vary the procedures it sets out where appropriate in a particular case. - -### Attribution - -This Code was inspired by the [Contributor Covenant](https://www.contributor-covenant.org/), version 1.4, available [here](https://www.contributor-covenant.org/version/1/4/code-of-conduct/). - -[^1]: Capitalized terms used herein without definition shall have the meanings assigned to them in the Bylaws. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e9c4990 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# DIM Middle Layer + +This repository contains the backend code for the DIM Middle Layer written in C#. + +## Installation + +To install the chart with the release name `dim`: + +```shell +$ helm repo add dim-repo https://github.com/Phil91/dim-client +$ helm install dim dim-repo/dim +``` + +To install the helm chart into your cluster with your values: + +```shell +$ helm install -f your-values.yaml dim dim-repo/dim +``` + +To use the helm chart as a dependency: + +```yaml +dependencies: + - name: dim + repository: https://github.com/Phil91/dim-client + version: 0.0.1 +``` + +## How to build and run + +Install the [.NET 7.0 SDK](https://www.microsoft.com/net/download). + +Run the following command from the CLI: + +```console +dotnet build src +``` + +Make sure the necessary config is added to the settings of the service you want to run. +Run the following command from the CLI in the directory of the service you want to run: + +```console +dotnet run +``` + +## License + +Distributed under the Apache 2.0 License. +See [LICENSE](./LICENSE) for more information. diff --git a/charts/chart-testing-config.yaml b/charts/chart-testing-config.yaml new file mode 100644 index 0000000..73e105a --- /dev/null +++ b/charts/chart-testing-config.yaml @@ -0,0 +1,22 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +validate-maintainers: false +chart-repos: + - bitnami=https://charts.bitnami.com/bitnami diff --git a/charts/dim/.helmignore b/charts/dim/.helmignore new file mode 100644 index 0000000..0bffc69 --- /dev/null +++ b/charts/dim/.helmignore @@ -0,0 +1,27 @@ +# 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/ + +# Custom dirs and files +argocd/ +*.gotmpl diff --git a/charts/dim/Chart.yaml b/charts/dim/Chart.yaml new file mode 100644 index 0000000..4ac40d3 --- /dev/null +++ b/charts/dim/Chart.yaml @@ -0,0 +1,31 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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: dim +type: application +version: 0.0.1 +appVersion: 0.0.1 +description: Helm chart for DIM Middle Layer +home: https://github.com/catenax-ng/dim-repo +dependencies: + - condition: postgresql.enabled + name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 12.12.x diff --git a/charts/dim/LICENSE b/charts/dim/LICENSE new file mode 100644 index 0000000..f49a4e1 --- /dev/null +++ b/charts/dim/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. \ No newline at end of file diff --git a/charts/dim/README.md b/charts/dim/README.md new file mode 100644 index 0000000..28bddbb --- /dev/null +++ b/charts/dim/README.md @@ -0,0 +1,134 @@ +# Helm chart for DIM Middle Layer + +This helm chart installs the DIM Middle Layer. + +For further information please refer to [Technical Documentation](./docs/technical-documentation). + +The referenced container images are for demonstration purposes only. + +## Installation + +To install the chart with the release name `dim`: + +```shell +$ helm repo add dim-repo https://github.com/Phil91/dim-client +$ helm install dim dim-repo/dim +``` + +To install the helm chart into your cluster with your values: + +```shell +$ helm install -f your-values.yaml dim dim-repo/dim +``` + +To use the helm chart as a dependency: + +```yaml +dependencies: + - name: dim + repository: https://github.com/Phil91/dim-client + version: 0.0.1 +``` + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| https://charts.bitnami.com/bitnami | postgresql | 12.12.x | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| dim.image.name | string | `"ghcr.io/dim-repo/dim-service"` | | +| dim.image.tag | string | `""` | | +| dim.imagePullPolicy | string | `"IfNotPresent"` | | +| dim.resources | object | `{"limits":{"cpu":"45m","memory":"200M"},"requests":{"cpu":"15m","memory":"200M"}}` | We recommend to review the default resource limits as this should a conscious choice. | +| dim.healthChecks.startup.path | string | `"/health/startup"` | | +| dim.healthChecks.startup.tags[0].name | string | `"HEALTHCHECKS__0__TAGS__1"` | | +| dim.healthChecks.startup.tags[0].value | string | `"dimdb"` | | +| dim.healthChecks.liveness.path | string | `"/healthz"` | | +| dim.healthChecks.readyness.path | string | `"/ready"` | | +| dim.swaggerEnabled | bool | `false` | | +| dim.rootDirectoryId | string | `"00000000-0000-0000-0000-000000000000"` | | +| migrations.name | string | `"migrations"` | | +| migrations.image.name | string | `"ghcr.io/dim-repo/dim-migrations"` | | +| migrations.image.tag | string | `""` | | +| migrations.imagePullPolicy | string | `"IfNotPresent"` | | +| migrations.resources | object | `{"limits":{"cpu":"45m","memory":"105M"},"requests":{"cpu":"15m","memory":"105M"}}` | We recommend to review the default resource limits as this should a conscious choice. | +| migrations.seeding.testDataEnvironments | string | `""` | | +| migrations.seeding.testDataPaths | string | `"Seeder/Data"` | | +| migrations.logging.default | string | `"Information"` | | +| processesworker.name | string | `"processesworker"` | | +| processesworker.image.name | string | `"ghcr.io/dim-repo/dim-processes-worker"` | | +| processesworker.image.tag | string | `""` | | +| processesworker.imagePullPolicy | string | `"IfNotPresent"` | | +| processesworker.resources | object | `{"limits":{"cpu":"45m","memory":"105M"},"requests":{"cpu":"15m","memory":"105M"}}` | We recommend to review the default resource limits as this should a conscious choice. | +| processesworker.dim.adminMail | string | `"mail@example.org"` | | +| processesworker.dim.clientIdCisCentral | string | `""` | | +| processesworker.dim.clientSecretCisCentral | string | `""` | | +| processesworker.dim.authUrl | string | `""` | | +| processesworker.subaccount.baseUrl | string | `""` | Url to the subaccount service api | +| processesworker.entitlement.baseUrl | string | `""` | Url to the entitlement service api | +| processesworker.cf.clientId | string | `""` | | +| processesworker.cf.clientSecret | string | `""` | | +| processesworker.cf.tokenAddress | string | `""` | | +| processesworker.cf.baseUrl | string | `""` | Url to the cf service api | +| processesworker.cf.grantType | string | `"client_credentials"` | | +| processesworker.callback.scope | string | `"openid"` | | +| processesworker.callback.grantType | string | `"client_credentials"` | | +| processesworker.callback.clientId | string | `""` | Provide client-id for callback. | +| processesworker.callback.clientSecret | string | `""` | Client-secret for callback client-id. Secret-key 'callback-client-secret'. | +| processesworker.callback.tokenAddress | string | `""` | | +| processesworker.callback.baseAddress | string | `""` | Url to the cf service api | +| existingSecret | string | `""` | Secret containing "client-secret-cis-central", "client-secret-cf" and "client-secret-callback" | +| dotnetEnvironment | string | `"Production"` | | +| dbConnection.schema | string | `"dim"` | | +| dbConnection.sslMode | string | `"Disable"` | | +| postgresql.enabled | bool | `true` | PostgreSQL chart configuration; default configurations: host: "dim-postgresql-primary", port: 5432; Switch to enable or disable the PostgreSQL helm chart. | +| postgresql.image | object | `{"tag":"15-debian-12"}` | Setting image tag to major to get latest minor updates | +| postgresql.commonLabels."app.kubernetes.io/version" | string | `"15"` | | +| postgresql.auth.username | string | `"dim"` | Non-root username. | +| postgresql.auth.database | string | `"dim"` | Database name. | +| postgresql.auth.existingSecret | string | `"{{ .Release.Name }}-dim-postgres"` | Secret containing the passwords for root usernames postgres and non-root username dim. Should not be changed without changing the "dim-postgresSecretName" template as well. | +| postgresql.auth.postgrespassword | string | `""` | Password for the root username 'postgres'. Secret-key 'postgres-password'. | +| postgresql.auth.password | string | `""` | Password for the non-root username 'dim'. Secret-key 'password'. | +| postgresql.auth.replicationPassword | string | `""` | Password for the non-root username 'repl_user'. Secret-key 'replication-password'. | +| postgresql.architecture | string | `"replication"` | | +| postgresql.audit.pgAuditLog | string | `"write, ddl"` | | +| postgresql.audit.logLinePrefix | string | `"%m %u %d "` | | +| postgresql.primary.extendedConfiguration | string | `""` | Extended PostgreSQL Primary configuration (increase of max_connections recommended - default is 100) | +| postgresql.primary.initdb.scriptsConfigMap | string | `"{{ .Release.Name }}-dim-cm-postgres"` | | +| postgresql.readReplicas.extendedConfiguration | string | `""` | Extended PostgreSQL read only replicas configuration (increase of max_connections recommended - default is 100) | +| externalDatabase.host | string | `"dim-postgres-ext"` | External PostgreSQL configuration IMPORTANT: non-root db user needs to be created beforehand on external database. And the init script (02-init-db.sql) available in templates/configmap-postgres-init.yaml needs to be executed beforehand. Database host ('-primary' is added as postfix). | +| externalDatabase.port | int | `5432` | Database port number. | +| externalDatabase.username | string | `"dim"` | Non-root username for dim. | +| externalDatabase.database | string | `"dim"` | Database name. | +| externalDatabase.password | string | `""` | Password for the non-root username (default 'dim'). Secret-key 'password'. | +| externalDatabase.existingSecret | string | `"dim-external-db"` | Secret containing the password non-root username, (default 'dim'). | +| ingress.enabled | bool | `false` | DIM ingress parameters, enable ingress record generation for dim. | +| ingress.tls[0] | object | `{"hosts":[""],"secretName":""}` | Provide tls secret. | +| ingress.tls[0].hosts | list | `[""]` | Provide host for tls secret. | +| ingress.hosts[0] | object | `{"host":"","paths":[{"backend":{"port":8080},"path":"/api/dim","pathType":"Prefix"}]}` | Provide default path for the ingress record. | +| portContainer | int | `8080` | | +| portService | int | `8080` | | +| replicaCount | int | `3` | | +| nodeSelector | object | `{}` | Node labels for pod assignment | +| tolerations | list | `[]` | Tolerations for pod assignment | +| affinity.podAntiAffinity | object | `{"preferredDuringSchedulingIgnoredDuringExecution":[{"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/name","operator":"DoesNotExist"}]},"topologyKey":"kubernetes.io/hostname"},"weight":100}]}` | Following Catena-X Helm Best Practices, [reference](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity). | +| updateStrategy.type | string | `"RollingUpdate"` | Update strategy type, rolling update configuration parameters, [reference](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies). | +| updateStrategy.rollingUpdate.maxSurge | int | `1` | | +| updateStrategy.rollingUpdate.maxUnavailable | int | `0` | | +| startupProbe | object | `{"failureThreshold":30,"initialDelaySeconds":10,"periodSeconds":10,"successThreshold":1,"timeoutSeconds":1}` | Following Catena-X Helm Best Practices, [reference](https://github.com/helm/charts/blob/master/stable/nginx-ingress/values.yaml#L210). | +| livenessProbe.failureThreshold | int | `3` | | +| livenessProbe.initialDelaySeconds | int | `10` | | +| livenessProbe.periodSeconds | int | `10` | | +| livenessProbe.successThreshold | int | `1` | | +| livenessProbe.timeoutSeconds | int | `10` | | +| readinessProbe.failureThreshold | int | `3` | | +| readinessProbe.initialDelaySeconds | int | `10` | | +| readinessProbe.periodSeconds | int | `10` | | +| readinessProbe.successThreshold | int | `1` | | +| readinessProbe.timeoutSeconds | int | `1` | | + +Autogenerated with [helm docs](https://github.com/norwoodj/helm-docs) diff --git a/charts/dim/README.md.gotmpl b/charts/dim/README.md.gotmpl new file mode 100644 index 0000000..5ef9c1e --- /dev/null +++ b/charts/dim/README.md.gotmpl @@ -0,0 +1,37 @@ +# {{ template "chart.description" . }} + +This helm chart installs the DIM Middle Layer. + +For further information please refer to [Technical Documentation](./docs/technical-documentation). + +The referenced container images are for demonstration purposes only. + +## Installation + +To install the chart with the release name `{{ template "chart.name" . }}`: + +```shell +$ helm repo add dim-repo https://github.com/Phil91/dim-client +$ helm install {{ template "chart.name" . }} dim-repo/{{ template "chart.name" . }} +``` + +To install the helm chart into your cluster with your values: + +```shell +$ helm install -f your-values.yaml {{ template "chart.name" . }} dim-repo/{{ template "chart.name" . }} +``` + +To use the helm chart as a dependency: + +```yaml +dependencies: + - name: {{ template "chart.name" . }} + repository: https://github.com/Phil91/dim-client + version: {{ template "chart.version" . }} +``` + +{{ template "chart.requirementsSection" . }} + +{{ template "chart.valuesSection" . }} + +Autogenerated with [helm docs](https://github.com/norwoodj/helm-docs) diff --git a/charts/dim/templates/_helpers.tpl b/charts/dim/templates/_helpers.tpl new file mode 100644 index 0000000..d70ffd4 --- /dev/null +++ b/charts/dim/templates/_helpers.tpl @@ -0,0 +1,128 @@ +{{- /* +* Copyright (c) 2024 BMW Group AG +* +* 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 +*/}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "dim.name" -}} +{{- default .Chart.Name .Values.nameOverride | 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 "dim.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 "dim.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Determine secret name. +*/}} +{{- define "dim.secretName" -}} +{{- if .Values.existingSecret -}} +{{- .Values.existingSecret }} +{{- else -}} +{{- include "dim.fullname" . -}} +{{- end -}} +{{- end -}} + +{{/* +Define secret name of postgres dependency. +*/}} +{{- define "dim.postgresSecretName" -}} +{{- printf "%s-%s" .Release.Name "dim-postgres" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "dim.labels" -}} +helm.sh/chart: {{ include "dim.chart" . }} +{{ include "dim.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "dim.selectorLabels" -}} +app.kubernetes.io/name: {{ include "dim.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "dim.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "dim.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Determine database hostname for subchart +*/}} + +{{- define "dim.postgresql.primary.fullname" -}} +{{- if eq .Values.postgresql.architecture "replication" }} +{{- printf "%s-primary" (include "dim.chart.name.postgresql.dependency" .) | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{- include "dim.chart.name.postgresql.dependency" . -}} +{{- end -}} +{{- end -}} + +{{- define "dim.postgresql.readReplica.fullname" -}} +{{- printf "%s-read" (include "dim.chart.name.postgresql.dependency" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "dim.chart.name.postgresql.dependency" -}} +{{- if .Values.postgresql.fullnameOverride -}} +{{- .Values.postgresql.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default "postgresql" .Values.postgresql.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/dim/templates/configmap-postgres-init.yaml b/charts/dim/templates/configmap-postgres-init.yaml new file mode 100644 index 0000000..e7a38e1 --- /dev/null +++ b/charts/dim/templates/configmap-postgres-init.yaml @@ -0,0 +1,35 @@ +{{- /* +* Copyright (c) 2024 BMW Group AG +* +* 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.postgresql.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-dim-cm-postgres + namespace: {{ .Release.Namespace }} +data: + 02-init-db.sql: | + CREATE SCHEMA dim; + ALTER SCHEMA dim OWNER TO dim; + CREATE TABLE public.__efmigrations_history_dim ( + migration_id character varying(150) NOT NULL, + product_version character varying(32) NOT NULL + ); + ALTER TABLE public.__efmigrations_history_dim OWNER TO dim; +{{- end -}} diff --git a/charts/dim/templates/cronjob-processes.yaml b/charts/dim/templates/cronjob-processes.yaml new file mode 100644 index 0000000..c8bad47 --- /dev/null +++ b/charts/dim/templates/cronjob-processes.yaml @@ -0,0 +1,123 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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: batch/v1 +kind: CronJob +metadata: + name: {{ include "dim.fullname" . }}-{{ .Values.processesworker.name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "dim.labels" . | nindent 4 }} +spec: + schedule: "*/5 * * * *" + concurrencyPolicy: Forbid + jobTemplate: + metadata: + name: {{ include "dim.fullname" . }}-{{ .Values.processesworker.name }} + spec: + template: + spec: + restartPolicy: OnFailure + containers: + - name: {{ include "dim.fullname" . }}-{{ .Values.processesworker.name }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + image: "{{ .Values.processesworker.image.name }}:{{ .Values.processesworker.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.processesworker.imagePullPolicy }}" + env: + - name: DOTNET_ENVIRONMENT + value: "{{ .Values.dotnetEnvironment }}" + {{- if .Values.postgresql.enabled }} + - name: "DIM_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ template "dim.postgresSecretName" . }}" + key: "password" + - name: "CONNECTIONSTRINGS__DIMDB" + value: "Server={{ template "dim.postgresql.primary.fullname" . }};Database={{ .Values.postgresql.auth.database }};Port={{ .Values.postgresql.auth.port }};User Id={{ .Values.postgresql.auth.username }};Password=$(DIM_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + {{- if not .Values.postgresql.enabled }} + - name: "DIM_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ .Values.externalDatabase.secret }}" + key: "password" + - name: "CONNECTIONSTRINGS__DIMDB" + value: "Server={{ .Values.externalDatabase.host }};Database={{ .Values.externalDatabase.database }};Port={{ .Values.externalDatabase.port }};User Id={{ .Values.externalDatabase.username }};Password=$(DIM_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + - name: "DIM__ADMINMAIL" + value: "{{ .Values.processesworker.dim.adminMail }}" + - name: "DIM__ROOTDIRECTORYID" + value: "{{ .Values.dim.rootDirectoryId }}" + - name: "DIM__CLIENTIDCISCENTRAL" + value: "{{ .Values.processesworker.dim.clientIdCisCentral }}" + - name: "DIM__CLIENTSECRETCISCENTRAL" + valueFrom: + secretKeyRef: + name: "{{ template "dim.secretName" . }}" + key: "client-secret-cis-central" + - name: "DIM__AUTHURL" + value: "{{ .Values.processesworker.dim.authUrl }}" + - name: "SUBACCOUNT__BASEURL" + value: "{{ .Values.processesworker.subaccount.baseUrl }}" + - name: "ENTITLEMENT__BASEURL" + value: "{{ .Values.processesworker.entitlement.baseUrl }}" + - name: "CF__CLIENTID" + value: "{{ .Values.processesworker.cf.clientId }}" + - name: "CF__CLIENTSECRET" + valueFrom: + secretKeyRef: + name: "{{ template "dim.secretName" . }}" + key: "client-secret-cf" + - name: "CF__TOKENADDRESS" + value: "{{ .Values.processesworker.cf.tokenAddress }}" + - name: "CF__BASEURL" + value: "{{ .Values.processesworker.cf.baseUrl }}" + - name: "CF__GRANTTYPE" + value: "{{ .Values.processesworker.cf.grantType }}" + - name: "CALLBACK__USERNAME" + value: "empty" + - name: "CALLBACK__PASSWORD" + value: "empty" + - name: "CALLBACK__CLIENTID" + value: "{{ .Values.processesworker.callback.clientId }}" + - name: "CALLBACK__CLIENTSECRET" + valueFrom: + secretKeyRef: + name: "{{ template "dim.secretName" . }}" + key: "client-secret-callback" + - name: "CALLBACK__GRANTTYPE" + value: "{{ .Values.processesworker.callback.grantType }}" + - name: "CALLBACK__SCOPE" + value: "{{ .Values.processesworker.callback.scope }}" + - name: "CALLBACK__TOKENADDRESS" + value: "{{ .Values.processesworker.callback.tokenAddress }}" + - name: "CALLBACK__BASEADDRESS" + value: "{{ .Values.processesworker.callback.baseAddress }}" + ports: + - name: http + containerPort: {{ .Values.portContainer }} + protocol: TCP + resources: + {{- toYaml .Values.processesworker.resources | nindent 14 }} diff --git a/charts/dim/templates/deployment.yaml b/charts/dim/templates/deployment.yaml new file mode 100644 index 0000000..5f51fce --- /dev/null +++ b/charts/dim/templates/deployment.yaml @@ -0,0 +1,131 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 "dim.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "dim.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + strategy: + {{- toYaml .Values.updateStrategy | nindent 4 }} + selector: + matchLabels: + {{- include "dim.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "dim.selectorLabels" . | nindent 8 }} + spec: + containers: + - name: {{ include "dim.fullname" . }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + image: "{{ .Values.dim.image.name }}:{{ .Values.dim.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.dim.imagePullPolicy }}" + env: + - name: DOTNET_ENVIRONMENT + value: "{{ .Values.dotnetEnvironment }}" + {{- if .Values.postgresql.enabled }} + - name: "DIM_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ template "dim.postgresSecretName" . }}" + key: "password" + - name: "CONNECTIONSTRINGS__DIMDB" + value: "Server={{ template "dim.postgresql.primary.fullname" . }};Database={{ .Values.postgresql.auth.database }};Port={{ .Values.postgresql.auth.port }};User Id={{ .Values.postgresql.auth.username }};Password=$(DIM_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + {{- if not .Values.postgresql.enabled }} + - name: "DIM_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ .Values.externalDatabase.existingSecret }}" + key: "password" + - name: "CONNECTIONSTRINGS__DIMDB" + value: "Server={{ .Values.externalDatabase.host }};Database={{ .Values.externalDatabase.database }};Port={{ .Values.externalDatabase.port }};User Id={{ .Values.externalDatabase.username }};Password=$(DIM_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + - name: "HEALTHCHECKS__0__PATH" + value: "{{ .Values.dim.healthChecks.startup.path}}" + {{- if .Values.dim.healthChecks.startup.tags }} + {{- toYaml .Values.dim.healthChecks.startup.tags | nindent 8 }} + {{- end }} + - name: "HEALTHCHECKS__1__PATH" + value: "{{ .Values.dim.healthChecks.readyness.path}}" + - name: "HEALTHCHECKS__2__PATH" + value: "{{ .Values.dim.healthChecks.liveness.path}}" + - name: "SWAGGERENABLED" + value: "{{ .Values.dim.swaggerEnabled }}" + - name: "DIM__ROOTDIRECTORYID" + value: "{{ .Values.dim.rootDirectoryId }}" + ports: + - name: http + containerPort: {{ .Values.portContainer }} + protocol: TCP + startupProbe: + httpGet: + path: {{ .Values.dim.healthChecks.startup.path }} + port: {{ .Values.portContainer }} + scheme: HTTP + initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} + successThreshold: {{ .Values.startupProbe.successThreshold }} + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + livenessProbe: + httpGet: + path: {{ .Values.dim.healthChecks.liveness.path }} + port: {{ .Values.portContainer }} + scheme: HTTP + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + readinessProbe: + httpGet: + path: {{ .Values.dim.healthChecks.readyness.path }} + port: {{ .Values.portContainer }} + scheme: HTTP + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + resources: + {{- toYaml .Values.dim.resources | nindent 10 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/dim/templates/ingress.yaml b/charts/dim/templates/ingress.yaml new file mode 100644 index 0000000..925c4a4 --- /dev/null +++ b/charts/dim/templates/ingress.yaml @@ -0,0 +1,80 @@ +{{- /* +* Copyright (c) 2024 BMW Group AG +* +* 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.ingress.enabled -}} +{{- $fullName := include "dim.fullname" . -}} +{{- $svcPort := .Values.portService -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "dim.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ .backend.port }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/dim/templates/job-migrations.yaml b/charts/dim/templates/job-migrations.yaml new file mode 100644 index 0000000..fd90349 --- /dev/null +++ b/charts/dim/templates/job-migrations.yaml @@ -0,0 +1,77 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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: batch/v1 +kind: Job +metadata: + name: {{ include "dim.fullname" . }}-{{ .Values.migrations.name }} + annotations: + "batch.kubernetes.io/job-tracking": "true" + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "-5" +spec: + template: + metadata: + name: {{ include "dim.fullname" . }}-{{ .Values.migrations.name }} + spec: + restartPolicy: Never + containers: + - name: {{ include "dim.fullname" . }}-{{ .Values.migrations.name }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + image: "{{ .Values.migrations.image.name }}:{{ .Values.migrations.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.migrations.imagePullPolicy }}" + env: + - name: DOTNET_ENVIRONMENT + value: "{{ .Values.dotnetEnvironment }}" + {{- if .Values.postgresql.enabled }} + - name: "DIM_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ template "dim.postgresSecretName" . }}" + key: "password" + - name: "CONNECTIONSTRINGS__DIMDB" + value: "Server={{ template "dim.postgresql.primary.fullname" . }};Database={{ .Values.postgresql.auth.database }};Port={{ .Values.postgresql.auth.port }};User Id={{ .Values.postgresql.auth.username }};Password=$(DIM_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + {{- if not .Values.postgresql.enabled }} + - name: "DIM_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ .Values.externalDatabase.existingSecret }}" + key: "password" + - name: "CONNECTIONSTRINGS__DIMDB" + value: "Server={{ .Values.externalDatabase.host }};Database={{ .Values.externalDatabase.database }};Port={{ .Values.externalDatabase.port }};User Id={{ .Values.externalDatabase.username }};Password=$(DIM_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + - name: "SEEDING__TESTDATAENVIRONMENTS__0" + value: "{{ .Values.migrations.seeding.testDataEnvironments }}" + - name: "SEEDING__DATAPATHS__0" + value: "{{ .Values.migrations.seeding.testDataPaths }}" + - name: "SERILOG__MINIMUMLEVEL__Default" + value: "{{ .Values.migrations.logging.default }}" + ports: + - name: http + containerPort: {{ .Values.portContainer }} + protocol: TCP + resources: + {{- toYaml .Values.migrations.resources | nindent 10 }} diff --git a/charts/dim/templates/secret-external-db.yaml b/charts/dim/templates/secret-external-db.yaml new file mode 100644 index 0000000..619849a --- /dev/null +++ b/charts/dim/templates/secret-external-db.yaml @@ -0,0 +1,39 @@ +{{- /* +* Copyright (c) 2024 BMW Group AG +* +* 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 not .Values.postgresql.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.externalDatabase.existingSecret }} + namespace: {{ .Release.Namespace }} +type: Opaque +# use lookup function to check if secret exists +{{- $secret := (lookup "v1" "Secret" .Release.Namespace .Values.externalDatabase.existingSecret) }} +{{ if $secret -}} +data: + # if secret exists, use value provided from values file (to cover update scenario) or existing value from secret + # use data map instead of stringData to prevent base64 encoding of already base64-encoded existing value from secret + password: {{ ( .Values.externalDatabase.password | b64enc ) | default $secret.data.password | quote }} +{{ else -}} +stringData: + # if secret doesn't exist, use provided value from values file or generate a random one + password: {{ .Values.externalDatabase.password | default ( randAlphaNum 32 ) | quote }} +{{ end }} +{{- end -}} diff --git a/charts/dim/templates/secret-postgres.yaml b/charts/dim/templates/secret-postgres.yaml new file mode 100644 index 0000000..8775429 --- /dev/null +++ b/charts/dim/templates/secret-postgres.yaml @@ -0,0 +1,45 @@ +{{- /* +* Copyright (c) 2024 BMW Group AG +* +* 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.postgresql.enabled -}} +{{- $secretName := include "dim.postgresSecretName" . -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ .Release.Namespace }} +type: Opaque +# use lookup function to check if secret exists +{{- $secret := (lookup "v1" "Secret" .Release.Namespace $secretName) }} +{{ if $secret -}} +data: + # if secret exists, use value provided from values file (to cover update scenario) or existing value from secret + # use data map instead of stringData to prevent base64 encoding of already base64-encoded existing value from secret + # use index function for secret keys with hyphen otherwise '$secret.data.secretKey' works too + postgres-password: {{ ( .Values.postgresql.auth.postgrespassword | b64enc ) | default ( index $secret.data "postgres-password" ) | quote }} + password: {{ ( .Values.postgresql.auth.password | b64enc ) | default $secret.data.password | quote }} + replication-password: {{ ( .Values.postgresql.auth.replicationPassword | b64enc ) | default ( index $secret.data "replication-password" ) | quote}} +{{ else -}} +stringData: + # if secret doesn't exist, use provided value from values file or generate a random one + postgres-password: {{ .Values.postgresql.auth.postgrespassword | default ( randAlphaNum 32 ) | quote }} + password: {{ .Values.postgresql.auth.password | default ( randAlphaNum 32 ) | quote }} + replication-password: {{ .Values.postgresql.auth.replicationPassword | default ( randAlphaNum 32 ) | quote }} +{{ end }} +{{- end -}} diff --git a/charts/dim/templates/secret.yaml b/charts/dim/templates/secret.yaml new file mode 100644 index 0000000..e8a317b --- /dev/null +++ b/charts/dim/templates/secret.yaml @@ -0,0 +1,47 @@ +{{- /* +* Copyright (c) 2024 BMW Group AG +* +* 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 not .Values.existingSecret }} +{{- $secretName := include "dim.secretName" . -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "dim.secretName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "dim.labels" . | nindent 4 }} +type: Opaque +# use lookup function to check if secret exists +{{- $secret := (lookup "v1" "Secret" .Release.Namespace $secretName) }} +{{ if $secret -}} +data: + # if secret exists, use value provided from values file (to cover update scenario) or existing value from secret or generate a random one (if keys are added later on) + # use data map instead of stringData to prevent base64 encoding of already base64-encoded existing value from secret + # use index function for secret keys with hyphen otherwise '$secret.data.secretKey' works too + client-secret-cis-central: {{ coalesce ( .Values.processesworker.dim.clientSecretCisCentral | b64enc ) ( index $secret.data "client-secret-cis-central" ) | default ( randAlphaNum 32 ) | quote }} + client-secret-cf: {{ coalesce ( .Values.processesworker.cf.clientSecret | b64enc ) ( index $secret.data "client-secret-cf" ) | default ( randAlphaNum 32 ) | quote }} + client-secret-callback: {{ coalesce ( .Values.processesworker.callback.clientSecret | b64enc ) ( index $secret.data "client-secret-callback" ) | default ( randAlphaNum 32 ) | quote }} +{{ else -}} +stringData: + # if secret doesn't exist, use provided value from values file or generate a random one + client-secret-cis-central: {{ .Values.processesworker.dim.clientSecretCisCentral | default ( randAlphaNum 32 ) | quote }} + client-secret-cf: {{ .Values.processesworker.cf.clientSecret | default ( randAlphaNum 32 ) | quote }} + client-secret-callback: {{ .Values.processesworker.callback.clientSecret | default ( randAlphaNum 32 ) | quote }} +{{ end }} +{{- end -}} diff --git a/charts/dim/templates/service.yaml b/charts/dim/templates/service.yaml new file mode 100644 index 0000000..e9d62f9 --- /dev/null +++ b/charts/dim/templates/service.yaml @@ -0,0 +1,33 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 "dim.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "dim.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: {{ .Values.portService }} + targetPort: {{ .Values.portContainer }} + selector: + {{- include "dim.selectorLabels" . | nindent 4 }} diff --git a/charts/dim/values.yaml b/charts/dim/values.yaml new file mode 100644 index 0000000..8d7e4c0 --- /dev/null +++ b/charts/dim/values.yaml @@ -0,0 +1,255 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +dim: + image: + name: "ghcr.io/phil91/dim-client_dim-service" + tag: "" + imagePullPolicy: "IfNotPresent" + # -- We recommend to review the default resource limits as this should a conscious choice. + resources: + requests: + cpu: 15m + memory: 200M + limits: + cpu: 45m + memory: 200M + healthChecks: + startup: + path: "/health/startup" + tags: + - name: "HEALTHCHECKS__0__TAGS__1" + value: "dimdb" + liveness: + path: "/healthz" + readyness: + path: "/ready" + swaggerEnabled: false + rootDirectoryId: "00000000-0000-0000-0000-000000000000" + +migrations: + name: "migrations" + image: + name: "ghcr.io/phil91/dim-client_dim-migrations" + tag: "" + imagePullPolicy: "IfNotPresent" + # -- We recommend to review the default resource limits as this should a conscious choice. + resources: + requests: + cpu: 15m + memory: 105M + limits: + cpu: 45m + memory: 105M + seeding: + testDataEnvironments: "" + testDataPaths: "Seeder/Data" + logging: + default: "Information" + +processesworker: + name: "processesworker" + image: + name: "ghcr.io/phil91/dim-client_dim-processes-worker" + tag: "" + imagePullPolicy: "IfNotPresent" + # -- We recommend to review the default resource limits as this should a conscious choice. + resources: + requests: + cpu: 15m + memory: 105M + limits: + cpu: 45m + memory: 105M + dim: + adminMail: "mail@example.org" + clientIdCisCentral: "" + clientSecretCisCentral: "" + authUrl: "" + subaccount: + # -- Url to the subaccount service api + baseUrl: "" + entitlement: + # -- Url to the entitlement service api + baseUrl: "" + cf: + clientId: "" + clientSecret: "" + tokenAddress: "" + # -- Url to the cf service api + baseUrl: "" + grantType: "client_credentials" + callback: + scope: "openid" + grantType: "client_credentials" + # -- Provide client-id for callback. + clientId: "" + # -- Client-secret for callback client-id. Secret-key 'callback-client-secret'. + clientSecret: "" + tokenAddress: "" + # -- Url to the cf service api + baseAddress: "" + +# -- Secret containing "client-secret-cis-central", "client-secret-cf" and "client-secret-callback" +existingSecret: "" + +dotnetEnvironment: "Production" + +dbConnection: + schema: "dim" + sslMode: "Disable" + +postgresql: + # -- PostgreSQL chart configuration; + # default configurations: + # host: "dim-postgresql-primary", + # port: 5432; + # Switch to enable or disable the PostgreSQL helm chart. + enabled: true + # -- Setting image tag to major to get latest minor updates + image: + tag: "15-debian-12" + commonLabels: + app.kubernetes.io/version: "15" + auth: + # -- Non-root username. + username: dim + # -- Database name. + database: dim + # -- Secret containing the passwords for root usernames postgres and non-root username dim. + # Should not be changed without changing the "dim-postgresSecretName" template as well. + existingSecret: "{{ .Release.Name }}-dim-postgres" + # -- Password for the root username 'postgres'. Secret-key 'postgres-password'. + postgrespassword: "" + # -- Password for the non-root username 'dim'. Secret-key 'password'. + password: "" + # -- Password for the non-root username 'repl_user'. Secret-key 'replication-password'. + replicationPassword: "" + architecture: replication + audit: + pgAuditLog: "write, ddl" + logLinePrefix: "%m %u %d " + primary: + # -- Extended PostgreSQL Primary configuration (increase of max_connections recommended - default is 100) + extendedConfiguration: "" + initdb: + scriptsConfigMap: "{{ .Release.Name }}-dim-cm-postgres" + readReplicas: + # -- Extended PostgreSQL read only replicas configuration (increase of max_connections recommended - default is 100) + extendedConfiguration: "" + +externalDatabase: + # -- External PostgreSQL configuration + # IMPORTANT: non-root db user needs to be created beforehand on external database. + # And the init script (02-init-db.sql) available in templates/configmap-postgres-init.yaml + # needs to be executed beforehand. + # Database host ('-primary' is added as postfix). + host: "dim-postgres-ext" + # -- Database port number. + port: 5432 + # -- Non-root username for dim. + username: "dim" + # -- Database name. + database: "dim" + # -- Password for the non-root username (default 'dim'). Secret-key 'password'. + password: "" + # -- Secret containing the password non-root username, (default 'dim'). + existingSecret: "dim-external-db" + +ingress: + # -- DIM ingress parameters, + # enable ingress record generation for dim. + enabled: false + # className: "nginx" + ## Optional annotations when using the nginx ingress class + # annotations: + # nginx.ingress.kubernetes.io/use-regex: "true" + # nginx.ingress.kubernetes.io/enable-cors: "true" + # nginx.ingress.kubernetes.io/proxy-body-size: "8m" + # # -- Provide CORS allowed origin. + # nginx.ingress.kubernetes.io/cors-allow-origin: "https://*.example.org" + tls: + # -- Provide tls secret. + - secretName: "" + # -- Provide host for tls secret. + hosts: + - "" + hosts: + # -- Provide default path for the ingress record. + - host: "" + paths: + - path: "/api/dim" + pathType: "Prefix" + backend: + port: 8080 + +portContainer: 8080 + +portService: 8080 + +replicaCount: 3 + +# -- Node labels for pod assignment +nodeSelector: {} + +# -- Tolerations for pod assignment +tolerations: [] + +affinity: +# -- Following Catena-X Helm Best Practices, +# [reference](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity). + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: DoesNotExist + topologyKey: kubernetes.io/hostname + +updateStrategy: +# -- Update strategy type, +# rolling update configuration parameters, +# [reference](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies). + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + +# -- Following Catena-X Helm Best Practices, +# [reference](https://github.com/helm/charts/blob/master/stable/nginx-ingress/values.yaml#L210). +startupProbe: + failureThreshold: 30 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 +livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 10 +readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 diff --git a/consortia/argocd-app-templates/appsetup-dev.yaml b/consortia/argocd-app-templates/appsetup-dev.yaml new file mode 100644 index 0000000..959def9 --- /dev/null +++ b/consortia/argocd-app-templates/appsetup-dev.yaml @@ -0,0 +1,41 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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: argoproj.io/v1alpha1 +kind: Application +metadata: + name: dim +spec: + destination: + namespace: product-portal + server: 'https://kubernetes.default.svc' + source: + path: charts/dim + repoURL: 'https://github.com/phil91/dim-client.git' + targetRevision: dev + plugin: + env: + - name: AVP_SECRET + value: vault-secret + - name: helm_args + value: '-f values.yaml -f ../../consortia/environments/values-dev.yaml' + project: project-portal + syncPolicy: + automated: + prune: true diff --git a/consortia/argocd-app-templates/appsetup-int.yaml b/consortia/argocd-app-templates/appsetup-int.yaml new file mode 100644 index 0000000..a38cff5 --- /dev/null +++ b/consortia/argocd-app-templates/appsetup-int.yaml @@ -0,0 +1,38 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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: argoproj.io/v1alpha1 +kind: Application +metadata: + name: dim +spec: + destination: + namespace: product-portal + server: 'https://kubernetes.default.svc' + source: + path: charts/dim + repoURL: 'https://github.com/phil91/dim-client.git' + targetRevision: dim-0.0.1 + plugin: + env: + - name: AVP_SECRET + value: vault-secret + - name: helm_args + value: '-f values.yaml -f ../../consortia/environments/values-int.yaml' + project: project-portal diff --git a/consortia/environments/values-dev.yaml b/consortia/environments/values-dev.yaml new file mode 100644 index 0000000..ffc131a --- /dev/null +++ b/consortia/environments/values-dev.yaml @@ -0,0 +1,93 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +ingress: + enabled: true + className: "nginx" + annotations: + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/enable-cors: "true" + nginx.ingress.kubernetes.io/proxy-body-size: "8m" + nginx.ingress.kubernetes.io/cors-allow-origin: "http://localhost:3000, https://*.dev.demo.catena-x.net" + tls: + - secretName: "tls-secret" + hosts: + - "dim.dev.demo.catena-x.net" + hosts: + - host: "dim.dev.demo.catena-x.net" + paths: + - path: "/api/dim" + pathType: "Prefix" + backend: + port: 8080 + +dim: + image: + tag: "dev" + imagePullPolicy: "Always" + swaggerEnabled: true + rootDirectoryId: "27fee02a-e265-4cfc-af70-4f217a33840b" + +migrations: + image: + tag: "dev" + imagePullPolicy: "Always" + logging: + default: "Debug" + +processesworker: + image: + tag: "dev" + imagePullPolicy: "Always" + logging: + default: "Debug" + dim: + adminMail: "phil.schneider@digitalnativesolutions.de" + clientIdCisCentral: "" + authUrl: "https://catena-x-int-dim.authentication.eu10.hana.ondemand.com" + subaccount: + # -- Url to the subaccount service api + baseUrl: "https://accounts-service.cfapps.eu10.hana.ondemand.com" + entitlement: + # -- Url to the entitlement service api + baseUrl: "https://entitlements-service.cfapps.eu10.hana.ondemand.com" + cf: + clientId: "" + clientSecret: "" + tokenAddress: "https://login.cf.eu10.hana.ondemand.com/oauth/token" + # -- Url to the cf service api + baseUrl: "https://api.cf.eu10.hana.ondemand.com" + grantType: "client_credentials" + callback: + scope: "openid" + grantType: "client_credentials" + # -- Provide client-id for callback. + clientId: "" + # -- Client-secret for callback client-id. Secret-key 'callback-client-secret'. + clientSecret: "" + tokenAddress: "http://centralidp.dev.demo.catena-x.net/auth/realms/CX-Central/protocol/openid-connect/token" + # -- Url to the cf service api + baseAddress: "https://portal-backend.dev.demo.catena-x.net/api/administration/registration/dim/" + +postgresql: + auth: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-int.yaml b/consortia/environments/values-int.yaml new file mode 100644 index 0000000..2473193 --- /dev/null +++ b/consortia/environments/values-int.yaml @@ -0,0 +1,84 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +ingress: + enabled: true + className: "nginx" + annotations: + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/enable-cors: "true" + nginx.ingress.kubernetes.io/proxy-body-size: "8m" + nginx.ingress.kubernetes.io/cors-allow-origin: "http://localhost:3000, https://*.int.demo.catena-x.net" + tls: + - secretName: "tls-secret" + hosts: + - "dim.int.demo.catena-x.net" + hosts: + - host: "dim.int.demo.catena-x.net" + paths: + - path: "/api/dim" + pathType: "Prefix" + backend: + port: 8080 + +dim: + swaggerEnabled: true + rootDirectoryId: "27fee02a-e265-4cfc-af70-4f217a33840b" + +migrations: + logging: + default: "Debug" + +processesworker: + logging: + default: "Debug" + dim: + adminMail: "phil.schneider@digitalnativesolutions.de" + clientIdCisCentral: "" + authUrl: "https://catena-x-int-dim.authentication.eu10.hana.ondemand.com" + subaccount: + # -- Url to the subaccount service api + baseUrl: "https://accounts-service.cfapps.eu10.hana.ondemand.com" + entitlement: + # -- Url to the entitlement service api + baseUrl: "https://entitlements-service.cfapps.eu10.hana.ondemand.com" + cf: + clientId: "" + clientSecret: "" + tokenAddress: "https://login.cf.eu10.hana.ondemand.com/oauth/token" + # -- Url to the cf service api + baseUrl: "https://api.cf.eu10.hana.ondemand.com" + grantType: "client_credentials" + callback: + scope: "openid" + grantType: "client_credentials" + # -- Provide client-id for callback. + clientId: "" + # -- Client-secret for callback client-id. Secret-key 'callback-client-secret'. + clientSecret: "" + tokenAddress: "http://centralidp.int.demo.catena-x.net/auth/realms/CX-Central/protocol/openid-connect/token" + # -- Url to the cf service api + baseAddress: "https://portal-backend.dev.demo.catena-x.net/api/administration/registration/dim/" + +postgresql: + auth: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/docker/Dockerfile-dim-migrations b/docker/Dockerfile-dim-migrations new file mode 100644 index 0000000..7122376 --- /dev/null +++ b/docker/Dockerfile-dim-migrations @@ -0,0 +1,36 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +FROM mcr.microsoft.com/dotnet/runtime:7.0-alpine AS base + +FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine-amd64 AS publish +WORKDIR / +COPY LICENSE / +COPY /src/database /src/database +COPY /src/processes/Processes.Worker.Library /src/processes/Processes.Worker.Library +WORKDIR /src/database/Dim.Migrations +RUN dotnet publish "Dim.Migrations.csproj" -c Release -o /migrations/publish + +FROM base AS final +ENV COMPlus_EnableDiagnostics=0 +WORKDIR /migrations +COPY --from=publish /migrations/publish . +RUN chown -R 1000:3000 /migrations +USER 1000:3000 +ENTRYPOINT ["dotnet", "Dim.Migrations.dll"] diff --git a/docker/Dockerfile-dim-processes-worker b/docker/Dockerfile-dim-processes-worker new file mode 100644 index 0000000..b0a87da --- /dev/null +++ b/docker/Dockerfile-dim-processes-worker @@ -0,0 +1,36 @@ +īģŋ############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +FROM mcr.microsoft.com/dotnet/runtime:7.0-alpine AS base + +FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine-amd64 AS publish +WORKDIR / +COPY LICENSE / +COPY src/ src/ +RUN dotnet restore "src/processes/Processes.Worker/Processes.Worker.csproj" +WORKDIR /src/processes/Processes.Worker +RUN dotnet publish "Processes.Worker.csproj" -c Release -o /app/publish + +FROM base AS final +ENV COMPlus_EnableDiagnostics=0 +WORKDIR /app +COPY --from=publish /app/publish . +RUN chown -R 1000:3000 /app +USER 1000:3000 +ENTRYPOINT ["dotnet", "Processes.Worker.dll"] diff --git a/docker/Dockerfile-dim-service b/docker/Dockerfile-dim-service new file mode 100644 index 0000000..11039a5 --- /dev/null +++ b/docker/Dockerfile-dim-service @@ -0,0 +1,37 @@ +############################################################### +# Copyright (c) 2024 BMW Group AG +# +# 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 +############################################################### + +FROM mcr.microsoft.com/dotnet/aspnet:7.0-alpine AS base + +FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine-amd64 AS publish +WORKDIR / +COPY LICENSE / +COPY src/ src/ +WORKDIR /src/web/Dim.Web +RUN dotnet publish "Dim.Web.csproj" -c Release -o /app/publish + +FROM base AS final +ENV COMPlus_EnableDiagnostics=0 +WORKDIR /app +COPY --from=publish /app/publish . +ENV ASPNETCORE_URLS http://+:8080 +EXPOSE 8080 +RUN chown -R 1000:3000 /app +USER 1000:3000 +ENTRYPOINT ["dotnet", "Dim.Web.dll"] diff --git a/src/clients/Dim.Clients/Api/Cf/AddSpaceRoleToUserRequest.cs b/src/clients/Dim.Clients/Api/Cf/AddSpaceRoleToUserRequest.cs index 168f9fd..60cc686 100644 --- a/src/clients/Dim.Clients/Api/Cf/AddSpaceRoleToUserRequest.cs +++ b/src/clients/Dim.Clients/Api/Cf/AddSpaceRoleToUserRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Cf/CfClient.cs b/src/clients/Dim.Clients/Api/Cf/CfClient.cs index 721ebcc..b4374e9 100644 --- a/src/clients/Dim.Clients/Api/Cf/CfClient.cs +++ b/src/clients/Dim.Clients/Api/Cf/CfClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Cf/CreateCfeRequest.cs b/src/clients/Dim.Clients/Api/Cf/CreateCfeRequest.cs index 46c5f26..b583d9f 100644 --- a/src/clients/Dim.Clients/Api/Cf/CreateCfeRequest.cs +++ b/src/clients/Dim.Clients/Api/Cf/CreateCfeRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Cf/DependencyInjection/CfClientServiceExtensions.cs b/src/clients/Dim.Clients/Api/Cf/DependencyInjection/CfClientServiceExtensions.cs index 544c9f0..f0aa38a 100644 --- a/src/clients/Dim.Clients/Api/Cf/DependencyInjection/CfClientServiceExtensions.cs +++ b/src/clients/Dim.Clients/Api/Cf/DependencyInjection/CfClientServiceExtensions.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Cf/DependencyInjection/CfSettings.cs b/src/clients/Dim.Clients/Api/Cf/DependencyInjection/CfSettings.cs index df0560e..ea2678c 100644 --- a/src/clients/Dim.Clients/Api/Cf/DependencyInjection/CfSettings.cs +++ b/src/clients/Dim.Clients/Api/Cf/DependencyInjection/CfSettings.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Cf/ICfClient.cs b/src/clients/Dim.Clients/Api/Cf/ICfClient.cs index 3e41e0f..7aab550 100644 --- a/src/clients/Dim.Clients/Api/Cf/ICfClient.cs +++ b/src/clients/Dim.Clients/Api/Cf/ICfClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Cf/ServicePlanResponse.cs b/src/clients/Dim.Clients/Api/Cf/ServicePlanResponse.cs index cbdb758..7678fa8 100644 --- a/src/clients/Dim.Clients/Api/Cf/ServicePlanResponse.cs +++ b/src/clients/Dim.Clients/Api/Cf/ServicePlanResponse.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Dim/ApplicationResponse.cs b/src/clients/Dim.Clients/Api/Dim/ApplicationResponse.cs index 0525faf..7e7894c 100644 --- a/src/clients/Dim.Clients/Api/Dim/ApplicationResponse.cs +++ b/src/clients/Dim.Clients/Api/Dim/ApplicationResponse.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Dim/CompanyIdentityPatch.cs b/src/clients/Dim.Clients/Api/Dim/CompanyIdentityPatch.cs index 91fb437..3124ba1 100644 --- a/src/clients/Dim.Clients/Api/Dim/CompanyIdentityPatch.cs +++ b/src/clients/Dim.Clients/Api/Dim/CompanyIdentityPatch.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Dim/CreateApplicationRequest.cs b/src/clients/Dim.Clients/Api/Dim/CreateApplicationRequest.cs index e2bf29b..198dbfe 100644 --- a/src/clients/Dim.Clients/Api/Dim/CreateApplicationRequest.cs +++ b/src/clients/Dim.Clients/Api/Dim/CreateApplicationRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Dim/CreateCompanyIdentityRequest.cs b/src/clients/Dim.Clients/Api/Dim/CreateCompanyIdentityRequest.cs index d27a7dc..2d6f86e 100644 --- a/src/clients/Dim.Clients/Api/Dim/CreateCompanyIdentityRequest.cs +++ b/src/clients/Dim.Clients/Api/Dim/CreateCompanyIdentityRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Dim/DependencyInjection/DimClientServiceExtensions.cs b/src/clients/Dim.Clients/Api/Dim/DependencyInjection/DimClientServiceExtensions.cs index a938f15..c4f9738 100644 --- a/src/clients/Dim.Clients/Api/Dim/DependencyInjection/DimClientServiceExtensions.cs +++ b/src/clients/Dim.Clients/Api/Dim/DependencyInjection/DimClientServiceExtensions.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Dim/DimClient.cs b/src/clients/Dim.Clients/Api/Dim/DimClient.cs index 810a169..79bede7 100644 --- a/src/clients/Dim.Clients/Api/Dim/DimClient.cs +++ b/src/clients/Dim.Clients/Api/Dim/DimClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Dim/IDimClient.cs b/src/clients/Dim.Clients/Api/Dim/IDimClient.cs index aef6ba2..5727cd6 100644 --- a/src/clients/Dim.Clients/Api/Dim/IDimClient.cs +++ b/src/clients/Dim.Clients/Api/Dim/IDimClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Directories/DependencyInjection/DirectoryClientServiceExtensions.cs b/src/clients/Dim.Clients/Api/Directories/DependencyInjection/DirectoryClientServiceExtensions.cs index 8046c45..47725e0 100644 --- a/src/clients/Dim.Clients/Api/Directories/DependencyInjection/DirectoryClientServiceExtensions.cs +++ b/src/clients/Dim.Clients/Api/Directories/DependencyInjection/DirectoryClientServiceExtensions.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Directories/DependencyInjection/DirectorySettings.cs b/src/clients/Dim.Clients/Api/Directories/DependencyInjection/DirectorySettings.cs index f009a26..e4a65c2 100644 --- a/src/clients/Dim.Clients/Api/Directories/DependencyInjection/DirectorySettings.cs +++ b/src/clients/Dim.Clients/Api/Directories/DependencyInjection/DirectorySettings.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Directories/DirectoryClient.cs b/src/clients/Dim.Clients/Api/Directories/DirectoryClient.cs index ccb8823..4c494a0 100644 --- a/src/clients/Dim.Clients/Api/Directories/DirectoryClient.cs +++ b/src/clients/Dim.Clients/Api/Directories/DirectoryClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Directories/DirectoryRequest.cs b/src/clients/Dim.Clients/Api/Directories/DirectoryRequest.cs index 7d1b860..39d09c1 100644 --- a/src/clients/Dim.Clients/Api/Directories/DirectoryRequest.cs +++ b/src/clients/Dim.Clients/Api/Directories/DirectoryRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Directories/IDirectoryClient.cs b/src/clients/Dim.Clients/Api/Directories/IDirectoryClient.cs index 9c25577..32a5b7d 100644 --- a/src/clients/Dim.Clients/Api/Directories/IDirectoryClient.cs +++ b/src/clients/Dim.Clients/Api/Directories/IDirectoryClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Entitlements/CreateSubAccountRequest.cs b/src/clients/Dim.Clients/Api/Entitlements/CreateSubAccountRequest.cs index aa5622a..e0d785e 100644 --- a/src/clients/Dim.Clients/Api/Entitlements/CreateSubAccountRequest.cs +++ b/src/clients/Dim.Clients/Api/Entitlements/CreateSubAccountRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Entitlements/DependencyInjection/EntitlementClientServiceExtensions.cs b/src/clients/Dim.Clients/Api/Entitlements/DependencyInjection/EntitlementClientServiceExtensions.cs index 768e672..8ec9e9b 100644 --- a/src/clients/Dim.Clients/Api/Entitlements/DependencyInjection/EntitlementClientServiceExtensions.cs +++ b/src/clients/Dim.Clients/Api/Entitlements/DependencyInjection/EntitlementClientServiceExtensions.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Entitlements/DependencyInjection/EntitlementSettings.cs b/src/clients/Dim.Clients/Api/Entitlements/DependencyInjection/EntitlementSettings.cs index 394967a..42c4fe2 100644 --- a/src/clients/Dim.Clients/Api/Entitlements/DependencyInjection/EntitlementSettings.cs +++ b/src/clients/Dim.Clients/Api/Entitlements/DependencyInjection/EntitlementSettings.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Entitlements/EntitlementClient.cs b/src/clients/Dim.Clients/Api/Entitlements/EntitlementClient.cs index 4f80830..35ba3e1 100644 --- a/src/clients/Dim.Clients/Api/Entitlements/EntitlementClient.cs +++ b/src/clients/Dim.Clients/Api/Entitlements/EntitlementClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Entitlements/IEntitlementClient.cs b/src/clients/Dim.Clients/Api/Entitlements/IEntitlementClient.cs index 8c37af8..902d613 100644 --- a/src/clients/Dim.Clients/Api/Entitlements/IEntitlementClient.cs +++ b/src/clients/Dim.Clients/Api/Entitlements/IEntitlementClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Provisioning/CreateCfeRequest.cs b/src/clients/Dim.Clients/Api/Provisioning/CreateCfeRequest.cs index cafca13..9122e14 100644 --- a/src/clients/Dim.Clients/Api/Provisioning/CreateCfeRequest.cs +++ b/src/clients/Dim.Clients/Api/Provisioning/CreateCfeRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Provisioning/DependencyInjection/ProvisioningClientServiceExtensions.cs b/src/clients/Dim.Clients/Api/Provisioning/DependencyInjection/ProvisioningClientServiceExtensions.cs index 1682055..738e525 100644 --- a/src/clients/Dim.Clients/Api/Provisioning/DependencyInjection/ProvisioningClientServiceExtensions.cs +++ b/src/clients/Dim.Clients/Api/Provisioning/DependencyInjection/ProvisioningClientServiceExtensions.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Provisioning/DependencyInjection/ProvisioningSettings.cs b/src/clients/Dim.Clients/Api/Provisioning/DependencyInjection/ProvisioningSettings.cs index d3d3070..73599c8 100644 --- a/src/clients/Dim.Clients/Api/Provisioning/DependencyInjection/ProvisioningSettings.cs +++ b/src/clients/Dim.Clients/Api/Provisioning/DependencyInjection/ProvisioningSettings.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Provisioning/IProvisioningClient.cs b/src/clients/Dim.Clients/Api/Provisioning/IProvisioningClient.cs index 0c3a111..99b9548 100644 --- a/src/clients/Dim.Clients/Api/Provisioning/IProvisioningClient.cs +++ b/src/clients/Dim.Clients/Api/Provisioning/IProvisioningClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Provisioning/ProvisioningClient.cs b/src/clients/Dim.Clients/Api/Provisioning/ProvisioningClient.cs index 1c090e8..0186b9f 100644 --- a/src/clients/Dim.Clients/Api/Provisioning/ProvisioningClient.cs +++ b/src/clients/Dim.Clients/Api/Provisioning/ProvisioningClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Services/CreateServiceInstanceRequest.cs b/src/clients/Dim.Clients/Api/Services/CreateServiceInstanceRequest.cs index 86c7ee7..581697b 100644 --- a/src/clients/Dim.Clients/Api/Services/CreateServiceInstanceRequest.cs +++ b/src/clients/Dim.Clients/Api/Services/CreateServiceInstanceRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Services/DependencyInjection/ServiceClientServiceExtensions.cs b/src/clients/Dim.Clients/Api/Services/DependencyInjection/ServiceClientServiceExtensions.cs index 3b0164e..bbac33a 100644 --- a/src/clients/Dim.Clients/Api/Services/DependencyInjection/ServiceClientServiceExtensions.cs +++ b/src/clients/Dim.Clients/Api/Services/DependencyInjection/ServiceClientServiceExtensions.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Services/IServiceClient.cs b/src/clients/Dim.Clients/Api/Services/IServiceClient.cs index 124aa63..8c998c6 100644 --- a/src/clients/Dim.Clients/Api/Services/IServiceClient.cs +++ b/src/clients/Dim.Clients/Api/Services/IServiceClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Services/ServiceClient.cs b/src/clients/Dim.Clients/Api/Services/ServiceClient.cs index 98d8060..f80bead 100644 --- a/src/clients/Dim.Clients/Api/Services/ServiceClient.cs +++ b/src/clients/Dim.Clients/Api/Services/ServiceClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/SubAccounts/CreateSubAccountRequest.cs b/src/clients/Dim.Clients/Api/SubAccounts/CreateSubAccountRequest.cs index 42e799e..0f878cc 100644 --- a/src/clients/Dim.Clients/Api/SubAccounts/CreateSubAccountRequest.cs +++ b/src/clients/Dim.Clients/Api/SubAccounts/CreateSubAccountRequest.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/SubAccounts/DependencyInjection/SubAccountClientServiceExtensions.cs b/src/clients/Dim.Clients/Api/SubAccounts/DependencyInjection/SubAccountClientServiceExtensions.cs index 321ddbe..3cda1ba 100644 --- a/src/clients/Dim.Clients/Api/SubAccounts/DependencyInjection/SubAccountClientServiceExtensions.cs +++ b/src/clients/Dim.Clients/Api/SubAccounts/DependencyInjection/SubAccountClientServiceExtensions.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/SubAccounts/DependencyInjection/SubAccountSettings.cs b/src/clients/Dim.Clients/Api/SubAccounts/DependencyInjection/SubAccountSettings.cs index 4712e81..deacb64 100644 --- a/src/clients/Dim.Clients/Api/SubAccounts/DependencyInjection/SubAccountSettings.cs +++ b/src/clients/Dim.Clients/Api/SubAccounts/DependencyInjection/SubAccountSettings.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/SubAccounts/ISubAccountClient.cs b/src/clients/Dim.Clients/Api/SubAccounts/ISubAccountClient.cs index e325ab2..54218d9 100644 --- a/src/clients/Dim.Clients/Api/SubAccounts/ISubAccountClient.cs +++ b/src/clients/Dim.Clients/Api/SubAccounts/ISubAccountClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/SubAccounts/SubAccountClient.cs b/src/clients/Dim.Clients/Api/SubAccounts/SubAccountClient.cs index fdcfbf5..80d8997 100644 --- a/src/clients/Dim.Clients/Api/SubAccounts/SubAccountClient.cs +++ b/src/clients/Dim.Clients/Api/SubAccounts/SubAccountClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/SubAccounts/UsedForProduction.cs b/src/clients/Dim.Clients/Api/SubAccounts/UsedForProduction.cs index 3bcdbd5..43630a9 100644 --- a/src/clients/Dim.Clients/Api/SubAccounts/UsedForProduction.cs +++ b/src/clients/Dim.Clients/Api/SubAccounts/UsedForProduction.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Subscriptions/DependencyInjection/SubscriptionClientServiceExtensions.cs b/src/clients/Dim.Clients/Api/Subscriptions/DependencyInjection/SubscriptionClientServiceExtensions.cs index 6d91fd5..3b4dbd7 100644 --- a/src/clients/Dim.Clients/Api/Subscriptions/DependencyInjection/SubscriptionClientServiceExtensions.cs +++ b/src/clients/Dim.Clients/Api/Subscriptions/DependencyInjection/SubscriptionClientServiceExtensions.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Subscriptions/ISubscriptionClient.cs b/src/clients/Dim.Clients/Api/Subscriptions/ISubscriptionClient.cs index ff59545..0b734e1 100644 --- a/src/clients/Dim.Clients/Api/Subscriptions/ISubscriptionClient.cs +++ b/src/clients/Dim.Clients/Api/Subscriptions/ISubscriptionClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Api/Subscriptions/SubscriptionClient.cs b/src/clients/Dim.Clients/Api/Subscriptions/SubscriptionClient.cs index e153f35..c54893d 100644 --- a/src/clients/Dim.Clients/Api/Subscriptions/SubscriptionClient.cs +++ b/src/clients/Dim.Clients/Api/Subscriptions/SubscriptionClient.cs @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/src/clients/Dim.Clients/Dim.Clients.csproj b/src/clients/Dim.Clients/Dim.Clients.csproj index 35d6649..5bd23c1 100644 --- a/src/clients/Dim.Clients/Dim.Clients.csproj +++ b/src/clients/Dim.Clients/Dim.Clients.csproj @@ -1,5 +1,5 @@ īģŋ + + + + 1.0.0 + + + From bf9ccc0b1a2d09894634379f4b374e314c1a1183 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 15:23:07 +0200 Subject: [PATCH 28/30] chore(changelog/v1.0.0): release 1.0.0 (#2) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Evelyn Gurschler Reviewed-by: Phil Schneider --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29..294c2d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +## 1.0.0 (2024-04-09) + + +### Features + +* **authorization:** add role authorization ([#19](https://github.com/SAP/ssi-dim-middle-layer/issues/19)) ([221a435](https://github.com/SAP/ssi-dim-middle-layer/commit/221a435c629149e5fadb0514be6a595fe968594a)) +* **client:** add dim client ([266e807](https://github.com/SAP/ssi-dim-middle-layer/commit/266e80764e0009be8cdad53781194f837140e151)) +* **net8:** upgrade to .net8 ([#23](https://github.com/SAP/ssi-dim-middle-layer/issues/23)) ([d3494de](https://github.com/SAP/ssi-dim-middle-layer/commit/d3494dedf046b05ffe7b346298abbfb2286f452f)) +* **statusList:** add statuslist endpoints ([#22](https://github.com/SAP/ssi-dim-middle-layer/issues/22)) ([167ff48](https://github.com/SAP/ssi-dim-middle-layer/commit/167ff48a404b17b226addac5695df02463cd5002)) + + +### Bug Fixes + +* **bindings:** adjust errorhandling for service instances ([#29](https://github.com/SAP/ssi-dim-middle-layer/issues/29)) ([5b8f6cc](https://github.com/SAP/ssi-dim-middle-layer/commit/5b8f6cc65a60e42d6791e8e3d5a85bbd2e2dffb3)) From df6f041ba032b5bda8524ff4d82b7801595b9d56 Mon Sep 17 00:00:00 2001 From: Phil Schneider Date: Tue, 9 Apr 2024 19:45:13 +0200 Subject: [PATCH 29/30] chore: adjust copyright header --- .github/dependabot.yml | 2 +- .github/workflows/chart-test.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/kics.yml | 2 +- .github/workflows/lint-pull-request.yml | 2 +- .github/workflows/migrations-docker.yml | 2 +- .github/workflows/owasp-zap.yml | 2 +- .github/workflows/processes-worker-docker.yml | 2 +- .github/workflows/release-please.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/service-docker.yml | 2 +- .github/workflows/sonarcloud.yml | 2 +- .github/workflows/trivy.yml | 2 +- .github/workflows/unit.tests-formatting.yml | 2 +- charts/chart-testing-config.yaml | 2 +- charts/dim/Chart.yaml | 2 +- charts/dim/templates/_helpers.tpl | 2 +- charts/dim/templates/configmap-postgres-init.yaml | 2 +- charts/dim/templates/cronjob-processes.yaml | 2 +- charts/dim/templates/deployment.yaml | 2 +- charts/dim/templates/ingress.yaml | 2 +- charts/dim/templates/job-migrations.yaml | 2 +- charts/dim/templates/secret-external-db.yaml | 2 +- charts/dim/templates/secret-postgres.yaml | 2 +- charts/dim/templates/secret.yaml | 2 +- charts/dim/templates/service.yaml | 2 +- charts/dim/values.yaml | 2 +- consortia/argocd-app-templates/appsetup-dev.yaml | 2 +- consortia/argocd-app-templates/appsetup-int.yaml | 2 +- consortia/environments/values-dev.yaml | 2 +- consortia/environments/values-int.yaml | 2 +- docker/Dockerfile-dim-migrations | 2 +- docker/Dockerfile-dim-processes-worker | 2 +- docker/Dockerfile-dim-service | 2 +- src/Directory.Build.props | 2 +- src/clients/Dim.Clients/Api/Cf/AddSpaceRoleToUserRequest.cs | 2 +- src/clients/Dim.Clients/Api/Cf/CfClient.cs | 2 +- src/clients/Dim.Clients/Api/Cf/CreateCfeRequest.cs | 2 +- .../Api/Cf/DependencyInjection/CfClientServiceExtensions.cs | 2 +- .../Dim.Clients/Api/Cf/DependencyInjection/CfSettings.cs | 2 +- src/clients/Dim.Clients/Api/Cf/ICfClient.cs | 2 +- src/clients/Dim.Clients/Api/Cf/ServicePlanResponse.cs | 2 +- src/clients/Dim.Clients/Api/Dim/ApplicationResponse.cs | 2 +- src/clients/Dim.Clients/Api/Dim/CompanyIdentityPatch.cs | 2 +- src/clients/Dim.Clients/Api/Dim/CreateApplicationRequest.cs | 2 +- src/clients/Dim.Clients/Api/Dim/CreateCompanyIdentityRequest.cs | 2 +- .../Api/Dim/DependencyInjection/DimClientServiceExtensions.cs | 2 +- src/clients/Dim.Clients/Api/Dim/DimClient.cs | 2 +- src/clients/Dim.Clients/Api/Dim/IDimClient.cs | 2 +- src/clients/Dim.Clients/Api/Dim/StatusListResponse.cs | 2 +- .../DependencyInjection/DirectoryClientServiceExtensions.cs | 2 +- .../Api/Directories/DependencyInjection/DirectorySettings.cs | 2 +- src/clients/Dim.Clients/Api/Directories/DirectoryClient.cs | 2 +- src/clients/Dim.Clients/Api/Directories/DirectoryRequest.cs | 2 +- src/clients/Dim.Clients/Api/Directories/IDirectoryClient.cs | 2 +- .../Dim.Clients/Api/Entitlements/CreateSubAccountRequest.cs | 2 +- .../DependencyInjection/EntitlementClientServiceExtensions.cs | 2 +- .../Api/Entitlements/DependencyInjection/EntitlementSettings.cs | 2 +- src/clients/Dim.Clients/Api/Entitlements/EntitlementClient.cs | 2 +- src/clients/Dim.Clients/Api/Entitlements/IEntitlementClient.cs | 2 +- src/clients/Dim.Clients/Api/Provisioning/CreateCfeRequest.cs | 2 +- .../DependencyInjection/ProvisioningClientServiceExtensions.cs | 2 +- .../Provisioning/DependencyInjection/ProvisioningSettings.cs | 2 +- src/clients/Dim.Clients/Api/Provisioning/IProvisioningClient.cs | 2 +- src/clients/Dim.Clients/Api/Provisioning/ProvisioningClient.cs | 2 +- .../Dim.Clients/Api/Services/CreateServiceInstanceRequest.cs | 2 +- .../DependencyInjection/ServiceClientServiceExtensions.cs | 2 +- src/clients/Dim.Clients/Api/Services/IServiceClient.cs | 2 +- src/clients/Dim.Clients/Api/Services/ServiceClient.cs | 2 +- .../Dim.Clients/Api/SubAccounts/CreateSubAccountRequest.cs | 2 +- .../DependencyInjection/SubAccountClientServiceExtensions.cs | 2 +- .../Api/SubAccounts/DependencyInjection/SubAccountSettings.cs | 2 +- src/clients/Dim.Clients/Api/SubAccounts/ISubAccountClient.cs | 2 +- src/clients/Dim.Clients/Api/SubAccounts/SubAccountClient.cs | 2 +- src/clients/Dim.Clients/Api/SubAccounts/UsedForProduction.cs | 2 +- .../DependencyInjection/SubscriptionClientServiceExtensions.cs | 2 +- .../Dim.Clients/Api/Subscriptions/ISubscriptionClient.cs | 2 +- src/clients/Dim.Clients/Api/Subscriptions/SubscriptionClient.cs | 2 +- src/clients/Dim.Clients/Dim.Clients.csproj | 2 +- src/clients/Dim.Clients/Extensions/HttpClientExtensions.cs | 2 +- src/clients/Dim.Clients/Extensions/JsonSerializerExtensions.cs | 2 +- src/clients/Dim.Clients/Token/AuthResponse.cs | 2 +- src/clients/Dim.Clients/Token/BasicAuthSettings.cs | 2 +- src/clients/Dim.Clients/Token/BasicAuthTokenService.cs | 2 +- src/clients/Dim.Clients/Token/GetBasicTokenSettings.cs | 2 +- src/clients/Dim.Clients/Token/IBasicAuthTokenService.cs | 2 +- .../DependencyInjection/DimRepositoriesServiceExtensions.cs | 2 +- src/database/Dim.DbAccess/Dim.DbAccess.csproj | 2 +- src/database/Dim.DbAccess/DimRepositories.cs | 2 +- src/database/Dim.DbAccess/IDimRepositories.cs | 2 +- .../Dim.DbAccess/Repositories/IProcessStepRepository.cs | 2 +- src/database/Dim.DbAccess/Repositories/ITenantRepository.cs | 2 +- src/database/Dim.DbAccess/Repositories/ProcessStepRepository.cs | 2 +- src/database/Dim.DbAccess/Repositories/TenantRepository.cs | 2 +- src/database/Dim.Entities/Dim.Entities.csproj | 2 +- src/database/Dim.Entities/DimDbContext.cs | 2 +- src/database/Dim.Entities/Entities/Process.cs | 2 +- src/database/Dim.Entities/Entities/ProcessStep.cs | 2 +- src/database/Dim.Entities/Entities/ProcessStepStatus.cs | 2 +- src/database/Dim.Entities/Entities/ProcessStepType.cs | 2 +- src/database/Dim.Entities/Entities/ProcessType.cs | 2 +- src/database/Dim.Entities/Entities/Tenant.cs | 2 +- src/database/Dim.Entities/Entities/VerifyProcessData.cs | 2 +- src/database/Dim.Entities/Enums/ProcessStepStatusId.cs | 2 +- src/database/Dim.Entities/Enums/ProcessStepTypeId.cs | 2 +- src/database/Dim.Entities/Enums/ProcessTypeId.cs | 2 +- src/database/Dim.Migrations/Dim.Migrations.csproj | 2 +- .../Migrations/20240403114716_Initial.Designer.cs | 2 +- .../Dim.Migrations/Migrations/20240403114716_Initial.cs | 2 +- .../Dim.Migrations/Migrations/DimDbContextModelSnapshot.cs | 2 +- src/database/Dim.Migrations/Program.cs | 2 +- .../DependencyInjection/DimProcessCollectionExtensions.cs | 2 +- src/processes/DimProcess.Executor/DimProcess.Executor.csproj | 2 +- src/processes/DimProcess.Executor/DimProcessTypeExecutor.cs | 2 +- src/processes/DimProcess.Library/Callback/CallbackDataModel.cs | 2 +- src/processes/DimProcess.Library/Callback/CallbackService.cs | 2 +- .../Callback/DependencyInjection/CallbackServiceExtensions.cs | 2 +- .../Callback/DependencyInjection/CallbackSettings.cs | 2 +- src/processes/DimProcess.Library/Callback/ICallbackService.cs | 2 +- .../DependencyInjection/DimHandlerExtensions.cs | 2 +- .../DependencyInjection/DimHandlerSettings.cs | 2 +- src/processes/DimProcess.Library/DimProcess.Library.csproj | 2 +- src/processes/DimProcess.Library/DimProcessHandler.cs | 2 +- src/processes/DimProcess.Library/IDimProcessHandler.cs | 2 +- src/processes/Processes.Library/ManualProcessStepData.cs | 2 +- .../Processes.Library/ManualProcessStepDataExtensions.cs | 2 +- src/processes/Processes.Library/Processes.Library.csproj | 2 +- src/processes/Processes.Worker.Library/IProcessExecutor.cs | 2 +- src/processes/Processes.Worker.Library/IProcessTypeExecutor.cs | 2 +- .../Processes.Worker.Library/ProcessExecutionService.cs | 2 +- .../ProcessExecutionServiceExtensions.cs | 2 +- .../Processes.Worker.Library/ProcessExecutionServiceSettings.cs | 2 +- src/processes/Processes.Worker.Library/ProcessExecutor.cs | 2 +- .../Processes.Worker.Library/Processes.Worker.Library.csproj | 2 +- src/processes/Processes.Worker/Processes.Worker.csproj | 2 +- src/processes/Processes.Worker/Program.cs | 2 +- src/web/Dim.Web/Authentication/CustomClaimTypes.cs | 2 +- src/web/Dim.Web/Authentication/KeycloakClaimsTransformation.cs | 2 +- src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs | 2 +- src/web/Dim.Web/BusinessLogic/DimSettings.cs | 2 +- src/web/Dim.Web/BusinessLogic/IDimBusinessLogic.cs | 2 +- src/web/Dim.Web/Controllers/DimController.cs | 2 +- src/web/Dim.Web/ErrorHandling/DimErrorMessageContainer.cs | 2 +- src/web/Dim.Web/Extensions/RouteHandlerBuilderExtensions.cs | 2 +- src/web/Dim.Web/Extensions/ServiceCollectionExtensions.cs | 2 +- src/web/Dim.Web/Models/Constants.cs | 2 +- src/web/Dim.Web/Program.cs | 2 +- .../DimProcess.Executor.Tests/DimProcessTypeExecutorTests.cs | 2 +- tests/processes/DimProcess.Executor.Tests/Usings.cs | 2 +- .../DimProcess.Library.Tests/DimProcessHandlerTests.cs | 2 +- tests/processes/DimProcess.Library.Tests/Usings.cs | 2 +- .../Processes.Library.Tests/ManualProcessDataExtensionsTests.cs | 2 +- .../Processes.Library.Tests/Processes.Library.Tests.csproj | 2 +- tests/processes/Processes.Library.Tests/Usings.cs | 2 +- .../ProcessExecutionServiceTests.cs | 2 +- .../Processes.Worker.Library.Tests/ProcessExecutorTests.cs | 2 +- .../Processes.Worker.Library.Tests.csproj | 2 +- tests/processes/Processes.Worker.Library.Tests/Usings.cs | 2 +- tests/shared/Tests.Shared/MockLogger.cs | 2 +- tests/shared/Tests.Shared/Tests.Shared.csproj | 2 +- 160 files changed, 160 insertions(+), 160 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6ac1ec9..9fac115 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/chart-test.yml b/.github/workflows/chart-test.yml index a9e5c18..ba1a46c 100644 --- a/.github/workflows/chart-test.yml +++ b/.github/workflows/chart-test.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d7a59ed..ed3abf4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/kics.yml b/.github/workflows/kics.yml index 5c56d58..9f0d9b6 100644 --- a/.github/workflows/kics.yml +++ b/.github/workflows/kics.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/lint-pull-request.yml b/.github/workflows/lint-pull-request.yml index 397b46d..698f4c6 100644 --- a/.github/workflows/lint-pull-request.yml +++ b/.github/workflows/lint-pull-request.yml @@ -1,5 +1,5 @@ # ############################################################################# -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/migrations-docker.yml b/.github/workflows/migrations-docker.yml index f3621bf..75030a8 100644 --- a/.github/workflows/migrations-docker.yml +++ b/.github/workflows/migrations-docker.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/owasp-zap.yml b/.github/workflows/owasp-zap.yml index 3a626a6..a624859 100644 --- a/.github/workflows/owasp-zap.yml +++ b/.github/workflows/owasp-zap.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/processes-worker-docker.yml b/.github/workflows/processes-worker-docker.yml index 2fb43d8..5f2ad11 100644 --- a/.github/workflows/processes-worker-docker.yml +++ b/.github/workflows/processes-worker-docker.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 618aba1..64ea5c7 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b4e79f5..6b6326f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/service-docker.yml b/.github/workflows/service-docker.yml index dceea94..4deeb3f 100644 --- a/.github/workflows/service-docker.yml +++ b/.github/workflows/service-docker.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index f9f6716..53d2528 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 1dc4ba6..11a5ba1 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/.github/workflows/unit.tests-formatting.yml b/.github/workflows/unit.tests-formatting.yml index bb6d215..2b61b8b 100644 --- a/.github/workflows/unit.tests-formatting.yml +++ b/.github/workflows/unit.tests-formatting.yml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/charts/chart-testing-config.yaml b/charts/chart-testing-config.yaml index 73e105a..dd8de8d 100644 --- a/charts/chart-testing-config.yaml +++ b/charts/chart-testing-config.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/charts/dim/Chart.yaml b/charts/dim/Chart.yaml index de0f778..666fa95 100644 --- a/charts/dim/Chart.yaml +++ b/charts/dim/Chart.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/charts/dim/templates/_helpers.tpl b/charts/dim/templates/_helpers.tpl index d70ffd4..b5d5f75 100644 --- a/charts/dim/templates/_helpers.tpl +++ b/charts/dim/templates/_helpers.tpl @@ -1,5 +1,5 @@ {{- /* -* Copyright (c) 2024 BMW Group AG +* Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/charts/dim/templates/configmap-postgres-init.yaml b/charts/dim/templates/configmap-postgres-init.yaml index e7a38e1..4ddda95 100644 --- a/charts/dim/templates/configmap-postgres-init.yaml +++ b/charts/dim/templates/configmap-postgres-init.yaml @@ -1,5 +1,5 @@ {{- /* -* Copyright (c) 2024 BMW Group AG +* Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/charts/dim/templates/cronjob-processes.yaml b/charts/dim/templates/cronjob-processes.yaml index c8bad47..6ab4ae6 100644 --- a/charts/dim/templates/cronjob-processes.yaml +++ b/charts/dim/templates/cronjob-processes.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/charts/dim/templates/deployment.yaml b/charts/dim/templates/deployment.yaml index 899a123..aa7792d 100644 --- a/charts/dim/templates/deployment.yaml +++ b/charts/dim/templates/deployment.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/charts/dim/templates/ingress.yaml b/charts/dim/templates/ingress.yaml index 925c4a4..488b27a 100644 --- a/charts/dim/templates/ingress.yaml +++ b/charts/dim/templates/ingress.yaml @@ -1,5 +1,5 @@ {{- /* -* Copyright (c) 2024 BMW Group AG +* Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/charts/dim/templates/job-migrations.yaml b/charts/dim/templates/job-migrations.yaml index fd90349..f8ed646 100644 --- a/charts/dim/templates/job-migrations.yaml +++ b/charts/dim/templates/job-migrations.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/charts/dim/templates/secret-external-db.yaml b/charts/dim/templates/secret-external-db.yaml index 619849a..5795e2c 100644 --- a/charts/dim/templates/secret-external-db.yaml +++ b/charts/dim/templates/secret-external-db.yaml @@ -1,5 +1,5 @@ {{- /* -* Copyright (c) 2024 BMW Group AG +* Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/charts/dim/templates/secret-postgres.yaml b/charts/dim/templates/secret-postgres.yaml index 8775429..cd8b00d 100644 --- a/charts/dim/templates/secret-postgres.yaml +++ b/charts/dim/templates/secret-postgres.yaml @@ -1,5 +1,5 @@ {{- /* -* Copyright (c) 2024 BMW Group AG +* Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/charts/dim/templates/secret.yaml b/charts/dim/templates/secret.yaml index e8a317b..d7591f9 100644 --- a/charts/dim/templates/secret.yaml +++ b/charts/dim/templates/secret.yaml @@ -1,5 +1,5 @@ {{- /* -* Copyright (c) 2024 BMW Group AG +* Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/charts/dim/templates/service.yaml b/charts/dim/templates/service.yaml index cc4ffc8..2eca167 100644 --- a/charts/dim/templates/service.yaml +++ b/charts/dim/templates/service.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/charts/dim/values.yaml b/charts/dim/values.yaml index 3578364..ac3d68e 100644 --- a/charts/dim/values.yaml +++ b/charts/dim/values.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/consortia/argocd-app-templates/appsetup-dev.yaml b/consortia/argocd-app-templates/appsetup-dev.yaml index f228e78..24996e3 100644 --- a/consortia/argocd-app-templates/appsetup-dev.yaml +++ b/consortia/argocd-app-templates/appsetup-dev.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/consortia/argocd-app-templates/appsetup-int.yaml b/consortia/argocd-app-templates/appsetup-int.yaml index 2637a87..a22bc56 100644 --- a/consortia/argocd-app-templates/appsetup-int.yaml +++ b/consortia/argocd-app-templates/appsetup-int.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/consortia/environments/values-dev.yaml b/consortia/environments/values-dev.yaml index 033fb6b..9f91c12 100644 --- a/consortia/environments/values-dev.yaml +++ b/consortia/environments/values-dev.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/consortia/environments/values-int.yaml b/consortia/environments/values-int.yaml index bd3bd29..522b8d5 100644 --- a/consortia/environments/values-int.yaml +++ b/consortia/environments/values-int.yaml @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/docker/Dockerfile-dim-migrations b/docker/Dockerfile-dim-migrations index 441b063..7d3b68a 100644 --- a/docker/Dockerfile-dim-migrations +++ b/docker/Dockerfile-dim-migrations @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/docker/Dockerfile-dim-processes-worker b/docker/Dockerfile-dim-processes-worker index 43336bf..30db907 100644 --- a/docker/Dockerfile-dim-processes-worker +++ b/docker/Dockerfile-dim-processes-worker @@ -1,5 +1,5 @@ īģŋ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/docker/Dockerfile-dim-service b/docker/Dockerfile-dim-service index 8ecb76c..bd0bb37 100644 --- a/docker/Dockerfile-dim-service +++ b/docker/Dockerfile-dim-service @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2024 BMW Group AG +# Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors. # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 08d0556..0ad9c13 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,5 +1,5 @@ + + + + 0.0.2 + + + diff --git a/src/clients/Dim.Clients/Api/Cf/CfClient.cs b/src/clients/Dim.Clients/Api/Cf/CfClient.cs index 30c1f82..aa515c7 100644 --- a/src/clients/Dim.Clients/Api/Cf/CfClient.cs +++ b/src/clients/Dim.Clients/Api/Cf/CfClient.cs @@ -208,13 +208,13 @@ private async Task GetServiceInstances(string tenantName, Guid? spaceId, C } } - public async Task CreateServiceInstanceBindings(string tenantName, Guid spaceId, CancellationToken cancellationToken) + public async Task CreateServiceInstanceBindings(string tenantName, string? keyName, Guid spaceId, CancellationToken cancellationToken) { var serviceInstanceId = await GetServiceInstances(tenantName, spaceId, cancellationToken).ConfigureAwait(false); var client = await _basicAuthTokenService.GetBasicAuthorizedLegacyClient(_settings, cancellationToken).ConfigureAwait(false); var data = new CreateServiceCredentialBindingRequest( "key", - $"{tenantName}-dim-key01", + $"{keyName ?? tenantName}-dim-key01", new ServiceCredentialRelationships( new DimServiceInstance(new DimData(serviceInstanceId))) ); diff --git a/src/clients/Dim.Clients/Api/Cf/ICfClient.cs b/src/clients/Dim.Clients/Api/Cf/ICfClient.cs index 7aab550..0ec25c8 100644 --- a/src/clients/Dim.Clients/Api/Cf/ICfClient.cs +++ b/src/clients/Dim.Clients/Api/Cf/ICfClient.cs @@ -26,7 +26,7 @@ public interface ICfClient Task GetServicePlan(string servicePlanName, string servicePlanType, CancellationToken cancellationToken); Task GetSpace(string tenantName, CancellationToken cancellationToken); Task CreateDimServiceInstance(string tenantName, Guid spaceId, Guid servicePlanId, CancellationToken cancellationToken); - Task CreateServiceInstanceBindings(string tenantName, Guid spaceId, CancellationToken cancellationToken); + Task CreateServiceInstanceBindings(string tenantName, string? keyName, Guid spaceId, CancellationToken cancellationToken); Task GetServiceBinding(string tenantName, Guid spaceId, string bindingName, CancellationToken cancellationToken); Task GetServiceBindingDetails(Guid id, CancellationToken cancellationToken); } diff --git a/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs b/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs index cb7fcd4..3596511 100644 --- a/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs +++ b/src/database/Dim.DbAccess/Repositories/ITenantRepository.cs @@ -35,4 +35,10 @@ public interface ITenantRepository Task<(Guid? DimInstanceId, string HostingUrl, bool IsIssuer)> GetDimInstanceIdAndHostingUrl(Guid tenantId); Task<(string? ApplicationId, Guid? CompanyId, Guid? DimInstanceId, bool IsIssuer)> GetApplicationAndCompanyId(Guid tenantId); Task<(bool Exists, Guid? CompanyId, Guid? InstanceId)> GetCompanyAndInstanceIdForBpn(string bpn); + Task<(bool Exists, Guid TenantId)> GetTenantForBpn(string bpn); + void CreateTenantTechnicalUser(Guid tenantId, string technicalUserName, Guid externalId, Guid processId); + void AttachAndModifyTechnicalUser(Guid technicalUserId, Action? initialize, Action modify); + Task<(bool Exists, Guid TechnicalUserId, string CompanyName, string Bpn)> GetTenantDataForTechnicalUserProcessId(Guid processId); + Task<(Guid? spaceId, string technicalUserName)> GetSpaceIdAndTechnicalUserName(Guid technicalUserId); + Task<(Guid ExternalId, string? TokenAddress, string? ClientId, byte[]? ClientSecret, byte[]? InitializationVector, int? EncryptionMode)> GetTechnicalUserCallbackData(Guid technicalUserId); } diff --git a/src/database/Dim.DbAccess/Repositories/TenantRepository.cs b/src/database/Dim.DbAccess/Repositories/TenantRepository.cs index 769ffc3..a96d25b 100644 --- a/src/database/Dim.DbAccess/Repositories/TenantRepository.cs +++ b/src/database/Dim.DbAccess/Repositories/TenantRepository.cs @@ -105,4 +105,44 @@ public void AttachAndModifyTenant(Guid tenantId, Action? initialize, Act _context.Tenants.Where(x => x.Bpn == bpn) .Select(x => new ValueTuple(true, x.CompanyId, x.DimInstanceId)) .SingleOrDefaultAsync(); + + public void CreateTenantTechnicalUser(Guid tenantId, string technicalUserName, Guid externalId, Guid processId) => + _context.TechnicalUsers.Add(new TechnicalUser(Guid.NewGuid(), tenantId, externalId, technicalUserName, processId)); + + public void AttachAndModifyTechnicalUser(Guid technicalUserId, Action? initialize, Action modify) + { + var technicalUser = new TechnicalUser(technicalUserId, Guid.Empty, Guid.Empty, null!, Guid.Empty); + initialize?.Invoke(technicalUser); + _context.TechnicalUsers.Attach(technicalUser); + modify(technicalUser); + } + + public Task<(bool Exists, Guid TenantId)> GetTenantForBpn(string bpn) => + _context.Tenants.Where(x => x.Bpn == bpn) + .Select(x => new ValueTuple(true, x.Id)) + .SingleOrDefaultAsync(); + + public Task<(bool Exists, Guid TechnicalUserId, string CompanyName, string Bpn)> GetTenantDataForTechnicalUserProcessId(Guid processId) => + _context.TechnicalUsers + .Where(x => x.ProcessId == processId) + .Select(x => new ValueTuple(true, x.Id, x.Tenant!.CompanyName, x.Tenant.Bpn)) + .SingleOrDefaultAsync(); + + public Task<(Guid? spaceId, string technicalUserName)> GetSpaceIdAndTechnicalUserName(Guid technicalUserId) => + _context.TechnicalUsers + .Where(x => x.Id == technicalUserId) + .Select(x => new ValueTuple(x.Tenant!.SpaceId, x.TechnicalUserName)) + .SingleOrDefaultAsync(); + + public Task<(Guid ExternalId, string? TokenAddress, string? ClientId, byte[]? ClientSecret, byte[]? InitializationVector, int? EncryptionMode)> GetTechnicalUserCallbackData(Guid technicalUserId) => + _context.TechnicalUsers + .Where(x => x.Id == technicalUserId) + .Select(x => new ValueTuple( + x.ExternalId, + x.TokenAddress, + x.ClientId, + x.ClientSecret, + x.InitializationVector, + x.EncryptionMode)) + .SingleOrDefaultAsync(); } diff --git a/src/database/Dim.Entities/DimDbContext.cs b/src/database/Dim.Entities/DimDbContext.cs index fed8346..9d251b6 100644 --- a/src/database/Dim.Entities/DimDbContext.cs +++ b/src/database/Dim.Entities/DimDbContext.cs @@ -40,6 +40,7 @@ public DimDbContext(DbContextOptions options) public virtual DbSet ProcessStepTypes { get; set; } = default!; public virtual DbSet ProcessTypes { get; set; } = default!; public virtual DbSet Tenants { get; set; } = default!; + public virtual DbSet TechnicalUsers { get; set; } = default!; protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { @@ -84,10 +85,25 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .Select(e => new ProcessStepType(e)) ); - modelBuilder.Entity() - .HasOne(d => d.Process) - .WithMany(p => p.Tenants) - .HasForeignKey(d => d.ProcessId) - .OnDelete(DeleteBehavior.ClientSetNull); + modelBuilder.Entity(t => + { + t.HasOne(d => d.Process) + .WithMany(p => p.Tenants) + .HasForeignKey(d => d.ProcessId) + .OnDelete(DeleteBehavior.ClientSetNull); + }); + + modelBuilder.Entity(tu => + { + tu.HasOne(d => d.Process) + .WithMany(p => p.TechnicalUsers) + .HasForeignKey(d => d.ProcessId) + .OnDelete(DeleteBehavior.ClientSetNull); + + tu.HasOne(t => t.Tenant) + .WithMany(t => t.TechnicalUsers) + .HasForeignKey(t => t.TenantId) + .OnDelete(DeleteBehavior.ClientSetNull); + }); } } diff --git a/src/database/Dim.Entities/Entities/Process.cs b/src/database/Dim.Entities/Entities/Process.cs index 830aae3..22fcba7 100644 --- a/src/database/Dim.Entities/Entities/Process.cs +++ b/src/database/Dim.Entities/Entities/Process.cs @@ -29,6 +29,7 @@ private Process() { ProcessSteps = new HashSet(); Tenants = new HashSet(); + TechnicalUsers = new HashSet(); } public Process(Guid id, ProcessTypeId processTypeId, Guid version) : this() @@ -51,4 +52,5 @@ public Process(Guid id, ProcessTypeId processTypeId, Guid version) : this() public virtual ProcessType? ProcessType { get; set; } public virtual ICollection ProcessSteps { get; private set; } public virtual ICollection Tenants { get; private set; } + public virtual ICollection TechnicalUsers { get; private set; } } diff --git a/src/database/Dim.Entities/Entities/TechnicalUser.cs b/src/database/Dim.Entities/Entities/TechnicalUser.cs new file mode 100644 index 0000000..b2a0593 --- /dev/null +++ b/src/database/Dim.Entities/Entities/TechnicalUser.cs @@ -0,0 +1,41 @@ +/******************************************************************************** + * Copyright (c) 2024 BMW Group AG + * + * 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 + ********************************************************************************/ + +namespace Dim.Entities.Entities; + +public class TechnicalUser( + Guid id, + Guid tenantId, + Guid externalId, + string technicalUserName, + Guid processId) +{ + public Guid Id { get; set; } = id; + public Guid TenantId { get; set; } = tenantId; + public Guid ExternalId { get; set; } = externalId; + public string TechnicalUserName { get; set; } = technicalUserName; + public string? TokenAddress { get; set; } + public string? ClientId { get; set; } + public byte[]? ClientSecret { get; set; } + public byte[]? InitializationVector { get; set; } + public int? EncryptionMode { get; set; } + public Guid ProcessId { get; set; } = processId; + public virtual Tenant? Tenant { get; set; } + public virtual Process? Process { get; set; } +} diff --git a/src/database/Dim.Entities/Entities/Tenant.cs b/src/database/Dim.Entities/Entities/Tenant.cs index eca1930..59621a7 100644 --- a/src/database/Dim.Entities/Entities/Tenant.cs +++ b/src/database/Dim.Entities/Entities/Tenant.cs @@ -19,28 +19,24 @@ namespace Dim.Entities.Entities; -public class Tenant +public class Tenant( + Guid id, + string companyName, + string bpn, + string didDocumentLocation, + bool isIssuer, + Guid processId, + Guid operatorId) { - public Tenant(Guid id, string companyName, string bpn, string didDocumentLocation, bool isIssuer, Guid processId, Guid operatorId) - { - Id = id; - CompanyName = companyName; - Bpn = bpn; - DidDocumentLocation = didDocumentLocation; - IsIssuer = isIssuer; - ProcessId = processId; - OperatorId = operatorId; - } + public Guid Id { get; set; } = id; + public string CompanyName { get; set; } = companyName; + public string Bpn { get; set; } = bpn; - public Guid Id { get; set; } - public string CompanyName { get; set; } - public string Bpn { get; set; } + public string DidDocumentLocation { get; set; } = didDocumentLocation; - public string DidDocumentLocation { get; set; } + public bool IsIssuer { get; set; } = isIssuer; - public bool IsIssuer { get; set; } - - public Guid ProcessId { get; set; } + public Guid ProcessId { get; set; } = processId; public Guid? SubAccountId { get; set; } @@ -56,6 +52,7 @@ public Tenant(Guid id, string companyName, string bpn, string didDocumentLocatio public string? ApplicationId { get; set; } public Guid? CompanyId { get; set; } public string? ApplicationKey { get; set; } - public Guid OperatorId { get; set; } + public Guid OperatorId { get; set; } = operatorId; public virtual Process? Process { get; set; } + public virtual ICollection TechnicalUsers { get; private set; } = new HashSet(); } diff --git a/src/database/Dim.Entities/Enums/ProcessStepTypeId.cs b/src/database/Dim.Entities/Enums/ProcessStepTypeId.cs index 2c7bbf2..2d47426 100644 --- a/src/database/Dim.Entities/Enums/ProcessStepTypeId.cs +++ b/src/database/Dim.Entities/Enums/ProcessStepTypeId.cs @@ -39,5 +39,10 @@ public enum ProcessStepTypeId CREATE_COMPANY_IDENTITY = 15, ASSIGN_COMPANY_APPLICATION = 16, CREATE_STATUS_LIST = 17, - SEND_CALLBACK = 18 + SEND_CALLBACK = 18, + + // Create Technical User + CREATE_TECHNICAL_USER = 100, + GET_TECHNICAL_USER_DATA = 101, + SEND_TECHNICAL_USER_CALLBACK = 102, } diff --git a/src/database/Dim.Entities/Enums/ProcessTypeId.cs b/src/database/Dim.Entities/Enums/ProcessTypeId.cs index f88cf37..c11e32e 100644 --- a/src/database/Dim.Entities/Enums/ProcessTypeId.cs +++ b/src/database/Dim.Entities/Enums/ProcessTypeId.cs @@ -21,5 +21,6 @@ namespace Dim.Entities.Enums; public enum ProcessTypeId { - SETUP_DIM = 1 + SETUP_DIM = 1, + CREATE_TECHNICAL_USER = 2 } diff --git a/src/database/Dim.Migrations/Migrations/20240409140733_1.0.1.Designer.cs b/src/database/Dim.Migrations/Migrations/20240409140733_1.0.1.Designer.cs new file mode 100644 index 0000000..e565ea1 --- /dev/null +++ b/src/database/Dim.Migrations/Migrations/20240409140733_1.0.1.Designer.cs @@ -0,0 +1,564 @@ +īģŋ/******************************************************************************** + * Copyright (c) 2024 BMW Group AG + * + * 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 + ********************************************************************************/ + +// +using System; +using Dim.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Dim.Migrations.Migrations +{ + [DbContext(typeof(DimDbContext))] + [Migration("20240409140733_1.0.1")] + partial class _101 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("dim") + .UseCollation("en_US.utf8") + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Dim.Entities.Entities.Process", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("LockExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("lock_expiry_date"); + + b.Property("ProcessTypeId") + .HasColumnType("integer") + .HasColumnName("process_type_id"); + + b.Property("Version") + .IsConcurrencyToken() + .HasColumnType("uuid") + .HasColumnName("version"); + + b.HasKey("Id") + .HasName("pk_processes"); + + b.HasIndex("ProcessTypeId") + .HasDatabaseName("ix_processes_process_type_id"); + + b.ToTable("processes", "dim"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.ProcessStep", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("DateCreated") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_created"); + + b.Property("DateLastChanged") + .HasColumnType("timestamp with time zone") + .HasColumnName("date_last_changed"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("ProcessStepStatusId") + .HasColumnType("integer") + .HasColumnName("process_step_status_id"); + + b.Property("ProcessStepTypeId") + .HasColumnType("integer") + .HasColumnName("process_step_type_id"); + + b.HasKey("Id") + .HasName("pk_process_steps"); + + b.HasIndex("ProcessId") + .HasDatabaseName("ix_process_steps_process_id"); + + b.HasIndex("ProcessStepStatusId") + .HasDatabaseName("ix_process_steps_process_step_status_id"); + + b.HasIndex("ProcessStepTypeId") + .HasDatabaseName("ix_process_steps_process_step_type_id"); + + b.ToTable("process_steps", "dim"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.ProcessStepStatus", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_process_step_statuses"); + + b.ToTable("process_step_statuses", "dim"); + + b.HasData( + new + { + Id = 1, + Label = "TODO" + }, + new + { + Id = 2, + Label = "DONE" + }, + new + { + Id = 3, + Label = "SKIPPED" + }, + new + { + Id = 4, + Label = "FAILED" + }, + new + { + Id = 5, + Label = "DUPLICATE" + }); + }); + + modelBuilder.Entity("Dim.Entities.Entities.ProcessStepType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_process_step_types"); + + b.ToTable("process_step_types", "dim"); + + b.HasData( + new + { + Id = 1, + Label = "CREATE_SUBACCOUNT" + }, + new + { + Id = 2, + Label = "CREATE_SERVICEMANAGER_BINDINGS" + }, + new + { + Id = 3, + Label = "ASSIGN_ENTITLEMENTS" + }, + new + { + Id = 4, + Label = "CREATE_SERVICE_INSTANCE" + }, + new + { + Id = 5, + Label = "CREATE_SERVICE_BINDING" + }, + new + { + Id = 6, + Label = "SUBSCRIBE_APPLICATION" + }, + new + { + Id = 7, + Label = "CREATE_CLOUD_FOUNDRY_ENVIRONMENT" + }, + new + { + Id = 8, + Label = "CREATE_CLOUD_FOUNDRY_SPACE" + }, + new + { + Id = 9, + Label = "ADD_SPACE_MANAGER_ROLE" + }, + new + { + Id = 10, + Label = "ADD_SPACE_DEVELOPER_ROLE" + }, + new + { + Id = 11, + Label = "CREATE_DIM_SERVICE_INSTANCE" + }, + new + { + Id = 12, + Label = "CREATE_SERVICE_INSTANCE_BINDING" + }, + new + { + Id = 13, + Label = "GET_DIM_DETAILS" + }, + new + { + Id = 14, + Label = "CREATE_APPLICATION" + }, + new + { + Id = 15, + Label = "CREATE_COMPANY_IDENTITY" + }, + new + { + Id = 16, + Label = "ASSIGN_COMPANY_APPLICATION" + }, + new + { + Id = 17, + Label = "CREATE_STATUS_LIST" + }, + new + { + Id = 18, + Label = "SEND_CALLBACK" + }, + new + { + Id = 100, + Label = "CREATE_TECHNICAL_USER" + }, + new + { + Id = 101, + Label = "GET_TECHNICAL_USER_DATA" + }, + new + { + Id = 102, + Label = "SEND_TECHNICAL_USER_CALLBACK" + }); + }); + + modelBuilder.Entity("Dim.Entities.Entities.ProcessType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_process_types"); + + b.ToTable("process_types", "dim"); + + b.HasData( + new + { + Id = 1, + Label = "SETUP_DIM" + }, + new + { + Id = 2, + Label = "CREATE_TECHNICAL_USER" + }); + }); + + modelBuilder.Entity("Dim.Entities.Entities.TechnicalUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ClientId") + .HasColumnType("text") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasColumnType("bytea") + .HasColumnName("client_secret"); + + b.Property("EncryptionMode") + .HasColumnType("integer") + .HasColumnName("encryption_mode"); + + b.Property("ExternalId") + .HasColumnType("uuid") + .HasColumnName("external_id"); + + b.Property("InitializationVector") + .HasColumnType("bytea") + .HasColumnName("initialization_vector"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("TechnicalUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("technical_user_name"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("tenant_id"); + + b.Property("TokenAddress") + .HasColumnType("text") + .HasColumnName("token_address"); + + b.HasKey("Id") + .HasName("pk_technical_users"); + + b.HasIndex("ProcessId") + .HasDatabaseName("ix_technical_users_process_id"); + + b.HasIndex("TenantId") + .HasDatabaseName("ix_technical_users_tenant_id"); + + b.ToTable("technical_users", "dim"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("text") + .HasColumnName("application_id"); + + b.Property("ApplicationKey") + .HasColumnType("text") + .HasColumnName("application_key"); + + b.Property("Bpn") + .IsRequired() + .HasColumnType("text") + .HasColumnName("bpn"); + + b.Property("CompanyId") + .HasColumnType("uuid") + .HasColumnName("company_id"); + + b.Property("CompanyName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("company_name"); + + b.Property("Did") + .HasColumnType("text") + .HasColumnName("did"); + + b.Property("DidDocumentLocation") + .IsRequired() + .HasColumnType("text") + .HasColumnName("did_document_location"); + + b.Property("DidDownloadUrl") + .HasColumnType("text") + .HasColumnName("did_download_url"); + + b.Property("DimInstanceId") + .HasColumnType("uuid") + .HasColumnName("dim_instance_id"); + + b.Property("IsIssuer") + .HasColumnType("boolean") + .HasColumnName("is_issuer"); + + b.Property("OperatorId") + .HasColumnType("uuid") + .HasColumnName("operator_id"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("ServiceBindingName") + .HasColumnType("text") + .HasColumnName("service_binding_name"); + + b.Property("ServiceInstanceId") + .HasColumnType("text") + .HasColumnName("service_instance_id"); + + b.Property("SpaceId") + .HasColumnType("uuid") + .HasColumnName("space_id"); + + b.Property("SubAccountId") + .HasColumnType("uuid") + .HasColumnName("sub_account_id"); + + b.HasKey("Id") + .HasName("pk_tenants"); + + b.HasIndex("ProcessId") + .HasDatabaseName("ix_tenants_process_id"); + + b.ToTable("tenants", "dim"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.Process", b => + { + b.HasOne("Dim.Entities.Entities.ProcessType", "ProcessType") + .WithMany("Processes") + .HasForeignKey("ProcessTypeId") + .IsRequired() + .HasConstraintName("fk_processes_process_types_process_type_id"); + + b.Navigation("ProcessType"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.ProcessStep", b => + { + b.HasOne("Dim.Entities.Entities.Process", "Process") + .WithMany("ProcessSteps") + .HasForeignKey("ProcessId") + .IsRequired() + .HasConstraintName("fk_process_steps_processes_process_id"); + + b.HasOne("Dim.Entities.Entities.ProcessStepStatus", "ProcessStepStatus") + .WithMany("ProcessSteps") + .HasForeignKey("ProcessStepStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_process_steps_process_step_statuses_process_step_status_id"); + + b.HasOne("Dim.Entities.Entities.ProcessStepType", "ProcessStepType") + .WithMany("ProcessSteps") + .HasForeignKey("ProcessStepTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_process_steps_process_step_types_process_step_type_id"); + + b.Navigation("Process"); + + b.Navigation("ProcessStepStatus"); + + b.Navigation("ProcessStepType"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.TechnicalUser", b => + { + b.HasOne("Dim.Entities.Entities.Process", "Process") + .WithMany("TechnicalUsers") + .HasForeignKey("ProcessId") + .IsRequired() + .HasConstraintName("fk_technical_users_processes_process_id"); + + b.HasOne("Dim.Entities.Entities.Tenant", "Tenant") + .WithMany("TechnicalUsers") + .HasForeignKey("TenantId") + .IsRequired() + .HasConstraintName("fk_technical_users_tenants_tenant_id"); + + b.Navigation("Process"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.Tenant", b => + { + b.HasOne("Dim.Entities.Entities.Process", "Process") + .WithMany("Tenants") + .HasForeignKey("ProcessId") + .IsRequired() + .HasConstraintName("fk_tenants_processes_process_id"); + + b.Navigation("Process"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.Process", b => + { + b.Navigation("ProcessSteps"); + + b.Navigation("TechnicalUsers"); + + b.Navigation("Tenants"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.ProcessStepStatus", b => + { + b.Navigation("ProcessSteps"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.ProcessStepType", b => + { + b.Navigation("ProcessSteps"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.ProcessType", b => + { + b.Navigation("Processes"); + }); + + modelBuilder.Entity("Dim.Entities.Entities.Tenant", b => + { + b.Navigation("TechnicalUsers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/database/Dim.Migrations/Migrations/20240409140733_1.0.1.cs b/src/database/Dim.Migrations/Migrations/20240409140733_1.0.1.cs new file mode 100644 index 0000000..e59715a --- /dev/null +++ b/src/database/Dim.Migrations/Migrations/20240409140733_1.0.1.cs @@ -0,0 +1,130 @@ +/******************************************************************************** + * Copyright (c) 2024 BMW Group AG + * + * 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 + ********************************************************************************/ + +using Microsoft.EntityFrameworkCore.Migrations; +using System; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Dim.Migrations.Migrations +{ + /// + public partial class _101 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "technical_users", + schema: "dim", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + tenant_id = table.Column(type: "uuid", nullable: false), + external_id = table.Column(type: "uuid", nullable: false), + technical_user_name = table.Column(type: "text", nullable: false), + token_address = table.Column(type: "text", nullable: true), + client_id = table.Column(type: "text", nullable: true), + client_secret = table.Column(type: "bytea", nullable: true), + initialization_vector = table.Column(type: "bytea", nullable: true), + encryption_mode = table.Column(type: "integer", nullable: true), + process_id = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_technical_users", x => x.id); + table.ForeignKey( + name: "fk_technical_users_processes_process_id", + column: x => x.process_id, + principalSchema: "dim", + principalTable: "processes", + principalColumn: "id"); + table.ForeignKey( + name: "fk_technical_users_tenants_tenant_id", + column: x => x.tenant_id, + principalSchema: "dim", + principalTable: "tenants", + principalColumn: "id"); + }); + + migrationBuilder.InsertData( + schema: "dim", + table: "process_step_types", + columns: new[] { "id", "label" }, + values: new object[,] + { + { 100, "CREATE_TECHNICAL_USER" }, + { 101, "GET_TECHNICAL_USER_DATA" }, + { 102, "SEND_TECHNICAL_USER_CALLBACK" } + }); + + migrationBuilder.InsertData( + schema: "dim", + table: "process_types", + columns: new[] { "id", "label" }, + values: new object[] { 2, "CREATE_TECHNICAL_USER" }); + + migrationBuilder.CreateIndex( + name: "ix_technical_users_process_id", + schema: "dim", + table: "technical_users", + column: "process_id"); + + migrationBuilder.CreateIndex( + name: "ix_technical_users_tenant_id", + schema: "dim", + table: "technical_users", + column: "tenant_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "technical_users", + schema: "dim"); + + migrationBuilder.DeleteData( + schema: "dim", + table: "process_step_types", + keyColumn: "id", + keyValue: 100); + + migrationBuilder.DeleteData( + schema: "dim", + table: "process_step_types", + keyColumn: "id", + keyValue: 101); + + migrationBuilder.DeleteData( + schema: "dim", + table: "process_step_types", + keyColumn: "id", + keyValue: 102); + + migrationBuilder.DeleteData( + schema: "dim", + table: "process_types", + keyColumn: "id", + keyValue: 2); + } + } +} diff --git a/src/database/Dim.Migrations/Migrations/DimDbContextModelSnapshot.cs b/src/database/Dim.Migrations/Migrations/DimDbContextModelSnapshot.cs index 0f77b75..b60b83a 100644 --- a/src/database/Dim.Migrations/Migrations/DimDbContextModelSnapshot.cs +++ b/src/database/Dim.Migrations/Migrations/DimDbContextModelSnapshot.cs @@ -1,4 +1,4 @@ -/******************************************************************************** +īģŋ/******************************************************************************** * Copyright (c) 2024 BMW Group AG * * See the NOTICE file(s) distributed with this work for additional @@ -34,7 +34,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder .HasDefaultSchema("dim") .UseCollation("en_US.utf8") - .HasAnnotation("ProductVersion", "7.0.13") + .HasAnnotation("ProductVersion", "8.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -266,6 +266,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = 18, Label = "SEND_CALLBACK" + }, + new + { + Id = 100, + Label = "CREATE_TECHNICAL_USER" + }, + new + { + Id = 101, + Label = "GET_TECHNICAL_USER_DATA" + }, + new + { + Id = 102, + Label = "SEND_TECHNICAL_USER_CALLBACK" }); }); @@ -291,9 +306,70 @@ protected override void BuildModel(ModelBuilder modelBuilder) { Id = 1, Label = "SETUP_DIM" + }, + new + { + Id = 2, + Label = "CREATE_TECHNICAL_USER" }); }); + modelBuilder.Entity("Dim.Entities.Entities.TechnicalUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ClientId") + .HasColumnType("text") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasColumnType("bytea") + .HasColumnName("client_secret"); + + b.Property("EncryptionMode") + .HasColumnType("integer") + .HasColumnName("encryption_mode"); + + b.Property("ExternalId") + .HasColumnType("uuid") + .HasColumnName("external_id"); + + b.Property("InitializationVector") + .HasColumnType("bytea") + .HasColumnName("initialization_vector"); + + b.Property("ProcessId") + .HasColumnType("uuid") + .HasColumnName("process_id"); + + b.Property("TechnicalUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("technical_user_name"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("tenant_id"); + + b.Property("TokenAddress") + .HasColumnType("text") + .HasColumnName("token_address"); + + b.HasKey("Id") + .HasName("pk_technical_users"); + + b.HasIndex("ProcessId") + .HasDatabaseName("ix_technical_users_process_id"); + + b.HasIndex("TenantId") + .HasDatabaseName("ix_technical_users_tenant_id"); + + b.ToTable("technical_users", "dim"); + }); + modelBuilder.Entity("Dim.Entities.Entities.Tenant", b => { b.Property("Id") @@ -417,6 +493,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ProcessStepType"); }); + modelBuilder.Entity("Dim.Entities.Entities.TechnicalUser", b => + { + b.HasOne("Dim.Entities.Entities.Process", "Process") + .WithMany("TechnicalUsers") + .HasForeignKey("ProcessId") + .IsRequired() + .HasConstraintName("fk_technical_users_processes_process_id"); + + b.HasOne("Dim.Entities.Entities.Tenant", "Tenant") + .WithMany("TechnicalUsers") + .HasForeignKey("TenantId") + .IsRequired() + .HasConstraintName("fk_technical_users_tenants_tenant_id"); + + b.Navigation("Process"); + + b.Navigation("Tenant"); + }); + modelBuilder.Entity("Dim.Entities.Entities.Tenant", b => { b.HasOne("Dim.Entities.Entities.Process", "Process") @@ -432,6 +527,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Navigation("ProcessSteps"); + b.Navigation("TechnicalUsers"); + b.Navigation("Tenants"); }); @@ -449,6 +546,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Navigation("Processes"); }); + + modelBuilder.Entity("Dim.Entities.Entities.Tenant", b => + { + b.Navigation("TechnicalUsers"); + }); #pragma warning restore 612, 618 } } diff --git a/src/processes/DimProcess.Executor/DependencyInjection/DimProcessCollectionExtensions.cs b/src/processes/DimProcess.Executor/DependencyInjection/DimProcessCollectionExtensions.cs index d3e995b..7a7cf91 100644 --- a/src/processes/DimProcess.Executor/DependencyInjection/DimProcessCollectionExtensions.cs +++ b/src/processes/DimProcess.Executor/DependencyInjection/DimProcessCollectionExtensions.cs @@ -30,4 +30,9 @@ public static IServiceCollection AddDimProcessExecutor(this IServiceCollection s services .AddTransient() .AddDimProcessHandler(config); + + public static IServiceCollection AddTechnicalUserProcessExecutor(this IServiceCollection services, IConfiguration config) => + services + .AddTransient() + .AddTechnicalUserProcessHandler(config); } diff --git a/src/processes/DimProcess.Executor/DimProcessTypeExecutor.cs b/src/processes/DimProcess.Executor/DimProcessTypeExecutor.cs index 04b7c1f..6777f3a 100644 --- a/src/processes/DimProcess.Executor/DimProcessTypeExecutor.cs +++ b/src/processes/DimProcess.Executor/DimProcessTypeExecutor.cs @@ -27,11 +27,11 @@ namespace DimProcess.Executor; -public class DimProcessTypeExecutor : IProcessTypeExecutor +public class DimProcessTypeExecutor( + IDimRepositories dimRepositories, + IDimProcessHandler dimProcessHandler) + : IProcessTypeExecutor { - private readonly IDimRepositories _dimRepositories; - private readonly IDimProcessHandler _dimProcessHandler; - private readonly IEnumerable _executableProcessSteps = ImmutableArray.Create( ProcessStepTypeId.CREATE_SUBACCOUNT, ProcessStepTypeId.CREATE_SERVICEMANAGER_BINDINGS, @@ -55,14 +55,6 @@ public class DimProcessTypeExecutor : IProcessTypeExecutor private Guid _tenantId; private string? _tenantName; - public DimProcessTypeExecutor( - IDimRepositories dimRepositories, - IDimProcessHandler dimProcessHandler) - { - _dimRepositories = dimRepositories; - _dimProcessHandler = dimProcessHandler; - } - public ProcessTypeId GetProcessTypeId() => ProcessTypeId.SETUP_DIM; public bool IsExecutableStepTypeId(ProcessStepTypeId processStepTypeId) => _executableProcessSteps.Contains(processStepTypeId); public IEnumerable GetExecutableStepTypeIds() => _executableProcessSteps; @@ -70,7 +62,7 @@ public DimProcessTypeExecutor( public async ValueTask InitializeProcess(Guid processId, IEnumerable processStepTypeIds) { - var (exists, tenantId, companyName, bpn) = await _dimRepositories.GetInstance().GetTenantDataForProcessId(processId).ConfigureAwait(false); + var (exists, tenantId, companyName, bpn) = await dimRepositories.GetInstance().GetTenantDataForProcessId(processId).ConfigureAwait(false); if (!exists) { throw new NotFoundException($"process {processId} does not exist or is not associated with an tenant"); @@ -97,41 +89,41 @@ public DimProcessTypeExecutor( { (nextStepTypeIds, stepStatusId, modified, processMessage) = processStepTypeId switch { - ProcessStepTypeId.CREATE_SUBACCOUNT => await _dimProcessHandler.CreateSubaccount(_tenantId, _tenantName, cancellationToken) + ProcessStepTypeId.CREATE_SUBACCOUNT => await dimProcessHandler.CreateSubaccount(_tenantId, _tenantName, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_SERVICEMANAGER_BINDINGS => await _dimProcessHandler.CreateServiceManagerBindings(_tenantId, cancellationToken) + ProcessStepTypeId.CREATE_SERVICEMANAGER_BINDINGS => await dimProcessHandler.CreateServiceManagerBindings(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.ASSIGN_ENTITLEMENTS => await _dimProcessHandler.AssignEntitlements(_tenantId, cancellationToken) + ProcessStepTypeId.ASSIGN_ENTITLEMENTS => await dimProcessHandler.AssignEntitlements(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_SERVICE_INSTANCE => await _dimProcessHandler.CreateServiceInstance(_tenantId, cancellationToken) + ProcessStepTypeId.CREATE_SERVICE_INSTANCE => await dimProcessHandler.CreateServiceInstance(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_SERVICE_BINDING => await _dimProcessHandler.CreateServiceBindings(_tenantId, cancellationToken) + ProcessStepTypeId.CREATE_SERVICE_BINDING => await dimProcessHandler.CreateServiceBindings(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.SUBSCRIBE_APPLICATION => await _dimProcessHandler.SubscribeApplication(_tenantId, cancellationToken) + ProcessStepTypeId.SUBSCRIBE_APPLICATION => await dimProcessHandler.SubscribeApplication(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_CLOUD_FOUNDRY_ENVIRONMENT => await _dimProcessHandler.CreateCloudFoundryEnvironment(_tenantId, _tenantName, cancellationToken) + ProcessStepTypeId.CREATE_CLOUD_FOUNDRY_ENVIRONMENT => await dimProcessHandler.CreateCloudFoundryEnvironment(_tenantId, _tenantName, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_CLOUD_FOUNDRY_SPACE => await _dimProcessHandler.CreateCloudFoundrySpace(_tenantId, _tenantName, cancellationToken) + ProcessStepTypeId.CREATE_CLOUD_FOUNDRY_SPACE => await dimProcessHandler.CreateCloudFoundrySpace(_tenantId, _tenantName, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.ADD_SPACE_MANAGER_ROLE => await _dimProcessHandler.AddSpaceManagerRole(_tenantId, cancellationToken) + ProcessStepTypeId.ADD_SPACE_MANAGER_ROLE => await dimProcessHandler.AddSpaceManagerRole(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.ADD_SPACE_DEVELOPER_ROLE => await _dimProcessHandler.AddSpaceDeveloperRole(_tenantId, cancellationToken) + ProcessStepTypeId.ADD_SPACE_DEVELOPER_ROLE => await dimProcessHandler.AddSpaceDeveloperRole(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_DIM_SERVICE_INSTANCE => await _dimProcessHandler.CreateDimServiceInstance(_tenantName, _tenantId, cancellationToken) + ProcessStepTypeId.CREATE_DIM_SERVICE_INSTANCE => await dimProcessHandler.CreateDimServiceInstance(_tenantName, _tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_SERVICE_INSTANCE_BINDING => await _dimProcessHandler.CreateServiceInstanceBindings(_tenantName, _tenantId, cancellationToken) + ProcessStepTypeId.CREATE_SERVICE_INSTANCE_BINDING => await dimProcessHandler.CreateServiceInstanceBindings(_tenantName, _tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.GET_DIM_DETAILS => await _dimProcessHandler.GetDimDetails(_tenantName, _tenantId, cancellationToken) + ProcessStepTypeId.GET_DIM_DETAILS => await dimProcessHandler.GetDimDetails(_tenantName, _tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_APPLICATION => await _dimProcessHandler.CreateApplication(_tenantName, _tenantId, cancellationToken) + ProcessStepTypeId.CREATE_APPLICATION => await dimProcessHandler.CreateApplication(_tenantName, _tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_COMPANY_IDENTITY => await _dimProcessHandler.CreateCompanyIdentity(_tenantId, _tenantName, cancellationToken) + ProcessStepTypeId.CREATE_COMPANY_IDENTITY => await dimProcessHandler.CreateCompanyIdentity(_tenantId, _tenantName, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.ASSIGN_COMPANY_APPLICATION => await _dimProcessHandler.AssignCompanyApplication(_tenantId, cancellationToken) + ProcessStepTypeId.ASSIGN_COMPANY_APPLICATION => await dimProcessHandler.AssignCompanyApplication(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.CREATE_STATUS_LIST => await _dimProcessHandler.CreateStatusList(_tenantId, cancellationToken) + ProcessStepTypeId.CREATE_STATUS_LIST => await dimProcessHandler.CreateStatusList(_tenantId, cancellationToken) .ConfigureAwait(false), - ProcessStepTypeId.SEND_CALLBACK => await _dimProcessHandler.SendCallback(_tenantId, cancellationToken) + ProcessStepTypeId.SEND_CALLBACK => await dimProcessHandler.SendCallback(_tenantId, cancellationToken) .ConfigureAwait(false), _ => (null, ProcessStepStatusId.TODO, false, null) }; diff --git a/src/processes/DimProcess.Executor/TechnicalUserProcessTypeExecutor.cs b/src/processes/DimProcess.Executor/TechnicalUserProcessTypeExecutor.cs new file mode 100644 index 0000000..0ceee9a --- /dev/null +++ b/src/processes/DimProcess.Executor/TechnicalUserProcessTypeExecutor.cs @@ -0,0 +1,103 @@ +/******************************************************************************** + * Copyright (c) 2024 BMW Group AG + * + * 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 + ********************************************************************************/ + +using Dim.DbAccess; +using Dim.DbAccess.Repositories; +using Dim.Entities.Enums; +using DimProcess.Library; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.Portal.Backend.Processes.Worker.Library; +using System.Collections.Immutable; + +namespace DimProcess.Executor; + +public class TechnicalUserProcessTypeExecutor( + IDimRepositories dimRepositories, + ITechnicalUserProcessHandler technicalUserProcessHandler) + : IProcessTypeExecutor +{ + private readonly IEnumerable _executableProcessSteps = ImmutableArray.Create( + ProcessStepTypeId.CREATE_TECHNICAL_USER, + ProcessStepTypeId.GET_TECHNICAL_USER_DATA, + ProcessStepTypeId.SEND_TECHNICAL_USER_CALLBACK); + + private Guid _technicalUserId; + private string? _tenantName; + + public ProcessTypeId GetProcessTypeId() => ProcessTypeId.CREATE_TECHNICAL_USER; + public bool IsExecutableStepTypeId(ProcessStepTypeId processStepTypeId) => _executableProcessSteps.Contains(processStepTypeId); + public IEnumerable GetExecutableStepTypeIds() => _executableProcessSteps; + public ValueTask IsLockRequested(ProcessStepTypeId processStepTypeId) => new(false); + + public async ValueTask InitializeProcess(Guid processId, IEnumerable processStepTypeIds) + { + var (exists, technicalUserId, companyName, bpn) = await dimRepositories.GetInstance().GetTenantDataForTechnicalUserProcessId(processId).ConfigureAwait(false); + if (!exists) + { + throw new NotFoundException($"process {processId} does not exist or is not associated with an technical user"); + } + + _technicalUserId = technicalUserId; + _tenantName = $"{bpn}_{companyName}"; + return new IProcessTypeExecutor.InitializationResult(false, null); + } + + public async ValueTask ExecuteProcessStep(ProcessStepTypeId processStepTypeId, IEnumerable processStepTypeIds, CancellationToken cancellationToken) + { + if (_technicalUserId == Guid.Empty || _tenantName is null) + { + throw new UnexpectedConditionException("technicalUserId and tenantName should never be empty here"); + } + + IEnumerable? nextStepTypeIds; + ProcessStepStatusId stepStatusId; + bool modified; + string? processMessage; + + try + { + (nextStepTypeIds, stepStatusId, modified, processMessage) = processStepTypeId switch + { + ProcessStepTypeId.CREATE_TECHNICAL_USER => await technicalUserProcessHandler.CreateServiceInstanceBindings(_tenantName, _technicalUserId, cancellationToken) + .ConfigureAwait(false), + ProcessStepTypeId.GET_TECHNICAL_USER_DATA => await technicalUserProcessHandler.GetTechnicalUserData(_tenantName, _technicalUserId, cancellationToken) + .ConfigureAwait(false), + ProcessStepTypeId.SEND_TECHNICAL_USER_CALLBACK => await technicalUserProcessHandler.SendCallback(_technicalUserId, cancellationToken) + .ConfigureAwait(false), + _ => (null, ProcessStepStatusId.TODO, false, null) + }; + } + catch (Exception ex) when (ex is not SystemException) + { + (stepStatusId, processMessage, nextStepTypeIds) = ProcessError(ex); + modified = true; + } + + return new IProcessTypeExecutor.StepExecutionResult(modified, stepStatusId, nextStepTypeIds, null, processMessage); + } + + private static (ProcessStepStatusId StatusId, string? ProcessMessage, IEnumerable? nextSteps) ProcessError(Exception ex) + { + return ex switch + { + ServiceException { IsRecoverable: true } => (ProcessStepStatusId.TODO, ex.Message, null), + _ => (ProcessStepStatusId.FAILED, ex.Message, null) + }; + } +} diff --git a/src/processes/DimProcess.Library/Callback/CallbackService.cs b/src/processes/DimProcess.Library/Callback/CallbackService.cs index 3d3589e..a5d59d2 100644 --- a/src/processes/DimProcess.Library/Callback/CallbackService.cs +++ b/src/processes/DimProcess.Library/Callback/CallbackService.cs @@ -29,20 +29,14 @@ namespace DimProcess.Library.Callback; -public class CallbackService : ICallbackService +public class CallbackService(ITokenService tokenService, IOptions options) + : ICallbackService { - private readonly ITokenService _tokenService; - private readonly CallbackSettings _settings; - - public CallbackService(ITokenService tokenService, IOptions options) - { - _tokenService = tokenService; - _settings = options.Value; - } + private readonly CallbackSettings _settings = options.Value; public async Task SendCallback(string bpn, ServiceCredentialBindingDetailResponse dimDetails, JsonDocument didDocument, string did, CancellationToken cancellationToken) { - var httpClient = await _tokenService.GetAuthorizedClient(_settings, cancellationToken) + var httpClient = await tokenService.GetAuthorizedClient(_settings, cancellationToken) .ConfigureAwait(false); var data = new CallbackDataModel( did, @@ -52,6 +46,17 @@ public async Task SendCallback(string bpn, ServiceCredentialBindingDetailRespons dimDetails.Credentials.Uaa.ClientId, dimDetails.Credentials.Uaa.ClientSecret) ); - await httpClient.PostAsJsonAsync($"{bpn}", data, JsonSerializerExtensions.Options, cancellationToken).ConfigureAwait(false); + await httpClient.PostAsJsonAsync($"/api/administration/registration/dim/{bpn}", data, JsonSerializerExtensions.Options, cancellationToken).ConfigureAwait(false); + } + + public async Task SendTechnicalUserCallback(Guid externalId, string tokenAddress, string clientId, string clientSecret, CancellationToken cancellationToken) + { + var httpClient = await tokenService.GetAuthorizedClient(_settings, cancellationToken) + .ConfigureAwait(false); + var data = new AuthenticationDetail( + tokenAddress, + clientId, + clientSecret); + await httpClient.PostAsJsonAsync($"/api/adminstration/serviceAccount/callback/{externalId}", data, JsonSerializerExtensions.Options, cancellationToken).ConfigureAwait(false); } } diff --git a/src/processes/DimProcess.Library/Callback/ICallbackService.cs b/src/processes/DimProcess.Library/Callback/ICallbackService.cs index 0107629..8dca0dd 100644 --- a/src/processes/DimProcess.Library/Callback/ICallbackService.cs +++ b/src/processes/DimProcess.Library/Callback/ICallbackService.cs @@ -25,4 +25,6 @@ namespace DimProcess.Library.Callback; public interface ICallbackService { Task SendCallback(string bpn, ServiceCredentialBindingDetailResponse dimDetails, JsonDocument didDocument, string did, CancellationToken cancellationToken); + + Task SendTechnicalUserCallback(Guid externalId, string tokenAddress, string clientId, string clientSecret, CancellationToken cancellationToken); } diff --git a/src/processes/DimProcess.Library/DependencyInjection/DimHandlerExtensions.cs b/src/processes/DimProcess.Library/DependencyInjection/DimHandlerExtensions.cs index 936c99e..e2d2069 100644 --- a/src/processes/DimProcess.Library/DependencyInjection/DimHandlerExtensions.cs +++ b/src/processes/DimProcess.Library/DependencyInjection/DimHandlerExtensions.cs @@ -53,4 +53,19 @@ public static IServiceCollection AddDimProcessHandler(this IServiceCollection se return services; } + + public static IServiceCollection AddTechnicalUserProcessHandler(this IServiceCollection services, IConfiguration config) + { + services.AddOptions() + .Bind(config.GetSection("TechnicalUserCreation")) + .ValidateOnStart(); + + services + .AddTransient() + .AddTransient() + .AddCfClient(config.GetSection("Cf")) + .AddCallbackClient(config.GetSection("Callback")); + + return services; + } } diff --git a/src/processes/DimProcess.Library/DependencyInjection/TechnicalUserSettings.cs b/src/processes/DimProcess.Library/DependencyInjection/TechnicalUserSettings.cs new file mode 100644 index 0000000..b0f0b06 --- /dev/null +++ b/src/processes/DimProcess.Library/DependencyInjection/TechnicalUserSettings.cs @@ -0,0 +1,15 @@ +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Validation; +using System.ComponentModel.DataAnnotations; + +namespace DimProcess.Library.DependencyInjection; + +public class TechnicalUserSettings +{ + [Required] + public int EncryptionConfigIndex { get; set; } + + [Required] + [DistinctValues("x => x.Index")] + public IEnumerable EncryptionConfigs { get; set; } = null!; +} diff --git a/src/processes/DimProcess.Library/DimProcess.Library.csproj b/src/processes/DimProcess.Library/DimProcess.Library.csproj index 8eeb03c..8120d7a 100644 --- a/src/processes/DimProcess.Library/DimProcess.Library.csproj +++ b/src/processes/DimProcess.Library/DimProcess.Library.csproj @@ -31,6 +31,7 @@ + diff --git a/src/processes/DimProcess.Library/DimProcessHandler.cs b/src/processes/DimProcess.Library/DimProcessHandler.cs index a78460e..7fb9812 100644 --- a/src/processes/DimProcess.Library/DimProcessHandler.cs +++ b/src/processes/DimProcess.Library/DimProcessHandler.cs @@ -35,42 +35,20 @@ namespace DimProcess.Library; -public class DimProcessHandler : IDimProcessHandler +public class DimProcessHandler( + IDimRepositories dimRepositories, + ISubAccountClient subAccountClient, + IServiceClient serviceClient, + ISubscriptionClient subscriptionClient, + IEntitlementClient entitlementClient, + IProvisioningClient provisioningClient, + ICfClient cfClient, + IDimClient dimClient, + ICallbackService callbackService, + IOptions options) + : IDimProcessHandler { - private readonly IDimRepositories _dimRepositories; - private readonly ISubAccountClient _subAccountClient; - private readonly IServiceClient _serviceClient; - private readonly IEntitlementClient _entitlementClient; - private readonly ISubscriptionClient _subscriptionClient; - private readonly IProvisioningClient _provisioningClient; - private readonly ICfClient _cfClient; - private readonly IDimClient _dimClient; - private readonly ICallbackService _callbackService; - private readonly DimHandlerSettings _settings; - - public DimProcessHandler( - IDimRepositories dimRepositories, - ISubAccountClient subAccountClient, - IServiceClient serviceClient, - ISubscriptionClient subscriptionClient, - IEntitlementClient entitlementClient, - IProvisioningClient provisioningClient, - ICfClient cfClient, - IDimClient dimClient, - ICallbackService callbackService, - IOptions options) - { - _dimRepositories = dimRepositories; - _subAccountClient = subAccountClient; - _serviceClient = serviceClient; - _entitlementClient = entitlementClient; - _subscriptionClient = subscriptionClient; - _provisioningClient = provisioningClient; - _cfClient = cfClient; - _dimClient = dimClient; - _callbackService = callbackService; - _settings = options.Value; - } + private readonly DimHandlerSettings _settings = options.Value; public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateSubaccount(Guid tenantId, string tenantName, CancellationToken cancellationToken) { @@ -83,8 +61,8 @@ public DimProcessHandler( ClientSecret = _settings.ClientsecretCisCentral }; - var subAccountId = await _subAccountClient.CreateSubaccount(subAccountAuth, adminMail, tenantName, parentDirectoryId, cancellationToken).ConfigureAwait(false); - _dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => + var subAccountId = await subAccountClient.CreateSubaccount(subAccountAuth, adminMail, tenantName, parentDirectoryId, cancellationToken).ConfigureAwait(false); + dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => { tenant.SubAccountId = null; }, @@ -108,14 +86,14 @@ public DimProcessHandler( ClientSecret = _settings.ClientsecretCisCentral }; - var tenantRepository = _dimRepositories.GetInstance(); + var tenantRepository = dimRepositories.GetInstance(); var subAccountId = await tenantRepository.GetSubAccountIdByTenantId(tenantId).ConfigureAwait(false); if (subAccountId == null) { throw new ConflictException("SubAccountId must not be null."); } - await _subAccountClient.CreateServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); + await subAccountClient.CreateServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.ASSIGN_ENTITLEMENTS, 1), @@ -132,13 +110,13 @@ public DimProcessHandler( ClientId = _settings.ClientidCisCentral, ClientSecret = _settings.ClientsecretCisCentral }; - var subAccountId = await _dimRepositories.GetInstance().GetSubAccountIdByTenantId(tenantId).ConfigureAwait(false); + var subAccountId = await dimRepositories.GetInstance().GetSubAccountIdByTenantId(tenantId).ConfigureAwait(false); if (subAccountId == null) { throw new ConflictException("SubAccountId must not be null."); } - await _entitlementClient.AssignEntitlements(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); + await entitlementClient.AssignEntitlements(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.CREATE_SERVICE_INSTANCE, 1), @@ -155,16 +133,16 @@ public DimProcessHandler( ClientId = _settings.ClientidCisCentral, ClientSecret = _settings.ClientsecretCisCentral }; - var subAccountId = await _dimRepositories.GetInstance().GetSubAccountIdByTenantId(tenantId).ConfigureAwait(false); + var subAccountId = await dimRepositories.GetInstance().GetSubAccountIdByTenantId(tenantId).ConfigureAwait(false); if (subAccountId == null) { throw new ConflictException("SubAccountId must not be null."); } - var saBinding = await _subAccountClient.GetServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); - var serviceInstance = await _serviceClient.CreateServiceInstance(saBinding, cancellationToken).ConfigureAwait(false); + var saBinding = await subAccountClient.GetServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); + var serviceInstance = await serviceClient.CreateServiceInstance(saBinding, cancellationToken).ConfigureAwait(false); - _dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => + dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => { tenant.ServiceInstanceId = null; }, @@ -187,7 +165,7 @@ public DimProcessHandler( ClientId = _settings.ClientidCisCentral, ClientSecret = _settings.ClientsecretCisCentral }; - var (subAccountId, serviceInstanceId) = await _dimRepositories.GetInstance().GetSubAccountAndServiceInstanceIdsByTenantId(tenantId).ConfigureAwait(false); + var (subAccountId, serviceInstanceId) = await dimRepositories.GetInstance().GetSubAccountAndServiceInstanceIdsByTenantId(tenantId).ConfigureAwait(false); if (subAccountId == null) { throw new ConflictException("SubAccountId must not be null."); @@ -198,10 +176,10 @@ public DimProcessHandler( throw new ConflictException("ServiceInstanceId must not be null."); } - var saBinding = await _subAccountClient.GetServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); - var serviceBinding = await _serviceClient.CreateServiceBinding(saBinding, serviceInstanceId, cancellationToken).ConfigureAwait(false); + var saBinding = await subAccountClient.GetServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); + var serviceBinding = await serviceClient.CreateServiceBinding(saBinding, serviceInstanceId, cancellationToken).ConfigureAwait(false); - _dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => + dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => { tenant.ServiceBindingName = null; }, @@ -224,7 +202,7 @@ public DimProcessHandler( ClientId = _settings.ClientidCisCentral, ClientSecret = _settings.ClientsecretCisCentral }; - var (subAccountId, serviceBindingName) = await _dimRepositories.GetInstance().GetSubAccountIdAndServiceBindingNameByTenantId(tenantId).ConfigureAwait(false); + var (subAccountId, serviceBindingName) = await dimRepositories.GetInstance().GetSubAccountIdAndServiceBindingNameByTenantId(tenantId).ConfigureAwait(false); if (subAccountId == null) { throw new ConflictException("SubAccountId must not be null."); @@ -235,9 +213,9 @@ public DimProcessHandler( throw new ConflictException("ServiceBindingName must not be null."); } - var saBinding = await _subAccountClient.GetServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); - var bindingResponse = await _serviceClient.GetServiceBinding(saBinding, serviceBindingName, cancellationToken).ConfigureAwait(false); - await _subscriptionClient.SubscribeApplication(saBinding.Url, bindingResponse, "decentralized-identity-management-app", "standard", cancellationToken).ConfigureAwait(false); + var saBinding = await subAccountClient.GetServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); + var bindingResponse = await serviceClient.GetServiceBinding(saBinding, serviceBindingName, cancellationToken).ConfigureAwait(false); + await subscriptionClient.SubscribeApplication(saBinding.Url, bindingResponse, "decentralized-identity-management-app", "standard", cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.CREATE_CLOUD_FOUNDRY_ENVIRONMENT, 1), @@ -255,7 +233,7 @@ public DimProcessHandler( ClientId = _settings.ClientidCisCentral, ClientSecret = _settings.ClientsecretCisCentral }; - var (subAccountId, serviceBindingName) = await _dimRepositories.GetInstance().GetSubAccountIdAndServiceBindingNameByTenantId(tenantId).ConfigureAwait(false); + var (subAccountId, serviceBindingName) = await dimRepositories.GetInstance().GetSubAccountIdAndServiceBindingNameByTenantId(tenantId).ConfigureAwait(false); if (subAccountId == null) { throw new ConflictException("SubAccountId must not be null."); @@ -266,9 +244,9 @@ public DimProcessHandler( throw new ConflictException("ServiceBindingName must not be null."); } - var saBinding = await _subAccountClient.GetServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); - var bindingResponse = await _serviceClient.GetServiceBinding(saBinding, serviceBindingName, cancellationToken).ConfigureAwait(false); - await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingResponse, tenantName, adminMail, cancellationToken) + var saBinding = await subAccountClient.GetServiceManagerBindings(subAccountAuth, subAccountId.Value, cancellationToken).ConfigureAwait(false); + var bindingResponse = await serviceClient.GetServiceBinding(saBinding, serviceBindingName, cancellationToken).ConfigureAwait(false); + await provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingResponse, tenantName, adminMail, cancellationToken) .ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( @@ -280,9 +258,9 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateCloudFoundrySpace(Guid tenantId, string tenantName, CancellationToken cancellationToken) { - var spaceId = await _cfClient.CreateCloudFoundrySpace(tenantName, cancellationToken).ConfigureAwait(false); + var spaceId = await cfClient.CreateCloudFoundrySpace(tenantName, cancellationToken).ConfigureAwait(false); - _dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => + dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => { tenant.SpaceId = null; }, @@ -300,13 +278,13 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> AddSpaceManagerRole(Guid tenantId, CancellationToken cancellationToken) { var adminMail = _settings.AdminMail; - var spaceId = await _dimRepositories.GetInstance().GetSpaceId(tenantId).ConfigureAwait(false); + var spaceId = await dimRepositories.GetInstance().GetSpaceId(tenantId).ConfigureAwait(false); if (spaceId == null) { throw new ConflictException("SpaceId must not be null."); } - await _cfClient.AddSpaceRoleToUser("space_manager", adminMail, spaceId.Value, cancellationToken).ConfigureAwait(false); + await cfClient.AddSpaceRoleToUser("space_manager", adminMail, spaceId.Value, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.ADD_SPACE_DEVELOPER_ROLE, 1), @@ -318,13 +296,13 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> AddSpaceDeveloperRole(Guid tenantId, CancellationToken cancellationToken) { var adminMail = _settings.AdminMail; - var spaceId = await _dimRepositories.GetInstance().GetSpaceId(tenantId).ConfigureAwait(false); + var spaceId = await dimRepositories.GetInstance().GetSpaceId(tenantId).ConfigureAwait(false); if (spaceId == null) { throw new ConflictException("SpaceId must not be null."); } - await _cfClient.AddSpaceRoleToUser("space_developer", adminMail, spaceId.Value, cancellationToken).ConfigureAwait(false); + await cfClient.AddSpaceRoleToUser("space_developer", adminMail, spaceId.Value, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.CREATE_DIM_SERVICE_INSTANCE, 1), @@ -335,9 +313,9 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateDimServiceInstance(string tenantName, Guid tenantId, CancellationToken cancellationToken) { - var servicePlanId = await _cfClient.GetServicePlan("decentralized-identity-management", "standard", cancellationToken).ConfigureAwait(false); - var spaceId = await _cfClient.GetSpace(tenantName, cancellationToken).ConfigureAwait(false); - await _cfClient.CreateDimServiceInstance(tenantName, spaceId, servicePlanId, cancellationToken).ConfigureAwait(false); + var servicePlanId = await cfClient.GetServicePlan("decentralized-identity-management", "standard", cancellationToken).ConfigureAwait(false); + var spaceId = await cfClient.GetSpace(tenantName, cancellationToken).ConfigureAwait(false); + await cfClient.CreateDimServiceInstance(tenantName, spaceId, servicePlanId, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.CREATE_SERVICE_INSTANCE_BINDING, 1), @@ -348,13 +326,13 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateServiceInstanceBindings(string tenantName, Guid tenantId, CancellationToken cancellationToken) { - var spaceId = await _dimRepositories.GetInstance().GetSpaceId(tenantId).ConfigureAwait(false); + var spaceId = await dimRepositories.GetInstance().GetSpaceId(tenantId).ConfigureAwait(false); if (spaceId == null) { throw new ConflictException("SpaceId must not be null."); } - await _cfClient.CreateServiceInstanceBindings(tenantName, spaceId.Value, cancellationToken).ConfigureAwait(false); + await cfClient.CreateServiceInstanceBindings(tenantName, null, spaceId.Value, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.GET_DIM_DETAILS, 1), @@ -365,15 +343,15 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> GetDimDetails(string tenantName, Guid tenantId, CancellationToken cancellationToken) { - var spaceId = await _dimRepositories.GetInstance().GetSpaceId(tenantId).ConfigureAwait(false); + var spaceId = await dimRepositories.GetInstance().GetSpaceId(tenantId).ConfigureAwait(false); if (spaceId == null) { throw new ConflictException("SpaceId must not be null."); } - var dimInstanceId = await _cfClient.GetServiceBinding(tenantName, spaceId.Value, $"{tenantName}-dim-key01", cancellationToken).ConfigureAwait(false); + var dimInstanceId = await cfClient.GetServiceBinding(tenantName, spaceId.Value, $"{tenantName}-dim-key01", cancellationToken).ConfigureAwait(false); - _dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => + dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => { tenant.DimInstanceId = null; }, @@ -390,13 +368,13 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateApplication(string tenantName, Guid tenantId, CancellationToken cancellationToken) { - var (dimInstanceId, _, _) = await _dimRepositories.GetInstance().GetDimInstanceIdAndHostingUrl(tenantId).ConfigureAwait(false); + var (dimInstanceId, _, _) = await dimRepositories.GetInstance().GetDimInstanceIdAndHostingUrl(tenantId).ConfigureAwait(false); if (dimInstanceId == null) { throw new ConflictException("DimInstanceId must not be null."); } - var dimDetails = await _cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); + var dimDetails = await cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); var dimAuth = new BasicAuthSettings { @@ -405,8 +383,8 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe ClientSecret = dimDetails.Credentials.Uaa.ClientSecret }; var dimBaseUrl = dimDetails.Credentials.Url; - var applicationId = await _dimClient.CreateApplication(dimAuth, dimBaseUrl, tenantName, cancellationToken).ConfigureAwait(false); - _dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => + var applicationId = await dimClient.CreateApplication(dimAuth, dimBaseUrl, tenantName, cancellationToken).ConfigureAwait(false); + dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => { tenant.ApplicationId = null; }, @@ -423,13 +401,13 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateCompanyIdentity(Guid tenantId, string tenantName, CancellationToken cancellationToken) { - var (dimInstanceId, hostingUrl, isIssuer) = await _dimRepositories.GetInstance().GetDimInstanceIdAndHostingUrl(tenantId).ConfigureAwait(false); + var (dimInstanceId, hostingUrl, isIssuer) = await dimRepositories.GetInstance().GetDimInstanceIdAndHostingUrl(tenantId).ConfigureAwait(false); if (dimInstanceId == null) { throw new ConflictException("DimInstanceId must not be null."); } - var dimDetails = await _cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); + var dimDetails = await cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); var dimAuth = new BasicAuthSettings { @@ -438,9 +416,9 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe ClientSecret = dimDetails.Credentials.Uaa.ClientSecret }; var dimBaseUrl = dimDetails.Credentials.Url; - var result = await _dimClient.CreateCompanyIdentity(dimAuth, hostingUrl, dimBaseUrl, tenantName, isIssuer, cancellationToken).ConfigureAwait(false); + var result = await dimClient.CreateCompanyIdentity(dimAuth, hostingUrl, dimBaseUrl, tenantName, isIssuer, cancellationToken).ConfigureAwait(false); - _dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => + dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => { tenant.DidDownloadUrl = null; tenant.Did = null; @@ -461,7 +439,7 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> AssignCompanyApplication(Guid tenantId, CancellationToken cancellationToken) { - var (applicationId, companyId, dimInstanceId, isIssuer) = await _dimRepositories.GetInstance().GetApplicationAndCompanyId(tenantId).ConfigureAwait(false); + var (applicationId, companyId, dimInstanceId, isIssuer) = await dimRepositories.GetInstance().GetApplicationAndCompanyId(tenantId).ConfigureAwait(false); if (applicationId == null) { throw new ConflictException("ApplicationId must always be set here"); @@ -477,7 +455,7 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe throw new ConflictException("DimInstanceId must not be null."); } - var dimDetails = await _cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); + var dimDetails = await cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); var dimAuth = new BasicAuthSettings { TokenAddress = $"{dimDetails.Credentials.Uaa.Url}/oauth/token", @@ -485,10 +463,10 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe ClientSecret = dimDetails.Credentials.Uaa.ClientSecret }; var dimBaseUrl = dimDetails.Credentials.Url; - var applicationKey = await _dimClient.GetApplication(dimAuth, dimBaseUrl, applicationId, cancellationToken); - await _dimClient.AssignApplicationToCompany(dimAuth, dimBaseUrl, applicationKey, companyId.Value, cancellationToken).ConfigureAwait(false); + var applicationKey = await dimClient.GetApplication(dimAuth, dimBaseUrl, applicationId, cancellationToken); + await dimClient.AssignApplicationToCompany(dimAuth, dimBaseUrl, applicationKey, companyId.Value, cancellationToken).ConfigureAwait(false); - _dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => + dimRepositories.GetInstance().AttachAndModifyTenant(tenantId, tenant => { tenant.ApplicationKey = null; }, @@ -505,7 +483,7 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateStatusList(Guid tenantId, CancellationToken cancellationToken) { - var (_, companyId, dimInstanceId, _) = await _dimRepositories.GetInstance().GetApplicationAndCompanyId(tenantId).ConfigureAwait(false); + var (_, companyId, dimInstanceId, _) = await dimRepositories.GetInstance().GetApplicationAndCompanyId(tenantId).ConfigureAwait(false); if (companyId == null) { throw new ConflictException("CompanyId must always be set here"); @@ -516,7 +494,7 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe throw new ConflictException("DimInstanceId must not be null."); } - var dimDetails = await _cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); + var dimDetails = await cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); var dimAuth = new BasicAuthSettings { TokenAddress = $"{dimDetails.Credentials.Uaa.Url}/oauth/token", @@ -524,7 +502,7 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe ClientSecret = dimDetails.Credentials.Uaa.ClientSecret }; var dimBaseUrl = dimDetails.Credentials.Url; - await _dimClient.CreateStatusList(dimAuth, dimBaseUrl, companyId.Value, cancellationToken).ConfigureAwait(false); + await dimClient.CreateStatusList(dimAuth, dimBaseUrl, companyId.Value, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( Enumerable.Repeat(ProcessStepTypeId.SEND_CALLBACK, 1), @@ -535,7 +513,7 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SendCallback(Guid tenantId, CancellationToken cancellationToken) { - var (bpn, downloadUrl, did, dimInstanceId) = await _dimRepositories.GetInstance().GetCallbackData(tenantId).ConfigureAwait(false); + var (bpn, downloadUrl, did, dimInstanceId) = await dimRepositories.GetInstance().GetCallbackData(tenantId).ConfigureAwait(false); if (downloadUrl == null) { throw new ConflictException("DownloadUrl must not be null."); @@ -551,10 +529,10 @@ await _provisioningClient.CreateCloudFoundryEnvironment(saBinding.Url, bindingRe throw new ConflictException("DimInstanceId must not be null."); } - var dimDetails = await _cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); - var didDocument = await _dimClient.GetDidDocument(downloadUrl, cancellationToken).ConfigureAwait(false); + var dimDetails = await cfClient.GetServiceBindingDetails(dimInstanceId.Value, cancellationToken).ConfigureAwait(false); + var didDocument = await dimClient.GetDidDocument(downloadUrl, cancellationToken).ConfigureAwait(false); - await _callbackService.SendCallback(bpn, dimDetails, didDocument, did, cancellationToken).ConfigureAwait(false); + await callbackService.SendCallback(bpn, dimDetails, didDocument, did, cancellationToken).ConfigureAwait(false); return new ValueTuple?, ProcessStepStatusId, bool, string?>( null, diff --git a/src/processes/DimProcess.Library/ITechnicalUserProcessHandler.cs b/src/processes/DimProcess.Library/ITechnicalUserProcessHandler.cs new file mode 100644 index 0000000..f84d75f --- /dev/null +++ b/src/processes/DimProcess.Library/ITechnicalUserProcessHandler.cs @@ -0,0 +1,29 @@ +/******************************************************************************** + * Copyright (c) 2024 BMW Group AG + * + * 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 + ********************************************************************************/ + +using Dim.Entities.Enums; + +namespace DimProcess.Library; + +public interface ITechnicalUserProcessHandler +{ + Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateServiceInstanceBindings(string tenantName, Guid technicalUserId, CancellationToken cancellationToken); + Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> GetTechnicalUserData(string tenantName, Guid technicalUserId, CancellationToken cancellationToken); + Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SendCallback(Guid technicalUserId, CancellationToken cancellationToken); +} diff --git a/src/processes/DimProcess.Library/TechnicalUserProcessHandler.cs b/src/processes/DimProcess.Library/TechnicalUserProcessHandler.cs new file mode 100644 index 0000000..54e16bc --- /dev/null +++ b/src/processes/DimProcess.Library/TechnicalUserProcessHandler.cs @@ -0,0 +1,140 @@ +/******************************************************************************** + * Copyright (c) 2024 BMW Group AG + * + * 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 + ********************************************************************************/ + +using Dim.Clients.Api.Cf; +using Dim.DbAccess; +using Dim.DbAccess.Repositories; +using Dim.Entities.Enums; +using DimProcess.Library.Callback; +using DimProcess.Library.DependencyInjection; +using Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Encryption; + +namespace DimProcess.Library; + +public class TechnicalUserProcessHandler( + IDimRepositories dimRepositories, + ICfClient cfClient, + ICallbackService callbackService, + IOptions options) : ITechnicalUserProcessHandler +{ + private readonly TechnicalUserSettings _settings = options.Value; + + public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> CreateServiceInstanceBindings(string tenantName, Guid technicalUserId, CancellationToken cancellationToken) + { + var (spaceId, technicalUserName) = await dimRepositories.GetInstance().GetSpaceIdAndTechnicalUserName(technicalUserId).ConfigureAwait(false); + if (spaceId == null) + { + throw new ConflictException("SpaceId must not be null."); + } + + await cfClient.CreateServiceInstanceBindings(tenantName, technicalUserName, spaceId.Value, cancellationToken).ConfigureAwait(false); + + return new ValueTuple?, ProcessStepStatusId, bool, string?>( + Enumerable.Repeat(ProcessStepTypeId.GET_TECHNICAL_USER_DATA, 1), + ProcessStepStatusId.DONE, + false, + null); + } + + public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> GetTechnicalUserData(string tenantName, Guid technicalUserId, CancellationToken cancellationToken) + { + var (spaceId, technicalUserName) = await dimRepositories.GetInstance().GetSpaceIdAndTechnicalUserName(technicalUserId).ConfigureAwait(false); + if (spaceId == null) + { + throw new ConflictException("SpaceId must not be null."); + } + + var dimInstanceId = await cfClient.GetServiceBinding(tenantName, spaceId.Value, $"{technicalUserName}-dim-key01", cancellationToken).ConfigureAwait(false); + var dimDetails = await cfClient.GetServiceBindingDetails(dimInstanceId, cancellationToken).ConfigureAwait(false); + var (secret, initializationVector, encryptionMode) = Encrypt(dimDetails.Credentials.Uaa.ClientSecret); + + dimRepositories.GetInstance().AttachAndModifyTechnicalUser(technicalUserId, technicalUser => + { + technicalUser.TokenAddress = null; + technicalUser.ClientId = null; + technicalUser.ClientSecret = null; + technicalUser.InitializationVector = null; + technicalUser.EncryptionMode = null; + }, + technicalUser => + { + technicalUser.TokenAddress = $"{dimDetails.Credentials.Uaa.Url}/oauth/token"; + technicalUser.ClientId = dimDetails.Credentials.Uaa.ClientId; + technicalUser.ClientSecret = secret; + technicalUser.InitializationVector = initializationVector; + technicalUser.EncryptionMode = encryptionMode; + }); + return new ValueTuple?, ProcessStepStatusId, bool, string?>( + Enumerable.Repeat(ProcessStepTypeId.SEND_TECHNICAL_USER_CALLBACK, 1), + ProcessStepStatusId.DONE, + false, + null); + } + + private (byte[] Secret, byte[] InitializationVector, int EncryptionMode) Encrypt(string clientSecret) + { + var cryptoConfig = _settings.EncryptionConfigs.SingleOrDefault(x => x.Index == _settings.EncryptionConfigIndex) ?? throw new ConfigurationException($"EncryptionModeIndex {_settings.EncryptionConfigIndex} is not configured"); + var (secret, initializationVector) = CryptoHelper.Encrypt(clientSecret, Convert.FromHexString(cryptoConfig.EncryptionKey), cryptoConfig.CipherMode, cryptoConfig.PaddingMode); + return (secret, initializationVector, _settings.EncryptionConfigIndex); + } + + public async Task<(IEnumerable? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SendCallback(Guid technicalUserId, CancellationToken cancellationToken) + { + var (externalId, tokenAddress, clientId, clientSecret, initializationVector, encryptionMode) = await dimRepositories.GetInstance().GetTechnicalUserCallbackData(technicalUserId).ConfigureAwait(false); + + if (string.IsNullOrWhiteSpace(clientId)) + { + throw new ConflictException("ClientId must not be null"); + } + + if (string.IsNullOrWhiteSpace(tokenAddress)) + { + throw new ConflictException("TokenAddress must not be null"); + } + + var secret = Decrypt(clientSecret, initializationVector, encryptionMode); + + await callbackService.SendTechnicalUserCallback(externalId, tokenAddress, clientId, secret, cancellationToken).ConfigureAwait(false); + + return new ValueTuple?, ProcessStepStatusId, bool, string?>( + null, + ProcessStepStatusId.DONE, + false, + null); + } + + private string Decrypt(byte[]? clientSecret, byte[]? initializationVector, int? encryptionMode) + { + if (clientSecret == null) + { + throw new ConflictException("ClientSecret must not be null"); + } + + if (encryptionMode == null) + { + throw new ConflictException("EncryptionMode must not be null"); + } + + var cryptoConfig = _settings.EncryptionConfigs.SingleOrDefault(x => x.Index == encryptionMode) ?? throw new ConfigurationException($"EncryptionModeIndex {encryptionMode} is not configured"); + + return CryptoHelper.Decrypt(clientSecret, initializationVector, Convert.FromHexString(cryptoConfig.EncryptionKey), cryptoConfig.CipherMode, cryptoConfig.PaddingMode); + } +} diff --git a/src/processes/Processes.Worker/Program.cs b/src/processes/Processes.Worker/Program.cs index d40b099..9a306d5 100644 --- a/src/processes/Processes.Worker/Program.cs +++ b/src/processes/Processes.Worker/Program.cs @@ -40,7 +40,8 @@ .AddTransient() .AddDatabase(hostContext.Configuration) .AddProcessExecutionService(hostContext.Configuration.GetSection("Processes")) - .AddDimProcessExecutor(hostContext.Configuration); + .AddDimProcessExecutor(hostContext.Configuration) + .AddTechnicalUserProcessExecutor(hostContext.Configuration); }) .AddLogging() .Build(); diff --git a/src/processes/Processes.Worker/appsettings.json b/src/processes/Processes.Worker/appsettings.json index 5850051..1e79cbc 100644 --- a/src/processes/Processes.Worker/appsettings.json +++ b/src/processes/Processes.Worker/appsettings.json @@ -21,7 +21,7 @@ } }, "ConnectionStrings": { - "DimDb": "Server=placeholder;Database=placeholder;Port=5432;User Id=placeholder;Password=placeholder;Ssl Mode=Disable;", + "DimDb": "Server=placeholder;Database=placeholder;Port=5432;User Id=placeholder;Password=placeholder;Ssl Mode=Disable;" }, "Dim": { "AdminMail": "", @@ -52,5 +52,16 @@ "Scope": "", "TokenAddress": "", "BaseAddress": "" + }, + "TechnicalUserCreation": { + "EncryptionConfigIndex": 0, + "EncryptionConfigs": [ + { + "Index": 0, + "EncryptionKey": "", + "CipherMode": "", + "PaddingMode": "" + } + ] } } diff --git a/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs b/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs index fe48706..9970337 100644 --- a/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs +++ b/src/web/Dim.Web/BusinessLogic/DimBusinessLogic.cs @@ -24,6 +24,7 @@ using Dim.DbAccess.Repositories; using Dim.Entities.Enums; using Dim.Web.ErrorHandling; +using Dim.Web.Models; using Microsoft.Extensions.Options; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; @@ -112,4 +113,22 @@ public async Task CreateStatusList(string bpn, CancellationToken cancell var dimBaseUrl = dimDetails.Credentials.Url; return await _dimClient.CreateStatusList(dimAuth, dimBaseUrl, companyId.Value, cancellationToken).ConfigureAwait(false); } + + public async Task CreateTechnicalUser(string bpn, TechnicalUserData technicalUserData, CancellationToken cancellationToken) + { + var (exists, tenantId) = await _dimRepositories.GetInstance().GetTenantForBpn(bpn).ConfigureAwait(false); + + if (!exists) + { + throw NotFoundException.Create(DimErrors.NO_COMPANY_FOR_BPN, new ErrorParameter[] { new("bpn", bpn) }); + } + + var processStepRepository = _dimRepositories.GetInstance(); + var processId = processStepRepository.CreateProcess(ProcessTypeId.CREATE_TECHNICAL_USER).Id; + processStepRepository.CreateProcessStep(ProcessStepTypeId.CREATE_TECHNICAL_USER, ProcessStepStatusId.TODO, processId); + + _dimRepositories.GetInstance().CreateTenantTechnicalUser(tenantId, technicalUserData.Name, technicalUserData.ExternalId, processId); + + await _dimRepositories.SaveAsync().ConfigureAwait(false); + } } diff --git a/src/web/Dim.Web/BusinessLogic/IDimBusinessLogic.cs b/src/web/Dim.Web/BusinessLogic/IDimBusinessLogic.cs index 757dce5..b01feab 100644 --- a/src/web/Dim.Web/BusinessLogic/IDimBusinessLogic.cs +++ b/src/web/Dim.Web/BusinessLogic/IDimBusinessLogic.cs @@ -17,6 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Dim.Web.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.DependencyInjection; namespace Dim.Web.BusinessLogic; @@ -26,4 +27,5 @@ public interface IDimBusinessLogic : ITransient Task StartSetupDim(string companyName, string bpn, string didDocumentLocation, bool isIssuer); Task GetStatusList(string bpn, CancellationToken cancellationToken); Task CreateStatusList(string bpn, CancellationToken cancellationToken); + Task CreateTechnicalUser(string bpn, TechnicalUserData technicalUserData, CancellationToken cancellationToken); } diff --git a/src/web/Dim.Web/Controllers/DimController.cs b/src/web/Dim.Web/Controllers/DimController.cs index f90b739..cd2d52c 100644 --- a/src/web/Dim.Web/Controllers/DimController.cs +++ b/src/web/Dim.Web/Controllers/DimController.cs @@ -65,6 +65,13 @@ public static RouteGroupBuilder MapDimApi(this RouteGroupBuilder group) .RequireAuthorization(r => r.RequireRole("create_status_list")) .Produces(StatusCodes.Status200OK, responseType: typeof(string), contentType: Constants.JsonContentType); + policyHub.MapPost("technical-user/{bpn}", ([FromRoute] string bpn, [FromBody] TechnicalUserData technicalUserData, CancellationToken cancellationToken, [FromServices] IDimBusinessLogic dimBusinessLogic) => dimBusinessLogic.CreateTechnicalUser(bpn, technicalUserData, cancellationToken)) + .WithSwaggerDescription("Creates a technical user for the dim of the given bpn", + "Example: Post: api/dim/technical-user/{bpn}", + "bpn of the company") + .RequireAuthorization(r => r.RequireRole("create_technical_user")) + .Produces(StatusCodes.Status200OK, contentType: Constants.JsonContentType); + return group; } } diff --git a/src/web/Dim.Web/Models/TechnicalUserData.cs b/src/web/Dim.Web/Models/TechnicalUserData.cs new file mode 100644 index 0000000..aa58199 --- /dev/null +++ b/src/web/Dim.Web/Models/TechnicalUserData.cs @@ -0,0 +1,6 @@ +namespace Dim.Web.Models; + +public record TechnicalUserData( + Guid ExternalId, + string Name +); diff --git a/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs b/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs index 703c219..4de8e14 100644 --- a/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs +++ b/tests/processes/DimProcess.Library.Tests/DimProcessHandlerTests.cs @@ -630,7 +630,7 @@ public async Task CreateServiceInstanceBindings_WithValidData_ReturnsExpected() var result = await _sut.CreateServiceInstanceBindings(_tenantName, _tenantId, CancellationToken.None); // Assert - A.CallTo(() => _cfClient.CreateServiceInstanceBindings(_tenantName, spaceId, A._)) + A.CallTo(() => _cfClient.CreateServiceInstanceBindings(_tenantName, null, spaceId, A._)) .MustHaveHappenedOnceExactly(); result.modified.Should().BeFalse();