diff --git a/LICENSE b/LICENSE index 7a43217e1..aa299662b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Amido +Copyright (c) 2024 Ensono Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 75fdbcd12..272161b8d 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,23 @@ -The full documentation on Amido Stacks can be found [here](https://amido.github.io/stacks/). +The full documentation on Ensono Stacks can be found [here](https://stacks.ensono.com/). ## Using the repository to build the Java Spring Boot Rest API application ### Customised solution -To customise the namespaces and create an application for your company please visit the full [documentation](https://stacks.amido.com/docs/) +To customise the namespaces and create an application for your company please visit the full [documentation](https://stacks.ensono.com/docs) ### Running the application locally 1. Clone one of the Java projects to your local machine from one of the following repos: --- - 1. Simple web API: [stacks-java repository](https://github.com/amido/stacks-java) - 2. Web API with CQRS: [stacks-java-cqrs repository](https://github.com/amido/stacks-java-cqrs) - 3. Web API with CQRS and events: [stacks-java-cqrs-events repository](https://github.com/amido/stacks-java-cqrs-events) + 1. Simple web API: [stacks-java repository](https://github.com/Ensono/stacks-java) + 2. Web API with CQRS: [stacks-java-cqrs repository](https://github.com/Ensono/stacks-java-cqrs) + 3. Web API with CQRS and events: [stacks-java-cqrs-events repository](https://github.com/Ensono/stacks-java-cqrs-events) 2. Build and run the application --- - Note that at a minimum [Java 11](https://adoptopenjdk.net/) should be installed. + Note that at a minimum [Java 17](https://adoptopenjdk.net/) should be installed. Move to the `/java` folder, then @@ -61,8 +61,8 @@ If using Auth0 for authorization, Auth0 itself will need to be configured with b There are corresponding configuration values required for the Stacks application, within the `auth.properties` file, e.g. ```text -auth0.issuer=https://amidostacks.eu.auth0.com/ -auth0.apiAudience=https://amidostacks.eu.auth0.com/api/v2/ +auth0.issuer=https://ensonostacks.eu.auth0.com/ +auth0.apiAudience=https://ensonostacks.eu.auth0.com/api/v2/ ``` These parameters are used to verify that the JWT supplied in the Authorization header of a request is valid. diff --git a/api-tests-karate/.mvn/jvm.config b/api-tests-karate/.mvn/jvm.config new file mode 100644 index 000000000..79d6be10d --- /dev/null +++ b/api-tests-karate/.mvn/jvm.config @@ -0,0 +1,11 @@ +--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED +--add-opens=java.base/java.util=ALL-UNNAMED +--add-opens=java.base/java.lang=ALL-UNNAMED +--add-opens=java.base/java.lang.invoke=ALL-UNNAMED +--add-opens java.base/java.lang.reflect=ALL-UNNAMED +--add-opens java.base/java.text=ALL-UNNAMED +--add-opens java.desktop/java.awt.font=ALL-UNNAMED diff --git a/api-tests-karate/pom.xml b/api-tests-karate/pom.xml index 367e5790b..c36536995 100644 --- a/api-tests-karate/pom.xml +++ b/api-tests-karate/pom.xml @@ -9,24 +9,21 @@ UTF-8 - 11 - 3.8.1 - 0.9.6 + 17 + + 3.1.2 + 3.11.0 + 1.4.1 5.5.3 3.1.2 8.44 4.2.3 4.5.2 + 10.0.3 3.0.0 - - com.intuit.karate - karate-apache - ${karate.version} - test - com.intuit.karate karate-junit5 @@ -75,6 +72,25 @@ + + owasp-dependency-check + + + + org.owasp + dependency-check-maven + ${owasp-dependency-check-plugin.version} + + + + check + + + + + + + @@ -93,11 +109,10 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven.compiler.version} + ${maven-compiler-plugin.version} UTF-8 - ${java.version} - ${java.version} + ${java.version} @@ -129,7 +144,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.22.2 + ${maven-surefire-plugin.version} com.github.spotbugs diff --git a/api-tests/.mvn/jvm.config b/api-tests/.mvn/jvm.config new file mode 100644 index 000000000..79d6be10d --- /dev/null +++ b/api-tests/.mvn/jvm.config @@ -0,0 +1,11 @@ +--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED +--add-opens=java.base/java.util=ALL-UNNAMED +--add-opens=java.base/java.lang=ALL-UNNAMED +--add-opens=java.base/java.lang.invoke=ALL-UNNAMED +--add-opens java.base/java.lang.reflect=ALL-UNNAMED +--add-opens java.base/java.text=ALL-UNNAMED +--add-opens java.desktop/java.awt.font=ALL-UNNAMED diff --git a/api-tests/pom.xml b/api-tests/pom.xml index a83439f0a..affc57feb 100644 --- a/api-tests/pom.xml +++ b/api-tests/pom.xml @@ -20,6 +20,7 @@ 4 2.12.3 + 17 @@ -48,12 +49,12 @@ 4.2.3 - 6.5.0 + 10.0.3 2.13 3.1.2 3.0.0-M5 3.0.0-M5 - 3.8.1 + 3.11.0 4.3.2 3.15.0 3.0.5 @@ -427,8 +428,8 @@ maven-compiler-plugin ${maven-compiler-plugin.version} - 11 - 11 + UTF-8 + ${java.version} diff --git a/build/azDevOps/azure/azure-pipelines-javaspring-k8s.yml b/build/azDevOps/azure/azure-pipelines-javaspring-k8s.yml index 245d536fa..64c9a05de 100644 --- a/build/azDevOps/azure/azure-pipelines-javaspring-k8s.yml +++ b/build/azDevOps/azure/azure-pipelines-javaspring-k8s.yml @@ -24,23 +24,23 @@ resources: repositories: - repository: templates type: github - name: amido/stacks-pipeline-templates + name: Ensono/stacks-pipeline-templates ref: feature/cycle4 # EXCHANGE THIS FOR YOUR OWN ENDPOINT CONNECTION TO GITHUB # REPOSITORY IS PUBLIC - endpoint: amidostacks + endpoint: ensonostacks containers: # Container for Java Build and Testing - container: azul_java - image: azul/zulu-openjdk-debian:11 + image: amidostacks/runner-pwsh-java:0.4.48-stable # Container for inlining Jacoco assets as Azure DevOps strips them # https://github.com/microsoft/azure-pipelines-tasks/issues/3027 - container: node image: amidostacks/node-14:0.0.1 # Container for Sonar Scanner - container: sonar_scanner - image: amidostacks/ci-sonarscanner:0.0.2 + image: amidostacks/runner-pwsh-dotnet:0.4.51-stable # Container for Kubernetes Deployment - container: k8s_deploy image: amidostacks/ci-k8s:0.0.12 @@ -89,7 +89,7 @@ variables: - name: version_minor value: 0 - name: version_patch - value: 0 + value: 1 - name: version_number value: $(version_major).$(version_minor).$(version_patch) @@ -112,9 +112,9 @@ variables: value: "azul_java" - name: k8s_docker_registry_nonprod - value: "${{ variables.docker_container_registry_name_nonprod }}.azurecr.io" + value: "$(DOCKER_CONTAINER_REGISTRY_NAME)" - name: k8s_docker_registry_prod - value: "${{ variables.docker_container_registry_name_prod }}.azurecr.io" + value: "$(DOCKER_CONTAINER_REGISTRY_NAME)" # BUILD ARTIFACTS across stages - name: build_artifact_deploy_path @@ -147,8 +147,12 @@ variables: value: true - name: vulnerability_scan_report value: "target/dependency-check-report.html" + - name: vulnerability_scan_api_key + value: "$(VULNERABILITY_SCAN_API_KEY)" - name: vulnerability_scan_fail_build_on_detection value: false + - name: vulnerability_scan_database_directory + value: ${{ variables.self_repo_dir }}/.vulnerability-database # Yamllint - name: yamllint_config_file @@ -178,15 +182,18 @@ stages: - stage: Build variables: # You can find notes in the READMEs around which values to use for each ENV variable group - - group: amido-stacks-infra-credentials-nonprod + - group: azure-sp-creds + - group: stacks-acr-creds + - group: stacks-infra-credentials-nonprod - group: stacks-credentials-nonprod-kv - - group: amido-stacks-java-api + - group: stacks-java-api jobs: - job: ApiBuild pool: vmImage: $(pool_vm_image) steps: - checkout: self + fetchDepth: 0 - checkout: templates @@ -203,7 +210,7 @@ stages: yamllint_config_file: "${{ variables.yamllint_config_file }}" yamllint_scan_directory: "${{ variables.yamllint_scan_directory }}" - # Runs a terraform fomatting check and a validation check + # Runs a terraform formatting check and a validation check - template: templates/steps/build/test-validate-terraform.yml parameters: pipeline_scripts_directory: "${{ variables.self_pipeline_scripts_dir }}" @@ -224,7 +231,9 @@ stages: docker_build_container: "${{ variables.docker_java_image }}" # Vulnerability Scanning vulnerability_scan: "${{ variables.vulnerability_scan }}" + vulnerability_scan_api_key: "${{ variables.vulnerability_scan_api_key }}" vulnerability_scan_fail_build_on_detection: "${{ variables.vulnerability_scan_fail_build_on_detection }}" + vulnerability_scan_database_directory: "${{ variables.vulnerability_scan_database_directory }}" project_type: "${{ variables.java_project_type }}" # Builds the Java API Tests @@ -245,10 +254,12 @@ stages: docker_build_container: "${{ variables.docker_java_image }}" # Vulnerability Scan vulnerability_scan: "${{ variables.vulnerability_scan }}" + vulnerability_scan_api_key: "${{ variables.vulnerability_scan_api_key }}" vulnerability_scan_fail_build_on_detection: "${{ variables.vulnerability_scan_fail_build_on_detection }}" + vulnerability_scan_database_directory: "${{ variables.vulnerability_scan_database_directory }}" project_type: "${{ variables.functional_test_project_type }}" - # Performs stati code analysis, such as Sonar Cloud + # Performs static code analysis, such as Sonar Cloud - template: templates/steps/build/test-static-code-analysis.yml parameters: project_root_dir: "${{ variables.self_project_dir }}" @@ -259,6 +270,7 @@ stages: pullrequest_number: "$(pullrequest_number)" # Sonar sonar_enable: true + # Set to false to speed up validation of deploy stage, revert once done sonar_container: "sonar_scanner" sonar_host_url: "https://sonarcloud.io" sonar_project_name: "$(SONAR_PROJECT_NAME)" @@ -281,12 +293,12 @@ stages: docker_build_additional_args: "." docker_image_name: "${{ variables.docker_image_name }}" docker_image_tag: "${{ variables.docker_image_tag }}" - docker_container_registry_name: "${{ variables.docker_container_registry_name_nonprod }}" + docker_container_registry_name: "$(DOCKER_USERNAME)" # Azure - azure_client_id: "$(azure-client-id)" - azure_client_secret: "$(azure-client-secret)" - azure_tenant_id: "$(azure-tenant-id)" - azure_subscription_id: "$(azure-subscription-id)" + azure_client_id: "$(ARM_CLIENT_ID)" + azure_client_secret: "$(ARM_CLIENT_SECRET)" + azure_tenant_id: "$(ARM_TENANT_ID)" + azure_subscription_id: "$(ARM_SUBSCRIPTION_ID)" # Post build tasks, such as Test and Coverage upload, and publishing artefacts - template: templates/steps/build/post-build-tasks.yml @@ -307,19 +319,32 @@ stages: java_project_type: "${{ variables.java_project_type }}" functional_test_project_type: "${{ variables.functional_test_project_type }}" + - task: Bash@3 + inputs: + targetType: "inline" + script: | + echo "Setting variable 'BUILD_ATTEMPT_NUMBER' with value '$(System.JobAttempt)'" + echo "##vso[task.setvariable variable=BUILD_ATTEMPT_NUMBER;isOutput=true]$(System.JobAttempt)" + name: build_attempt_number + displayName: "Output: Set Job Attempt Output Variable" + - stage: Dev dependsOn: Build condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master')) variables: - - group: amido-stacks-infra-credentials-nonprod + - group: azure-sp-creds + - group: stacks-acr-creds + - group: stacks-infra-credentials-nonprod - group: stacks-credentials-nonprod-kv - - group: amido-stacks-java-api + - group: stacks-java-api - name: dns_name value: "$(Environment.ShortName)-java-api" - name: core_resource_group value: $(tf_core_resource_group_nonprod) - name: Environment.ShortName value: dev + - name: BUILD_ATTEMPT_NUMBER + value: "$[ stageDependencies.Build.ApiBuild.outputs['build_attempt_number.BUILD_ATTEMPT_NUMBER'] ]" jobs: - deployment: AppInfraDev container: terraform_custom @@ -357,6 +382,8 @@ stages: runOnce: deploy: steps: + - download: none + - checkout: self - checkout: templates @@ -365,20 +392,20 @@ stages: parameters: pipeline_scripts_directory: "${{ variables.self_pipeline_scripts_dir }}" docker_terraform_container: "terraform_custom" - # Azure Credenitals (For Deploying) - azure_client_id: "$(azure-client-id)" - azure_client_secret: "$(azure-client-secret)" - azure_tenant_id: "$(azure-tenant-id)" - azure_subscription_id: "$(azure-subscription-id)" + # Azure Credentials (For Deploying) + azure_client_id: "$(ARM_CLIENT_ID)" + azure_client_secret: "$(ARM_CLIENT_SECRET)" + azure_tenant_id: "$(ARM_TENANT_ID)" + azure_subscription_id: "$(ARM_SUBSCRIPTION_ID)" # Terraform terraform_directory: '$(self_repo_tf_dir)' # Backend Azure State Storage Credentials # Change these if your state storage is in a different # location to your deployment - terraform_backend_azure_client_id: "$(azure-client-id)" - terraform_backend_azure_client_secret: "$(azure-client-secret)" - terraform_backend_azure_tenant_id: "$(azure-tenant-id)" - terraform_backend_azure_subscription_id: "$(azure-subscription-id)" + terraform_backend_azure_client_id: "$(ARM_CLIENT_ID)" + terraform_backend_azure_client_secret: "$(ARM_CLIENT_SECRET)" + terraform_backend_azure_tenant_id: "$(ARM_TENANT_ID)" + terraform_backend_azure_subscription_id: "$(ARM_SUBSCRIPTION_ID)" terraform_state_rg: ${{ variables.tf_state_rg }} terraform_state_storage: ${{ variables.tf_state_storage }} terraform_state_container: ${{ variables.tf_state_container }} @@ -452,6 +479,8 @@ stages: runOnce: deploy: steps: + - download: none + - checkout: self - checkout: templates @@ -493,10 +522,10 @@ stages: additional_args: "-no-empty", }, ] - azure_client_id: "$(azure-client-id)" - azure_client_secret: "$(azure-client-secret)" - azure_tenant_id: "$(azure-tenant-id)" - azure_subscription_id: "$(azure-subscription-id)" + azure_client_id: "$(ARM_CLIENT_ID)" + azure_client_secret: "$(ARM_CLIENT_SECRET)" + azure_tenant_id: "$(ARM_TENANT_ID)" + azure_subscription_id: "$(ARM_SUBSCRIPTION_ID)" aks_cluster_resourcegroup: "${{ variables.aks_cluster_resourcegroup }}" aks_cluster_name: "${{ variables.aks_cluster_name }}" # Used to do a `kubectl rollout status` @@ -534,15 +563,19 @@ stages: dependsOn: Build condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) variables: - - group: amido-stacks-infra-credentials-prod + - group: azure-sp-creds + - group: stacks-acr-creds + - group: stacks-infra-credentials-prod - group: stacks-credentials-prod-kv - - group: amido-stacks-java-api + - group: stacks-java-api - name: dns_name value: "$(Environment.ShortName)-java-api" - name: core_resource_group value: $(tf_core_resource_group_prod) - name: Environment.ShortName value: prod + - name: BUILD_ATTEMPT_NUMBER + value: "$[ stageDependencies.Build.ApiBuild.outputs['build_attempt_number.BUILD_ATTEMPT_NUMBER'] ]" jobs: - deployment: AppInfraProd container: terraform_custom @@ -647,8 +680,8 @@ stages: vmImage: $(pool_vm_image) environment: ${{ variables.domain }}-prod variables: - - group: amido-stacks-infra-credentials-nonprod - - group: amido-stacks-infra-credentials-prod + - group: stacks-infra-credentials-nonprod + - group: stacks-infra-credentials-prod - group: stacks-credentials-prod-kv - group: stacks-credentials-nonprod-kv strategy: @@ -665,10 +698,10 @@ stages: arguments: > -a "$(docker_image_name):$(docker_image_tag)" -b "$(k8s_docker_registry_nonprod)" - -c "$(azure-subscription-id)" - -d "$(azure-client-id)" - -e "$(azure-client-secret)" - -f "$(azure-tenant-id)" + -c "$(ARM_SUBSCRIPTION_ID)" + -d "$(ARM_CLIENT_ID)" + -e "$(ARM_CLIENT_SECRET)" + -f "$(ARM_TENANT_ID)" -g "$(k8s_docker_registry_prod)" -h "$(prod-azure-subscription-id)" -i "$(prod-azure-client-id)" @@ -797,7 +830,7 @@ stages: - Prod condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['create_release'], 'true')) variables: - - group: amido-stacks-infra-credentials-nonprod + - group: stacks-infra-credentials-nonprod jobs: - job: CreateGitHubRelease pool: diff --git a/build/azDevOps/azure/azuredevops-vars.yml b/build/azDevOps/azure/azuredevops-vars.yml index e9c6c80ba..bd1066758 100644 --- a/build/azDevOps/azure/azuredevops-vars.yml +++ b/build/azDevOps/azure/azuredevops-vars.yml @@ -2,7 +2,7 @@ variables: - name: region value: westeurope - name: company - value: amido + value: ensono - name: project value: stacks - name: domain @@ -24,9 +24,9 @@ variables: # avoid running anything past dev that is not on master # sample value: company-webapp - name: tf_state_rg - value: Stacks-Ancillary-Resources + value: stacks-terraform-state - name: tf_state_storage - value: amidostackstfstate + value: stacksstatehjfis - name: tf_state_container value: tfstate - name: tf_state_key @@ -35,54 +35,54 @@ variables: # TF Variables # --nonprod - name: tf_app_insights_name_nonprod - value: amido-stacks-nonprod-euw-core + value: ed-stacks-nonprod-euw-core - name: tf_app_gateway_frontend_ip_name_nonprod - value: amido-stacks-nonprod-euw-core + value: ed-stacks-nonprod-euw-core - name: tf_core_resource_group_nonprod - value: amido-stacks-nonprod-euw-core + value: ed-stacks-nonprod-euw-core # --prod - name: tf_app_insights_name_prod - value: amido-stacks-prod-euw-core + value: ed-stacks-prod-euw-core - name: tf_app_gateway_frontend_ip_name_prod - value: amido-stacks-prod-euw-core + value: ed-stacks-prod-euw-core - name: tf_core_resource_group_prod - value: amido-stacks-prod-euw-core + value: ed-stacks-prod-euw-core # Kubernetes configuration # --nonprod - name: kubernetes_clustername_nonprod - value: amido-stacks-nonprod-euw-core + value: ed-stacks-nonprod-euw-core # --prod - name: kubernetes_clustername_prod - value: amido-stacks-prod-euw-core + value: ed-stacks-prod-euw-core # Container registry configuration - name: docker_container_registry_name_nonprod - value: amidostacksnonprodeuwcore + value: ensonostackseuweirdfmu - name: docker_container_registry_name_prod value: amidostacksprodeuwcore # Domain names - name: base_domain_nonprod - value: nonprod.amidostacks.com + value: nonprod.stacks.ensono.com - name: base_domain_internal_nonprod - value: nonprod.amidostacks.internal + value: nonprod.stacks.ensono.internal - name: base_domain_prod - value: prod.amidostacks.com + value: prod.stacks.ensono.com - name: base_domain_internal_prod - value: prod.amidostacks.internal + value: prod.stacks.ensono.internal # Environment # Set the name of the resource group that has the DNS zones to be updated - name: dns_zone_resource_group - value: "Stacks-Ancillary-Resources" + value: "stacks-ancillary-resources" - # GitHub infomration + # GitHub information - name: create_release value: true - name: github_release_service_connection - value: GitHubReleases + value: ensonostacks - name: github_org value: $(company) diff --git a/build/azDevOps/azure/templates/steps/build/build-api-tests-cli.yml b/build/azDevOps/azure/templates/steps/build/build-api-tests-cli.yml index e2bfacce0..a61674531 100644 --- a/build/azDevOps/azure/templates/steps/build/build-api-tests-cli.yml +++ b/build/azDevOps/azure/templates/steps/build/build-api-tests-cli.yml @@ -15,7 +15,9 @@ parameters: docker_build_container: "" # Vulnerability Scanning vulnerability_scan: true + vulnerability_scan_api_key: "$(VULNERABILITY_SCAN_API_KEY)" vulnerability_scan_fail_build_on_detection: true + vulnerability_scan_database_directory: "" project_type: "" steps: @@ -73,6 +75,8 @@ steps: inputs: filePath: "${{ parameters.pipeline_scripts_directory }}/test-maven-owasp-dependency-check.bash" arguments: > + -W "${{ parameters.vulnerability_scan_database_directory }}" + -X "${{ parameters.vulnerability_scan_api_key }}" -Y "${{ parameters.vulnerability_scan_fail_build_on_detection }}" -Z "${{ parameters.maven_cache_directory }}" workingDirectory: "${{ parameters.functional_test_project_root_dir }}" diff --git a/build/azDevOps/azure/templates/steps/build/build-api-tests.yml b/build/azDevOps/azure/templates/steps/build/build-api-tests.yml index 0d54eadf9..e4b54ba6f 100644 --- a/build/azDevOps/azure/templates/steps/build/build-api-tests.yml +++ b/build/azDevOps/azure/templates/steps/build/build-api-tests.yml @@ -15,7 +15,9 @@ parameters: docker_build_container: "" # Vulnerability Scanning vulnerability_scan: true + vulnerability_scan_api_key: "$(VULNERABILITY_SCAN_API_KEY)" vulnerability_scan_fail_build_on_detection: true + vulnerability_scan_database_directory: "" project_type: "" steps: @@ -37,7 +39,9 @@ steps: docker_build_container: "${{ parameters.docker_build_container }}" # Vulnerability Scan vulnerability_scan: "${{ parameters.vulnerability_scan }}" + vulnerability_scan_api_key: "${{ parameters.vulnerability_scan_api_key }}" vulnerability_scan_fail_build_on_detection: "${{ parameters.vulnerability_scan_fail_build_on_detection }}" + vulnerability_scan_database_directory: "${{ parameters.vulnerability_scan_database_directory }}" project_type: "${{ parameters.project_type }}" - template: ./build-api-tests-cli.yml @@ -57,5 +61,7 @@ steps: docker_build_container: "${{ parameters.docker_build_container }}" # Vulnerability Scan vulnerability_scan: "${{ parameters.vulnerability_scan }}" + vulnerability_scan_api_key: "${{ parameters.vulnerability_scan_api_key }}" vulnerability_scan_fail_build_on_detection: "${{ parameters.vulnerability_scan_fail_build_on_detection }}" + vulnerability_scan_database_directory: "${{ parameters.vulnerability_scan_database_directory }}" project_type: "${{ parameters.project_type }}" diff --git a/build/azDevOps/azure/templates/steps/build/build-java.yml b/build/azDevOps/azure/templates/steps/build/build-java.yml index 9bc5daaab..d1ec3a35f 100644 --- a/build/azDevOps/azure/templates/steps/build/build-java.yml +++ b/build/azDevOps/azure/templates/steps/build/build-java.yml @@ -10,7 +10,9 @@ parameters: docker_build_container: "" # Vulnerability Scanning vulnerability_scan: true + vulnerability_scan_api_key: "$(VULNERABILITY_SCAN_API_KEY)" vulnerability_scan_fail_build_on_detection: true + vulnerability_scan_database_directory: "" project_type: "" steps: @@ -23,6 +25,38 @@ steps: path: "${{ parameters.project_root_dir }}/${{ parameters.maven_cache_directory }}" displayName: Cache Maven packages (${{ parameters.project_type }}) + - ${{ if eq(parameters.vulnerability_scan, true) }}: + - task: Bash@3 + inputs: + targetType: "inline" + script: | + DATE="$(date "+%F")" + HOUR="$(date "+%H")" + + # NVD Cache lasts 4 hours (240 mins) and so cache based on the hour's time + # in 24 hours. E.g. 0-3 are 0, 1-4 are 1, 20-23 are 5 etc.. This gives a + # cache that lasts roughly 4 hours at a time. + HOUR_BY_FOUR="$(( ${HOUR} / 4 ))" + + NVD_CACHE_FILE="${DATE}-${HOUR_BY_FOUR}" + + echo "echoing to a file '${{ parameters.repo_root_dir }}/.nvd-cache-day' with value '${DATE}'" + echo "echoing to a file '${{ parameters.repo_root_dir }}/.nvd-cache-full' with value '${NVD_CACHE_FILE}'" + + # Partial (slow) download lasts 24 hours + echo "${DATE}" > ${{ parameters.repo_root_dir }}/.nvd-cache-day + # Full Cache is 4 hours, so use the by four computed variable + echo "${NVD_CACHE_FILE}" > ${{ parameters.repo_root_dir }}/.nvd-cache-full + displayName: Set NVD Cache Variable + + - task: Cache@2 + inputs: + key: '${{ parameters.repo_root_dir }}/.nvd-cache-day | ${{ parameters.repo_root_dir }}/.nvd-cache-full' + restoreKeys: | + ${{ parameters.repo_root_dir }}/.nvd-cache-day + path: "${{ parameters.vulnerability_scan_database_directory }}" + displayName: Cache NVD Datatbase + - task: Bash@3 inputs: filePath: "${{ parameters.pipeline_scripts_directory }}/build-maven-install.bash" @@ -68,6 +102,8 @@ steps: inputs: filePath: "${{ parameters.pipeline_scripts_directory }}/test-maven-owasp-dependency-check.bash" arguments: > + -W "${{ parameters.vulnerability_scan_database_directory }}" + -X "${{ parameters.vulnerability_scan_api_key }}" -Y "${{ parameters.vulnerability_scan_fail_build_on_detection }}" -Z "${{ parameters.maven_cache_directory }}" workingDirectory: "${{ parameters.project_root_dir }}" @@ -146,7 +182,7 @@ steps: - bash: | set -euxo pipefail cp "${{ parameters.repo_root_dir }}/build/azDevOps/azure/coverage/"* . - npm i + npm ci ./node_modules/.bin/gulp inline-css-images ./node_modules/.bin/gulp inline-sources workingDirectory: "${{ parameters.project_root_dir }}/target/site/" diff --git a/build/azDevOps/azure/templates/steps/build/post-build-tasks-cli.yml b/build/azDevOps/azure/templates/steps/build/post-build-tasks-cli.yml index 407107dca..42115e017 100644 --- a/build/azDevOps/azure/templates/steps/build/post-build-tasks-cli.yml +++ b/build/azDevOps/azure/templates/steps/build/post-build-tasks-cli.yml @@ -31,21 +31,21 @@ steps: condition: always() inputs: path: "${{ parameters.project_root_dir }}/${{ parameters.vulnerability_scan_report }}" - artifact: "owasp-vulnerability-report-java" + artifact: "owasp-vulnerability-report-java-$(System.JobAttempt)" displayName: "Publish: Vulnerability Scan Report Artefact (${{ parameters.java_project_type }})" - task: PublishPipelineArtifact@1 condition: always() inputs: path: "${{ parameters.functional_test_project_root_dir }}/${{ parameters.vulnerability_scan_report }}" - artifact: "owasp-vulnerability-report-functional-test" + artifact: "owasp-vulnerability-report-functional-test-$(System.JobAttempt)" displayName: "Publish: Vulnerability Scan Report Artefact (${{ parameters.functional_test_project_type }})" # Publish Artefacts if required - ${{ if eq(parameters.functional_test, true) }}: - task: PublishPipelineArtifact@1 inputs: - path: "${{ parameters.functional_test_artefact_path }}" + path: "${{ parameters.functional_test_artefact_path }}-$(System.JobAttempt)" artifact: "${{ parameters.functional_test_artefact_name }}" displayName: "Publish: Functional Tests Artefact" @@ -53,5 +53,5 @@ steps: - task: PublishPipelineArtifact@1 inputs: path: "${{ parameters.build_file_path }}" - artifact: "${{ parameters.build_file_artefact_name }}" + artifact: "${{ parameters.build_file_artefact_name }}-$(System.JobAttempt)" displayName: "Publish: Build Artefacts" diff --git a/build/azDevOps/azure/templates/steps/build/post-build-tasks.yml b/build/azDevOps/azure/templates/steps/build/post-build-tasks.yml index c0c13e4a0..6fa4192a3 100644 --- a/build/azDevOps/azure/templates/steps/build/post-build-tasks.yml +++ b/build/azDevOps/azure/templates/steps/build/post-build-tasks.yml @@ -31,21 +31,21 @@ steps: condition: always() inputs: path: "${{ parameters.project_root_dir }}/${{ parameters.vulnerability_scan_report }}" - artifact: "owasp-vulnerability-report-java" + artifact: "owasp-vulnerability-report-java-$(System.JobAttempt)" displayName: "Publish: Vulnerability Scan Report Artefact (${{ parameters.java_project_type }})" - task: PublishPipelineArtifact@1 condition: always() inputs: path: "${{ parameters.functional_test_project_root_dir }}/${{ parameters.vulnerability_scan_report }}" - artifact: "owasp-vulnerability-report-functional-test" + artifact: "owasp-vulnerability-report-functional-test-$(System.JobAttempt)" displayName: "Publish: Vulnerability Scan Report Artefact (${{ parameters.functional_test_project_type }})" - task: PublishPipelineArtifact@1 condition: always() inputs: path: "${{ parameters.functional_test_project_root_dir }}-karate/${{ parameters.vulnerability_scan_report }}" - artifact: "owasp-vulnerability-report-functional-test-karate" + artifact: "owasp-vulnerability-report-functional-test-karate-$(System.JobAttempt)" displayName: "Publish: Vulnerability Scan Report Artefact (${{ parameters.functional_test_project_type }})" # Publish Artefacts if required @@ -53,18 +53,18 @@ steps: - task: PublishPipelineArtifact@1 inputs: path: "${{ parameters.functional_test_artefact_path }}" - artifact: "${{ parameters.functional_test_artefact_name }}" + artifact: "${{ parameters.functional_test_artefact_name }}-$(System.JobAttempt)" displayName: "Publish: Functional Tests Artefact" - task: PublishPipelineArtifact@1 inputs: path: "${{ parameters.functional_test_artefact_path }}-karate" - artifact: "${{ parameters.functional_test_artefact_name }}-karate" + artifact: "${{ parameters.functional_test_artefact_name }}-karate-$(System.JobAttempt)" displayName: "Publish: Functional Tests Artefact" - ${{ if eq(parameters.build_file, true) }}: - task: PublishPipelineArtifact@1 inputs: path: "${{ parameters.build_file_path }}" - artifact: "${{ parameters.build_file_artefact_name }}" + artifact: "${{ parameters.build_file_artefact_name }}-$(System.JobAttempt)" displayName: "Publish: Build Artefacts" diff --git a/build/azDevOps/azure/templates/steps/deploy/deploy-post-deploy-tests-karate.yml b/build/azDevOps/azure/templates/steps/deploy/deploy-post-deploy-tests-karate.yml index 6fcdeed92..b87383548 100644 --- a/build/azDevOps/azure/templates/steps/deploy/deploy-post-deploy-tests-karate.yml +++ b/build/azDevOps/azure/templates/steps/deploy/deploy-post-deploy-tests-karate.yml @@ -13,8 +13,12 @@ parameters: auth0_credentials: {} steps: - ${{ if eq(parameters.functional_test, true) }}: - - download: current - artifact: "${{ parameters.functional_test_artefact_name }}" + # $(BUILD_ATTEMPT_NUMBER) comes from the Stage Variables and is an output from the ApiBuild job + - task: DownloadPipelineArtifact@2 + inputs: + buildType: 'current' + artifact: "${{ parameters.functional_test_artefact_name }}-$(BUILD_ATTEMPT_NUMBER)" + targetPath: ${{ parameters.functional_test_artefact_download_location }} displayName: "Download: Post-Deploy Test Artefacts" # Files downloaded from artefacts seem to lose their permissions... diff --git a/build/azDevOps/azure/templates/steps/deploy/deploy-post-deploy-tests-serenity.yml b/build/azDevOps/azure/templates/steps/deploy/deploy-post-deploy-tests-serenity.yml index 09ac9591a..cda6d0050 100644 --- a/build/azDevOps/azure/templates/steps/deploy/deploy-post-deploy-tests-serenity.yml +++ b/build/azDevOps/azure/templates/steps/deploy/deploy-post-deploy-tests-serenity.yml @@ -13,8 +13,12 @@ parameters: auth0_credentials: {} steps: - ${{ if eq(parameters.functional_test, true) }}: - - download: current - artifact: "${{ parameters.functional_test_artefact_name }}" + # $(BUILD_ATTEMPT_NUMBER) comes from the Stage Variables and is an output from the ApiBuild job + - task: DownloadPipelineArtifact@2 + inputs: + buildType: 'current' + artifact: "${{ parameters.functional_test_artefact_name }}-$(BUILD_ATTEMPT_NUMBER)" + targetPath: ${{ parameters.functional_test_artefact_download_location }} displayName: "Download: Post-Deploy Test Artefacts" # Files downloaded from artefacts seem to lose their permissions... diff --git a/build/jenkins/azure/jenkins-pipelines-javaspring-k8s.Jenkinsfile b/build/jenkins/azure/jenkins-pipelines-javaspring-k8s.Jenkinsfile index 01d53b4f8..ae3026321 100644 --- a/build/jenkins/azure/jenkins-pipelines-javaspring-k8s.Jenkinsfile +++ b/build/jenkins/azure/jenkins-pipelines-javaspring-k8s.Jenkinsfile @@ -117,7 +117,7 @@ pipeline { // e.g.: // args '-v /var/run/docker.sock:/var/run/docker.sock -u 1000:999' // Please check with your admin on any required steps you need to take to ensure a SUDOers access inside the containers - image "azul/zulu-openjdk-debian:11" + image "azul/zulu-openjdk-debian:17" } } @@ -215,7 +215,7 @@ pipeline { agent { docker { // add additional args if you need to here - image "azul/zulu-openjdk-debian:11" + image "azul/zulu-openjdk-debian:17" } } @@ -364,7 +364,7 @@ pipeline { agent { docker { // add additional args if you need to here - image "azul/zulu-openjdk-debian:11" + image "azul/zulu-openjdk-debian:17" } } @@ -866,7 +866,7 @@ pipeline { stage("PostDeployDev") { agent { docker { - image "azul/zulu-openjdk-debian:11" + image "azul/zulu-openjdk-debian:17" } } diff --git a/deploy/k8s/app/base_api-deploy.yml b/deploy/k8s/app/base_api-deploy.yml index 9599259c6..e7f809afc 100644 --- a/deploy/k8s/app/base_api-deploy.yml +++ b/deploy/k8s/app/base_api-deploy.yml @@ -9,7 +9,7 @@ metadata: --- -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: @@ -18,7 +18,6 @@ metadata: applicationId: ${project}/${app_name} applicationName: ${project}-${app_name} customerID: ${company} - kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/force-ssl-redirect: "false" nginx.ingress.kubernetes.io/rewrite-target: /$$2 nginx.ingress.kubernetes.io/ssl-redirect: "true" @@ -34,14 +33,18 @@ metadata: name: ${resource_def_name} namespace: ${namespace} spec: + ingressClassName: nginx rules: - host: ${dns_pointer} http: paths: - - backend: - serviceName: ${resource_def_name} - servicePort: 80 - path: ${k8s_app_path}(/|$)(.*) + - path: ${k8s_app_path}(/|$)(.*) + pathType: Prefix + backend: + service: + name: ${resource_def_name} + port: + number: 80 tls: - hosts: - ${tls_domain} diff --git a/java/.mvn/jvm.config b/java/.mvn/jvm.config new file mode 100644 index 000000000..79d6be10d --- /dev/null +++ b/java/.mvn/jvm.config @@ -0,0 +1,11 @@ +--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED +--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED +--add-opens=java.base/java.util=ALL-UNNAMED +--add-opens=java.base/java.lang=ALL-UNNAMED +--add-opens=java.base/java.lang.invoke=ALL-UNNAMED +--add-opens java.base/java.lang.reflect=ALL-UNNAMED +--add-opens java.base/java.text=ALL-UNNAMED +--add-opens java.desktop/java.awt.font=ALL-UNNAMED diff --git a/java/Dockerfile b/java/Dockerfile index 025d03033..3c76f2826 100644 --- a/java/Dockerfile +++ b/java/Dockerfile @@ -1,4 +1,4 @@ -FROM azul/zulu-openjdk-alpine:11 as build +FROM azul/zulu-openjdk-alpine:17.0.9 as build WORKDIR /workspace/app # Copy the m2 directory if it exists to re-use an external cache. @@ -13,12 +13,13 @@ COPY src src RUN ls -la /root/.m2/repository -RUN ./mvnw dependency:go-offline --quiet\ - && ./mvnw process-resources --quiet \ - && ./mvnw clean package -Dmaven.default-test.skip=true -Dmaven.test.skip=true -DskipTests --no-transfer-progress --quiet\ - && mkdir -p extracted && java -Djarmode=layertools -jar target/*.jar extract --destination extracted +RUN ./mvnw dependency:go-offline --quiet \ + && ./mvnw process-resources --quiet \ + && ./mvnw clean package -Dmaven.default-test.skip=true -Dmaven.test.skip=true -DskipTests --no-transfer-progress --quiet \ + && mkdir -p extracted && find target -maxdepth 1 -type f -name '*.jar' ! -name '*-javadoc.jar' ! -name '*-sources.jar' -exec java -Djarmode=layertools -jar {} extract --destination extracted \; -FROM azul/zulu-openjdk-alpine:11-jre + +FROM azul/zulu-openjdk-alpine:17-jre VOLUME /tmp diff --git a/java/pom.xml b/java/pom.xml index 95b1cc700..a8077569c 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -5,11 +5,9 @@ 4.0.0 - org.springframework.boot - spring-boot-starter-parent - 2.6.1 - - + com.amido.stacks.modules + stacks-modules-parent + 2.0.7-RELEASE com.amido.stacks.workloads @@ -20,53 +18,25 @@ Demo project for Java - 1.0.3.2-RELEASE - 1.0.3 + 1.0.5.11-RELEASE + 2.0.7 no-aws no-azure - 11 - 1.18.0 - 1.6.1 2.6.4 - 3.6.0 - 2.13.0 - 4.1.0 - 1.18.22 - 2.2 - 1.7.3 - 0.8.7 - 3.0.0-M5 - test - 5.8.2 - 3.8.1 - 3.8.1 - 6.5.0 - 1.4.1 - 1.0.11 - 1.2.8 - 2.4.7 - 1.81 - 4.0.10 - + 4.0.0 + 4.0.10 4.3.2 - 9.9 4.2.7 - 2.17.0 - 1.5.2.Final - 1.12.273 + 1.12.470 1.9.9.1 - - 2.13 - 3.1.2 - 9.2 - 4.2.3 - 4.5.2 3.0.0 - + 2022.0.4 3.5.24 + 3.3.1 + 10.0.3 @@ -79,11 +49,13 @@ + - io.projectreactor - reactor-bom - 2020.0.14 + org.springframework.cloud + spring-cloud-dependencies + ${spring.cloud.dependencies.version} pom + import @@ -111,54 +83,49 @@ org.springframework.boot - spring-boot-starter-actuator + spring-boot-properties-migrator + runtime - org.springframework.boot - spring-boot-starter-web + org.springframework.cloud + spring-cloud-starter-bootstrap - org.springdoc - springdoc-openapi-ui - ${org.springdoc-openapi.version} + org.springframework.cloud + spring-cloud-starter-config - org.springdoc - springdoc-openapi-data-rest - ${org.springdoc-openapi.version} + org.springframework.boot + spring-boot-starter-actuator - net.minidev - json-smart + org.yaml + snakeyaml - org.apache.logging.log4j - log4j-api - ${log4j-version} + org.springframework.boot + spring-boot-starter-web com.fasterxml.jackson.core jackson-core - ${jackson.version} com.fasterxml.jackson.core jackson-databind - ${jackson.version} com.fasterxml.jackson.core jackson-annotations - ${jackson.version} @@ -199,36 +166,20 @@ - - ch.qos.logback - logback-core - ${ch.qos.logback.logback-core.version} - - net.minidev json-smart - ${net.minidev.json-smart-version} com.beust jcommander - ${com.beust.jcommander-version} com.auth0 auth0-spring-security-api - ${auth0-spring-security-api.version} - - - - org.projectlombok - lombok - ${lombok.version} - provided @@ -251,41 +202,6 @@ - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} - test - - - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - - - - org.mockito - mockito-junit-jupiter - ${mockito.version} - test - - - - org.hamcrest - hamcrest - ${hamcrest.version} - test - - - - nl.jqno.equalsverifier - equalsverifier - ${equals-verifier.version} - test - - au.com.dius pact-jvm-provider-spring @@ -303,14 +219,12 @@ org.pitest pitest-parent - ${pitest.version} pom com.nimbusds oauth2-oidc-sdk - ${com.nimbusds.oauth2-oidc-sdk-version} runtime @@ -319,67 +233,36 @@ aws-java-sdk-s3 ${aws-java-sdk-s3.version} - - - - - - org.apache.maven.plugins - maven-surefire-report-plugin - ${maven-surefire-plugin.version} - - - + + jakarta.persistence + jakarta.persistence-api + + + org.springframework.data + spring-data-commons + ${spring.data.commons} + + + - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} - 11 - 11 - - - org.projectlombok - lombok - ${lombok.version} - - - - org.projectlombok - lombok-mapstruct-binding - 0.2.0 - - - - org.mapstruct - mapstruct-processor - ${org.mapstruct.version} - - - true + com.amido.stacks.workloads.Application - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - default-test - - ${maven-surefire-phase} + + repackage + - - org.springframework.boot - spring-boot-maven-plugin - org.jacoco jacoco-maven-plugin @@ -435,7 +318,6 @@ true - ${pact.api.name} @@ -444,16 +326,7 @@ ${pact.api.port} - - - - integration-test - - verify - - - com.coveo diff --git a/java/sonar-project.properties b/java/sonar-project.properties index f5691ee6a..7157d9950 100644 --- a/java/sonar-project.properties +++ b/java/sonar-project.properties @@ -3,7 +3,7 @@ # sonar.projectKey=${env.SONAR_PROJECT_KEY} # sonar.projectName=${env.SONAR_PROJECT_NAME} # sonar.projectVersion=${env.BUILD_NUMBER} -# sonar.login=${env.SONAR_TOKEN} +# sonar.token=${env.SONAR_TOKEN} # sonar.organization=${env.SONAR_ORGANIZATION} sonar.sourceEncoding=UTF-8 @@ -27,7 +27,7 @@ sonar.java.libraries=.m2 sonar.junit.reportPaths=target/surefire-reports sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml sonar.language=java -sonar.java.source=11 +sonar.java.source=17 sonar.cpd.exclusions=**/model/* sonar.coverage.exclusions=**/AuthControllerImpl*,**/ApplicationConfig* diff --git a/java/src/main/java/com/amido/stacks/workloads/ApplicationConfig.java b/java/src/main/java/com/amido/stacks/workloads/ApplicationConfig.java index 0b6d7d049..75dab57cb 100644 --- a/java/src/main/java/com/amido/stacks/workloads/ApplicationConfig.java +++ b/java/src/main/java/com/amido/stacks/workloads/ApplicationConfig.java @@ -1,26 +1,28 @@ package com.amido.stacks.workloads; -import com.auth0.spring.security.api.JwtWebSecurityConfigurer; import java.util.Arrays; +import java.util.List; import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; /** ApplicationConfig - Configuration class for Auth0 application security. */ -@Configuration("MySecurityConfig") +@Configuration("mySecurityConfig") @EnableWebSecurity @Order(Ordered.HIGHEST_PRECEDENCE) -public class ApplicationConfig extends WebSecurityConfigurerAdapter { +public class ApplicationConfig { + private static final String ALLOWED_ORIGINS = "enosono.com"; private static final String V1_MENU_ENDPOINT = "/v1/menu"; private static final String V1_MENU = "/v1/menu/**"; private static final String V2_MENU_ENDPOINT = "/v2/menu"; @@ -43,7 +45,7 @@ public class ApplicationConfig extends WebSecurityConfigurerAdapter { @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(Arrays.asList("*")); + configuration.setAllowedOrigins(List.of(ALLOWED_ORIGINS)); configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT")); configuration.setAllowCredentials(true); configuration.addAllowedHeader("Authorization"); @@ -62,14 +64,13 @@ CorsConfigurationSource corsConfigurationSource() { * @param http * @throws Exception */ - @Override - protected void configure(HttpSecurity http) throws Exception { - http.cors(); + @Bean + public SecurityFilterChain configure(HttpSecurity http) throws Exception { + http.cors(Customizer.withDefaults()); if (BooleanUtils.isTrue(isEnabled)) { - enableAuth(http); - } else { - permitAll(http); + return enableAuth(http); } + return permitAll(http); } /** @@ -78,18 +79,19 @@ protected void configure(HttpSecurity http) throws Exception { * @param http * @throws Exception */ - private void enableAuth(HttpSecurity http) throws Exception { - JwtWebSecurityConfigurer.forRS256(apiAudience, issuer) - .configure(http) - .authorizeRequests() - .antMatchers(V1_MENU_ENDPOINT) - .authenticated() - .antMatchers(V2_MENU_ENDPOINT) - .authenticated() - .antMatchers(V1_MENU) - .authenticated() - .antMatchers(V2_MENU) - .authenticated(); + private SecurityFilterChain enableAuth(HttpSecurity http) throws Exception { + return http.authorizeHttpRequests( + authConfig -> + authConfig + .requestMatchers(V1_MENU_ENDPOINT) + .authenticated() + .requestMatchers(V2_MENU_ENDPOINT) + .authenticated() + .requestMatchers(V1_MENU) + .authenticated() + .requestMatchers(V2_MENU) + .authenticated()) + .build(); } /** @@ -98,11 +100,9 @@ private void enableAuth(HttpSecurity http) throws Exception { * @param http * @throws Exception */ - private void permitAll(HttpSecurity http) throws Exception { - JwtWebSecurityConfigurer.forRS256(apiAudience, issuer) - .configure(http) - .authorizeRequests() - .antMatchers("/**") - .permitAll(); + private SecurityFilterChain permitAll(HttpSecurity http) throws Exception { + return http.authorizeHttpRequests(authConfig -> authConfig.requestMatchers("/**").permitAll()) + .httpBasic(Customizer.withDefaults()) + .build(); } } diff --git a/java/src/main/java/com/amido/stacks/workloads/ApplicationNoSecurity.java b/java/src/main/java/com/amido/stacks/workloads/ApplicationNoSecurity.java index bad57873f..774ff4b1b 100644 --- a/java/src/main/java/com/amido/stacks/workloads/ApplicationNoSecurity.java +++ b/java/src/main/java/com/amido/stacks/workloads/ApplicationNoSecurity.java @@ -1,11 +1,14 @@ package com.amido.stacks.workloads; +import static org.springframework.security.config.Customizer.withDefaults; + +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.web.SecurityFilterChain; /** * Exclude security for test profile Add @ActiveProfiles("test") to exclude test from security (for @@ -14,18 +17,16 @@ @Configuration @EnableWebSecurity @Profile("test") -public class ApplicationNoSecurity extends WebSecurityConfigurerAdapter { +public class ApplicationNoSecurity { /** * allows configuration of web-based security at a resource level, based on a selection match - * e.g. The example below restricts the URLs that start with /admin/ to users that have ADMIN * role, and declares that any other URLs need to be successfully authenticated. - * - * @param web */ - @Override - public void configure(WebSecurity web) { - web.ignoring().antMatchers("/**"); + @Bean + public WebSecurityCustomizer webSecurityCustomizer() { + return web -> web.ignoring().requestMatchers("/**"); } /** @@ -37,8 +38,10 @@ public void configure(WebSecurity web) { * @param http * @throws Exception */ - @Override - protected void configure(HttpSecurity http) throws Exception { - http.antMatcher("**/*").anonymous(); + @Bean(name = "testSecurityFilterChain") + public SecurityFilterChain configure(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(auth -> auth.requestMatchers("**/*").anonymous()) + .httpBasic(withDefaults()); + return http.build(); } } diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/OpenApiConfiguration.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/OpenApiConfiguration.java index 210e7ba46..2f3245b62 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/OpenApiConfiguration.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/OpenApiConfiguration.java @@ -9,7 +9,7 @@ import io.swagger.v3.oas.models.servers.Server; import java.util.ArrayList; import java.util.List; -import org.springdoc.core.GroupedOpenApi; +import org.springdoc.core.models.GroupedOpenApi; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -21,8 +21,8 @@ scheme = "bearer") public class OpenApiConfiguration { - private static final String PROJECT_URL = "https://github.com/amido/stacks-java"; - private static final String STACKS_EMAIL = "stacks@amido.com"; + private static final String PROJECT_URL = "https://github.com/Ensono/stacks-java"; + private static final String STACKS_EMAIL = "stacks@ensono.com"; private static final String SPRING_DOC = "http://springdoc.org"; /** OAS/Swagger Configuration. */ @@ -38,7 +38,7 @@ public OpenAPI customOpenApi() { .title("Menu API") .version("1.0") .description("APIs used to interact and manage menus for a restaurant") - .contact(new Contact().name("Amido").url(PROJECT_URL).email(STACKS_EMAIL)) + .contact(new Contact().name("Ensono").url(PROJECT_URL).email(STACKS_EMAIL)) .license(new License().name("Apache 2.0").url(SPRING_DOC))); } diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/CategoryController.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/CategoryController.java index 4cbc63ab3..c718cdec5 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/CategoryController.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/CategoryController.java @@ -12,8 +12,8 @@ import com.amido.stacks.workloads.menu.service.v1.CategoryService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import jakarta.validation.Valid; import java.util.UUID; -import javax.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/ItemController.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/ItemController.java index c21ab46b0..126e1f66e 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/ItemController.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/ItemController.java @@ -12,8 +12,8 @@ import com.amido.stacks.workloads.menu.service.v1.ItemService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import jakarta.validation.Valid; import java.util.UUID; -import javax.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/MenuController.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/MenuController.java index 8fffba5e3..28b72a8ce 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/MenuController.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/MenuController.java @@ -19,8 +19,8 @@ import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.validation.Valid; import java.util.UUID; -import javax.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateCategoryRequest.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateCategoryRequest.java index d1a391ab4..b2747cc9c 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateCategoryRequest.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateCategoryRequest.java @@ -1,7 +1,7 @@ package com.amido.stacks.workloads.menu.api.v1.dto.request; import com.fasterxml.jackson.annotation.JsonProperty; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateItemRequest.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateItemRequest.java index 7ec2245c9..b64eb0042 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateItemRequest.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateItemRequest.java @@ -1,9 +1,9 @@ package com.amido.stacks.workloads.menu.api.v1.dto.request; import com.fasterxml.jackson.annotation.JsonProperty; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateMenuRequest.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateMenuRequest.java index b3425992a..0f17cd287 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateMenuRequest.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/CreateMenuRequest.java @@ -1,9 +1,9 @@ package com.amido.stacks.workloads.menu.api.v1.dto.request; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import java.util.UUID; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateCategoryRequest.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateCategoryRequest.java index 22d3a908c..f66385dd7 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateCategoryRequest.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateCategoryRequest.java @@ -1,7 +1,7 @@ package com.amido.stacks.workloads.menu.api.v1.dto.request; import com.fasterxml.jackson.annotation.JsonProperty; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateItemRequest.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateItemRequest.java index 019068879..a11cac0c1 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateItemRequest.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateItemRequest.java @@ -1,9 +1,9 @@ package com.amido.stacks.workloads.menu.api.v1.dto.request; import com.fasterxml.jackson.annotation.JsonProperty; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateMenuRequest.java b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateMenuRequest.java index 0be7ee9c9..0c53a6cee 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateMenuRequest.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/api/v1/dto/request/UpdateMenuRequest.java @@ -1,8 +1,8 @@ package com.amido.stacks.workloads.menu.api.v1.dto.request; import com.fasterxml.jackson.annotation.JsonProperty; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/CategoryService.java b/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/CategoryService.java index 772ded52b..e99f657a6 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/CategoryService.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/CategoryService.java @@ -4,8 +4,8 @@ import com.amido.stacks.core.api.dto.response.ResourceUpdatedResponse; import com.amido.stacks.workloads.menu.api.v1.dto.request.CreateCategoryRequest; import com.amido.stacks.workloads.menu.api.v1.dto.request.UpdateCategoryRequest; +import jakarta.validation.Valid; import java.util.UUID; -import javax.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/ItemService.java b/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/ItemService.java index 46d25bce0..c2cc68520 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/ItemService.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/ItemService.java @@ -4,8 +4,8 @@ import com.amido.stacks.core.api.dto.response.ResourceUpdatedResponse; import com.amido.stacks.workloads.menu.api.v1.dto.request.CreateItemRequest; import com.amido.stacks.workloads.menu.api.v1.dto.request.UpdateItemRequest; +import jakarta.validation.Valid; import java.util.UUID; -import javax.validation.Valid; import org.springframework.stereotype.Service; @Service diff --git a/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/MenuService.java b/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/MenuService.java index 6b076ce5e..e80f2303e 100644 --- a/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/MenuService.java +++ b/java/src/main/java/com/amido/stacks/workloads/menu/service/v1/MenuService.java @@ -12,11 +12,10 @@ import com.amido.stacks.workloads.menu.mappers.MenuMapper; import com.amido.stacks.workloads.menu.mappers.SearchMenuResultItemMapper; import com.amido.stacks.workloads.menu.service.utility.MenuHelperService; +import jakarta.validation.Valid; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; -import javax.validation.Valid; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -61,9 +60,7 @@ public SearchMenuResult search( menuList.add(mockMenu); return new SearchMenuResult( - pageSize, - pageNumber, - menuList.stream().map(searchMenuResultItemMapper::toDto).collect(Collectors.toList())); + pageSize, pageNumber, menuList.stream().map(searchMenuResultItemMapper::toDto).toList()); } public MenuDTO get(UUID id, String correlationId) { diff --git a/java/src/main/resources/application-azure.yml b/java/src/main/resources/application-azure.yml index 89231add7..b40c95182 100644 --- a/java/src/main/resources/application-azure.yml +++ b/java/src/main/resources/application-azure.yml @@ -4,7 +4,7 @@ azure: enabled: true keyvault: enabled: false - uri: https://amido.stacks-tmp.vault.azure.net/ + uri: https://ensono.stacks-tmp.vault.azure.net/ client-id: xxxxxx client-key: xxxxxx tenant-id: xxxxxx diff --git a/java/src/main/resources/auth.properties b/java/src/main/resources/auth.properties index 9f57a6c72..74bfe6a35 100644 --- a/java/src/main/resources/auth.properties +++ b/java/src/main/resources/auth.properties @@ -1,12 +1,12 @@ #The issuer of the JWT Token. Typically, this is your Auth0 domain with an https:// -auth.issuer=https://amidostacks.eu.auth0.com/ +auth.issuer=https://ensonostacks.eu.auth0.com/ #The unique identifier for your API -auth.apiAudience=https://amidostacks.eu.auth0.com/api/v2/ +auth.apiAudience=https://ensonostacks.eu.auth0.com/api/v2/ #Config switch to enable (true) or disable(false) Auth0.Provide either true or false to enable or disable auth.isEnabled=false -auth.resource.url=https://amidostacks.eu.auth0.com/oauth/tokenLocal +auth.resource.url=https://ensonostacks.eu.auth0.com/oauth/tokenLocal -auth.token.url=/v1/tokenLocal \ No newline at end of file +auth.token.url=/v1/tokenLocal diff --git a/java/src/main/resources/local/application-azure.yml b/java/src/main/resources/local/application-azure.yml index 89231add7..b40c95182 100644 --- a/java/src/main/resources/local/application-azure.yml +++ b/java/src/main/resources/local/application-azure.yml @@ -4,7 +4,7 @@ azure: enabled: true keyvault: enabled: false - uri: https://amido.stacks-tmp.vault.azure.net/ + uri: https://ensono.stacks-tmp.vault.azure.net/ client-id: xxxxxx client-key: xxxxxx tenant-id: xxxxxx diff --git a/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/CategoryControllerTest.java b/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/CategoryControllerTest.java index dd237e36c..190d49ecb 100644 --- a/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/CategoryControllerTest.java +++ b/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/CategoryControllerTest.java @@ -26,7 +26,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; diff --git a/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/ItemControllerTest.java b/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/ItemControllerTest.java index d39694bc0..9f72446f6 100644 --- a/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/ItemControllerTest.java +++ b/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/ItemControllerTest.java @@ -29,7 +29,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; diff --git a/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/MenuControllerTest.java b/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/MenuControllerTest.java index 2c8e3f0af..010a09f82 100644 --- a/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/MenuControllerTest.java +++ b/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/MenuControllerTest.java @@ -37,7 +37,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; diff --git a/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/SecretsControllerTest.java b/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/SecretsControllerTest.java index 1477c5591..56838aa54 100644 --- a/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/SecretsControllerTest.java +++ b/java/src/test/java/com/amido/stacks/workloads/menu/api/v1/SecretsControllerTest.java @@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpStatus; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.TestPropertySource; diff --git a/java/src/test/java/com/amido/stacks/workloads/menu/api/v2/MenuControllerV2Test.java b/java/src/test/java/com/amido/stacks/workloads/menu/api/v2/MenuControllerV2Test.java index f78959b65..c07c397b1 100644 --- a/java/src/test/java/com/amido/stacks/workloads/menu/api/v2/MenuControllerV2Test.java +++ b/java/src/test/java/com/amido/stacks/workloads/menu/api/v2/MenuControllerV2Test.java @@ -13,7 +13,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.ActiveProfiles; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) diff --git a/stackscli.yml b/stackscli.yml index 7c863508d..0cc7d7d74 100644 --- a/stackscli.yml +++ b/stackscli.yml @@ -4,7 +4,7 @@ framework: name: java commands: - name: java - version: ">= 11" + version: ">= 17" # Pipeline files pipeline: @@ -17,15 +17,15 @@ pipeline: replacements: - pattern: ^.*stacks-credentials-nonprod-kv$ value: "" - - pattern: ^.*amido-stacks-infra-credentials-nonprod$ + - pattern: ^.*stacks-infra-credentials-nonprod$ value: "" - - pattern: ^.*amido-stacks-infra-credentials-prod$ + - pattern: ^.*stacks-infra-credentials-prod$ value: "" - pattern: ^.*stacks-credentials-prod-kv$ value: "" - pattern: ^.*stacks-credentials-nonprod-kv$ value: "" - - pattern: ^.*amido-stacks-java-api$ + - pattern: ^.*stacks-java-api$ value: "" # The init stage are things that are required to run before the template is run diff --git a/stacksclipom.xml b/stacksclipom.xml index 405f762a6..7cbff91d8 100644 --- a/stacksclipom.xml +++ b/stacksclipom.xml @@ -8,8 +8,8 @@ 1.0.0 - 11 - 11 + 17 + 17 . ${main.basedir}/stacks ${main.basedir}/build