diff --git a/.asciidoctorconfig.adoc b/.asciidoctorconfig.adoc new file mode 100644 index 0000000000000000000000000000000000000000..d3cddb773a0372bb53eb3f0e430e006862c1c643 --- /dev/null +++ b/.asciidoctorconfig.adoc @@ -0,0 +1,12 @@ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// + Initial AsciiDoc editor configuration file - V1.0 + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Did not find any configuration files, so creating this at project root level. +// If you do not like those files to be generated - you can turn it off inside Asciidoctor Editor preferences. +// +// You can define editor specific parts here. +// For example: with next line you could set imagesdir attribute to subfolder "images" relative to the folder where this config file is located. +// :imagesdir: {asciidoctorconfigdir}/images +// +// For more information please take a look at https://github.com/de-jcup/eclipse-asciidoctor-editor/wiki/Asciidoctor-configfiles diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..01d35d64e78c71576561c45c892462bf54e98fd0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/target/ +/kubernetes/_apply +.project +.classpath +/.settings + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..3787a3a10426e4b68004fc09bc4d40280e81c4f9 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,14 @@ +include: + - ci-templates/default.yml + + - local: ci-templates/build.yml + rules: + - if: '$CI_COMMIT_REF_NAME == "main" || $CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_PROTECTED' + + - local: ci-templates/build_unprotected.yml + rules: + - if: '$CI_COMMIT_REF_NAME != "main" && $CI_COMMIT_REF_NAME != "develop" && !$CI_COMMIT_REF_PROTECTED' + + +maven_build: + extends: .maven_build diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0908fe38bbeed532b730e19fa53ea244747e2f89 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,17 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +# Build documentation in the doc/ directory with mkdocs +mkdocs: + configuration: mkdocs.yml + fail_on_warning: false \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 96af08010a111837a8c1d7bb5cfe4397a02372a0..71f8e6c55902c63dbf1561ee251a60228d54d6b1 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,4 @@ # org.etsi.osl.main +Main parent project used to install openslice - -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: - -``` -cd existing_repo -git remote add origin https://labs.etsi.org/rep/osl/code/org.etsi.osl.main.git -git branch -M main -git push -uf origin main -``` - -## Integrate with your tools - -- [ ] [Set up project integrations](https://labs.etsi.org/rep/osl/code/org.etsi.osl.main/-/settings/integrations) - -## Collaborate with your team - -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) - -## Test and Deploy - -Use the built-in continuous integration in GitLab. - -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) - -*** - -# Editing this README - -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. - -## Suggestions for a good README -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. - -## Name -Choose a self-explaining name for your project. - -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. - -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. - -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. - -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. - -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. - -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. - -## Contributing -State if you are open to contributions and what your requirements are for accepting them. - -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. - -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. - -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. - -## License -For open source projects, say how it is licensed. - -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt new file mode 100644 index 0000000000000000000000000000000000000000..abb990fa4a5cdb86db5a13d723ae4a9e4322021c --- /dev/null +++ b/ReleaseNotes.txt @@ -0,0 +1,20 @@ +Q3 2023 1.2.0-SNAPSHOT + +Upgraded to java17 and SpingBoot3 +Upgraded from ActiveMQ to Artemis + +Upgrade Keycloak to 16 + +backup your previous database if necessary: +sudo docker exec amysql /usr/bin/mysqldump -u root --password=letmein ostmfdb > backup_ostmfdb.sql +restore your previous database: +cat backup_ostmfdb.sql | docker exec -i amysql /usr/bin/mysql -u root --password=letmein ostmfdb + + +Q3 2021 + +- There have been some minor changes in the databases. THerefore some older artifacts might be deleted. Especially RFS relationships +- The CONFIG attribute of RFSs must be renamed to OSM_CONFIG. OSM_CONFIG includes now the json configuration to pass to OSM when creating NSDs +- Edit your docker-compose.yaml and add oasapi section. Edit the oasapi section according to your needs (db password, keycloak etc) +- Edit your /openslice/org.etsi.osl.tmf.web/dist/io-openslice-portal-web/assets/config/config.prod.json with the new API endpoints. Please consult the config.prod.default.json +- Edit nginx.conf to add the new oas-api diff --git a/ci-templates/build.yml b/ci-templates/build.yml new file mode 100644 index 0000000000000000000000000000000000000000..4d10538a5c87e46e6291c9551aff61b437360221 --- /dev/null +++ b/ci-templates/build.yml @@ -0,0 +1,41 @@ +.maven_build: + extends: .default + stage: build + image: maven:3.9.5-ibm-semeru-17-focal + script: + - mvn deploy -s ci_settings.xml -Dversion=$APP_VERSION + artifacts: + paths: + - target/ + +.docker_build: + extends: .default + stage: build + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + script: + - /kaniko/executor --context "${CI_PROJECT_DIR}" --dockerfile "${CI_PROJECT_DIR}/Dockerfile" --destination "${CI_REGISTRY_IMAGE}:$APP_VERSION" + - | + if [ "$CI_COMMIT_REF_NAME" = "main" ]; then + echo "Pushing Docker image with tag 'latest'" + /kaniko/executor --context "${CI_PROJECT_DIR}" --dockerfile "${CI_PROJECT_DIR}/Dockerfile" --destination "${CI_REGISTRY_IMAGE}:latest" + fi + +.angular_build: + extends: .default + stage: build + image: trion/ng-cli:14.2.6 + script: + - | + if [ ! -f "./src/assets/config/theming.scss" ]; then + cp ./src/assets/config/theming.default.scss ./src/assets/config/theming.scss + fi + if [ ! -f "./src/assets/config/config.prod.json" ]; then + cp ./src/assets/config/config.prod.default.json ./src/assets/config/config.prod.json + fi + - npm install + - ng build --configuration production --deleteOutputPath=false + artifacts: + paths: + - dist/ diff --git a/ci-templates/build_unprotected.yml b/ci-templates/build_unprotected.yml new file mode 100644 index 0000000000000000000000000000000000000000..a5c86697e727ef62c38b8c1801f0f23ec20c0b4e --- /dev/null +++ b/ci-templates/build_unprotected.yml @@ -0,0 +1,36 @@ +.maven_build: + extends: .default + stage: build + image: maven:3.9.5-ibm-semeru-17-focal + script: + - mvn install -s ci_settings.xml + artifacts: + paths: + - target/ + +.docker_build: + extends: .default + stage: build + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + script: + - /kaniko/executor --context "${CI_PROJECT_DIR}" --dockerfile "${CI_PROJECT_DIR}/Dockerfile" --destination "${CI_REGISTRY_IMAGE}:$APP_VERSION" --no-push + +.angular_build: + extends: .default + stage: build + image: trion/ng-cli:14.2.6 + script: + - | + if [ ! -f "./src/assets/config/theming.scss" ]; then + cp ./src/assets/config/theming.default.scss ./src/assets/config/theming.scss + fi + if [ ! -f "./src/assets/config/config.prod.json" ]; then + cp ./src/assets/config/config.prod.default.json ./src/assets/config/config.prod.json + fi + - npm install + - ng build --configuration production --deleteOutputPath=false + artifacts: + paths: + - dist/ diff --git a/ci-templates/default.yml b/ci-templates/default.yml new file mode 100644 index 0000000000000000000000000000000000000000..bb0d5538bb3ecf2424bc1b9bdf05137db1eb8a46 --- /dev/null +++ b/ci-templates/default.yml @@ -0,0 +1,17 @@ +stages: + - .pre + - build + - test + - post + - security + +.default: + before_script: + - | + if [ "$CI_COMMIT_REF_NAME" = "main" ] && [ -n "$CI_COMMIT_TAG" ]; then + export APP_VERSION=$CI_COMMIT_TAG + elif [ "$CI_COMMIT_REF_NAME" = "develop" ]; then + export APP_VERSION="develop" + else + export APP_VERSION=$CI_COMMIT_REF_NAME + fi diff --git a/ci_settings.xml b/ci_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..69ad06ed6c63795d191555afde6ea2d1da4e133d --- /dev/null +++ b/ci_settings.xml @@ -0,0 +1,16 @@ + + + + gitlab-maven + + + + Job-Token + ${CI_JOB_TOKEN} + + + + + + diff --git a/compose/.gitignore b/compose/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3645699793fa5f6a9ba124b5ec951841e316af0d --- /dev/null +++ b/compose/.gitignore @@ -0,0 +1,3 @@ +/repo/ +/docker-compose.yaml +/mysql/ diff --git a/compose/deploy.sh b/compose/deploy.sh new file mode 100644 index 0000000000000000000000000000000000000000..94071cf2f48c5741be21fe658c795d238f8382db --- /dev/null +++ b/compose/deploy.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +dirlocation=`pwd`/. +# If no argument is provided, use "main" as the default value +default_branch="main" +branch="${1:-$default_branch}" + +echo "Selected branch: $branch" +echo "We're working with $dirlocation" +cd $dirlocation + + +updaterepo(){ + cd $dirlocation + echo "Build " $1 + if [ ! -d $1 ]; then + git clone https://labs.etsi.org/rep/osl/code/$1.git + fi + + cd $1/ + git checkout $branch + git pull + + # Build maven project if .pom file is present + if [ -f "./pom.xml" ]; then + docker run -it --rm -v "/home/ubuntu/.m2":/root/.m2 -v "$(pwd)":/opt/maven -w /opt/maven maven:3.9.5-ibm-semeru-17-focal mvn clean verify -DskipTests + fi +} + + +updaterepo org.etsi.osl.main +#updaterepo org.etsi.osl.sol005nbi.osm +#updaterepo org.etsi.osl.sol005nbi.osm10 +#updaterepo org.etsi.osl.centrallog.client +updaterepo org.etsi.osl.centrallog.service +#updaterepo org.etsi.osl.model.nfv +#updaterepo org.etsi.osl.model.tmf +#updaterepo org.etsi.osl.model.k8s +updaterepo org.etsi.osl.portal.api +updaterepo org.etsi.osl.mano +updaterepo org.etsi.osl.bugzilla +updaterepo org.etsi.osl.osom +updaterepo org.etsi.osl.oas +updaterepo org.etsi.osl.tmf.api +updaterepo org.etsi.osl.cridge + +updaterepo org.etsi.osl.tmf.web +updaterepo org.etsi.osl.portal.web + + +echo "Build org.etsi.osl.tmf.web" + +cd $dirlocation/org.etsi.osl.tmf.web + +if [ ! -f "./src/assets/config/theming.scss" ]; then + cp ./src/assets/config/theming.default.scss ./src/assets/config/theming.scss +fi +if [ ! -f "./src/assets/config/config.prod.json" ]; then + cp ./src/assets/config/config.prod.default.json ./src/assets/config/config.prod.json +fi + +echo "Installing npm packages..." + +docker run -u 0 --rm -v "$PWD":/app trion/ng-cli:13.3.7 npm install +docker run -u 0 --rm -v "$PWD":/app trion/ng-cli:13.3.7 ng build --configuration production --deleteOutputPath=false diff --git a/compose/docker-compose.yaml.configure b/compose/docker-compose.yaml.configure new file mode 100644 index 0000000000000000000000000000000000000000..ef91ade0954af0c895c9f542a699f38845277944 --- /dev/null +++ b/compose/docker-compose.yaml.configure @@ -0,0 +1,402 @@ +version: '3.4' +services: + + artemis: + container_name: anartemis + image: apache/activemq-artemis:2.30.0 + restart: always + profiles: ["dev", "prod"] + ports: + - 8161:8161 + - 61616:61616 + - 61613:61613 + volumes: + - /var/log/activemq:/var/log/activemq + networks: + - back + + nginx: + container_name: anginx + image: nginx + restart: always + profiles: ["dev", "prod"] + ports: + - 80:80 + - 443:443 + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf + - ./nginx/certificates:/etc/nginx/certificates + - ../../org.etsi.osl.portal.web/src:/webstatic/nfvportal + - ../../org.etsi.osl.tmf.web/dist/org.etsi.osl.tmf.web:/webstatic/services + networks: + - front + + mysql-portal: + container_name: amysql + restart: always + image: mysql:5.7.43 + profiles: ["dev", "prod"] + environment: + MYSQL_ROOT_PASSWORD: letmein +# MYSQL_DATABASE: osdb +# MYSQL_USER: portaluser +# MYSQL_PASSWORD: 12345 + MYSQL_ROOT_HOST: "%" + ports: + - "13306:3306" + volumes: + - ~/mysql/data:/var/lib/mysql + - ./mysql-init:/docker-entrypoint-initdb.d + networks: + - back + + keycloak: + container_name: keycloak + image: quay.io/keycloak/keycloak:16.1.1 + restart: always + profiles: ["dev", "prod"] + environment: + DB_VENDOR: MYSQL + DB_ADDR: amysql + DB_DATABASE: keycloak + DB_USER: keycloak + DB_PASSWORD: password + KEYCLOAK_USER: admin + KEYCLOAK_PASSWORD: Pa55w0rd + JDBC_PARAMS: "useSSL=false" + JAVA_OPTS: "-server -Xms512m -Xmx2048m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -XX:+UseAdaptiveSizePolicy -XX:MaxMetaspaceSize=1024m -Djava.net.preferIPv4Stack=true -Djboss.as.management.blocking.timeout=3600" + KEYCLOAK_IMPORT: /tmp/realm-export.json + PROXY_ADDRESS_FORWARDING: "true" + volumes: + - ./keycloak-init:/tmp + ports: + - 8080:8080 + - 8443:8443 + depends_on: + - mysql-portal + networks: + - front + - back + + + osportalapi: + container_name: openslice-portalapi + restart: always + profiles: ["prod"] + build: + context: ../../org.etsi.osl.portal.api/ + dockerfile: Dockerfile + image: labs.etsi.org:5050/osl/code/org.etsi.osl.portal.api:develop + environment: + SPRING_APPLICATION_JSON: '{ + "origins": "http://localhost", + "spring.datasource.url": "jdbc:mysql://amysql/osdb?createDatabaseIfNotExist=true", + "spring.datasource.username":"root", + "spring.datasource.password":"letmein", + "spring-addons.issuers[0].uri": "http://keycloak:8080/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "http://keycloak:8080/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id" : "osapiWebClientId", + "springdoc.oauth.clientsecret" : "secret", + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO", + "logging.level.org.etsi.osl.portal.api": "INFO", + "spring.portal.main.domain": "http://localhost", + "spring.portal.portal.title": "Openslice", + "server.forward-headers-strategy":"FRAMEWORK" + }' + logging: + driver: "json-file" + options: + max-size: "1g" + max-file: "3" + volumes: + - ./repo:/root + ports: + - 13000:13000 + networks: + - front + - back + depends_on: + - mysql-portal + + + manoclient: + container_name: manoclient + restart: always + profiles: ["prod"] + build: + context: ../../org.etsi.osl.mano/ + dockerfile: Dockerfile + image: labs.etsi.org:5050/osl/code/org.etsi.osl.mano:develop + environment: + SPRING_APPLICATION_JSON: '{ + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO" + }' + logging: + driver: "json-file" + options: + max-size: "1g" + max-file: "3" + ports: + - 13011:13011 + networks: + - back + + + bugzilla: + container_name: abugzilla + restart: always + profiles: ["prod"] + build: + context: ../../org.etsi.osl.bugzilla/ + dockerfile: Dockerfile + image: labs.etsi.org:5050/osl/code/org.etsi.osl.bugzilla:develop + environment: + SPRING_APPLICATION_JSON: '{ + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "bugzillaurl":"", + "bugzillakey":"", + "main_operations_product":"" + }' + ports: + - 13010:13010 + networks: + - front + - back + + + + + osscapi: + container_name: openslice-scapi + restart: always + profiles: ["prod"] + build: + context: ../../org.etsi.osl.tmf.api/ + dockerfile: Dockerfile + image: labs.etsi.org:5050/osl/code/org.etsi.osl.tmf.api:develop + environment: + SPRING_APPLICATION_JSON: '{ + "origins": "http://localhost", + "spring.datasource.url": "jdbc:mysql://amysql/ostmfdb?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", + "spring.datasource.username":"root", + "spring.datasource.password":"letmein", + "spring-addons.issuers[0].uri": "http://keycloak:8080/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "http://keycloak:8080/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id" : "osapiWebClientId", + "springdoc.oauth.clientsecret" : "secret", + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO", + "logging.level.org.etsi.osl.tmf.api" : "INFO", + "kroki.serverurl" : "http://localhost/kroki", + "server.forward-headers-strategy":"FRAMEWORK" + }' + logging: + driver: "json-file" + options: + max-size: "1g" + max-file: "3" + volumes: + - ./repo:/root + ports: + - 13082:13082 + networks: + - front + - back + depends_on: + - mysql-portal + + + osom: + container_name: openslice-osom + restart: always + profiles: ["prod"] + build: + context: ../../org.etsi.osl.osom/ + dockerfile: Dockerfile + image: labs.etsi.org:5050/osl/code/org.etsi.osl.osom:develop + environment: + SPRING_APPLICATION_JSON: '{ + "spring.datasource.url" : "jdbc:h2:/tmp/tempdb;DB_CLOSE_DELAY=-1", + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO", + "logging.level.org.etsi.osl.osom" : "INFO" + }' + ports: + - 13100:13100 + networks: + - front + - back + depends_on: + - mysql-portal + + + oasapi: + container_name: openslice-oasapi + restart: always + profiles: ["prod"] + build: + context: ../../org.etsi.osl.oas/ + dockerfile: Dockerfile + image: labs.etsi.org:5050/osl/code/org.etsi.osl.oas:develop + environment: + SPRING_APPLICATION_JSON: '{ + "origins": "http://localhost", + "spring.datasource.url": "jdbc:mysql://amysql/ostmfdb?createDatabaseIfNotExist=true&useUnicode=true&nullCatalogMeansCurrent=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", + "spring.datasource.username":"root", + "spring.datasource.password":"letmein", + "spring-addons.issuers[0].uri": "http://keycloak:8080/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "http://keycloak:8080/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id" : "osapiWebClientId", + "springdoc.oauth.clientsecret" : "secret", + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO", + "server.forward-headers-strategy":"FRAMEWORK" + }' + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "3" + volumes: + - ./repo:/root + ports: + - 13101:13101 + networks: + - front + - back + + cridge: + container_name: openslice-cridge + restart: always + profiles: [ "prod"] + build: + context: ../../org.etsi.osl.cridge/ + dockerfile: Dockerfile + image: labs.etsi.org:5050/osl/code/org.etsi.osl.cridge:develop + environment: + SPRING_APPLICATION_JSON: '{ + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO", + "logging.level.org.etsi.osl.cridge" : "INFO" + }' + logging: + driver: "json-file" + options: + max-size: "800m" + max-file: "3" + networks: + - front + - back + volumes: + - ./kubedir/:/root/.kube + depends_on: + - osscapi + + + + portainer: + container_name: portainer + image: portainer/portainer-ce:2.18.4 + restart: always + profiles: ["dev", "prod"] + networks: + - front + ports: + - 9000:9000 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_data:/data + + centrallog: + container_name: centrallog + restart: always + profiles: ["prod"] + build: + context: ../../org.etsi.osl.centrallog.service/ + dockerfile: Dockerfile + image: labs.etsi.org:5050/osl/code/org.etsi.osl.centrallog.service:develop + environment: + SPRING_APPLICATION_JSON: '{ + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "centrallogurl":"http://elk_ip:elk_port/index_name/_doc", + "logging.level.org.springframework" : "INFO" + }' + ports: + - 13013:13013 + networks: + - back + + kroki: + container_name: kroki + restart: always + image: yuzutech/kroki:0.18.0 + profiles: ["dev", "prod"] + depends_on: + - blockdiag + environment: + - KROKI_BLOCKDIAG_HOST=blockdiag + ports: + - "8000:8000" + networks: + - front + - back + + + blockdiag: + image: yuzutech/kroki-blockdiag:0.18.0 + restart: always + profiles: ["dev", "prod"] + expose: + - "8001" + networks: + - front + - back + + +networks: + front: + driver: bridge + driver_opts: + com.docker.network.driver.mtu: 1450 + back: + driver: bridge + driver_opts: + com.docker.network.driver.mtu: 1450 + + +volumes: + portainer_data: + diff --git a/compose/docker-images-build.sh b/compose/docker-images-build.sh new file mode 100644 index 0000000000000000000000000000000000000000..f829089f8c3ba2e751924da092622d2735d92ffe --- /dev/null +++ b/compose/docker-images-build.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +dirlocation=`pwd`/. +echo "We're working with $dirlocation" +cd $dirlocation +tagname=latest + +buildimg(){ + cd $dirlocation/$1 + echo "Build " $1 + sudo docker build -t openslice/$1:$tagname -f $2 . + sudo docker push openslice/$1:$tagname +} + +buildimg org.etsi.osl.centrallog.service Dockerfile.centrallog +buildimg org.etsi.osl.portal.api Dockerfile.portalapi +buildimg org.etsi.osl.mano Dockerfile.mano +buildimg org.etsi.osl.bugzilla Dockerfile.bugzilla +buildimg org.etsi.osl.osom Dockerfile.osom +buildimg org.etsi.osl.portal.web Dockerfile +buildimg org.etsi.osl.tmf.api Dockerfile.tmfapi +buildimg org.etsi.osl.oas Dockerfile.oasapi + + + +cd $dirlocation/org.etsi.osl.tmf.web +docker run -u 0 --rm -v "$PWD":/app trion/ng-cli npm install +docker run -u 0 --rm -v "$PWD":/app trion/ng-cli ng build --prod --deleteOutputPath=false +buildimg org.etsi.osl.tmf.web Dockerfile \ No newline at end of file diff --git a/compose/keycloak-init/.gitignore b/compose/keycloak-init/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..8937e9b70f905f404bf15773b836352c4bca90e0 --- /dev/null +++ b/compose/keycloak-init/.gitignore @@ -0,0 +1,3 @@ +/hsperfdata_jboss/ +/vertx-cache/ +/hsperfdata_keycloak/ diff --git a/compose/keycloak-init/realm-export.json b/compose/keycloak-init/realm-export.json new file mode 100644 index 0000000000000000000000000000000000000000..f74761ad1204c69097b2b036d532a717fce21b75 --- /dev/null +++ b/compose/keycloak-init/realm-export.json @@ -0,0 +1,2221 @@ +{ + "id": "openslice", + "realm": "openslice", + "displayName": "Openslice", + "notBefore": 1586721661, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 3600, + "accessTokenLifespanForImplicitFlow": 3600, + "ssoSessionIdleTimeout": 7200, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "1741dd77-ee50-4fd7-bec6-1a6d3d9d778a", + "name": "MENTOR", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "f61e8649-b003-42e2-8670-4116885a1e26", + "name": "NFV_DEVELOPER", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "379857ba-17b0-4299-9191-4df27ce9425b", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "a2685809-e874-4009-8435-92ded0c7180d", + "name": "ADMIN", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "af2ef7e2-d78a-4f4e-844c-174c64168316", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "8b544ccb-d0de-4550-b879-985c86b8d018", + "name": "USER", + "composite": false, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "0f367333-06dc-4740-931a-b2d6b3b06577", + "name": "EXPERIMENTER", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "ec900678-a7df-4955-a78d-a90b138a5121", + "name": "TESTBED_PROVIDER", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + } + ], + "client": { + "openslice-service": [], + "realm-management": [ + { + "id": "679a9d01-6d85-42f5-9c6b-f3d923dd1a0a", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "06f2873b-3926-4d97-9179-769e342f86e9", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "63f7b29c-c463-40d8-82de-4ae894de65ea", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "09422e3f-4358-466a-a46a-e887cb5f5189", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients", + "create-client", + "view-realm", + "manage-events", + "query-groups", + "manage-identity-providers", + "view-events", + "view-users", + "view-clients", + "manage-clients", + "impersonation", + "manage-authorization", + "manage-users", + "query-realms", + "query-users", + "manage-realm", + "view-authorization", + "view-identity-providers" + ] + } + }, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "2d6c5511-1cb7-4283-90f5-50d751c2eb92", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "dbb571cf-7d5e-418e-95d7-ca2160eceba6", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "31f02966-2fa2-479b-bcf1-fa2a000e7b0f", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "46c57172-f46d-466c-a73c-4b4f58eb23ce", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "006e604a-1915-4165-bf8a-709f77d07c99", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "22b0f1f4-b2de-4829-ae70-5b6a2ffb90c0", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "2ec8e15f-d086-4c49-a2dc-ccf1b85b645f", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "841fcb24-6965-4299-a2a8-2a0caf98b022", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "16a19114-7aa5-4c7c-a741-424e74b379b9", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "7c81140a-8b70-44fc-af0e-d6b83f6be914", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "1690c8e2-971a-4472-a21c-d2c403f46907", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "3b455fa3-45ce-4210-b138-c3a64b69271f", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "9cfae318-c817-428c-8a41-9f37fa3b8848", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "a085267a-ac93-4004-9899-b76b74d06c31", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "1dd16fc9-7abd-41fe-bb23-5887f01fa295", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "osapiWebClientId": [], + "account-console": [], + "broker": [ + { + "id": "be197fdb-fe78-4b10-87d3-9e17826b05c9", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "92128d63-9887-4e70-b5e2-9797756279d3", + "attributes": {} + } + ], + "account": [ + { + "id": "e2d74a05-f1a0-4fb1-8b03-a3e9b691d82b", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "f661e78f-1ce3-4af2-9a7c-a5cb7a09d4b5", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "3094e791-7572-4845-b64b-3dbbb763fdb7", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "05ddbf6c-7b93-4c49-83e9-154255ac877e", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "84bad9b3-a179-4700-84a4-fdcbf0ae2991", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "d3e32349-192a-464e-91f8-b73ed6a8f170", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRoles": [ + "uma_authorization", + "offline_access" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account" + ] + } + ] + }, + "clients": [ + { + "id": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/openslice/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": [ + "view-profile", + "manage-account" + ], + "redirectUris": [ + "/realms/openslice/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "7838e492-c9ce-4812-a9e9-629244fe1295", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/openslice/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/realms/openslice/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "48e276a8-68a7-45ef-929a-18d2afbab527", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "b233eb6d-e3df-4d8d-8b09-3666f043258f", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "92128d63-9887-4e70-b5e2-9797756279d3", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "41a307d8-9465-463e-89ad-8c30af4ad5c0", + "clientId": "openslice-service", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "40742f38-d000-431b-a0a5-f5101a730a5a", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "5115e3c5-8453-4c8b-a6a7-67e16f56eda9", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "a194cc8d-d541-42f8-8c3c-3553568b3d2c", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "40ec2a52-1033-4471-80a3-404167935e6f", + "clientId": "osapiWebClientId", + "rootUrl": "http://localhost:13000", + "adminUrl": "http://localhost:13000", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "http://openslice.io/*", + "http://localhost:13000/osapi/webjars/springfox-swagger-ui/oauth2-redirect.html", + "http://localhost:13082/*", + "http://localhost:13000/*", + "http://localhost/*", + "http://localhost:13000/osapi/testweb/oauthresp.html" + ], + "webOrigins": [ + "http://localhost:13082", + "http://localhost", + "http://openslice.io", + "http://localhost:13000" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "37a4e3c2-48be-4ee0-b50f-6e439ed2cdb2", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/openslice/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/admin/openslice/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "d7eaa5b1-22be-4ab4-86b4-2e415aeca815", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "562b8e42-c857-4cf6-8241-28efb2642c4b", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "5a5001cb-4bd0-480f-a7a3-c0bcba80ad3a", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "f6653189-9761-4ef3-936c-38affde191d8", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "767ac64d-5809-4239-b406-edcdd9050e80", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "e8d8398b-37ea-43bb-9196-f934ac296014", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "09a290c7-2b47-4151-9bc5-157c74aca908", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "f00e6912-4087-4887-a322-28e138d4b39f", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + }, + { + "id": "b782ede1-459f-4e6a-bf8b-88b18a6772d6", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "a12e8651-599f-4ddb-b653-d8cb5b0184d7", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "0f2b29e9-8093-455c-a5a9-f0c1c928942f", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "f4ec14ee-b067-40bf-b7c0-6dd7df5a602f", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "65664f25-c82d-433d-bf36-c08ded829901", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "c712880d-9ef1-4ea2-86bf-810054d40b26", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "b18c9def-9b75-4706-9936-2d4178c7b5a6", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "dbef3b60-3c68-4bb7-9d2a-d8a85f6f7004", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "bdf07a0c-c5ca-4608-b494-b8a1ddc063c4", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "81e16a30-df1f-416b-80c3-6983101166d1", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "b44f4f26-6d0d-406e-9009-c5d8dfdd5d16", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "86c5c86e-cb21-4abd-a17a-85dc63617995", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "d78aedcd-828c-4773-ad70-22091d874bbd", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "95e1cb5d-4f42-4b2a-8e3a-69e39055b66d", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "id": "ac157f2a-50b9-404e-bde0-965910a47d05", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "4edc4427-0ebe-4825-89a8-0e8e80620f5a", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "6ce933f3-a5b4-4676-b5db-b6425d45021d", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "bd070586-ba31-42c4-b2fa-0614ad88e792", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "397b1ae7-6c83-4a4c-a97d-75102563ae57", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "a40de263-79e3-4adf-9dc6-584b1f537a06", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "6ca378b4-4e3b-4cc2-bee4-ef3479d59114", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "57d2d578-eb49-4756-8d41-c999c2849f1a", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "b322295e-fae9-4ade-9b0e-138a44732f3e", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "f24c94cb-8156-4f4e-b5f2-e7b3000f4f81", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "27c412ff-97ef-49d2-8a80-f42fd8649b7a", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "377da2df-94e7-43de-98f6-b3b4326cfa02", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "39e41a56-6439-40da-9aa7-fa3b8a57c759", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "bb450b68-fcda-4f82-b16c-6d83cd28aa8f", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "web-origins", + "roles", + "profile", + "email" + ], + "defaultOptionalClientScopes": [ + "microprofile-jwt", + "phone", + "address", + "offline_access" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "34e415a5-18a4-4e32-a17c-daf41c5cbf19", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "7d113054-e7c7-44cb-a6d8-d257195b1364", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "388b5ffd-ea57-48bc-b7af-43b21b529e8a", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper" + ] + } + }, + { + "id": "70080b90-b144-421e-9ec4-4106a6181d88", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "d556fcc1-038a-4ed2-992b-5803e4c599be", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "67803167-d874-41b2-970b-b2de89d0250b", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-address-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper", + "saml-user-attribute-mapper" + ] + } + }, + { + "id": "a4381728-f174-492f-9404-c8ecaddc8bd9", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "c60d614f-36b1-4a0f-b359-f2c4c7e7a2d5", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "472544bd-20bd-467d-8d5c-f71468017b90", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "56cdedf5-b827-4ca7-be55-8e12df78b974", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "9d0c7f22-b432-4223-baf1-83dbfbca38db", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "8357d622-c8b1-428d-b134-3315622f398d", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "f373c5c3-0467-47c7-8aa4-f6fe1acfe380", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "1647396e-5d80-47c0-9780-1b0601d81f55", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "4b75ca24-90fb-46da-ba2b-ba11e96b9cee", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "df72819f-b96b-47b9-88f5-bf0033798b40", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "241c2432-5771-4a42-90f3-4198b6e9fd62", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Account verification options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "fc2f23d5-003a-4e2a-947b-8f426c52694c", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c152dd74-8690-4c1f-b83f-2da74289cc1e", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "db2da225-e43a-42ad-977f-508895169efa", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "6bda8474-8636-4bff-9e86-b95552f5944a", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2dcccc92-8c58-4b18-9773-a991977fc829", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "34a83f8f-e241-412e-93c5-398495bc8f2a", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 30, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "d3849e68-145f-44ac-a360-d16930a6eb09", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "30ed0330-9d8a-4992-aa0c-56313cf60790", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "User creation or linking", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2521a30f-27ba-441e-821b-8515f63380c9", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "3f9984f5-a163-4b57-a947-1a7b72240dec", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Authentication Options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "273c03f3-8fc2-4e81-a9f7-fbf72158e129", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "07afd274-0910-43d8-b627-422d4d9e2ed8", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "7b72931e-ad78-41fd-add0-1e622e208d55", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 40, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2e95fbe8-90de-4ad0-af7c-b8a598456a19", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "0c8464aa-a2ea-479e-9f21-e3b4ba670b46", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "060e864c-a566-4551-ba54-2c280aafda02", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": {}, + "keycloakVersion": "9.0.2", + "userManagedAccessAllowed": false +} \ No newline at end of file diff --git a/compose/kubedir/put.kubeconf.file.here b/compose/kubedir/put.kubeconf.file.here new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/compose/mysql-init/01-databases.sql b/compose/mysql-init/01-databases.sql new file mode 100644 index 0000000000000000000000000000000000000000..76e1ab47c3b2504d7701ad6f5840f5659e537b50 --- /dev/null +++ b/compose/mysql-init/01-databases.sql @@ -0,0 +1,12 @@ +# create databases +CREATE DATABASE IF NOT EXISTS `osdb`; +CREATE DATABASE IF NOT EXISTS `keycloak`; + +# create root user and grant rights +CREATE USER 'portaluser'@'localhost' IDENTIFIED BY '12345'; +GRANT ALL PRIVILEGES ON *.* TO 'portaluser'@'%' IDENTIFIED BY '12345'; + + +# create root user and grant rights +CREATE USER 'keycloak'@'localhost' IDENTIFIED BY 'password'; +GRANT ALL PRIVILEGES ON *.* TO 'keycloak'@'%' IDENTIFIED BY 'password'; diff --git a/compose/nginx/.gitignore b/compose/nginx/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..a772b85e8be4a0fc30cc75f23532e7ca1a45cd1f --- /dev/null +++ b/compose/nginx/.gitignore @@ -0,0 +1 @@ +/nginx.conf diff --git a/compose/nginx/certificates/readme.txt b/compose/nginx/certificates/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..6ee01e6cd3e3f0e7ce183be4294188732ec0ae8b --- /dev/null +++ b/compose/nginx/certificates/readme.txt @@ -0,0 +1,3 @@ +here to deploy the certificates +fullchain.pem +privkey.pem \ No newline at end of file diff --git a/compose/nginx/nginx.conf.default b/compose/nginx/nginx.conf.default new file mode 100644 index 0000000000000000000000000000000000000000..c2478c41a224135c92dcbc547e1aa8ff5d917171 --- /dev/null +++ b/compose/nginx/nginx.conf.default @@ -0,0 +1,105 @@ +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + client_max_body_size 5000M; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + #include /etc/nginx/conf.d/*.conf; + + server { + listen 80; + listen [::]:80; + server_name localhost; + + location / { + root /webstatic/services/; + index index.html; + try_files $uri $uri/ /index.html; + } + + location /nfvportal { + root /webstatic; + index index.html; + autoindex off; + try_files $uri $uri/ /nfvportal/index.html; + } + + location /osapi { + proxy_pass http://osportalapi:13000/osapi; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /tmf-api { + proxy_pass http://osscapi:13082/tmf-api; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /oas-api { + proxy_pass http://oasapi:13101/oas-api; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # For http + location /auth { + proxy_pass http://keycloak:8080/auth; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + } + + location /kroki { + rewrite /kroki/(.*) /$1 break; + proxy_pass http://kroki:8000; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + } + + # For https +# location /auth { +# proxy_pass https://keycloak:8443/auth; +# proxy_set_header X-Real-IP $remote_addr; +# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +# proxy_set_header Host $http_host; +# proxy_set_header X-Forwarded-Server $host; +# proxy_set_header X-Forwarded-Proto $scheme; +# proxy_set_header X-Forwarded-Port 443; +# } + + } + +} + diff --git a/compose/readme.txt b/compose/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..3896a14b8d5e1f2647b9c384e32ee1f95c49557f --- /dev/null +++ b/compose/readme.txt @@ -0,0 +1,109 @@ +backend API Development + +nginx.conf: +- comment location /osapi +- comment location /tmf-api +- comment location /oas-api + +fix auth location in nginx.conf as follows: + + location /auth { + proxy_pass http://keycloak:8080/auth; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + } + + +docker-compose --profile dev down;docker-compose --profile dev up -d + +Keycloak for development + + +Add 127.0.0.1 keycloak in your hosts file and replace http://localhost/auth/ with http://keycloak:8080/auth/ in your Keycloak config for TypeScript/Angular. + +Hosts File Location: + +In Linux/Unix, its location is at: /etc/hosts In windows, its location is at c:\Windows\System32\Drivers\etc\hosts. + +Explanation: + + The Nginx uses the http://keycloak:8080 URL which is the network inside the docker system. + The front-end (TS/Angular) uses the http://keycloak:8080 + You will not get the invalid token error, as you are getting the token from http://keycloak:8080 and as well verifying with the same URL. + + + +nginx serves already the frontend from the project org.etsi.osl.tmf.web + + + + +If you would like to use the frontend to test your backend config.prod.json should look similar to the following example + + +{ + "TITLE": "Openslice demo", + "PORTALVERSION":"1.1.0-SNAPSHOT", + "WIKI": "http://wiki.localhost", + "BUGZILLA": "{BASEURL}/bugzilla/", + "STATUS": "http://status.localhost/", + "WEBURL": "{BASEURL}", + "PORTAL_REPO_APIURL": "{BASEURL}/osapi", + "ASSURANCE_SERVICE_MGMT_APIURL": "{BASEURL}/oas-api", + "APITMFURL": "http://localhost:13082/tmf-api", + "OAUTH_CONFIG" : { + "issuer": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/auth", + "loginUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/auth", + "tokenEndpoint": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/token", + "redirectUri": "{BASEURL}/redirect", + "logoutUrl": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/logout", + "postLogoutRedirectUri": "{BASEURL}/services/services_marketplace", + + "responseType": "code", + "oidc": false, + "clientId": "osapiWebClientId", + "dummyClientSecret": "secret", + + "requireHttps": false, + "useHttpBasicAuth": true, + "clearHashAfterLogin": false, + + "showDebugInformation": true + } +} + + + +for the NFV frontend, config.js should be like the following: + +var appConfig = angular.module('portalwebapp.config',[]); + + +appConfig.factory('APIEndPointService', function() { + return { + TITLE: "Openslice", + WIKI: "ROOTURL", + BUGZILLA: "ROOTURL/bugzilla/", + STATUS: "ROOTURL/status/", + APIURL: "http://localhost:13000", + WEBURL: "ROOTURL/nfvportal", + APIOAUTHURL: "http://keycloak:8080/auth/realms/openslice", + APITMFURL: "http://localhost:13082/tmf-api/serviceCatalogManagement/v4" + + }; +}); + + + + + +--- + +Run openslice on host + +Build first + +docker-compose --profile prod down;docker-compose --profile prod up -d --build + + \ No newline at end of file diff --git a/doc/alarms_actions.md b/doc/alarms_actions.md new file mode 100644 index 0000000000000000000000000000000000000000..b7715494e2c504668c69d5a690197346fdb7be4b --- /dev/null +++ b/doc/alarms_actions.md @@ -0,0 +1,113 @@ +# Alarms + +In Openslice parts of TMF642 Alarm Management API are currently implemented. Alarms can be managed through the TMF API endpoint as well as the UI. + + + +## Alarms and Actions + +Note: Actions is an experimental feature. We expect to have a more mature solution in future. The component in the architecture is the Openslcie Assurance Services + +Alarms can be automatically resolved by specific actions. Today only the following actions are offered. + +* execDay2 +* scaleServiceEqually + + +## execDay2 + +Usually used to perform a Day2 configuration (towards OSM). To use it, Create a New Action Specification Name=execDay2 as following + +[![Openslice usage](./images/alarms_actions/day2actionspec.png)](./images/alarms_actions/day2actionspec.png) + + +Now make a Service Order for your service. In this example ςε used a cirros NSD + +Create a New Action Rule for the running services as the following example: + + +[![Openslice usage](./images/alarms_actions/action_rule_exampleday2.png)](./images/alarms_actions/action_rule_exampleday2.png) + +The scope is the running cirros service. + +Params should be paramname=value;paramname2=value2;paramname3=value3 (must exist in the VNF otherwise OSM will raise an error). + +In this case should be filename=test.txt + +Primitive=touch + +ServiceId = select the service which will accept the Day2. In this case is the same + +To test it: + +Go to the Service Inventory and select the active Service. + +Note the UUID of the service (e.g. c4e7990a-e174-4cd2-9133-b10e56721e08 copy from address bar), DeploymentRequestID and NSDID from characteristics + +You can either use the UUID of the service or the DeploymentRequestID and POST to the Alarms endpoint ( /tmf-api/alarmManagement/v4/alarm) + + +If the DeploymentRequestID is used then POST: + +``` + +{ + "alarmRaisedTime": "2021-06-29T12:30:24.675Z", + "alarmReportingTime": "2021-06-29T12:30:54.675Z", + "state": "raised", + "alarmType": "qualityOfServiceAlarm", + "probableCause": "thresholdCrossed", + "ackState": "unacknowledged", + "perceivedSeverity": "major", + "sourceSystemId": "mano-client-service", + "alarmDetails": "NSID=3;DeploymentRequestID=1", + "specificProblem": "myalram raised" +} + +``` + + +If the UUID is used then POST: + +``` + +{ + "alarmRaisedTime": "2021-06-29T12:30:24.675Z", + "alarmReportingTime": "2021-06-29T12:30:54.675Z", + "state": "raised", + "alarmType": "qualityOfServiceAlarm", + "probableCause": "thresholdCrossed", + "ackState": "unacknowledged", + "perceivedSeverity": "major", + "sourceSystemId": "mano-client-service", + "alarmDetails": "analarm", + "specificProblem": "myalram raised", + "affectedService": [ + { + "id": "c4e7990a-e174-4cd2-9133-b10e56721e08" + } + ] + +} + +``` + +The Alarm to be created must have the affected Service ID equal to the running service from the scope (the cirros_ns) + +Go to service inventory you will see the notes and also the service characteristics for any EXEC_ACTION updates + +You can also adjust the alarm conditions. They must match true so the alarm to be acknowledged +So if another external service raises an Alarm (with POST) for the running service, a Day2 will be performed on another Service + + +## scaleServiceEqually + + +This action is used from getting a scaling event from OSM. Please see the next demo for details on how it works + + +### Prototype demo + +You can watch how we used the prototype on the following ETSI ZMS PoC #2 + +* ETSI ZMS PoC #2: diff --git a/doc/architecture/architecture.md b/doc/architecture/architecture.md new file mode 100644 index 0000000000000000000000000000000000000000..9181348600e7706d51ec95802c023ccc68a3982b --- /dev/null +++ b/doc/architecture/architecture.md @@ -0,0 +1,49 @@ +# Architecture + + +Openslice offers the following main functionalities: + +* Service Catalog Management: A CSP will have the ability to manage the Service Catalog Items, their attributes , organize in categories and decide what to make available to Customers +* Services Specifications: A CSP will be able to manage Service Specifications +* Service Catalog Exposure: A CSP will be able to expose catalog to customers and related parties +* Service Catalog to Service Catalog: Openslice able to consume and provide Service Catalog items to other catalogs +* Service Order: The Customer will be able to place a Service Order +* Service Inventory: The Customer and Provider will be able to view deployed Services status + + +The following figure displays the overall architecture of Openslice. + +[![Openslice architecture](../images/architecture.png)](../images/architecture.png) + + +Openslice allows Vertical Customers browsing the available offered service specifications. It consists of: + +* Web frontend UIs that consist of mainly two portals: i) a NFV portal allowing users self-service management and onboarding VNFDs/NSDs to facility’s NFVO ii) a Services Portal, which allows users to browse the Service Catalog, Service Blueprints specifications and the Service Inventory +* An API gateway that proxies the internal APIs and used by the web front end as well as any other 3rd party service +* A Message Bus where all microservices use it to exchange messages either via message queues or via publish/subscribe topics +* An authentication server implementing Oauth2 authentication scheme +* A microservice offering TMF compliant API services (eg Service Catalog API, Service Ordering APIetc) +* A microservice offering NFV API services (eg VNF/NSD onboarding etc) and allows to store VNFDs and NSDs in a catalog +* A microservice that is capable to interface to an issue management system. For example it raises an issue to all related stakeholders (CSP, NOP, CSC) that a new Service Order is requested +* Central logging microservice that is capable to log all distributed actions in to an Elasticsearch cluster +* A Service Orchestrator solution that will propagate Service Ordering requests to the equivalent SOs and NFVOs + + +The following figure depicts how Openslice microservices are deployed + +[![Openslice microservices network deployment](../images/microservices_network_deployment.png)](../images/microservices_network_deployment.png) + + + +## Deploying Openslice in multi domain scenarios + +A typical deployment across domains, involves today some typical components: i) an OSS/BSS to allow customers access the service catalog and perform service orders, ii) a Service Orchestrator (SO) component for executing the service order workflow, as well as iii) a Network Functions Virtualization Orchestrator (NFVO) for configuring the iv) network resources. + +TMF Open APIs are introduced not only for exposing catalogues and accepting service orders, but also implementing the East-West interfaces between the domains, fulfilling also the LSO requirements as introduced by MEF. + +The following figure shows how openslice could be used in such scenarios: + +[![Openslice multi-domain-architecture](../images/multi-domain-architecture.png)](../images/multi-domain-architecture.png) + + +See more [Consuming Services From External Partner Organizations](./consumingServicesFromExternalPartners.md) diff --git a/doc/architecture/centrallog.md b/doc/architecture/centrallog.md new file mode 100644 index 0000000000000000000000000000000000000000..a6cbc2b8f2572e1dabf61324306b4c7326998e13 --- /dev/null +++ b/doc/architecture/centrallog.md @@ -0,0 +1,5 @@ +# Central Logging + +Openslice follows the centralized log management concept, i.e. a type of logging solution system that consolidates the log data from different services and pushes it to a central, accessible and easy-to-use interface. + +For that reason, Elasticsearch is elected as an open-source centralized logging solution for collecting, parsing and storing logs towards a real-time data analytics tool that provides insights from any type of structured and unstructured data source. \ No newline at end of file diff --git a/doc/architecture/consumingServicesFromExternalPartners.md b/doc/architecture/consumingServicesFromExternalPartners.md new file mode 100644 index 0000000000000000000000000000000000000000..090a9f754b059ee4dd5251f9bfc7ccfcca15063f --- /dev/null +++ b/doc/architecture/consumingServicesFromExternalPartners.md @@ -0,0 +1,185 @@ +# Consuming Services From External Partner Organizations + +A typical deployment across domains, involves today some typical components: i) an OSS/BSS to allow customers access the service catalog and perform service orders, ii) a Service Orchestrator (SO) component for executing the service order workflow, as well as iii) a Network Functions Virtualization Orchestrator (NFVO) for configuring the iv) network resources. + +TMF Open APIs are introduced not only for exposing catalogues and accepting service orders, but also implementing the East-West interfaces between the domains, fulfilling also the LSO requirements as introduced by MEF. + +The following figure shows how openslice could be used in such scenarios: + +[![Openslice multi-domain-architecture](../images/multi-domain-architecture.png)](../images/multi-domain-architecture.png) + + +In Openslice we can consume services from 3rd parties via Open APIs. + +We use the TMF 632 Party Management model to specify Organizations that we can exchange items and other information such as: + +- Import Service Specifications +- Create a Service Order +- Use the Service Inventory to query the status of the service ordered to the external partner organization + +## Define an Organization as 3rd party to consume services East-West + +An organization must have the following characteristics in openslice catalog, like for example: + +"EXTERNAL_TMFAPI_BASEURL", "http://portal.openslice.io" + +"EXTERNAL_TMFAPI_CLIENTREGISTRATIONID", "authOpensliceProvider" + +"EXTERNAL_TMFAPI_OAUTH2CLIENTID", "osapiWebClientId" + +"EXTERNAL_TMFAPI_OAUTH2CLIENTSECRET", "secret" + +"EXTERNAL_TMFAPI_OAUTH2SCOPES", scopes + +"EXTERNAL_TMFAPI_OAUTH2TOKENURI", "http://portal.openslice.io/osapi-oauth-server/oauth/token" + +"EXTERNAL_TMFAPI_USERNAME", "admin" + +"EXTERNAL_TMFAPI_PASSWORD", "openslice" + +"EXTERNAL_TMFAPI_SERVICE_CATALOG_URLS" = "/tmf-api/serviceCatalogManagement/v4/serviceSpecification?type=CustomerFacingServiceSpecification" (this is optional, fetch a list of service specs it will be relative with the BASEURL. If the url is empty then no specs will be fetched, the EXTERNAL_TMFAPI_SERVICE_CATEGORY_URLS might be used) + +"EXTERNAL_TMFAPI_SERVICE_CATEGORY_URLS" = "/tmf-api/serviceCatalogManagement/v4/serviceCategory/{categoryid}" (this example will fetch all specs in a category. You may define comma separated URLs of categories API URL . This will fetch specifications of every defined category. If you want only one specific category put for example the uuid only of one category: "/tmf-api/serviceCatalogManagement/v4/serviceCategory/bda02821-bc4d-4bd6-b64b-d9c2aa5f8e6d". multiple urls should be "/tmf-api/serviceCatalogManagement/v4/serviceCategory/bda02821-bc4d-4bd6-b64b-d9c2aa5f8e6d,/tmf-api/serviceCatalogManagement/v4/serviceCategory/9b6d8bf3-abd2-43c4-8154-c8c6fe5545b2") + +"EXTERNAL_TMFAPI_SERVICE_SPEC" = "/tmf-api/serviceCatalogManagement/v4/serviceSpecification" + +"EXTERNAL_TMFAPI_SERVICE_ORDER_URLS"= "/test/v1/serviceorder" (this is optional) + + +An example Organization defined example in json: +``` + +{ + "uuid": "1a09a8b5-6bd5-444b-b0b9-a73c69eb42ae", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": null, + "href": null, + "name": "Openslice.io", + "id": "1a09a8b5-6bd5-444b-b0b9-a73c69eb42ae", + "isHeadOffice": null, + "isLegalEntity": null, + "nameType": null, + "organizationType": null, + "tradingName": null, + "contactMedium": [], + "creditRating": [], + "existsDuring": null, + "externalReference": [], + "organizationChildRelationship": [], + "organizationIdentification": [], + "organizationParentRelationship": null, + "otherName": [], + "partyCharacteristic": [ + { + "uuid": "3a2f7221-e0a2-4a6b-88d1-534c8e1963f6", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": null, + "href": null, + "name": "EXTERNAL_TMFAPI_CLIENTREGISTRATIONID", + "valueType": null, + "value": { + "value": "authOpensliceProvider", + "alias": null + } + }, + { + "uuid": "c24bb527-f178-4d38-9b93-2027c1732876", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": null, + "href": null, + "name": "EXTERNAL_TMFAPI_USERNAME", + "valueType": null, + "value": { + "value": "admin", + "alias": null + } + }, + { + "uuid": "27e45df8-414b-44c6-a5d5-3f064e2cfd3b", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": null, + "href": null, + "name": "EXTERNAL_TMFAPI_PASSWORD", + "valueType": null, + "value": { + "value": "openslice", + "alias": null + } + }, + { + "uuid": "e0e470b8-6024-4014-8a18-2333e5465ce1", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": null, + "href": null, + "name": "EXTERNAL_TMFAPI_OAUTH2CLIENTSECRET", + "valueType": null, + "value": { + "value": "secret", + "alias": null + } + }, + { + "uuid": "3e0de762-ac80-4c1e-a0a1-f265ff0899b4", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": null, + "href": null, + "name": "EXTERNAL_TMFAPI_OAUTH2SCOPES", + "valueType": null, + "value": { + "value": "admin;read", + "alias": null + } + }, + { + "uuid": "0bbb8314-f7f2-420d-9fed-ba054b15f886", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": null, + "href": null, + "name": "EXTERNAL_TMFAPI_OAUTH2TOKENURI", + "valueType": null, + "value": { + "value": "http://portal.openslice.io/osapi-oauth-server/oauth/token", + "alias": null + } + }, + { + "uuid": "3a567de4-79eb-4006-a500-3e5229b44175", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": null, + "href": null, + "name": "EXTERNAL_TMFAPI_OAUTH2CLIENTID", + "valueType": null, + "value": { + "value": "osapiWebClientId", + "alias": null + } + }, + { + "uuid": "6dca729f-dbe1-46b7-89f1-5c4f9fe89d4e", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": null, + "href": null, + "name": "EXTERNAL_TMFAPI_BASEURL", + "valueType": null, + "value": { + "value": "http://portal.openslice.io", + "alias": null + } + } + ], + "relatedParty": [], + "status": null, + "taxExemptionCertificate": [] +} + +``` + \ No newline at end of file diff --git a/doc/architecture/issuemgt.md b/doc/architecture/issuemgt.md new file mode 100644 index 0000000000000000000000000000000000000000..b50f5459a186f1eff82bebcb5e805c0752d6dde8 --- /dev/null +++ b/doc/architecture/issuemgt.md @@ -0,0 +1,7 @@ +# Issue Management + +For issue management support, Openslice relies on Bugzilla. Bugzilla is a ticketing tool that allows issue reporting and tracking via tickets to all relevant stakeholders. + +The figure below displays the overall issue management service architecture integrating Bugzilla as its core and how this tool interacts with other Openslice services presenting some distinctive scenarios. It should be noted that Bugzilla tickets will not only be used for bugs/errors, but also for general requests, e.g. Service Order procedure. + +[![Issue management system](../images/issue_management.png)](../images/issue_management.png) \ No newline at end of file diff --git a/doc/architecture/messagebus.md b/doc/architecture/messagebus.md new file mode 100644 index 0000000000000000000000000000000000000000..a228afb52670b03e7036a2199cbfecd1454a2d50 --- /dev/null +++ b/doc/architecture/messagebus.md @@ -0,0 +1,816 @@ +# Message Bus and exchanged Messages + +Openslice has a Message bus which allows Openslice services to exchange messages via queues and topics. + +It is based on ActiveMQ. + +3rd party services can be attached to bus and subscribe to message topics or request resources via queues. + + +## QUEUE MESSAGES + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_SERVICEORDERS | +|**Name** | jms:queue:CATALOG.GET.SERVICEORDERS | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | | +|**Description** | Return a List as String Json| + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_SERVICEORDER_BY_ID | +|**Name** | jms:queue:CATALOG.GET.SERVICEORDER_BY_ID | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | String orderid | +|**Description** | Return a ServiceOrder as String Json | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_UPD_SERVICEORDER_BY_ID | +|**Name** | jms:queue:CATALOG.UPD.SERVICEORDER_BY_ID | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | ServiceOrderUpdate serviceOrder | +|**Headers** | "orderid"= orderid | +|**Description** | Returns a ServiceOrder as String | + + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_SERVICESPEC_BY_ID | +|**Name** | jms:queue:CATALOG.GET.SERVICESPEC_BY_ID | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | specid | +|**Description** | Return a ServiceSpecification | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_ADD_SERVICESPEC | +|**Name** | jms:queue:CATALOG.ADD.SERVICESPEC | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | CRIDGE | +|**Body** | ServiceSpecCreate | +|**Description** | Creates a ServiceSpecification and returns a ServiceSpecification as String | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_UPD_SERVICESPEC | +|**Name** | jms:queue:CATALOG.UPD.SERVICESPEC | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | CRIDGE | +|**Body** | ServiceSpecUpdate | +|**Headers** | "serviceSpecid" = serviceSpecId| +|**Description** | Updates a ServiceSpecification and returns a ServiceSpecification as String. | +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_UPDADD_SERVICESPEC | +|**Name** | jms:queue:CATALOG.UPDADD.SERVICESPEC | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | CRIDGE | +|**Body** | ServiceSpecUpdate | +|**Headers** | "serviceSpecid" = serviceSpecId, "forceId"=forceId | +|**Description** | Updates a ServiceSpecification and returns a ServiceSpecification as String. If forceId is true then tries to assign the requested ID to the spec | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_ADD_SERVICEORDER | +|**Name** | jms:queue:CATALOG.ADD.SERVICEORDER | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | ServiceOrderCreate serviceOrder | +|**Headers** | | +|**Description** | Creates a ServiceOrder and returns a ServiceOrder as String | + +--- + + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_INITIAL_SERVICEORDERS_IDS | +|**Name** | jms:queue:CATALOG.GET.INITIAL_SERVICEORDERS | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | | +|**Body** | | +|**Description** | Return a List as String Json| + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_SERVICEORDER_IDS_BY_STATE | +|**Name** | jms:queue:CATALOG.GET.ACKNOWLEDGED_SERVICEORDERS | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | | +|**Headers** | "orderstate"= orderState | +|**Description** | String Json ArrayList of ServiceOrders | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_ADD_SERVICE | +|**Name** | jms:queue:CATALOG.ADD.SERVICE | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | ServiceCreate String json | +|**Headers** | "orderid"=orderid, "serviceSpecid"= specid | +|**Description** | Creates Service based an a Service Spec, Returns a Service object | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_UPD_SERVICE | +|**Name** | jms:queue:CATALOG.UPD.SERVICE | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | | +|**Body** | ServiceUpdate | +|**Headers** | "serviceid" = serviceId, "propagateToSO" = true/false | +|**Description** | will update a service by id and return the service instance. If propagateToSO=true then any service change will be handled by OSOM. This is needed to be controlled in order to avoid update loops| + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_SERVICE_BY_ID | +|**Name** | jms:queue:CATALOG.GET.SERVICE | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | String serviceID | +|**Description** | returns a Service instance | + +---| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_SERVICE_BY_ORDERID | +|**Name** | jms:queue:CATALOG.GET.SERVICE_BY_ORDERID | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | | +|**Body** | String serviceID | +|**Description** | returns Service IDs of a specific order given then order id | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_SERVICE_QUEUE_ITEMS_GET | +|**Name** | jms:queue:CATALOG.SERVICEQUEUEITEMS.GET | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | | +|**Description** | returns a LIST OF Service Queue Items | +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_SERVICE_QUEUE_ITEM_UPD | +|**Name** | jms:queue:CATALOG.SERVICEQUEUEITEM.UPDATE | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | String SERVICEQUEUEITEM | +|**Headers** | "itemid" = SERVICEQUEUEITEM id | +|**Description** | ill update a service queue item by id and return the instance | +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_SERVICE_QUEUE_ITEM_DELETE | +|**Name** | jms:queue:CATALOG.SERVICEQUEUEITEM.DELETE | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | | +|**Headers** | "itemid" = SERVICEQUEUEITEM id | +|**Description** | ill delete a service queue item by id | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_SERVICES_TO_TERMINATE | +|**Name** | jms:queue:CATALOG.GET.SERVICETOTERMINATE | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | | +|**Headers** | | +|**Description** | Get a list of ACTIVE services with END DAte in the past | +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_SERVICES_OF_PARTNERS | +|**Name** | jms:queue:CATALOG.GET.SERVICESOFPARTNERS | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | | +|**Headers** | | +|**Description** | Get a list of ACTIVE services from the inventory of partners | + + + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | NFV_CATALOG_GET_NSD_BY_ID | +|**Name** | jms:queue:NFVCATALOG.GET.NSD_BY_ID | +|**Type** | queue | +|**Destination** | NFV Catalog service | +|**Producers** | TMF API, OSOM | +|**Body** | NSDid | +|**Description** | Returns a NetworkServiceDescriptor object | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | NFV_CATALOG_DEPLOY_NSD_REQ | +|**Name** | jms:queue:NFVCATALOG.DEPLOY.NSD_REQ | +|**Type** | queue | +|**Destination** | NFV Catalog service | +|**Producers** | OSOM | +|**Body** | DeploymentDescriptor as Json String | +|**Headers** | NSD id | +|**Description** | Returns a DeploymentDescriptor object as json string containing deployment info| + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | NFV_CATALOG_UPD_DEPLOYMENT_BY_ID | +|**Name** | jms:queue:NFVCATALOG.UPD.DEPLOYMENT_BY_ID | +|**Type** | queue | +|**Destination** | NFV Catalog service | +|**Producers** | OSOM | +|**Body** | DeploymentDescriptor as Json String | +|**Headers** | DeploymentDescriptor id | +|**Description** | Updates and Returns a DeploymentDescriptor object as json string containing deployment info| + +--- + + + +| Message | | +| ------------- |----------------| +|**Alias** | GET_USER_BY_USERNAME | +|**Name** | jms:queue:GET.USER_BY_USERNAME | +|**Type** | queue | +|**Destination** | NFV Catalog service (this is temproary for now) | +|**Producers** | TMF API | +|**Body** | username | +|**Headers** | | +|**Description** | Returns a PortalUser object as json string containing user info| + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | NFV_CATALOG_GET_DEPLOYMENT_BY_ID | +|**Name** | jms:queue:NFVCATALOG.GET.DEPLOYMENT_BY_ID | +|**Type** | queue | +|**Destination** | NFV Catalog service | +|**Producers** | OSOM | +|**Body** | Deployment ID | +|**Description** | Returns a DeploymentDescriptor object | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_EXTERNAL_SERVICE_PARTNERS | +|**Name** | jms:queue:CATALOG.GET.EXTERNALSERVICEPARTNERS | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | | +|**Headers** | | +|**Description** | As a String Json ArrayList of Organizaton objects containing the characteristic name **EXTERNAL_TMFAPI** | + +--- + + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_UPD_EXTERNAL_SERVICESPEC | +|**Name** | jms:queue:CATALOG.UPD.EXTERNAL_SERVICESPEC | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM or maybe used by others that would like to update a Service Spec | +|**Body** | A serviceSpecification as json string | +|**Headers** | servicespecification id, orgid id | +|**Description** | Updates (or inserts if does not exist in catalog) an external service specification) | + +--- + + + + +| Message | | +| ------------- |----------------| +|**Alias** | NFV_CATALOG_NSACTIONS_SCALE | +|**Name** | jms:queue:NSACTIONS.SCALE | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM or maybe used by others that would like scale a NS | +|**Body** | A ScaleDescriptor as json string | +|**Headers** | none | +|**Description** | performs a scale | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | NFV_CATALOG_NS_LCMCHANGED | +|**Name** | NFV_CATALOG_NS_LCMCHANGED | +|**Type** | topic | +|**Destination** | any | +|**Producers** | MANO client | +|**Body** | A json string | +|**Headers** | none | +|**Description** | A NFV_CATALOG_NS_LCMCHANGED message is published when LCM of a running NS is changed | + +--- + +#ALARMS + + +| Message | | +| ------------- |----------------| +|**Alias** | ALARMS_ADD_ALARM | +|**Name** | jms:queue:ALARMS.ADD.ALARM | +|**Type** | queue | +|**Publishers** | | +|**Consumers** | TMF API | +|**Body** | AlarmCreate | +|**Headers** | | +|**Description** | Add an alarm | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | ALARMS_UPDATE_ALARM | +|**Name** | jms:queue:ALARMS.UPDATE.ALARM | +|**Type** | queue | +|**Publishers** | | +|**Consumers** | TMF API | +|**Body** | AlarmUpdate | +|**Headers** | alarmid = alarm id, body (AlarmUpdate object) | +|**Description** | Update an alarm | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | ALARMS_GET_ALARM | +|**Name** | jms:queue:ALARMS.GET.ALARM | +|**Type** | queue | +|**Publishers** | | +|**Consumers** | TMF API | +|**Body** | | +|**Headers** | alarmid = alarm id | +|**Description** | get an alarm | + +--- + +## EVENT TOPICS IN Message Bus +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_SERVICE_CREATE | +|**Name** | jms:topic:EVENT.SERVICE.CREATE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | - | +|**Body** | Notification object | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | xx | + +--- +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_SERVICE_STATE_CHANGED | +|**Name** | jms:topic:EVENT.SERVICE.STATECHANGED | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | - | +|**Body** | Notification object | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | xx | + +--- +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_SERVICE_DELETE | +|**Name** | jms:topic:EVENT.SERVICE.DELETE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | - | +|**Body** | Notification object. Can be one of ServiceOrderCreateNotification, ServiceOrderStateChangeNotification, ServiceOrderAttributeValueChangeNotification, ServiceOrderDeleteNotification, etc | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | xx | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED | +|**Name** | jms:topic:EVENT.SERVICE.ATTRCHANGED | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | - | +|**Body** | Notification object. Can be one of ServiceOrderCreateNotification, ServiceOrderStateChangeNotification, ServiceOrderAttributeValueChangeNotification, ServiceOrderDeleteNotification, etc | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | xx | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_SERVICE_ORDER_CREATE | +|**Name** | jms:topic:EVENT.SERVICEORDER.CREATE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | BUGZILLA Service, CentralLog Service | +|**Body** | Notification object. Can be one of ServiceOrderCreateNotification, ServiceOrderStateChangeNotification, ServiceOrderAttributeValueChangeNotification, ServiceOrderDeleteNotification, etc | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | The Event of the Notification object contains the ServiceOrder object. Bugzilla service for example uses this to create a new issue | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_SERVICE_ORDER_STATE_CHANGED | +|**Name** | jms:topic:EVENT.SERVICEORDER.STATECHANGED | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | BUGZILLA Service, CentralLog Service | +|**Body** | Notification object. Can be one of ServiceOrderCreateNotification, ServiceOrderStateChangeNotification, ServiceOrderAttributeValueChangeNotification, ServiceOrderDeleteNotification, etc | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | The Event of the Notification object contains the ServiceOrder object. Bugzilla service for example uses this to update an issue | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_SERVICE_ORDER_DELETE | +|**Name** | jms:topic:EVENT.SERVICEORDER.DELETE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | BUGZILLA Service, CentralLog Service | +|**Body** | Notification object. Can be one of ServiceOrderCreateNotification, ServiceOrderStateChangeNotification, ServiceOrderAttributeValueChangeNotification, ServiceOrderDeleteNotification, etc | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | The Event of the Notification object contains the ServiceOrder object | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_SERVICE_ORDER_ATTRIBUTE_VALUE_CHANGED | +|**Name** | jms:topic:EVENT.SERVICEORDER.ATTRCHANGED | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | BUGZILLA Service, CentralLog Service | +|**Body** | Notification object. Can be one of ServiceOrderCreateNotification, ServiceOrderStateChangeNotification, ServiceOrderAttributeValueChangeNotification, ServiceOrderDeleteNotification, etc | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | The Event of the Notification object contains the ServiceOrder object | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_ALARM_CREATE | +|**Name** | jms:topic:EVENT.ALARM.CREATE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | OAS, BUGZILLA Service, CentralLog Service | +|**Body** | AlarmCreateEvent | +|**Headers** | | +|**Description** | The Event contains the Alarm object in payload | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_ADD_RESOURCE | +|**Name** | jms:queue:CATALOG.ADD.RESOURCE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | ResourceCreate | +|**Headers** | | +|**Description** | The Body contains the ResourceCreate object to add | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_UPD_RESOURCE | +|**Name** | jms:queue:CATALOG.UPD.RESOURCE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | ResourceUpdate | +|**Headers** | resourceid , propagateToSO | +|**Description** | The Body contains the ResourceCreate object to update | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_RESOURCE_BY_ID | +|**Name** | jms:queue:CATALOG.GET.RESOURCE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | resourceid | +|**Headers** | | +|**Description** | The Body contains the ResourceCreate object to update | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_RESOURCES_OF_PARTNERS | +|**Name** | jms:queue:CATALOG.GET.SERVICESOFPARTNERS | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | none | +|**Headers** | none | +|**Description** | retrieve all active services of partners | + +--- +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_ADD_RESOURCESPEC | +|**Name** | jms:queue:CATALOG.ADD.RESOURCESPEC | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | ResourceSpecificationCreate | +|**Headers** | | +|**Description** | The Body contains the ResourceSpecificationCreate object to add | + +--- +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_UPD_RESOURCESPEC | +|**Name** | jms:queue:CATALOG.UPD.RESOURCESPEC | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | ResourceSpecificationUpdate | +|**Headers** | resourceSpecId | +|**Description** | The Body contains the ResourceSpecificationCreate object to update | + + +--- +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_RESOURCESPEC_BY_ID | +|**Name** | jms:queue:CATALOG.GET.RESOURCESPEC_BY_ID | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | resourceSpecid | +|**Headers** | | +|**Description** | The Body contains the object id to find | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_UPDADD_RESOURCESPEC | +|**Name** | jms:queue:CATALOG.UPDADD.RESOURCESPEC | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | resourceid | +|**Headers** | | +|**Description** | The Body contains the ResourceSpecificationCreate object to update or create if not exist | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_RESOURCE_CREATE | +|**Name** | jms:topic:EVENT.RESOURCE.CREATE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | BUGZILLA Service, CentralLog Service, other | +|**Body** | Notification object. | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | The Event of the Notification object contains the Resource object | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_RESOURCE_STATE_CHANGED | +|**Name** | jms:topic:EVENT.RESOURCE.STATECHANGED | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | BUGZILLA Service, CentralLog Service, other | +|**Body** | Notification object. | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | The Event of the Notification object contains the Resource object | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_RESOURCE_DELETE | +|**Name** | jms:topic:EVENT.SERVICE.RESOURCE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | BUGZILLA Service, CentralLog Service, other | +|**Body** | Notification object. | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | The Event of the Notification object contains the Resource object | + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | EVENT_RESOURCE_ATTRIBUTE_VALUE_CHANGED | +|**Name** | jms:topic:EVENT.RESOURCE.ATTRCHANGED | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | BUGZILLA Service, CentralLog Service, other | +|**Body** | Notification object. | +|**Headers** | "eventid"=eventid, "objId"= objId | +|**Description** | The Event of the Notification object contains the Resource object | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_LCMRULE_BY_ID | +|**Name** | jms:queue:CATALOG.GET.LCMRULE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | lcmid | +|**Headers** | | +|**Description** | The Body contains the LCMRuleSpec object | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_LCMRULES_BY_SPECID_PHASE | +|**Name** | jms:queue:CATALOG.GET.LCMRULES_BY_SPECID_PHASE | +|**Type** | topic | +|**Publishers** | TMF API | +|**Consumers** | any | +|**Body** | | +|**Headers** | header.servicespecid, header.phasename | +|**Description** | The Body contains the LCMRuleSpec objects of the specific Service Spec and the specific phase | + + + + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_SERVICETESTSPEC_BY_ID | +|**Name** | jms:queue:CATALOG.GET.SERVICETESTSPEC_BY_ID | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | specid | +|**Description** | Return a ServiceTestSpecification | + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_ADD_SERVICETEST | +|**Name** | jms:queue:CATALOG.ADD.SERVICETEST | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | ServiceTestCreate String json | +|**Headers** | "orderid"=orderid, "serviceTestSpecid"= specid | +|**Description** | Creates Service Test based an a Service Test Spec, Returns a ServiceTest object | + +--- + + + + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_UPD_SERVICETEST | +|**Name** | jms:queue:CATALOG.UPD.SERVICETEST | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | | +|**Body** | ServiceTestUpdate | +|**Headers** | "serviceid" = serviceId, "propagateToSO" = true/false | +|**Description** | will update a service test by id and return the service instance. If propagateToSO=true then any service change will be handled by OSOM. This is needed to be controlled in order to avoid update loops| + +--- + + +| Message | | +| ------------- |----------------| +|**Alias** | CATALOG_GET_SERVICETEST_BY_ID | +|**Name** | jms:queue:CATALOG.GET.SERVICETEST | +|**Type** | queue | +|**Destination** | TMF API service | +|**Producers** | OSOM | +|**Body** | String serviceID | +|**Description** | returns a Service TEST instance | + + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CRD_DEPLOY_CR_REQ | +|**Name** | jms:queue:CRD.DEPLOY.CR_REQ | +|**Type** | queue | +|**Destination** | CRD service | +|**Producers** | OSOM | +|**Body** | CR spec as String | +|**Headers** | related service id | +|**Description** | Returns a String object containing deployment info| + +--- + +| Message | | +| ------------- |----------------| +|**Alias** | CRD_PATCH_CR_REQ | +|**Name** | jms:queue:CRD.PATCH.CR_REQ | +|**Type** | queue | +|**Destination** | CRD service | +|**Producers** | OSOM | +|**Body** | CR as String | +|**Headers** | related service id | +|**Description** | Returns a String object containing PATCH info| + + +| Message | | +| ------------- |----------------| +|**Alias** | CRD_DELETE_CR_REQ | +|**Name** | jms:queue:CRD.DELETE.CR_REQ | +|**Type** | queue | +|**Destination** | CRD service | +|**Producers** | OSOM | +|**Body** | CR as String | +|**Headers** | related service id | +|**Description** | Returns a String object containing deletion info| \ No newline at end of file diff --git a/doc/architecture/nfvapi.md b/doc/architecture/nfvapi.md new file mode 100644 index 0000000000000000000000000000000000000000..f31f195812fda0c41cf8165c5448c32a4931884c --- /dev/null +++ b/doc/architecture/nfvapi.md @@ -0,0 +1,207 @@ +# API interaction + +## OAuth token + +See [oauth](./oauth.md) + +## Request a protected API resource + +Example: Get all vxfs (check the `Authorization:Bearer` to be correct) + +``` +curl -H "Authorization:Bearer eybGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbIm9wZW5hcGkiLCJhZG1pbiIsInJlYWQiLCJ3cml0ZSJdLCJvcmdhbml6YXRpb24iOiJteW9yZ2FuaXp0aW9uIiwiZXhwIjoxNTcxOTI0MjU2LCJhdXRob3JpdGllcyI6WyJST0xFX01FTlRPUiIsIlJPTEVfQURNSU4iXSwianRpIjoiNzNkZmIxODEtNTMwOS00MmExLThkOWUtOGM3YmQ0YTE1YmU0IiwiY2xpZW50X2lkIjoib3NhcGlXZWJDbGllbnRJZE91dCJ9.Pj_hxnyMGhFhN8avU_DiAw1-LlcaIz5Hp9HNqalw-X4" http://localhost:13000/osapi/admin/vxfs +``` +Example response: + +``` +[ + { + "id": 1, + "owner": { + "id": 1, + "organization": "ee", + "name": "Portal Administrator", + "email": "", + "username": "admin", + "createdAt": null + }, + "uuid": "a954daf2-16da-4b7e-ae42-4825936d453c", + "name": "cirros_vnfd", + "iconsrc": "/osapi/images/a954daf2-16da-4b7e-ae42-4825936d453c/cirros-64.png", + "shortDescription": "cirros_vnfd", + "longDescription": "Simple VNF example with a cirros", + "version": "1.0", + "packageLocation": "/osapi/packages/a954daf2-16da-4b7e-ae42-4825936d453c/cirros_vnf.tar.gz", + "dateCreated": 1568971426000, + "dateUpdated": 1568981107000, + "categories": [ + { + "id": 3, + "name": "Service", + "productsCount": 1, + "appscount": 0, + "vxFscount": 1 + }, + { + "id": 2, + "name": "Networking", + "productsCount": 1, + "appscount": 0, + "vxFscount": 1 + } + ], + "extensions": [], + "validationJobs": [], + "screenshots": "", + "vendor": "OSM", + "published": false, + "termsOfUse": null, + "descriptor": "vnfd-catalog:\n vnfd:\n - connection-point:\n - name: eth0\n type: VPORT\n description: Simple VNF example with a cirros\n id: cirros_vnfd\n logo: cirros-64.png\n mgmt-interface:\n cp: eth0\n name: cirros_vnfd\n short-name: cirros_vnfd\n vdu:\n - count: 1\n description: cirros_vnfd-VM\n id: cirros_vnfd-VM\n image: cirros034\n interface:\n - external-connection-point-ref: eth0\n name: eth0\n position: '1'\n type: EXTERNAL\n virtual-interface:\n bandwidth: '0'\n type: VIRTIO\n vpci: 0000:00:0a.0\n name: cirros_vnfd-VM\n vm-flavor:\n memory-mb: 512\n storage-gb: 1\n vcpu-count: 1\n vendor: OSM\n version: '1.0'\n", + "descriptorHTML": "

cirros_vnfd


Vendor: OSM
Version: 1.0
Description: Simple VNF example with a cirros
VM Count: 1
vCPU Count: 1
Memory: 512 MB
Storage: 1 GB
", + "certified": false, + "certifiedBy": null, + "validationStatus": "UNDER_REVIEW", + "packagingFormat": "OSMvFIVE", + "supportedMANOPlatforms": [ + { + "id": 1, + "name": "osm fivee", + "version": "osm fivee", + "description": "osm five" + } + ], + "vxfOnBoardedDescriptors": [], + "vfimagesVDU": [ + { + "id": 1, + "name": "cirros034", + "uuid": "d4549610-8abd-42ad-97f4-0a64e1c93977", + "shortDescription": "Automatically created during vxf cirros_vnfd submission. Owner must update.", + "packageLocation": null, + "publicURL": null, + "dateCreated": 1568971426000, + "dateUpdated": null, + "refVxFs": [ + { + "id": 1, + "name": "cirros_vnfd" + } + ], + "owner": { + "id": 1, + "organization": "ee", + "name": "Portal Administrator", + "email": "", + "username": "admin", + "active": true, + "currentSessionID": null, + "apikey": "e41c1cc4-aa56-4b7e-9f4d-64589549d768", + "createdAt": 1568711859000, + "roles": [ + "ADMIN", + "MENTOR" + ] + }, + "published": false, + "termsOfUse": null, + "deployedInfrastructures": [] + } + ] + }, + { + "id": 2, + "owner": { + "id": 1, + "organization": "ee", + "name": "Portal Administrator", + "email": "", + "username": "admin", + "createdAt": null + }, + "uuid": "4ab80095-a63e-4fe7-8598-e1c7e880706e", + "name": "cirros_sriov_vnfd", + "iconsrc": null, + "shortDescription": "cirros_sriov_vnf", + "longDescription": "Simple VNF example with a cirros SRIOV interface", + "version": "1.0", + "packageLocation": "/osapi/packages/4ab80095-a63e-4fe7-8598-e1c7e880706e/cirros_sriov.tar.gz", + "dateCreated": 1568971740000, + "dateUpdated": 1568981100000, + "categories": [ + { + "id": 4, + "name": "tyu", + "productsCount": 1, + "appscount": 0, + "vxFscount": 1 + }, + { + "id": 5, + "name": "tyi", + "productsCount": 1, + "appscount": 0, + "vxFscount": 1 + } + ], + "extensions": [], + "validationJobs": [], + "screenshots": "", + "vendor": "OSM", + "published": false, + "termsOfUse": null, + "descriptor": "vnfd:vnfd-catalog:\n vnfd:\n - connection-point:\n - name: eth0\n type: VPORT\n - name: eth1\n type: VPORT\n description: Simple VNF example with a cirros SRIOV interface\n id: cirros_sriov_vnfd\n logo: cirros-64.png\n mgmt-interface:\n cp: eth0\n name: cirros_sriov_vnf\n short-name: cirros_sriov_vnf\n vdu:\n - count: 1\n description: cirros_sriov_vnfd-VM\n guest-epa:\n cpu-pinning-policy: DEDICATED\n cpu-thread-pinning-policy: PREFER\n mempage-size: SMALL\n numa-node-policy:\n mem-policy: STRICT\n node:\n - id: '1'\n node-cnt: '1'\n id: cirros_sriov_vnfd-VM\n image: cirros-0.3.6-x86_64\n interface:\n - external-connection-point-ref: eth0\n name: eth0\n position: '1'\n type: EXTERNAL\n virtual-interface:\n bandwidth: '0'\n type: VIRTIO\n vpci: 0000:00:0a.0\n - external-connection-point-ref: eth1\n name: eth1\n position: '2'\n type: EXTERNAL\n virtual-interface:\n type: SR-IOV\n name: cirros_sriov_vnfd-VM\n vm-flavor:\n memory-mb: 4096\n storage-gb: 10\n vcpu-count: 4\n vendor: OSM\n version: '1.0'\n", + "descriptorHTML": "

cirros_sriov_vnf


Vendor: OSM
Version: 1.0
Description: Simple VNF example with a cirros SRIOV interface
VM Count: 1
vCPU Count: 1
Memory: 4096 MB
Storage: 10 GB
", + "certified": false, + "certifiedBy": null, + "validationStatus": "UNDER_REVIEW", + "packagingFormat": "OSMvFIVE", + "supportedMANOPlatforms": [ + { + "id": 1, + "name": "osm fivee", + "version": "osm fivee", + "description": "osm five" + } + ], + "vxfOnBoardedDescriptors": [], + "vfimagesVDU": [ + { + "id": 2, + "name": "cirros-0.3.6-x86_64", + "uuid": "be121176-1d62-4a1b-a3c1-7dce2e069d22", + "shortDescription": "Automatically created during vxf cirros_sriov_vnfd submission. Owner must update.", + "packageLocation": null, + "publicURL": null, + "dateCreated": 1568971740000, + "dateUpdated": null, + "refVxFs": [ + { + "id": 2, + "name": "cirros_sriov_vnfd" + } + ], + "owner": { + "id": 1, + "organization": "ee", + "name": "Portal Administrator", + "email": "", + "username": "admin", + "active": true, + "currentSessionID": null, + "apikey": "e41c1cc4-aa56-4b7e-9f4d-64589549d768", + "createdAt": 1568711859000, + "roles": [ + "ROLE_ADMIN", + "ROLE_MENTOR" + ] + }, + "published": false, + "termsOfUse": null, + "deployedInfrastructures": [] + } + ] + } +] +``` + + diff --git a/doc/architecture/nfvweb.md b/doc/architecture/nfvweb.md new file mode 100644 index 0000000000000000000000000000000000000000..b96dee34a9662e14f4c5eb3f41f507817686b094 --- /dev/null +++ b/doc/architecture/nfvweb.md @@ -0,0 +1,11 @@ +# Openslice NFV Web Portal + +The [NFV Web Portal](http://portal.openslice.io/nfvportal) offers a domain-specific UI to manage NFV Services. + +Indicatively, the portal can be used to: +- Register new a new MANO provider (e.g. OSM) +- Synchronize the onboarded VNF/NS packages, and the VIMs of the registered MANO provider +- Onboard/Delete VNF/NS packages on specific MANO provider +- Deploy a NS to a target MANO provider + +More information can be found at [NFV Services](../nfvcatalogs.md). \ No newline at end of file diff --git a/doc/architecture/oauth.md b/doc/architecture/oauth.md new file mode 100644 index 0000000000000000000000000000000000000000..e836842620424d03e68971f2406eba6d11269d7c --- /dev/null +++ b/doc/architecture/oauth.md @@ -0,0 +1,35 @@ +# Authentication Server + +Authentication is based on oAuth2. Our authentication service is a Keycloak server which is deployed with Openslice deployment + +API users needs to authenticate. +All APIs (except grant token request) must include Bearer token in request Authorization header. + + + +##OAuth token + +Get first an oauth token, using your username and password. +``` +curl -X POST http://portal.openslice.io/auth/realms/openslice/protocol/openid-connect/token -H 'Content-Type: application/x-www-form-urlencoded' -d 'username=demouser' -d 'password=demouser' -d 'grant_type=password' -d 'client_id=osapiWebClientId' +``` +response: + +``` + {"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJHZFRjQnpxczg2VW10NTRVZV8ybTJyWHJkV3dzaWdSZE9EUldMYm1memNvIn0.eyJleHAiOjE1ODgyNDA1NzAsImlhdCI6MTU4ODI0MDI3MCwianRpIjoiOGI2ZTU0NWUtNDIyYy00NzFiLWEwN2UtYTUzYzY1NDQ0MzZmIiwiaXNzIjoiaHR0cDovL3BvcnRhbC5vcGVuc2xpY2UuaW8vYXV0aC9yZWFsbXMvb3BlbnNsaWNlIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImExYTI3NjVhLWVjODMtNDQ1Ni1iN2IyLTIwNzMxOTg2ZTAzNSIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9zYXBpV2ViQ2xpZW50SWQiLCJzZXNzaW9uX3N0YXRlIjoiMzM1MGY0OTMtNjYyNy00MzczLTg1NDQtZGVmZDI3YWQzYzc0IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjEzMDgyIiwiaHR0cDovL2xvY2FsaG9zdCIsImh0dHA6Ly9vcGVuc2xpY2UuaW8iLCJodHRwOi8vbG9jYWxob3N0OjEzMDAwIiwiaHR0cDovL2xvY2FsaG9zdDo0MjAwIiwiaHR0cDovL3BvcnRhbC5vcGVuc2xpY2UuaW8iXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIk5GVl9ERVZFTE9QRVIiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiRVhQRVJJTUVOVEVSIiwiVVNFUiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJkZW1vdXNlciJ9.TnzzpRLMD94UTKpT5_wkr1h4_3KUQmr4TGvFLpJ7cZx-Klrv8tB_eRkWnPqqzCAM9G21a1qXboL8MLMW8ECzG7HYKpobKOGr7LSczMOTdA2ZDyBCRUSOdW77pchu54tJ0ITEkFaDwSKMKKt04V_Sy4U-eIndj0XzzRlkDolWDnK4Z2lRaXAI6fMwOKx1Toa6RfOcemxtzl3pdtjPx92zo6MaKlbIqHK82lxdK0k8aQQaT6TmIrXbZKV2dU_1d3O0q0dVUEZJ_1kzwqOFkmxr9w0EnndC6ccYJlDAr_-GgUhhhNOn5v6tjYLUQdj5e4KEAsxIPzaCreK4un7mEAPmDw","expires_in":300,"refresh_expires_in":1800,"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIwZjUxMDk5Yy0wNTIzLTRjNGQtODM0Zi1iNDc0YzBjOTA1MzkifQ.eyJleHAiOjE1ODgyNDIwNzAsImlhdCI6MTU4ODI0MDI3MCwianRpIjoiZmViOTg5NWEtOTY5ZS00MzIzLWJjY2QtZTY2YzQ0NGE1MzJlIiwiaXNzIjoiaHR0cDovL3BvcnRhbC5vcGVuc2xpY2UuaW8vYXV0aC9yZWFsbXMvb3BlbnNsaWNlIiwiYXVkIjoiaHR0cDovL3BvcnRhbC5vcGVuc2xpY2UuaW8vYXV0aC9yZWFsbXMvb3BlbnNsaWNlIiwic3ViIjoiYTFhMjc2NWEtZWM4My00NDU2LWI3YjItMjA3MzE5ODZlMDM1IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6Im9zYXBpV2ViQ2xpZW50SWQiLCJzZXNzaW9uX3N0YXRlIjoiMzM1MGY0OTMtNjYyNy00MzczLTg1NDQtZGVmZDI3YWQzYzc0Iiwic2NvcGUiOiJwcm9maWxlIGVtYWlsIn0.cDTx9BE1Df8EfGYm3VLr_MNFeymxZtJhMtlK7PVbIuk","token_type":"bearer","not-before-policy":1586797346,"session_state":"3350f493-6627-4373-8544-defd27ad3c74","scope":"profile email"} + +``` + +The `access_token` will be used next as a Bearer. + +``` +curl http://portal.openslice.io/tmf-api/serviceCatalogManagement/v4/serviceCatalog -H 'Authorization: Bearer yJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJHZFRjQnpxczg2VW10NTRVZV8ybTJyWHJkV3dzaWdSZE9EUldMYm1memNvIn0.eyJleHAiOjE1ODgyNDA1MjQsImlhdCI6MTU4ODI0MDIyNCwianRpIjoiYjg0NGYxZDAtMzk3Mi00YTMyLThiMWEtZDAxMDY3OGZjMTQ4IiwiaXNzIjoiaHR0cDovL3BvcnRhbC5vcGVuc2xpY2UuaW8vYXV0aC9yZWFsbXMvb3BlbnNsaWNlIiwic3ViIjoiYTFhMjc2NWEtZWM4My00NDU2LWI3YjItMjA3MzE5ODZlMDM1IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYWRtaW4tY2xpIiwic2Vzc2lvbl9zdGF0ZSI6ImFmMmMzZmY1LTE4YWQtNDFkNC1hYTAyLTFlMGJkNzNmOTM5MSIsImFjciI6IjEiLCJzY29wZSI6InByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwicHJlZmVycmVkX3VzZXJuYW1lIjoiZGVtb3VzZXIifQ.SMtgV1E44_K_MQumGXZtWsLGVhYNaoM8Pk-DiFIZtUP4Zu-ervOsxHVQMX1frgVERR4jJidBcSshy9TnJ3UjF4l33WujHltbs-1UPy-gaIufVuEpl8RmbjOti3Up70vLfLXbzb6kN6WaahgobWXlbJsSXXwaBPQP6vSX5KigCa8TmzXcuqom14lOrlU-RB2zQTlJ30p7d9ag-a7o3I5m9GZWLJCZW2UYMl1JkskTHKgilA8HFQY4C9DYwWu8YDMyzqQSNumrTlURalBFidFbZvb1kp4dAyct8TysSWSbxxiwaL2RX1PWUqk-5Fpc1Q6BnBC8muMheiukFuoSkuADAg'^C +ubuntu@portal:~$ curl http://portal.openslice.io/tmf-api/serviceCatalogManagement/v4/serviceCatalog -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJHZFRjQnpxczg2VW10NTRVZV8ybTJyWHJkV3dzaWdSZE9EUldMYm1memNvIn0.eyJleHAiOjE1ODgyNDA1NzAsImlhdCI6MTU4ODI0MDI3MCwianRpIjoiOGI2ZTU0NWUtNDIyYy00NzFiLWEwN2UtYTUzYzY1NDQ0MzZmIiwiaXNzIjoiaHR0cDovL3BvcnRhbC5vcGVuc2xpY2UuaW8vYXV0aC9yZWFsbXMvb3BlbnNsaWNlIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImExYTI3NjVhLWVjODMtNDQ1Ni1iN2IyLTIwNzMxOTg2ZTAzNSIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9zYXBpV2ViQ2xpZW50SWQiLCJzZXNzaW9uX3N0YXRlIjoiMzM1MGY0OTMtNjYyNy00MzczLTg1NDQtZGVmZDI3YWQzYzc0IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjEzMDgyIiwiaHR0cDovL2xvY2FsaG9zdCIsImh0dHA6Ly9vcGVuc2xpY2UuaW8iLCJodHRwOi8vbG9jYWxob3N0OjEzMDAwIiwiaHR0cDovL2xvY2FsaG9zdDo0MjAwIiwiaHR0cDovL3BvcnRhbC5vcGVuc2xpY2UuaW8iXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIk5GVl9ERVZFTE9QRVIiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiRVhQRVJJTUVOVEVSIiwiVVNFUiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJkZW1vdXNlciJ9.TnzzpRLMD94UTKpT5_wkr1h4_3KUQmr4TGvFLpJ7cZx-Klrv8tB_eRkWnPqqzCAM9G21a1qXboL8MLMW8ECzG7HYKpobKOGr7LSczMOTdA2ZDyBCRUSOdW77pchu54tJ0ITEkFaDwSKMKKt04V_Sy4U-eIndj0XzzRlkDolWDnK4Z2lRaXAI6fMwOKx1Toa6RfOcemxtzl3pdtjPx92zo6MaKlbIqHK82lxdK0k8aQQaT6TmIrXbZKV2dU_1d3O0q0dVUEZJ_1kzwqOFkmxr9w0EnndC6ccYJlDAr_-GgUhhhNOn5v6tjYLUQdj5e4KEAsxIPzaCreK4un7mEAPmDw' + +Response: + + +[{"uuid":"9e186cd5-b2b2-4a06-b1d6-895720193bc9","lastUpdate":"2020-03-11T23:19:05Z","@baseType":"BaseEntity","@schemaLocation":null,"@type":"ServiceCatalog","href":null,"name":"Example Facility Services","description":"Example Facility Services","lifecycleStatus":"Active","version":"1.0","validFor":{"endDateTime":"2039-11-20T23:07:21Z","startDateTime":"2019-11-20T23:07:21Z"},"relatedParty":null,"id":"9e186cd5-b2b2-4a06-b1d6-895720193bc9","category":[{"@baseType":"org.etsi.osl.tmf.scm633.model.ServiceCategoryRef","@schemaLocation":null,"@type":"org.etsi.osl.tmf.scm633.model.ServiceCategoryRef","href":null,"name":"Generic Services","@referredType":null,"id":"98b9adf1-a1d6-4165-855f-153ddc2131b1"},{"@baseType":"org.etsi.osl.tmf.scm633.model.ServiceCategoryRef","@schemaLocation":null,"@type":"org.etsi.osl.tmf.scm633.model.ServiceCategoryRef","href":null,"name":"External","@referredType":null,"id":"08ffdb3c-6237-45d0-9f3a-d43b5fc5f0b6"},{"@baseType":"org.etsi.osl.tmf.scm633.model.ServiceCategoryRef","@schemaLocation":null,"@type":"org.etsi.osl.tmf.scm633.model.ServiceCategoryRef","href":null,"name":"eMBB","@referredType":null,"id":"ef2c90dd-b65e-4a9f-a9c3-427c9fb0219b"}]}] + + +``` \ No newline at end of file diff --git a/doc/architecture/osom.md b/doc/architecture/osom.md new file mode 100644 index 0000000000000000000000000000000000000000..173aa8017d603bb3854eb6b4c0e9baa905e512f6 --- /dev/null +++ b/doc/architecture/osom.md @@ -0,0 +1,137 @@ +# Openslice Service Orchestration and Order Management - OSOM + +OSOM is a service responsible for: + +* Service Order Management (SOM) +* Service Orchestration (SO) + +It uses open source Flowable Business process engine (https://www.flowable.org) . + +A Service Order follows the states as defined in TMF641 specification: + +[![Service Order state](../images/service_order_states.png)](../images/service_order_states.png) + + +## Initial state + +When a new order is created, it goes into the Initial state. It is stored in the repository and triggers an Event. + +[![Initial state](../images/service_order_initial_state.png)](../images/service_order_initial_state.png) + +Administrators are notified usually from the Ticketing System of a new order. They login to Openslice and change the State of the order either to ACKNOWLEDGED or REJECTED. If ACKNOWLEDGED they can Propose a startDate, add Notes, and add any additional service items + +## Order scheduler + +A process checks every 1 minute for ACKNOWLEDGED orders. + +[![Order scheduler BPM](../images/order_scheduler_bpm.png)](../images/order_scheduler_bpm.png) + +[![Order scheduler](../images/order_scheduler_diagram.png)](../images/order_scheduler_diagram.png) + +It retrieves all orders that are in ACKNOWLEDGED state and if the start date is in time it will initialize the process by settingn the order in IN_PROGRESS state. Finally the Start Order Process will start. + + +## Start order process + +This process for now is a draft simple prototype to make a simple orchestration via NFVO. Here the actual Services (TMF638/640 model) are created and attached to Service Order and Service Inventory. + +[![Start Order BPM](../images/start_order_process_bpm.png)](../images/start_order_process_bpm.png) + +[![Start Order interactions](../images/start_order_process_diagram.png)](../images/start_order_process_diagram.png) + +We expect here to check which tasks can be orchestrated by NFVO and which by human. We create the equivalent Services(TMF638/640 model) for this order. + +1. During check it should decide to create Service(s) for this service order O1 and send it to ServiceInventory +2. The Services(TMF638 model) are assigned to the Order O1 In supportService List +3. Each OrderItem OI1 is related to one serviceSpecification +4. Each ServiceSpecification has also related serviceSpecRelationships +5. So if we receive an order O1 for a ServiceSpec A which relates to (a bundle of) 3 specs(2 CFS, 1 RFS) we do the following: + 1. Create a Service S_A(TMF638 model) for ServiceSpec A for Order O1 + 2. We create also 3 Services S_C1, S_C2 and S_R1 equivalent to the serviceSpecRelationships (2 CFS, 1 RFS) + 3. At this point the order will have 1 Local Service Orchestration Process(S_A), 2 supportingServices refs(S_C1, S_C2) and 1 supportingResource(S_R1) + 4. The 3 supportingServices and 1 supportingResource correspond to total 4 Services in ServiceInventory + 5. Service S_A will have: + 1. startMode 1: Automatically by the managed environment + 2. State: RESERVED and the Lifecycle will be handled by OSOM + 6. Services S_C1 and S_C2 we decide that cannot be orchestrated then they have + 1. startMode: 3: Manually by the Provider of the Service + 2. State: RESERVED and the Lifecycle will be handled by OSOM + 3. If the CFS is a bundle spec it is further recursively orchestrated + 7. Service S_R1 will have + 1. startMode 1: Automatically by the managed environment. + 2. State: RESERVED + 3. IF The Service has the characteristic CharacteristicByName( "NSDID") it will be further processed by the NFVO + + +There will be two instances of task "User Task Manual Complete Service" each for Services S_C1 and S_C2. The task is Transient for now. It displays only the services that are not automated! +Here is a flow for future: + +1. We wait here for human decision. +2. From API we get a result: + a. If set to ACTIVE/TERMINATED then we complete the task + b. In any other state we stay in this task until it is resolved as in step a + c. The Status of ORDER O1 is also updated to PARTIAL + +There will be an instance of NFVODeploymentRequest process each for Service S_R1. (see later) + +1. This process is related with the NFVO orchestration +2. It will send a msg to NFVO(s?) for a specific deployment request + + +All services in "Order Complete" are in a status: + +1. Depending on the result the service S_A is either ACTIVE or INACTIVE or TERMINATED +2. The Status of ORDER O1 is also updated to COMPLETED or PARTIAL (in case we have some services running) or FAILED (in cases we have errors) + + +A Service follows the states as defined in TMF638 Service Inventory specification: + +[![Service state](../images/service_states.png)](../images/service_states.png) + + + +## NFVODeploymentRequest process + + +[![NFVODeploymentRequest BPM](../images/NFVODeploymentReq_process.png)](../images/NFVODeploymentReq_process.png) + +This process is related with the NFVO orchestration +It will send a msg to NFVO(s?) for a specific deployment request +Then it checks the deployment status. It will wait 30 secs each time until the deployment is running (or failed) + + + +## Check In Progress orders process + +Every 1 minute the "Check In Progress Orders" process is executed checking if a supported Service changed state (i.e. to ACTIVE) then the whole Order will change state (e.g. go to COMPLETED) + +[![Check In Progress BPM](../images/check_inProgress_orders.png)](../images/check_inProgress_orders.png) + + +## External Service Provider Deployment Request process + +[![External Service Provider Deployment Request process BPM](../images/externalSPDeploymentReq.png)](../images/externalSPDeploymentReq.png) + +This process contains tasks for submitting order requests to external partners. +- Submit Order To External Service Provider Task: This task creates automatically a Service Order request to a 3rd party provider SO that hosts the Service Specification +- Check external service order fulfillment task: This task Check external partner for Service creations and updates our local inventory of services the service characteristics of remote Service Inventory + + +## Fetch Partner Services Process + + +[![Fetch Partner Services Process BPM](../images/fetchPartnerServices.png)](../images/fetchPartnerServices.png) + +Every 2 minutes the "fetchPartnerServicesProcess" process is executed checking remote Partner Organizations for changes in the published catalogues. +The Fetch and Update External Partner Services Task is executed in paralle l for each Partner Organization + + +## Local Service Orchestration Process + + +[![Local Service Orchestration Process BPM](../images/LocalServiceOrchestrationProcess.png)](../images/LocalServiceOrchestrationProcess.png) + +This process handles automatically services that need to be further orchestrated or processed by OSOM. For example, for a CFS Bundled service we create such automated service instances that just aggregate the underlying services. + + + \ No newline at end of file diff --git a/doc/architecture/tmfapi.md b/doc/architecture/tmfapi.md new file mode 100644 index 0000000000000000000000000000000000000000..f7944969741681c840db830a70fc688a0224295e --- /dev/null +++ b/doc/architecture/tmfapi.md @@ -0,0 +1,65 @@ +# TMF OpenAPI specification + +PLease check the complete specification [here](http://portal.openslice.io/tmf-api/swagger-ui/index.html). + +## API interaction + +### OAuth token + +See [oauth](./oauth.md) + +### Request a protected API resource + +Example: Get all Service Catalogs (check the `Authorization:Bearer` to be correct) + +``` +curl -H "Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbIm9wZW5hcGkiLCJhZG1pbiIsInJlYWQiLCJ3cml0ZSJdLCJvcmdhbml6YXRpb24iOiJteW9yZ2FuaXp0aW9uIiwiZXhwIjoxNTc4NTA1MDcyLCJhdXRob3JpdGllcyI6WyJST0xFX01FTlRPUiIsIlJPTEVfQURNSU4iXSwianRpIjoiMTFlNGYxYTUtZDY0Ny00YzA1LWE0ZGMtYWFhYzUyMjk4YzMwIiwiY2xpZW50X2lkIjoib3NhcGlXZWJDbGllbnRJZE91dCJ9.gm7cKdusDrdMRkxEiFU5sENKGRC1xwVj2SgPRmE9xxx" -H "accept: application/json;charset=utf-8" -X GET "http://portal.openslice.io/tmf-api/serviceCatalogManagement/v4/serviceCatalog" + +``` + + +response: + + +``` +[ + { + "uuid": "9e186cd5-b2b2-4a06-b1d6-895720193bc9", + "lastUpdate": "2019-12-19T10:45:55Z", + "@baseType": "BaseEntity", + "@schemaLocation": null, + "@type": "ServiceCatalog", + "href": null, + "name": "Example Facility Services", + "description": "Example Facility Services", + "lifecycleStatus": "Active", + "version": "1.0", + "validFor": { + "endDateTime": "2039-11-20T23:07:21Z", + "startDateTime": "2019-11-20T23:07:21Z" + }, + "relatedParty": null, + "id": "9e186cd5-b2b2-4a06-b1d6-895720193bc9", + "category": [ + { + "@baseType": "org.etsi.osl.tmf.scm633.model.ServiceCategoryRef", + "@schemaLocation": null, + "@type": "org.etsi.osl.tmf.scm633.model.ServiceCategoryRef", + "href": null, + "name": "eMBB", + "@referredType": null, + "id": "ef2c90dd-b65e-4a9f-a9c3-427c9fb0219b" + }, + { + "@baseType": "org.etsi.osl.tmf.scm633.model.ServiceCategoryRef", + "@schemaLocation": null, + "@type": "org.etsi.osl.tmf.scm633.model.ServiceCategoryRef", + "href": null, + "name": "Generic Services", + "@referredType": null, + "id": "98b9adf1-a1d6-4165-855f-153ddc2131b1" + } + ] + } +] +``` \ No newline at end of file diff --git a/doc/architecture/tmfweb.md b/doc/architecture/tmfweb.md new file mode 100644 index 0000000000000000000000000000000000000000..729eed65fa1833982885623ca9108e67b44ab20c --- /dev/null +++ b/doc/architecture/tmfweb.md @@ -0,0 +1,39 @@ +# Openslice TMF Web Portal + +Openslice comprises of a [web landing page](http://portal.openslice.io/) that navigates to the respective TMF Portal. + +- [Services Portal](http://portal.openslice.io/services) +- [Products Portal](http://portal.openslice.io/products) +- [Testing Portal](http://portal.openslice.io/testing) +- [Resources Portal](http://portal.openslice.io/resources) + +The landing page and the TMF portals (Services, Products, Testing, Resources) are written in Angular and are maintained under the same Angular project. + +Following you may find the scope each portal focuses on and the main TMF APIs it supports. + +**Services Portal** is a designated portal for the: +- Service Designer - To design Customer Facing Services as bundles of Resource Facing Services that map to specific Resourses (e.g. NFV, Testing, General Resources). Then, it is charged with the designed Services' exposure to public Service Catalogs. +- Service Customer - To browse the public Service Catalogs and order the offered Services. The fulfilment process of the Service Order is also captured and the final deployed Services are exposed to the Customer. + +**Products Portal** is a designated portal for the: +- Product Designer - To design Products as bundles of available Services. Then, it is charged with the designed Products' exposure to public Product Catalogs. +- Product Customer - To browse the public Product Catalogs and navigate to the respective offered Services. + +**Testing Portal** is a designated portal for the: +- Testing Designer - To design Tests and provide the testing scripts as attachments to the latter. The Tests can be imported as Services at the Services Portal, and can be included in a Service Bundle. + +**Resources Portal** is a designated portal for the: +- Resource Administrator - To view the available Resources that are being synchronized from the underlying infrastructure. + + + + +| | TMF620 | TMF632 | TMF633 | TMF634 | TMF638 | TMF639 | TMF640 | TMF641 | TMF642 | TMF653 | TMF685 | +| ------------- |:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:| +|**Services Portal** | |x |x | |x | |x |x |x | | | +|**Products Portal** |x |x | | | | | | | | | | +|**Testing Portal** | |x | | | | | | | |x | | +|**Resources Portal** | |x | |x | |x | | | | |x | + + +From the landing page, the user can also navigate towards the NFV portal. See [NFV WEB](./nfvweb.md). \ No newline at end of file diff --git a/doc/catalogs.md b/doc/catalogs.md new file mode 100644 index 0000000000000000000000000000000000000000..3b3538d0b5dcaedf1690154bea22e70caf85551b --- /dev/null +++ b/doc/catalogs.md @@ -0,0 +1,147 @@ +# Catalogs and Templates + +The Openslice Service Catalogue (accessible through the API or Services portal) contains the representation of Service Specifications, either created from the provider defining service attributes, or by supporting the GSMA Generic Slice Templates (GST) as well as the VINNI Service Blueprint. The following scenarios are supported by the Openslice Service Catalogue. + + +## Create/Design a Service Specification + +### First Import some Resources as Resource Facing Services (RFSs) + +If you have any NSDs as NFV artifacts, import them through the UI menu (Import from NSD list). Then an NSD is imported as a resource and an RFS automatically is created. RFSs then later are used to design a Customer Facing Service Specification + +### Create/Design a Customer Facing Service Specification + +Customer Facing Service Specification are the services offered to customers. +You can create a new Service Specification from the menu. The services created through the UI are Customer Facing Services (CFS). Usually you create a CFS as a bundle and then you include Service Specification Relationships with RFSs or/and CFSs. + +Any Service Specification Characteristics from the RFS are copied to the CFS specification. A CFS can include multiple RFS or/and CFSs. +For example you can create a CFS spec called "A 5G Service" which is a bundle of two other services (include them in Service Specification Relationships) such as 5G eMBB Slice and a Customer VPN. So when the user orders "A 5G Service" services from 5G eMBB Slice and a Customer VPN will be created during the order. + +### Initial configuration for OSM deployment + +if you have an initial configuration that needs to be applied in the NSD deployment, then you go to the RFS (or CFS) and in Service Specification Characteristics go and edit the OSM_CONFIG characteristic. +You can add in the Service Characteristic Value, in the Value field something like the following example which gives a floating IP to a VNF: + +``` +{ "nsdId": "e855be91-567b-45cf-9f86-18653e7ea", "vimAccountId": "4efd8bf4-5292-4634-87b7-7b3d49108" , "vnf": [ {"member-vnf-index": "1", "vdu": [ {"id": "MyCharmedVNF-VM", "interface": [{"name": "eth0", "floating-ip-required": true }]}]}]} + +``` + +or a more complex example (beautify it first if you want to view it, but in the parameter OSM_CONFIG must be minified like the example): + +``` +{"nsdId":"e855be91-567b-45cf-9f86-18653e7","vimAccountId":"4efd8bf4-5292-4634-87b7-7b3d491","vnf":[{"member-vnf-index":"1","vdu":[{"id":"haproxy_vdu","interface":[{"name":"haproxy_vdu_eth1","floating-ip-required":true}]}]}],"vld":[{"name":"pub_net","vim-network-name":"OSMFIVE_selfservice01"},{"name":"management","vim-network-name":"OSMFIVE_selfservice01"},{"name":"lba_net","vim-network-name":"lba_net","vnfd-connection-point-ref":[{"member-vnf-index-ref":"1","vnfd-connection-point-ref":"haproxy_private","ip-address":"192.168.28.2"}]},{"name":"backend_net","vim-network-name":"backend_net","vnfd-connection-point-ref":[{"member-vnf-index-ref":"3","vnfd-connection-point-ref":"haproxy_public","ip-address":"192.168.20.2"}]},{"name":"lb_sb_net","vim-network-name":"lb_sb_net","vnfd-connection-point-ref":[{"member-vnf-index-ref":"3","vnfd-connection-point-ref":"haproxy_private","ip-address":"192.168.28.2"}]},{"name":"breaking_point_Spain","vim-network-name":"sb_repo_net"},{"name":"breaking_point_Greece","vim-network-name":"5TONICexternal"}],"additionalParamsForVnf":[{"member-vnf-index":"2","additionalParams":{"target_IP":"192.168.20.2"}},{"member-vnf-index":"4","additionalParams":{"target1_IP":"192.168.21.2","target2_IP":"10.154.252.10"}}]} +``` + +You can leave the Alias and Unit of Measure as is. Check also the is Default. + + + +### Day 2 Primitive Actions + +NFVOs like OSM allow to perform actions while a service is running, for example change attributes or make actions on a specific VNF. To design this do something similar to the following example: + +- Go to the RFS related to the NSD that contains VNFs with primitives +- create a characteristic named Primitive:: , e.g. Primitive::touch +- select Value Type: ARRAY +- add Service Characteristic Value: i) alias=primitive, value= (e.g. touch), ii) alias=member_vnf_index, value= (e.g. 1), iii) add the params that the user will change in alias the name of param and in value an initial value (e.g. alias=filename, value=myfile.txt) + +In the above example, when the service is running and the user goes to service inventory to MODIFY it, changes the value of the alias=filename, value=myfile.txt, to value =secondfile.txt. Then inside the VNF a file will be created called secondfile.txt + + + +### Generic Slice Templates (GST) +(Offered only as a design for now. THere is no direct implementation to NFV) +On October 16th 2019 GSMA published NG.116 Version 2.0 which defines the Generic Network Slice Template (GST). GST is a set of attributes that can characterise a type of network slice/service. GST is generic and is not tied to any specific network deployment. Here is a list of the various attributes of the template: + +- Availability +- Area of Service +- Delay tolerance +- Deterministic communication +- Downlink throughput per network slice +- Downlink throughput per UE +- Energy efficiency +- Group communication support +- Isolation level +- Location based message delivery +- Maximum supported packet size +- Mission critical support +- MMTel support +- NB-IoT support +- Network Slice Customer network functions +- Number of connections +- Number of terminals +- Performance monitoring +- Performance prediction +- Positioning support +- Radio spectrum +- Reliability +- Root cause investigation +- Session and Service Continuity support +- Simultaneous use of the network slice +- Slice quality of service parameters +- Support for non-IP traffic +- Supported access technologies +- Supported device velocity +- Synchronicity +- Terminal density +- Uplink throughput per network slice +- Uplink throughput per UE +- User management openness +- User data access +- V2X communication mode + +Openslice offers the GST in a format that is machine readable and aligned with the TMF SID model. Here is a tentative approach in JSON : + +Providers can clone a GST as e NEST directly in Openslice Web portal and the adjust the default attributes to their Service Specification + + +### 5G-VINNI Service Blueprint +(Offered only as a design for now. THere is no direct implementation to NFV) +5G-VINNI Service Blueprint is a special Service Specification defined by teh 5G-VINNI project. Many details can be found in document + +5G-VINNI Service Blueprint is a reusable self-contained specification of required network slice service (instances). As described in GST mapping VINNI-SB is also machine readable. + +Here is a tentative approach in JSON : + +5G-VINNI SB has many commonalities with GST as well as it offers Testing as a Service attributes. + + Next figure presents the high-level object model of a 5G-VINNI service blueprint. + +The 5G-VINNI SB as a first prototype approach is conceived as a CFS of a ‘bundle’ of services. It has some characteristics, like name, description, service type (eMBB, etc) and others. The constituent services are: + +- A “Service Topology” Service Specification which is related to a Network Service Resource topology (a Logical Resource Spec). It is considered at this stage as an RFS but is subject to change in future +- A “VINNI SB Service Requirements” Service Specification which is related to Service requirements. This is very similar to GST. It is considered at this stage a CFS. +- A “VINNI SB Service Exposure Level 1” Service Specification which contains characteristics for service exposure on level 1 ( see D3.1 for details). It is considered at this stage a CFS. +- A “VINNI SB Service Exposure Level 2” Service Specification which contains characteristics for service exposure on level 2. It is considered at this stage a CFS. +- A “VINNI SB Service Exposure Level 3” Service Specification which contains characteristics for service exposure on level 3. It is considered at this stage a CFS. +- A “VINNI SB Service Exposure Level 4” Service Specification which contains characteristics for service exposure on level 4. It is considered at this stage a CFS. +- A “VINNI SB Service 3rd part VNF” Service Specification which contains characteristics for support 3rd party VNFs to be included in the service. It is considered at this stage as an RFS but is subject to change in future +- A “VINNI SB Service 3rd part NSD” Service Specification which contains characteristics for support 3rd party NSDs to be included in the service. It is considered at this stage as an RFS but is subject to change in future +- A “VINNI SB Service Monitoring” Service Specification which contains characteristics for offering Monitoring capabilities on the requested Service. It is considered at this stage a CFS. +- A “VINNI SB Service Testing” Service Specification which contains characteristics for offering Testing capabilities on the requested Service. It is considered at this stage a CFS. + + +[![VINNI SB Template Model diagram](../images/vinni_sb_model_diagram.png)](../images/vinni_sb_model_diagram.png) + + +## Manage a Service Specification + +You can manage them though the Web UI + + +## Assign a Service Specification to Service Categories and Publish + +Just create categories and from the menu select the category and add services + + +## Retire/Remove a Service Specification + +Delete it from the category + + +## Consume and expose Service Specifications from other Service Catalogues + +See more on [Consuming Services From External Partner Organizations](./architecture/consumingServicesFromExternalPartners.md) + + diff --git a/doc/contributing/developing.md b/doc/contributing/developing.md new file mode 100644 index 0000000000000000000000000000000000000000..7e4523eaaac1cd20ce5a6970d74f2d9dd3b823da --- /dev/null +++ b/doc/contributing/developing.md @@ -0,0 +1,89 @@ + +# Developing + +Openslice backend services are mainly implemented with Java 17 or above and Spring boot. + +Openslice uses various subsystems and depending on the module would you like to work, other subsystems must be present (you can disable them though in the code, e.g. at application.yml file) + +To get the latest development branch: +``` +wget https://raw.githubusercontent.com/openslice/org.etsi.osl.main/develop/compose/deploy.sh +sudo ./deploy.sh develop [or replace develop with other branch name] +``` + +## Slack + +* Slack: https://openslice.slack.com + +## General subsystems + +- Docker and Docker Compose should be installed in your development environment + +### Consul +consul service registry should be up and running. You can launch consul with docker: +`sudo docker run -d --name consul -p 8500:8500 -p 8600:8600 consul` + +### ActiveMQ +ActiveMQ is our messaging system. You can launch an instance of ActiveMQ: +`sudo docker run --name='activemq' -d -e 'ACTIVEMQ_NAME=amqp-srv1' -e 'ACTIVEMQ_REMOVE_DEFAULT_ACCOUNT=true' -e 'ACTIVEMQ_ADMIN_LOGIN=admin' -e 'ACTIVEMQ_ADMIN_PASSWORD=admin' -e 'ACTIVEMQ_WRITE_LOGIN=producer_login' -e 'ACTIVEMQ_WRITE_PASSWORD=producer_password' -e 'ACTIVEMQ_READ_LOGIN=consumer_login' -e 'ACTIVEMQ_READ_PASSWORD=consumer_password' -e 'ACTIVEMQ_JMX_LOGIN=jmx_login' -e 'ACTIVEMQ_JMX_PASSWORD=jmx_password' -e 'ACTIVEMQ_STATIC_TOPICS=topic1;topic2;topic3' -e 'ACTIVEMQ_STATIC_QUEUES=queue1;queue2;queue3' -e 'ACTIVEMQ_MIN_MEMORY=1024' -e 'ACTIVEMQ_MAX_MEMORY=4096' -e 'ACTIVEMQ_ENABLED_SCHEDULER=true' -v /home/ctranoris/testcompose/data/activemq:/data/activemq -v /var/log/activemq:/var/log/activemq -p 8161:8161 -p 61616:61616 -p 61613:61613 webcenter/activemq:5.14.3` + +### MySQL server +We use mysql as a storage DB. Please make sure that you have it installed in your system. There are instructions on internet how to install it. Check also our docker-compose installation script + + +## Oauth server + +Keycloak is used as the authentication server. + +> Note: Please check the Post installation steps -> Keycloak at localhost, at [Deployment/Installation](../deployment.md), if you are developing in a local environment + + +## VNF/NSD Catalog Management and NSD Deployment API service + +Clone the repository: https://github.com/openslice/org.etsi.osl.portal.api + +Check the application.yml file. Default port is 13080. Especially the datasource username/password, server port. + +make sure that the General subsystems are up and running as well as the OAuth server + +run it with `mvn spring-boot:run` + +You can check your consul server if it registered. + +### Swagger API +Swagger API of the service is at `http://localhost:13000/osapi/swagger-ui/`. You can try there various REST actions and authenticate via the OAuth server + + +## VNF/NSD Catalog Management and NSD Deployment WEB UI service + +The Web UI is written in AngularJS + +Clone the repository: https://github.com/openslice/org.etsi.osl.portal.web + +by default the project org.etsi.osl.portal.api exposes the folder ../org.etsi.osl.portal.web/src/ in a folder testweb (Check class MvcConfig.java in org.etsi.osl.portal.api) for development. (In production nginx is used). Point your browser to `http://localhost:13000/osapi/testweb/index.html/` + + +--- + +## Version/release management + +Check this nice article on how we develop and release versions + +https://nvie.com/posts/a-successful-git-branching-model/ + +We develop in the develop branch + +--- +## Wishlist + +Check also our wishlist of new features. You can add your own + +See [Wishlist](./wishlist.md) + + + + + + + + diff --git a/doc/contributing/wishlist.md b/doc/contributing/wishlist.md new file mode 100644 index 0000000000000000000000000000000000000000..de91c7741f0ed1a31bf6cd0e0802c2dccdf114aa --- /dev/null +++ b/doc/contributing/wishlist.md @@ -0,0 +1,59 @@ +# TMF API + +- RBAC of API endpoints +- TMF Ticketing API support +- TMF Product +- HATEOAS integration +- Select Specs that can be exposed to partners (maybe with a characteristic?) + +## resource management + +- Resource Activation and Configuration API TMF702 (NEW) (https://projects.tmforum.org/wiki/pages/viewpage.action?pageId=128855518) + +# TMF WEB + + +# OSOM + +- Actions on service order item and acknowledge order status will define the lifecycle +- action shutdown on specific date for service order +- action edit on service order item + +## Dynamic attribute transformation + +- DTM decision tables support per Service Specification +- Schedule Termination of completed order on running services + + + +# NFVO connectivity + +## OSM Client + +- VNF/NSD config params Day 2 +- NSD Lifcecylce +- NST support + +# NFV API + + +# NFV WEB + + +# 3rd party connectivity + +## FlowOne connector + + +## Openstack connector + + +## Kubernetes connector + + +# CentralLog + +- Events from TMF to be written to Central Log + +# Authentication + diff --git a/doc/deployment.md b/doc/deployment.md new file mode 100644 index 0000000000000000000000000000000000000000..ff6417cb10efaf90549ce9fd2beca076f5425ecc --- /dev/null +++ b/doc/deployment.md @@ -0,0 +1,541 @@ +# Preparing the environment + +Note: See the Kubernetes section, if you would like to deploy Openslice in a Kubernetes cluster + +
+ +1 - Backup your previous database if necessary: +``` +sudo docker exec amysql /usr/bin/mysqldump -u root --password=letmein ostmfdb > backup_ostmfdb.sql +``` + + 2 - Install docker + +_NOTE:_ Since July 2023 Docker Compose V1 stopped receiving updates. Openslice fully reverted to Compose V2, which is integrated in the Docker installation. + + +3 - Download environment preparation script +``` +wget https://raw.githubusercontent.com/openslice/org.etsi.osl.main/master/compose/deploy.sh +``` + +4 - Work with main/master branch: + +``` +sudo ./deploy.sh +``` +Alternatively, work with develop or any other branch: + +``` +sudo ./deploy.sh develop [or replace develop with other branch name] +``` + +5 - Create configuration specific docker compose file +``` +cd org.etsi.osl.main/compose/ +sudo cp docker-compose.yaml.configure docker-compose.yaml +``` + +6 - Configure containers to properly resolve the DNS of your domain + +edit /etc/docker/daemon.json and add: + +``` +{ + "dns": ["8.8.8.8", "8.8.4.4"] +} +``` + +and restart docker daemon. + +
+ +# Configure docker-compose services + + +Edit your configuration specific docker-compose.yaml that is previously created: + +
+ +## 1. mysql-portal container + +In folder mysql-init edit the file 01-databases.sql. Edit the credentials that services connect to the database (if you wish) of portaluser (default is 12345) and keycloak (default is password). + +delete the exposed ports + +## 2.keycloak container + +2.1 Edit the following if you changed mysql credentials +``` +DB_DATABASE: keycloak +DB_USER: keycloak +DB_PASSWORD: password +``` + +2.2 Change the keycloak admin password +``` +KEYCLOAK_PASSWORD: Pa55w0rd +``` + + +## 3.osportalapi container (NFV services) + +Edit the following if you changed mysql and keycloak credentials and adjust properly the domain (if you are using a non-local domain, replace everywhere the http://keycloak:8080) + +``` +SPRING_APPLICATION_JSON: '{ + "spring.datasource.url": "jdbc:mysql://amysql/osdb?createDatabaseIfNotExist=true", + "spring.datasource.username":"root", + "spring.datasource.password":"letmein", + "spring-addons.issuers[0].uri": "http://portal.openslice.io/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "http://portal.openslice.io/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "http://portal.openslice.io/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "http://portal.openslice.io/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id" : "osapiWebClientId", + "springdoc.oauth.clientsecret" : "secret", + "spring.activemq.brokerUrl": "tcp://anartemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO" + + +``` + + +## 4.bugzilla container + +If you would like to use the Bugzilla connector + +``` +"bugzillaurl":"bugzillaurl.xx:443/bugzilla/", +"bugzillakey":"exampleKeyeqNNwxBlgxZgMEIne0Oeq0Bz", +"main_operations_product":"Main Site Operations" //this is the default product to issue tickets +``` + +Bugzilla under this product should have components: +- NSD Deployment Request: Component used to schedule deployment req +- Onboarding: Issues related to VNF/NSD Onboarding +- Operations Support: Default component for operations support +- Validation: Use to track validation processes of VNFs and NSDs +- VPN Credentials/Access: Used for requesting VPN Credentials/Access + + +Also in the 'Main Site Operations' product, please create a version named 'unspecified' + + +## 5.osscapi container (TMF-API service) + +Edit the following if you changed mysql and keycloak credentials + +``` +"spring.datasource.username":"xx", +"spring.datasource.password":"xx", +"keycloak-admin-password": "Pa55w0rd", +Edit properly with your domain "swagger.authserver" : "http://localhost/auth/realms/openslice", + +``` + +Delete the exposed ports in other services like activemq + +
+ +# Configure nginx + +``` +cd nginx +sudo cp nginx.conf.default nginx.conf +``` + +Edit server_name + +
+ +# Configure Web UI + +``` +cd org.etsi.osl.portal.web/src/js/ +cp config.js.default config.js +``` + +Edit config.js with your domain + +``` +TITLE: "Openslice demo", + WIKI: "http://localhost", + BUGZILLA: "https://localhost/bugzilla/", + STATUS: "http://status.localhost/", + APIURL: "http://localhost", + WEBURL: "http://localhost", + APIOAUTHURL: "http://localhost/auth/realms/openslice", + APITMFURL: "http://localhost/tmf-api/serviceCatalogManagement/v4" + +``` + +
+ +# Configure TMF Web UI + +There are 3 files available for configuration: + +* config.prod.json (Basic information + API configuration) +* theming.scss (CSS color palette theming) +* config.theming.json (HTML configuration - Logo, Favicon, Footer) + + +The first 2 files above (i.e. config.prod.json, theming.scss) are essential for the successful deployment of Openslice, thus created automatically during the initial deployment at **org.etsi.osl.tmf.web/src/assets/config** directory as a copy of the default ones from the remote repository. + +
+ +Ensure that you check the **config.prod.json** file and readjust to your deployment if needed. + +``` +cd org.etsi.osl.tmf.web/src/assets/config +``` +and edit config.prod.json + +E.g. Edit "TITLE" or "WIKI" property with your domain title + +``` +TITLE: 'Openslice', +WIKI: 'https://openslice.io', +``` + +_NOTE:_ The {BASEURL} placeholder in the file automatically detects the Origin (Protocol://Domain:Port) of the deployment and applies it to every respective property. E.g. If you are attempting a local deployment of Openslice, then {BASEURL} is automatically translated to "http://localhost". Similarly, you may use {BASEURL} to translate to a public deployment configuration, e.g. "https://portal.openslice.io". + +
+ +If further customization, apart from the default provided, is needed for branding (Logo, Footer) then **config.theming.json** needs to be created in **org.etsi.osl.tmf.web/src/assets/config** directory, as follows: + +``` +cd org.etsi.osl.tmf.web/src/assets/config +sudo cp config.theming.default.json config.theming.json +``` + +
+ +> **_IMPORTANT NOTE:_** If you want to apply changes to the JSON configuration files without the need to rebuild the application, you have to apply the changes at the **org.etsi.osl.tmf.web/dist/io-openslice-portal-web/assets/config** directory. Although, it is mandatory to also apply these changes to the **org.etsi.osl.tmf.web/src/assets/config** for persistancy, as after any future rebuild of Openslice the **/dist** directory is being ovewritten along with its contents. The Openslice team strongly recommends to always apply your changes to the TMF web UI configuration files at **org.etsi.osl.tmf.web/src/assets/config** and rebuild the application. + +
+ + +# Deploying docker compose + + + + +Go to compose directory and issue: +``` +sudo docker compose --profile prod down;sudo docker compose --profile prod up -d --build +``` + +Note: Depending on your machine, this process might take time. + + +
+ + +# Validating deployments and container monitoring + +You can monitor containers status with portainer at port 9000 (http://your-ip:9000) + +Initially, you may monitor the local machine at portainer. + +Please check that all containers are in running state. + +
+ +# Kubernetes installation + + +Openslice can be installed in a Kubernetes cluster. (This is a work in progress) + +The related scripts are inside the kubernetes folder. Follow these steps along the lines. You need to configure the ingress properly depending on how you want to expose Openslice. + +1) Create an openslice namespace + +``` +kubectl create namespace openslice +``` + +2) Apply or create an ingress. Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource. +An Ingress may be configured to give Services externally-reachable URLs, load balance traffic, terminate SSL / TLS, and offer name-based virtual hosting. An Ingress controller is responsible for fulfilling the Ingress, usually with a load balancer, though it may also configure your edge router or additional frontends to help handle the traffic. You must have an Ingress controller to satisfy an Ingress. +You may need to deploy an Ingress controller such as ingress-nginx. + +You can also adapt it to connect to public cloud load balancers depending on your needs. + +The following will expose an ingress resource from one of your a k8s nodes on port 80 + +``` + kubectl apply -f openslice-ingress.yaml +``` + + +Finding the ingress IP: + + +``` + +kubectl describe -f openslice-ingress.yaml + + +Name: openslice-ingress +Namespace: openslice +Address: 10.10.10.35 +Default backend: default-http-backend:80 () +Rules: + Host Path Backends + ---- ---- -------- + * + /services tmfweb:80 () + /tmf-api osscapi:13082 () + /auth keycloak:8080 () + /osapi osportalapi:13000 () + / portalweb:80 () +Annotations: kubernetes.io/ingress.class: nginx +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Sync 9m29s (x2 over 9m58s) nginx-ingress-controller Scheduled for sync + +``` + +From the above example, our exposed ingress is at Address: 10.10.10.35 + +3) We need to configure the expose address and deploy openslice (IP or URL e.g. http://myopenslice.xxx) + +``` +./k8sdeploy.sh 10.10.10.35 +``` + + +4) Check the status of Openslice in the cluster. Should be similar to the following: + +``` + +kubectl get pods --namespace=openslice -o wide + +NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES +activemq-59d4bfdb4b-bvjqr 1/1 Running 0 109s 192.168.43.97 kc-2 +bugzilla-client-7dd7cb47cb-8qb8m 1/1 Running 0 100s 192.168.12.114 kc-3 +centrallog-95bbf7867-k8fpt 1/1 Running 0 100s 192.168.12.107 kc-3 +consul-b5dd76b76-64dzk 1/1 Running 0 107s 192.168.43.90 kc-2 +keycloak-7c5b6bbc95-k2qfl 1/1 Running 0 105s 192.168.12.106 kc-3 +manoclient-95f68f4c9-c9t6r 1/1 Running 0 104s 192.168.12.113 kc-3 +mysql-portal-0 1/1 Running 0 107s 192.168.43.99 kc-2 +osom-6d548cf555-q8ptj 1/1 Running 0 104s 192.168.43.93 kc-2 +osportalapi-5fff744db8-5g4zs 1/1 Running 0 103s 192.168.43.98 kc-2 +osscapi-6d68b54d97-jn8tz 0/1 Running 0 102s 192.168.12.104 kc-3 +portalweb-8469d57df4-94tfj 1/1 Running 0 101s 192.168.48.44 kc-nfs +tmfweb-868f7bb9c5-x4lfh 1/1 Running 0 102s 192.168.48.43 kc-nfs + + +kubectl get deployments --namespace=openslice -o wide + +NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR +activemq 1/1 1 1 2m15s anactivemq webcenter/activemq:5.14.3 org.etsi.osl.service=activemq +bugzilla-client 1/1 1 1 2m6s bugzilla-client openslice/org.etsi.osl.bugzilla:latest org.etsi.osl.service=bugzilla-client +centrallog 1/1 1 1 2m6s centrallog openslice/org.etsi.osl.centrallog.service org.etsi.osl.service=centrallog +consul 1/1 1 1 2m13s aconsul consul org.etsi.osl.service=consul +keycloak 1/1 1 1 2m11s keycloak quay.io/keycloak/keycloak:11.0.3 org.etsi.osl.service=keycloak +manoclient 1/1 1 1 2m10s manoclient openslice/org.etsi.osl.mano:latest org.etsi.osl.service=manoclient +osom 1/1 1 1 2m10s openslice-osom openslice/org.etsi.osl.osom:latest org.etsi.osl.service=osom +osportalapi 1/1 1 1 2m9s openslice-portalapi openslice/org.etsi.osl.portal.api:latest org.etsi.osl.service=osportalapi +osscapi 1/1 1 1 2m8s openslice-scapi openslice/org.etsi.osl.tmf.api:latest org.etsi.osl.service=osscapi +portalweb 1/1 1 1 2m7s openslice-portalweb openslice/org.etsi.osl.portal.web:latest org.etsi.osl.service=portalweb +tmfweb 1/1 1 1 2m8s openslice-tmfweb openslice/org.etsi.osl.tmf.web:latest org.etsi.osl.service=tmfweb + + +kubectl get services --namespace=openslice -o wide + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR +activemq ClusterIP 10.111.160.120 8161/TCP,61616/TCP 2m22s org.etsi.osl.service=activemq +bugzilla-client ClusterIP 10.101.43.28 13010/TCP 2m14s org.etsi.osl.service=bugzilla-client +centrallog ClusterIP 10.109.15.151 13013/TCP 2m14s org.etsi.osl.service=centrallog +consul ClusterIP 10.101.103.240 8500/TCP,8600/TCP 2m21s org.etsi.osl.service=consul +keycloak ClusterIP 10.110.216.62 8080/TCP,8443/TCP 2m19s org.etsi.osl.service=keycloak +manoclient ClusterIP 10.108.112.84 13011/TCP 2m18s org.etsi.osl.service=manoclient +mysql-portal ClusterIP None 3306/TCP 2m19s org.etsi.osl.service=mysql-portal +osom ClusterIP 10.105.173.85 13100/TCP 2m18s org.etsi.osl.service=osom +osportalapi ClusterIP 10.104.121.164 13000/TCP 2m17s org.etsi.osl.service=osportalapi +osscapi ClusterIP 10.108.6.161 13082/TCP 2m16s org.etsi.osl.service=osscapi +portalweb ClusterIP 10.97.126.98 80/TCP 2m15s org.etsi.osl.service=portalweb +tmfweb ClusterIP 10.98.56.82 80/TCP 2m15s org.etsi.osl.service=tmfweb + +``` + +
+ +# Post installation steps + +
+ +## Configure Keycloak server + +Keycloack server is managing authentication and running on a container at port 8080. It is proxied to your host via nginx under http://localhost/auth. + +* Go to http://domain.com/auth/ or https://domain.com/auth/ , (http://ipaddress:8080/auth/ or https://ipaddress:8443/auth/ are direct with no proxy) + +* Navigate to Administration Console + + +> NOTE: if you are running in HTTP you will get a message: HTTPS required + +Go to https://ipaddress:8443/auth/ + +Login with the credentials from section 2.2 + +user admin and your KEYCLOAK_PASSWORD + +Select the master realm from top left corner, go to login Tab and select "Require SSL": None + +Do the same for realm Openslice + +> NOTE: If you are running in HTTPS, then leave Require SSL to external requests + +
+ +### Configure redirects + +Go to realm Openslice, client, osapiWebClientId and change Root URL to your domain. + +Also, insert your domain, e.g. http://example.org/*, at: +* Valid Redirect URIs +* Web Origins + +
+ +### Configure email in Keycloak + +Keycloak also allows new users to register. + +On Tab Login -> check User registration, Verify email, Forgot password etc. + +Also, enter the details on Realm -> Email -> Enable Authentication + +
+ +### Add an Openslice admin user + +Go to manage/users and add an Openslice admin user, e.g. username=admin. Set a password and go also to Role Mappings and add to Assigned Roles ADMIN and MENTOR. + +> Note: That user is different from the Keycloak admin user. It is used to login and browse the OpenSlice Web UI. The Roles ADMIN and MENTOR guarantee full access through the Openslice UI, thus such a user is always required. + +
+ +## Keycloak at localhost + +> **This is an important step if you run Keycloak on localhost** + +1 - Edit your hosts file, adding the line below + +```127.0.0.1 keycloak``` + +2 - Replace http://localhost/auth/ with http://keycloak:8080/auth/ in your Keycloak config for TypeScript/Angular (see examples below). + + +Hosts File Location: + + - In Linux/Unix, the file's location is at /etc/hosts + + - In Windows, its location is at c:\Windows\System32\Drivers\etc\hosts + +Explanation: + + Nginx uses the http://keycloak:8080 URL, which is accessible via the internal docker system's network. + The Front-end (TS/Angular) shall also use the http://keycloak:8080. + This way, you will not get the invalid token error, as the API is getting the token from http://keycloak:8080 (internally) and the Front-end is getting verified with the same URL, as well. + + + +Nginx serves the Front-end from the project org.etsi.osl.tmf.web. + + + + +If you would like to use the Front-end to test your backend, then: + +1. config.prod.json (org.etsi.osl.tmf.web project) should look similar to the following example: + +``` +{ + "TITLE": "Openslice demo", + "PORTALVERSION":"1.1.0-SNAPSHOT", + "WIKI": "http://wiki.localhost", + "BUGZILLA": "{BASEURL}/bugzilla/", + "STATUS": "http://status.localhost/", + "WEBURL": "{BASEURL}", + "PORTAL_REPO_APIURL": "{BASEURL}/osapi", + "ASSURANCE_SERVICE_MGMT_APIURL": "{BASEURL}/oas-api", + "APITMFURL": "http://localhost:13082/tmf-api", + "OAUTH_CONFIG" : { + "issuer": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/auth", + "loginUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/auth", + "tokenEndpoint": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/token", + "redirectUri": "{BASEURL}/redirect", + "logoutUrl": "http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/logout", + "postLogoutRedirectUri": "{BASEURL}/services/services_marketplace", + + "responseType": "code", + "oidc": false, + "clientId": "osapiWebClientId", + "dummyClientSecret": "secret", + + "requireHttps": false, + "useHttpBasicAuth": true, + "clearHashAfterLogin": false, + + "showDebugInformation": true + } +} +``` +> Note the difference in changing {BASEURL} -> http://keycloak:8080 + +2. config.js (org.etsi.osl.portal.web) should look similar to the following example: + +``` +var appConfig = angular.module('portalwebapp.config',[]); + + +appConfig.factory('APIEndPointService', function() { + return { + TITLE: "Openslice", + WIKI: "ROOTURL", + BUGZILLA: "ROOTURL/bugzilla/", + STATUS: "ROOTURL/status/", + APIURL: "http://localhost:13000", + WEBURL: "ROOTURL/nfvportal", + APIOAUTHURL: "http://keycloak:8080/auth/realms/openslice", + APITMFURL: "http://localhost:13082/tmf-api/serviceCatalogManagement/v4" + + }; +}); +``` +> Note the difference in "APIOAUTHURL" property + +
+ +## NFV Portal Landing page + +You may configure the landing page for the NFV Portal at + +``` +org.etsi.osl.portal.web/src/openslicehome/index.html +``` + +
+ +## NFV Orchestrator Configuration + +See [NFV Orchestrator Configuration](./nfvoconfig.md). + +
+ +## Important Note + +There is a case where the first time the services fail to start due to failed mysql connections. Please just issue again: + +`sudo docker compose --profile prod down;sudo docker compose --profile prod up -d --build` + diff --git a/doc/eclipse-java-google-style.xml b/doc/eclipse-java-google-style.xml new file mode 100644 index 0000000000000000000000000000000000000000..7bb6804eb39f988b43f6ac997d66c203272d4969 --- /dev/null +++ b/doc/eclipse-java-google-style.xml @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/images/LocalServiceOrchestrationProcess.png b/doc/images/LocalServiceOrchestrationProcess.png new file mode 100644 index 0000000000000000000000000000000000000000..2543ac37b71faeda2bc5988ad1640aa8d4fe789c Binary files /dev/null and b/doc/images/LocalServiceOrchestrationProcess.png differ diff --git a/doc/images/NFVODeploymentReq_process.png b/doc/images/NFVODeploymentReq_process.png new file mode 100644 index 0000000000000000000000000000000000000000..860a20f797acd1c4dce1ce48cc18a14b0dfeb6ca Binary files /dev/null and b/doc/images/NFVODeploymentReq_process.png differ diff --git a/doc/images/alarms_actions/action_rule_exampleday2.png b/doc/images/alarms_actions/action_rule_exampleday2.png new file mode 100644 index 0000000000000000000000000000000000000000..073e08224a4dd92e79d8323c5ff403c81ba54b81 Binary files /dev/null and b/doc/images/alarms_actions/action_rule_exampleday2.png differ diff --git a/doc/images/alarms_actions/day2actionspec.png b/doc/images/alarms_actions/day2actionspec.png new file mode 100644 index 0000000000000000000000000000000000000000..3e95537b08a1bff2db98bf6d177ade01add62b52 Binary files /dev/null and b/doc/images/alarms_actions/day2actionspec.png differ diff --git a/doc/images/architecture.png b/doc/images/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..adf76473931f463e46d70ce8b9a6b9c488bf9d6b Binary files /dev/null and b/doc/images/architecture.png differ diff --git a/doc/images/architecture_ 2019-10-24.png b/doc/images/architecture_ 2019-10-24.png new file mode 100644 index 0000000000000000000000000000000000000000..12445339e443a12a4f39e0185c823f79b347da7c Binary files /dev/null and b/doc/images/architecture_ 2019-10-24.png differ diff --git a/doc/images/check_inProgress_orders.png b/doc/images/check_inProgress_orders.png new file mode 100644 index 0000000000000000000000000000000000000000..5d28abf380109bdf0a7654912747f7f87cf94185 Binary files /dev/null and b/doc/images/check_inProgress_orders.png differ diff --git a/doc/images/externalSPDeploymentReq.png b/doc/images/externalSPDeploymentReq.png new file mode 100644 index 0000000000000000000000000000000000000000..5438fdd051f6acb048e33188380db5b194886cd0 Binary files /dev/null and b/doc/images/externalSPDeploymentReq.png differ diff --git a/doc/images/fetchPartnerServices.png b/doc/images/fetchPartnerServices.png new file mode 100644 index 0000000000000000000000000000000000000000..3e296db37290a28e22c462dc4448cc4b17a14388 Binary files /dev/null and b/doc/images/fetchPartnerServices.png differ diff --git a/doc/images/index_intro_architecture.png b/doc/images/index_intro_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..635912d49ddc2c3b70b283b2139a8430b6a0e210 Binary files /dev/null and b/doc/images/index_intro_architecture.png differ diff --git a/doc/images/issue_management.png b/doc/images/issue_management.png new file mode 100644 index 0000000000000000000000000000000000000000..1fd7f3ef9991cd0f79ace3a3c89d5a470d3ccca6 Binary files /dev/null and b/doc/images/issue_management.png differ diff --git a/doc/images/lcm/lcmfig1.png b/doc/images/lcm/lcmfig1.png new file mode 100644 index 0000000000000000000000000000000000000000..b92f84e1b0ed0cf3509f7330581ae692187600d5 Binary files /dev/null and b/doc/images/lcm/lcmfig1.png differ diff --git a/doc/images/lcm/lcmfig10.png b/doc/images/lcm/lcmfig10.png new file mode 100644 index 0000000000000000000000000000000000000000..cf09ef445be678e26f3c4ce6ceb3e565beb653f5 Binary files /dev/null and b/doc/images/lcm/lcmfig10.png differ diff --git a/doc/images/lcm/lcmfig11.png b/doc/images/lcm/lcmfig11.png new file mode 100644 index 0000000000000000000000000000000000000000..9d344d761c9d8fd0cc2d1404d5ab1b43ecfd1681 Binary files /dev/null and b/doc/images/lcm/lcmfig11.png differ diff --git a/doc/images/lcm/lcmfig12.png b/doc/images/lcm/lcmfig12.png new file mode 100644 index 0000000000000000000000000000000000000000..79197901027c59ebacfdefaecc49e9034ba87a44 Binary files /dev/null and b/doc/images/lcm/lcmfig12.png differ diff --git a/doc/images/lcm/lcmfig13.png b/doc/images/lcm/lcmfig13.png new file mode 100644 index 0000000000000000000000000000000000000000..809848a4c4087c8d7305adfb2c929d616c0de558 Binary files /dev/null and b/doc/images/lcm/lcmfig13.png differ diff --git a/doc/images/lcm/lcmfig14.png b/doc/images/lcm/lcmfig14.png new file mode 100644 index 0000000000000000000000000000000000000000..cb3afe1747a16838bf9b0ae4f9bf1caf1d463508 Binary files /dev/null and b/doc/images/lcm/lcmfig14.png differ diff --git a/doc/images/lcm/lcmfig1_osom.png b/doc/images/lcm/lcmfig1_osom.png new file mode 100644 index 0000000000000000000000000000000000000000..ceee5261e9da4257069be451b28e5db3fd5378e9 Binary files /dev/null and b/doc/images/lcm/lcmfig1_osom.png differ diff --git a/doc/images/lcm/lcmfig2.png b/doc/images/lcm/lcmfig2.png new file mode 100644 index 0000000000000000000000000000000000000000..a664f77fc67ed25a32245c1ae6e1081be97b7849 Binary files /dev/null and b/doc/images/lcm/lcmfig2.png differ diff --git a/doc/images/lcm/lcmfig3.png b/doc/images/lcm/lcmfig3.png new file mode 100644 index 0000000000000000000000000000000000000000..2c3d2a1fb75dca83d3f470fb095f293aeadaaf7b Binary files /dev/null and b/doc/images/lcm/lcmfig3.png differ diff --git a/doc/images/lcm/lcmfig4.png b/doc/images/lcm/lcmfig4.png new file mode 100644 index 0000000000000000000000000000000000000000..e4f1f7c1f91620b8614783ab4a5b7df674e2d75e Binary files /dev/null and b/doc/images/lcm/lcmfig4.png differ diff --git a/doc/images/lcm/lcmfig5.png b/doc/images/lcm/lcmfig5.png new file mode 100644 index 0000000000000000000000000000000000000000..e16168aaad019450fe22a1c761c952d8c47570c5 Binary files /dev/null and b/doc/images/lcm/lcmfig5.png differ diff --git a/doc/images/lcm/lcmfig6.png b/doc/images/lcm/lcmfig6.png new file mode 100644 index 0000000000000000000000000000000000000000..2d9c8a985f545c9e41643ad82a3cb2fb3704d47a Binary files /dev/null and b/doc/images/lcm/lcmfig6.png differ diff --git a/doc/images/lcm/lcmfig7.png b/doc/images/lcm/lcmfig7.png new file mode 100644 index 0000000000000000000000000000000000000000..b3554530c7e94d96191257c8ac1609fabd14584a Binary files /dev/null and b/doc/images/lcm/lcmfig7.png differ diff --git a/doc/images/lcm/lcmfig8.png b/doc/images/lcm/lcmfig8.png new file mode 100644 index 0000000000000000000000000000000000000000..d3df01871b79890d111d5a20b1a881811b4b8a29 Binary files /dev/null and b/doc/images/lcm/lcmfig8.png differ diff --git a/doc/images/lcm/lcmfig9.png b/doc/images/lcm/lcmfig9.png new file mode 100644 index 0000000000000000000000000000000000000000..10b653fe894eeab9364bd21ca95f3fc2419080c8 Binary files /dev/null and b/doc/images/lcm/lcmfig9.png differ diff --git a/doc/images/microservices_network_deployment.png b/doc/images/microservices_network_deployment.png new file mode 100644 index 0000000000000000000000000000000000000000..5087c9a5ad03dad4285c515827b0ecc81e7ba7de Binary files /dev/null and b/doc/images/microservices_network_deployment.png differ diff --git a/doc/images/multi-domain-architecture.png b/doc/images/multi-domain-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..e66685567979a2e4de8a42efb751ff5691c8c405 Binary files /dev/null and b/doc/images/multi-domain-architecture.png differ diff --git a/doc/images/multi-domain-organizations.png b/doc/images/multi-domain-organizations.png new file mode 100644 index 0000000000000000000000000000000000000000..461bffcc70c8ddea609ef594b459975f6fb2f47b Binary files /dev/null and b/doc/images/multi-domain-organizations.png differ diff --git a/doc/images/openslice_logo.png b/doc/images/openslice_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..61a38a515223bb67a78da6694c34dbe08c89e942 Binary files /dev/null and b/doc/images/openslice_logo.png differ diff --git a/doc/images/order_scheduler_bpm.png b/doc/images/order_scheduler_bpm.png new file mode 100644 index 0000000000000000000000000000000000000000..dab22ad2ae255167795967cb74cdb26dd6191393 Binary files /dev/null and b/doc/images/order_scheduler_bpm.png differ diff --git a/doc/images/order_scheduler_diagram.png b/doc/images/order_scheduler_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..e732812b568387200832946cdfc571049de6ef64 Binary files /dev/null and b/doc/images/order_scheduler_diagram.png differ diff --git a/doc/images/osm_ecosystem_ossbss.png b/doc/images/osm_ecosystem_ossbss.png new file mode 100644 index 0000000000000000000000000000000000000000..5db4c1dead6f732348268710b116f7318424fd61 Binary files /dev/null and b/doc/images/osm_ecosystem_ossbss.png differ diff --git a/doc/images/service_order_initial_state.png b/doc/images/service_order_initial_state.png new file mode 100644 index 0000000000000000000000000000000000000000..931ec7b43cdd59a43ec8d204d99ab0ef82e2913b Binary files /dev/null and b/doc/images/service_order_initial_state.png differ diff --git a/doc/images/service_order_states.png b/doc/images/service_order_states.png new file mode 100644 index 0000000000000000000000000000000000000000..b609a78c2c871da7064e70adb5680c8ce5612255 Binary files /dev/null and b/doc/images/service_order_states.png differ diff --git a/doc/images/service_specification_instantiation.png b/doc/images/service_specification_instantiation.png new file mode 100644 index 0000000000000000000000000000000000000000..4bdaea9b5ac8702a2dfd801d7c85669c8cba8a97 Binary files /dev/null and b/doc/images/service_specification_instantiation.png differ diff --git a/doc/images/service_states.png b/doc/images/service_states.png new file mode 100644 index 0000000000000000000000000000000000000000..582f6de14e7a3a2673e28b46e6263231aad407c7 Binary files /dev/null and b/doc/images/service_states.png differ diff --git a/doc/images/start_order_process_bpm.png b/doc/images/start_order_process_bpm.png new file mode 100644 index 0000000000000000000000000000000000000000..c16355cf30212e3aa511ef8fcd53baab315f0777 Binary files /dev/null and b/doc/images/start_order_process_bpm.png differ diff --git a/doc/images/start_order_process_diagram.png b/doc/images/start_order_process_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..4c225e5efb33e4771d0160dec86bcbea01507f21 Binary files /dev/null and b/doc/images/start_order_process_diagram.png differ diff --git a/doc/images/vinni_sb_model_diagram.png b/doc/images/vinni_sb_model_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..463b5082b12ab02481cd54f4056743eb1f9be1dd Binary files /dev/null and b/doc/images/vinni_sb_model_diagram.png differ diff --git a/doc/index.md b/doc/index.md new file mode 100644 index 0000000000000000000000000000000000000000..3b68017c472df31e7a9f72b7894d5dd1c2af6349 --- /dev/null +++ b/doc/index.md @@ -0,0 +1,127 @@ +drawing + +version: 2023-Q3 1.2.0-SNAPSHOT + +Openslice is a prototype open source, operations support system. It supports VNF/NSD onboarding to OpenSourceMANO (OSM) and NSD deployment management. It also supports TMFORUM OpenAPIs regarding Service Catalog Management, Ordering, Resource, etc. + + +## Usage + +Openslice allows Vertical Customers to browse the available offered service specifications and also allows NFV developers to onboard and manage VNF and Network Service artifacts. +The following figure displays the usage of Openslice. + +[![Openslice usage](./images/index_intro_architecture.png)](./images/index_intro_architecture.png) + + +There are two portals offering UI friendly access to users: + +* The Services portal allows users to access services and service providers to design services. +* The NFV portal allows users to self-manage NFV artifacts and onboard them to a target MANO/NFV Orchestrator. + +3rd party applications can use Openslice through TMForum Open APIs. + +Service Specifications reside into Service Catalogs, grouped in Categories. Openslice offers a Service Orchestrator called [OSOM](./architecture/osom.md). OSOM instantiates Service Specifications by requesting Network Services from target MANOs/NFVOs. NFV artifacts reside into a VNF/NSD catalog and are onboarded to a target MANO/NFV Orchestrator. Service Specifications reference NSD from the VNF/NSD catalog. + +Customers make Service Orders and Openslice instantiates the requested Service Specifications of the Service Order. Running Services instantiated by Openslice, reside in Openslice Service Inventory. The following picture displays how Service Specifications are related to Running Services and how Running Services relate with instantiated running Network Services. (See also [Service Inventory](./service_inventory.md) ) + +[![Openslice Service Specification instantiation](./images/service_specification_instantiation.png)](./images/service_specification_instantiation.png) + +## Service Lifecycle Rules + +Openslice constains support for defining rules of services, affecting their behavior. See [LCm Rules](./lcm.md) + +## Multidomain scenarios and federation + +Openslice can be used to exchange service specifications/catalogs and make service orders between Organizations as the following figure displays. + +[![Openslice Service Specification instantiation](./images/multi-domain-organizations.png)](./images/multi-domain-organizations.png) + +An Identity federation is also possible since our authentication service is based on Keycloak (see [OAuth](./architecture/oauth.md) ) + +See more on [Consuming Services From External Partner Organizations](./architecture/consumingServicesFromExternalPartners.md) + + +## Live Demo + +* Openslice demo: +* Openslice Service Catalogs and ordering: +* Openslice NFV Services onboarding: +> username=admin, password=openslice
or
username=admin, password=changeme + + +## Video demo + +* + +--- + +## Installing + +See [Deployment/Installation](./deployment.md) + +--- + +## Hardware requirements + +The complete environment consists of microservices deployed as docker containers. Portainer is also installed to monitor them at port 9000 + +If you would like to operate all APIs, OSOM, the Mysql Server, nginx, etc then you need at least: + +- 4 cores +- 8GB RAM +- 20GB HD space + +(NOTE: Bugzilla or ELK are not included and we assume they run elsewhere) + +However you can try with a minimum installation on a VM on a laptop with: + +- 2 cores +- 4GB of RAM + + + +## Supported APIs + +For a quick access check our swagger links: + +* TMF APIs: +* API for VNF/NSD management: + +## Source code + +Get source code here: + +## Contributing + +[Contributing](./contributing/developing.md) + +## Social Media + +* Twitter: +* Slack: https://openslice.slack.com + +## History + +* The NFV portal part of Openslice was initially developed in H2020 European project 5GinFIRE (https://5ginfire.eu) by University of Patras, Greece +* Openslice services, APIs and current version are actively maintained by University of Patras, Greece in H2020 European project 5G-VINNI (https://5g-vinni.eu/) + + +[![Part of OSM Ecosystem](./images/osm_ecosystem_ossbss.png)](https://osm.etsi.org/wikipub/index.php/OSS_BSS) + + +## Citation + +Please cite our [![paper]](https://arxiv.org/abs/2102.03290) if you use Openslice + +``` + +@misc{tranoris2021openslice, + title={Openslice: An opensource OSS for Delivering Network Slice as a Service}, + author={Christos Tranoris}, + year={2021}, + eprint={2102.03290}, + archivePrefix={arXiv}, + primaryClass={cs.NI} +} + +``` \ No newline at end of file diff --git a/doc/lcm.md b/doc/lcm.md new file mode 100644 index 0000000000000000000000000000000000000000..b668b908c58da2c6972e11a0b6ca50450fd02176 --- /dev/null +++ b/doc/lcm.md @@ -0,0 +1,158 @@ +# Lifecycle Management (LCM) Rules + +* NOTE: This is a prototype/experimental feature. So issues might raise during operation + +LCM Rules are used for defining complex conditions and actions during the lifecycle of a service. In Openslice there are four types of rules defined: + +* PRE_PROVISION +* CREATION +* AFTER_ACTIVATION +* SUPERVISION +* AFTER_DEACTIVATION + + +The following figure displays the different phases that the rules are performed, during the lifecycle of a Network Slice Instance. + +[![Rules in NSI](../images/lcm/lcmfig1.png)](../images/lcm/lcmfig1.png) + +* PRE_PROVISION rules: Run only once just before creating a service with a given priority. +* CREATION rules: Run while the referenced service dependencies of a service are created +* AFTER_ACTIVATION rules: Run only once just after a service get the ACTIVE state +* SUPERVISION rules: Run when a characteristic of a service is changed and the service is in the ACTIVE state +* AFTER_DEACTIVATION rules: Run only once just after a service get the INACTIVE/TERMINATED state + +In general the rules allow to perform many actions during service LCM. Thes are some examples: + +* Modify service specification parameters before the instantiation of a service (or during operation) based on other dependencies. These parameters might be part of other services already included in Service order +* Translate GST/NEST parameter values to other values passed later to NFVO for instantiation or control +* Define complex OSM Configs based on other dependencies and passing variables +* Define any dependencies when creating the referenced services +* Dynamically include new service dependencies +* Create new service orders so include dynamically other services +* Call external (RESTful) services (via http(s), define payload, examine response) + + + + +## Examine if the rules are executed successfully + +Rules are transformed automatically to executable code (currently is Java). If a rule is performed successfully or has any issues (e.g. unexpected syntax errors or exceptions) appear in OSOM logfiles and also tey are attached as Notes to the running Service. + +## LCM Rules and OSOM Service Orchestration + +OSOM is the responsible service for executing the rules on a specific phase. The following image explains the design in the BPMN phases: + + +[![Rules](../images/lcm/lcmfig1_osom.png)](../images/lcm/lcmfig1_osom.png) + + + +## Define rules + +Rules are defined when designing a Service Spec. Here is an example of a list of rules: + + +[![lcmrules](../images/lcm/lcmfig2.png)](../images/lcm/lcmfig2.png) + +Execution order of rules on a specific phase is random + +* NOTE: There is a priority field. The lower the number the highest the priority of rule execution. For example Rule with priority 0 will run before rule with priority 1. + + +### Definition language + +* The visual language that Openslice used is based on Google's Blockly (see https://developers.google.com/blockly) +* The blockly graph is automatically translated to Java internally and then dynamically executed during orchestration phases. + +The following figure is an example of such a rule design. The rule for example will run in PRE_PROVISION phase: + +[![lcmrules](../images/lcm/lcmfig3.png)](../images/lcm/lcmfig3.png) + +* The goal of the above rule is to properly define a variable AreaCodes given the chosen AreaOfService from a Service Order. +* On the right side the user can define some rule properties or observe the underlying generated java code. + + +## The blocks library + +The following images describe some blocks found in the library. + +Blockly has syntax rules. It helps with colours to define them. + +So for example a parameter that is a Number cannot be "glued" with a String. Will need some conversion first + +[![lcmrules](../images/lcm/lcmfig4.png)](../images/lcm/lcmfig4.png) +[![lcmrules](../images/lcm/lcmfig5.png)](../images/lcm/lcmfig5.png) +[![lcmrules](../images/lcm/lcmfig6.png)](../images/lcm/lcmfig6.png) +[![lcmrules](../images/lcm/lcmfig7.png)](../images/lcm/lcmfig7.png) +[![lcmrules](../images/lcm/lcmfig8.png)](../images/lcm/lcmfig8.png) + +## Examples of Rules + + +The following images provide some examples of rules. + +### define variables according to cases + +In the following example we : + +* define a String variable. +* Then according to the Area of Service selected from the Service Order of the Service Specification we need to define it properly. +* We output the value to the OSOM Log +* Define dynamically the value of another parameter (This is fictional) and then do some other condition check + +The strAreaCodes could be passed then e.g. to NFVO for instantiation of services to these cells. + + +[![lcmrules](../images/lcm/lcmfig9.png)](../images/lcm/lcmfig9.png) + + + +### Define complex OSM configs for DAY 0 + +The following displays some complex examples for defining the parameters to pass to the NFV. In this case is OSM. + +* NOTE: The OSM_CONFIG characteristic of a service is the one that it is used in orchestration to instantiate NS from OSM + +* check the variable strTargetsParam. It is passed to the variable strOsmConfig3 which is executed if the Number of Cameras is more than 100. +* if the Video quality requested is 3, then the Maximum Namber of camers will be 8. Check the OSM detailed configuration block and its syntax. +* if the Video quality requested is 2, we use a simpler OSM Config block to configure the parameter OSM_CONFIG. We just injected a json text ( watch the Escape of the string for the Quotes!) +* if the Video quality requested is 1, again we use a simpler OSM Config block to configure the parameter OSM_CONFIG. We use as injected json text a variable constructed later + + +[![lcmrules](../images/lcm/lcmfig10.png)](../images/lcm/lcmfig10.png) + + +### Define and instantiate different services according to Service Order request + +In the following example we would like to offer a service either as Platinum, Gold or Silver. Depending on the selection we need to instantiate different services. + +There are different ways to accomplish this: + +* create dynamically New Service Orders of RFSs with equivalent quality of Services +* change for example the VIMs that you deploy the NS +* change the NSD (that is use different VNFs) + +The following image displays for example the latter case. + +[![lcmrules](../images/lcm/lcmfig11.png)](../images/lcm/lcmfig11.png) + + +### Call an external RESTful service + +This is useful in cases for example of alarms , external logging, calling other services e.g. email or even a complex algorithm written in other language e.g. call an external service and get a result. (service e.g. a Python service) + + +[![lcmrules](../images/lcm/lcmfig12.png)](../images/lcm/lcmfig12.png) + +[![lcmrules](../images/lcm/lcmfig13.png)](../images/lcm/lcmfig13.png) + +### Create New Service Orders + +The following example calls to Order a New Service Specification with specific Parameter Values + +[![lcmrules](../images/lcm/lcmfig14.png)](../images/lcm/lcmfig14.png) + + + + + diff --git a/doc/lcmrules_main.pu b/doc/lcmrules_main.pu new file mode 100644 index 0000000000000000000000000000000000000000..7616cc5a93a268d9996f88c19fe94924994e49cd --- /dev/null +++ b/doc/lcmrules_main.pu @@ -0,0 +1,24 @@ +@startuml + +note + Notes + ---- + Each LCM rule might be executed during the following phases: + "Pre-provision phase" + "Activation phase" + "Supervision phase", + "De-activation phase" + + A rule may: + 1) Modify some parameters of the requested service according to user request. + These parameters might be part of other services (or related resources?) already included in Service order + 2) Modify the service order by including other services + 3) Initiate new Service Orders for Other Services (including their parameters) + 4) May call external services (e.g. via REST) +end note + +start +stop + + +@enduml \ No newline at end of file diff --git a/doc/nfvcatalogs.md b/doc/nfvcatalogs.md new file mode 100644 index 0000000000000000000000000000000000000000..ad055840d65abfe337af4a5b60a3e7e10097ec42 --- /dev/null +++ b/doc/nfvcatalogs.md @@ -0,0 +1,42 @@ +# NFV Services + +NFV Services are managed through a dedicate UI the NFV portal (eg http://portal.openslice.io/nfvportal) + +Users are able through this portal to manage their NFV artifacts towards the NFVO, ( for example onboard VNFs and NSDs to a target OSM) + + +Openslice NFV Services target to accommodate the following envisaged user roles. All users are assumed to be Authenticated: + +* NFV developer: This role is responsible to upload VNF and NSD Descriptors in the Openslice services towards NFVO like OSM +* Services administrator: This role represents the user that are responsible for maintenance of the Openslice services + +(obsolete: ) + +* Testbed provider: This role represents users that are responsible for testbed administration, configuration, integration, adaptation, support, etc +* Experimenter: This role represents the user that will utilize our services and tools to deploy an experiment. That is the experiment description in terms of e.g.: NSD (Network Service Descriptor) or TOSCA Specification (in future versions) + + +Finally an anonymous user role exists who has some really simple usage scenarios (e.g. signup through the portal) + + +During the onboarding process the following occurs: + +• A NFV developer submits a NFV archive (VNF or NSD) (he can later manage if needed some metadata) +• The administrator can manage the NFV artifact (e.g. edit it) +• The administrator On-Boards the NFV artifact to the target MANO +• The administrator can optionally mark the NFV: +o As public in order to be publicly visible by all portal users +o As Certified which means this is certified by a certain entity + + +## Request a new NSD deployment (this is different in comparison to Services) + + +A developer requests a new network service deployment (which NSD, tentative dates, target infrastructure, etc.). The request is marked as UNDER_REVIEW + +* The administrator is notified about the new request and he has the following options: +* Schedule the deployment for the requested dates or propose other dates. The request is marked as SCHEDULED +* Reject the request for some reason. The Request is marked as REJECTED +* Deploy the request to target VIM(s). The Request is marked as RUNNING +* Finalize the deployment and release resources. The Request is marked as COMPLETED +* every change of the request-lifecycle the experimenter is notified. \ No newline at end of file diff --git a/doc/nfvoconfig.md b/doc/nfvoconfig.md new file mode 100644 index 0000000000000000000000000000000000000000..91efd366f981905fa7cd16fdf3838b2c6954c4ed --- /dev/null +++ b/doc/nfvoconfig.md @@ -0,0 +1,19 @@ +# NFV Orchestrator configuration + +NOTE: Currently we support Open Source MANO version SEVEN/EIGHT/TEN/ELEVEN. Later versions of OSM may also be supported by the existing configuration, as from OSM 9+ the project converged to the SOL005 interface, regarding the NBI, and SOL006 (YANG model), regarding the NFV/NSD packaging. Also an implementation of a generic SOL005 interface is supported, but not extensively tested. + +Configuration of your target(s) NFVOs/MANO services with Openslice is performed through the NFV portal. + +Login to http://yourdomain/nfvportal/ + +Navigate to Admin->Manage MANO Platforms and pick one of the supported MANO platform(s), e.g. Name=OSMvTEN, Version=OSMvTEN and save + +Navigate to Admin->Manage MANO providers and enter a New MANO Provider: + +* Name whatever you wish +* API URL Endpoint, eg: https://10.10.10.10:9999 (This is the SOL005 NBI endpoint) +* Username, password and Project of your OSM tenant. + +Check EnabledForONBOARDING, so when users onboard VNFs/NSDs they will be automatically ONBOARDED to this MANO. If left unchecked, the onboarding must be performed manually after the VNF/NSD is uploaded to the portal. + +Check EnabledForSYNC, if you want to support MANO->Openslice auto synchronization. When enabled, the existing VNFs/NSDs and VIMs (and any updates on them) of the registered MANO are also reflected to the portal. \ No newline at end of file diff --git a/doc/service_inventory.md b/doc/service_inventory.md new file mode 100644 index 0000000000000000000000000000000000000000..480b92f111424c67ab3b4efbba089f4339ddb732 --- /dev/null +++ b/doc/service_inventory.md @@ -0,0 +1,39 @@ +# Service Inventory + +After a Service Order completion, active services with their additional characteristics are found: + +* From the Order Items of a selected Service order +* from the menu of Service inventory and then selecting details of each service +* through the Service Inventory API (TMF 638 - Service Inventory Management ) + + +Openslice creates a Service for the requested CFS. Customers make Service Orders and Openslice instantiates the requested Service Specifications for each Service Order Item of a Service Order. Running Services instantiated by Openslice, reside in Openslice Service Inventory. The following picture displays how Service Specifications are related to Running Services and how Running Services relate with instantiated running Network Services. + + +[![Openslice Service Specification instantiation](./images/service_specification_instantiation.png)](./images/service_specification_instantiation.png) + + +There is a hierarchy of services. Usually an Instantiated CFS has Supporting Services some Instantiated RFSs. Then an Instantiated RFS is related to some running NS managed by NFVO + + +## Interacting with an Active Service (Day 2 config) + +In some cases, if the underlying service is configured with actions (for example in OSM Day 2 primitive actions), there are characteristics that can be modified. Usually they are named like : ::Primitive:: + +The user can edit the characteristic with a new value. The value is propagated through the OSOM and NFVO down to the related VNF. + +## Terminating/Inactivating a service + +You can terminate the service with one of the following processes: + +* Select the related Service Order and terminate the Order Item. This will delete all the underlying related active services. The Order goes to ACKNOWLEDGED->INPROGRESS->COMPLETE +* To terminate or inactivate a service, select the specific service from the inventory, press Edit and set the State either to Inactive or Terminated + +Warning: if you terminate or inactivate a service the action cannot be undone. + + +## uml: sequence diagram +Here I will embed PlantUML markup to generate a sequence diagram. + +I can include as many plantuml segments as I want in my Markdown, and the diagrams can be of any type supported by PlantUML. + diff --git a/doc/so_ServiceCreationProcess.pu b/doc/so_ServiceCreationProcess.pu new file mode 100644 index 0000000000000000000000000000000000000000..d5404da18d1f2d2ad279583c6c3f0151c56dace0 --- /dev/null +++ b/doc/so_ServiceCreationProcess.pu @@ -0,0 +1,106 @@ +@startuml + + +start + +:create Underl Service for ServiceSpecification and for ServiceSpecRelationships; +:Create Service in RESERVED; +->human accepts; +:Service has state=RESERVED; + +:Process Create Rules; +repeat :for each service reference + :decide what to create; + if (anyNotCreatedSupportingServices[!allSupportingServicesCreatedAndActive]) then (yes) + if (allSupportingServicesCreated ) then (yes) + :wait a few seconds; + else + partition "**process** Create Service" { + } + endif + endif + +repeat while + +:Automation Check; + note right: allSupportingServicesCreatedAndActive +note + Automation Check process + ---- + //Automation Check process + decides which + services can be automatically + handled by NFVO + or can be managed + by external partner// +end note + + + + if ( partnerOrg != null ) then (yes) + :createServiceByServiceSpec + AUTOMATICALLY_MANAGED; + :execute any LCM rules "PRE_PROVISION" phase; + partition "**process** External Service Provider Deployment Request" { + :Submit Order To External Service Provider; + :Check external service order fulfilment; + } + else if ( "CustomerFacingServiceSpecification" && isIsBundle) then (yes) + :createServiceByServiceSpec + AUTOMATICALLY_MANAGED; + :copy characteristics from Service Order Item; + :copy the rest of characteristics from Service Spec; + :execute any LCM rules "PRE_PROVISION" phase; + :create the related Service Instance; + note + the underlying actual + running service + is not created here. + this spec is not an RFS + end note + partition "**process** Local Service Orchestration" { + :Local Service Orchestration; + :Check Service Deployment Task; + } + else if ( CustomerFacingServiceSpecification) && (specrel.findSpecCharacteristicByName("OSAUTOMATED") ) then + :createServiceByServiceSpec + AUTOMATICALLY_MANAGED; + :execute any LCM rules "PRE_PROVISION" phase; + else if ( ResourceFacingServiceSpecification ) then + :createServiceByServiceSpec + AUTOMATICALLY_MANAGED; + :copy characteristics from Service Order Item; + :copy the rest of characteristics from Service Spec; + :execute any LCM rules "PRE_PROVISION" phase; + :create the related Service Instance; + note + the underlying actual + running service + is not created yet + but is propaged + to NFVO next + if there is an NSD + end note + if ( specrel.findSpecCharacteristicByName( "NSDID" ) != null ) then + :servicesHandledByNFVOAutomated.add(createdServ.getId()); + else + :servicesLocallyAutomated.add(createdServ.getId()); + endif + partition "**process** NFVO Deployment Request" { + :NFVO RFS Task; + :Check service deployment; + } + else + :createServiceByServiceSpec + (sor, soi, specrel, EServiceStartMode.MANUALLY_BY_SERVICE_PROVIDER, null);; + partition "**process** User Task Manual Complete Service" { + :UserOrderCompleteService; + } + endif + + + :Evaluate Created Services Task ; + + +stop +@enduml \ No newline at end of file diff --git a/doc/so_activity_main.pu b/doc/so_activity_main.pu new file mode 100644 index 0000000000000000000000000000000000000000..bd108c37e734207d49ae605d498311a568d6353a --- /dev/null +++ b/doc/so_activity_main.pu @@ -0,0 +1,48 @@ +@startuml + + +start + +:Check for service orders; +->human accepts; +:Order is changed from INITIAL to ACKNOWLEDGED; +stop + +start +-> TIMER; +:Fetch Acknowledged Orders; +-> List of ordersToBeProcessed; +:Initialize Process Order; +note right: Each order is INPROGRESS +partition "**process** Start Order Process" { + note + Start Order Process + ---- + //Start Order Process// + end note + :Find Order Items; + repeat :for each ServiceOrderItem + + partition "**process** Process Order Item" { + :ProcessOrderItemActionCheck; + if (ServiceOrderActionType.ADD) then (yes) + :Action Add; + :CreateServiceProcess; + + + else if (ServiceOrderActionType.MODIFY) then (yes) + :Action MODIFY; + else if (ServiceOrderActionType.DELETE) then (yes) + :Action DELETE; + endif + :Process OrderItemComplete; + + } + repeat while + +} + + + +stop +@enduml \ No newline at end of file diff --git a/kubernetes/helm/README.md b/kubernetes/helm/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b3459eb5a726dcd1e85b697d617c433a81a156e1 --- /dev/null +++ b/kubernetes/helm/README.md @@ -0,0 +1,386 @@ +# OpenSlice Installation Guide with Kubernetes + +## Requirements + +### Hardware requirements: + +| **Minimum Hardware Requirements** | **Recommended Hardware Requirements** | +| --------------------------------- | ------------------------------------ | +| 4 CPU cores | 8 CPU cores | +| 8 GB RAM | 16 GB RAM | +| 30 GB storage | 50 GB storage | + +### Software Requirements: + +* **git:** For cloning the project repository. +* **Kubernetes:** A running cluster where OpenSlice will be deployed. + * **Disclaimer:** The current manual setup of Persistent Volumes using `hostPath` is designed to operate with **only a single worker node**. This setup will not support data persistence if a pod is rescheduled to another node. +* **Helm:** For managing the deployment of OpenSlice. +* **Ingress Controller:** Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource. An Ingress may be configured to give Services externally-reachable URLs, load balance traffic, terminate SSL / TLS, and offer name-based virtual hosting. An Ingress controller is responsible for fulfilling the Ingress, usually with a load balancer, though it may also configure your edge router or additional frontends to help handle the traffic. You must have an Ingress controller to satisfy an Ingress. + * An Nginx ingress controller is required, which can be installed using [this guide](https://docs.nginx.com/nginx-ingress-controller/installation/installing-nic/installation-with-helm/). + * If you use another type of ingress controller, you'll need to modify `[repo-root]/kubernetes/helm/openslice/templates/openslice-ingress.yaml` to conform to your ingress controller's requirements. +* **Network Load Balancer:** Required for exposing the service (e.g., GCP, AWS, Azure, MetalLB). +* **Domain/IP Address:** Necessary for accessing the application. This should be configured in `[repo-root]/kubernetes/helm/openslice/values.yaml` under `rooturl`. + +### Additional Configuration + +* **Storage Class:** In a production environment, specify your `storageClass` in `[repo-root]/kubernetes/helm/openslice/values.yaml` under `storageClass`. If not defined, PVs will be created and managed manually. + * **Disclaimer:** Before deploying, confirm that your storage system supports claims of one 10G and two 1G volumes. + +## Preparing the environment + +### 1. Setting Up A Kubernetes Cluster +Refer to the official Kubernetes documentation for setting up a cluster. Ensure your cluster meets the hardware requirements specified above. + +### 2. Installing Helm +Helm must be installed on your machine to deploy OpenSlice via Helm charts. Follow the [official Helm installation guide](https://helm.sh/docs/intro/install/). + +## Downloading the project + +### 1. Create a new folder to download the project + +```bash +mkdir openslice +cd openslice +``` + +### 2. Download the project code +Clone the project code from the GitLab repository. +**Note:** This process will be simplified once the charts are published in the GitLab registry, requiring only the chart to be pulled. + +```bash +git clone https://labs.etsi.org/rep/osl/code/org.etsi.osl.main.git +cd org.etsi.osl.main/kubernetes/helm/openslice/ +``` + +### 3. Prerequisites before deployment + +Before deploying the Helm chart, ensure you have configured the necessary components as detailed in the following section, i.e. [Configure Helm Chart Services](#configure-helm-chart-services). By default, the `main` branch is selected for deployment. + +We recommend: + +* main branch for the most stable experience and +* develop branch for an experience with the latest features (for develop branch installation, it is strongly advisable that you may as well follow the [develop documentation](https://osl.etsi.org/documentation/develop/deployment/)) + + +## Configure Helm Chart Services + +When deploying OpenSlice with Helm, service configurations are handled through the `values.yaml` file. This file allows you to define all necessary configurations for your deployment, including database credentials, service URLs, and logging levels. Below are examples of how to configure your services in Helm based on your provided values. + +### Configuring Services + +#### 1. Database Configuration + +To configure MySQL and other related services, you can directly set the values in your `values.yaml` file under the `oscreds` and `mysql` sections. For example: + +```yaml +oscreds: + mysql: + username: "root" + password: "letmein" + openslicedb: "osdb" + keycloak: + database: "keycloak" + username: "keycloak" + password: "password" + adminpassword: "Pa55w0rd" + portal: + database: "osdb" + username: "portaluser" + password: "12345" +``` + +#### 2. External Services Configuration + +For configuring external services like Bugzilla and CentralLog, specify their URLs and credentials in the `values.yaml` file: + +```yaml +bugzillaurl: "example.com:443/bugzilla" +bugzillakey: "VH2Vw0iI5aYgALFFzVDWqhACwt6Hu3bXla9kSC1Z" +main_operations_product: "Main Site Operations" // this is the default product to issue tickets +centrallogurl: "http://elk_ip:elk_port/index_name/_doc" +``` + +Bugzilla should have the following components under the specified product: + +* NSD Deployment Request: Component used to schedule deployment req +* Onboarding: Issues related to VNF/NSD Onboarding +* Operations Support: Default component for operations support +* Validation: Use to track validation processes of VNFs and NSDs +* VPN Credentials/Access: Used for requesting VPN Credentials/Access + +Also in the 'Main Site Operations' product, a version named 'unspecified' must be created. + +#### 3. Keycloak Configuration + +Keycloak settings, including the database and admin password, are part of the `oscreds.mysql.keycloak` section. If you need to adjust Keycloak-specific settings like realms or client configurations, you'll likely need to customize your Helm chart further or manage these settings directly within Keycloak after deployment. The Keycloak realm configuration that is imported by default can be found under `kubernetes/helm/openslice/files/keycloak-init/realm-export.json`. + +```yaml +oscreds: + mysql: + keycloak: + database: "keycloak" + username: "keycloak" + password: "password" + adminpassword: "Pa55w0rd" +``` + +#### 4. Application and Logging Configuration + +Application-specific configurations, such as OAuth client secrets, can be set in the `spring` section: + +```yaml +spring: + oauthClientSecret: "secret" +``` + +#### 5. Ingress and Root URL + +To configure the ingress controller and root URL for OpenSlice, update the rooturl field with your ingress load balancer IP or domain. This setting is crucial for external access to your application: + +```yaml +rooturl: "http://openslice.com" # Example domain +# or +rooturl: "http://3.15.198.35:8080" # Example IP with port +``` + +#### 6. Persistent Volume for MySQL + +For persistent storage, especially for MySQL, define the storage size under the `mysql` section. This ensures that your database retains data across pod restarts and deployments. + +```yaml +mysql: + storage: "10Gi" +``` + +## Configure Web UI + +In folder `kubernetes/helm/openslice/files/org.etsi.osl.portal.web/src/js` you must make a copy of `config.js.default` file and rename it to `config.js`. + +This is **mandatory** for the configuration file to be discoverable. + +Edit the `config.js` configuration file with your static configuration, if needed. + +``` +{ + TITLE: "OpenSlice by ETSI", + WIKI: "https://osl.etsi.org/documentation/", + BUGZILLA: "{{ .Values.rooturl }}/bugzilla", + STATUS: "{{ .Values.rooturl }}/status", + APIURL: "{{ .Values.rooturl }}", + WEBURL: "{{ .Values.rooturl }}/nfvportal", + APIOAUTHURL: "{{ .Values.rooturl }}/auth/realms/openslice", + APITMFURL: "{{ .Values.rooturl }}/tmf-api/serviceCatalogManagement/v4" +} +``` + + + +## Configure TMF Web UI + +In the folder `kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config` there are 3 files available for configuration: + +* config.prod.default.json (Basic information + API configuration) +* theming.default.scss (CSS color palette theming) +* config.theming.default.json (HTML configuration - Logo, Favicon, Footer) + +You must make a copy of files: + +* `config.prod.default.json` and rename it to `config.prod.json` +* `theming.default.scss` and rename it to `theming.scss` + +The 2 files above (i.e. config.prod.json, theming.scss) are essential for the successful deployment of OpenSlice, and executing the above steps is **mandatory** for the configuration files to be discoverable. + +Ensure that you check the `config.prod.json` and `theming.scss` files and readjust to your deployment if needed. + +```bash +# Starting from the root project directory +cd kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config +``` + +E.g. You may edit "TITLE", "WIKI", etc properties with your domain title. Also configure TMF's API and Keycloak's location for the web application, if needed. + +``` +{ + "TITLE": "OpenSlice by ETSI", + "PORTALVERSION":"2024Q2", + "WIKI": "https://osl.etsi.org/documentation", + "BUGZILLA": "{BASEURL}/bugzilla/", + "STATUS": "{BASEURL}/status/", + "WEBURL": "{BASEURL}", + "PORTAL_REPO_APIURL": "{BASEURL}/osapi", + "ASSURANCE_SERVICE_MGMT_APIURL": "{BASEURL}/oas-api", + "APITMFURL": "{BASEURL}/tmf-api", + "OAUTH_CONFIG" : { + "issuer": "{BASEURL}/auth/realms/openslice", + "loginUrl": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/auth", + "tokenEndpoint": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/token", + "userinfoEndpoint": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/userinfo", + "redirectUri": "{BASEURL}/redirect", + "logoutUrl": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/logout", + "postLogoutRedirectUri": "{BASEURL}", + + "responseType": "code", + "oidc": false, + "clientId": "osapiWebClientId", + "dummyClientSecret": "secret", + + "requireHttps": false, + "useHttpBasicAuth": true, + "clearHashAfterLogin": false, + + "showDebugInformation": true + } +} +``` + +> The {BASEURL} placeholder in the file automatically detects the Origin (Protocol://Domain:Port) of the deployment and applies it to every respective property. E.g. If you are attempting a local deployment of OpenSlice, then {BASEURL} is automatically translated to "http://localhost". Similarly, you may use {BASEURL} to translate to a public deployment configuration, e.g. "https://portal.openslice.io". + +If further customization, apart from the default provided, is needed for branding (Logo, Footer) then `config.theming.json` needs to be created in kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config directory, as follows: + +```bash +# Starting from the root project directory +cd kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config +``` + +```bash +sudo cp config.theming.default.json config.theming.json +``` + + +### 3. Deploy the Helm Chart + +After configuring the services, and editing the `values.yaml` file accordingly, the helm install command can be performed. + +```bash +cd kubernetes/helm/openslice/ +helm install myopenslice . --namespace openslice --create-namespace +``` + +## Validating deployments and container monitoring + +In a Kubernetes environment, you can monitor the status of your deployments and containers using `kubectl`, the Kubernetes command-line tool, which provides powerful capabilities for inspecting the state of resources in your cluster. + +### Checking the Status of your application's deployment + +To check the status of your deployment, use the following commands. The output should be similar: + +```bash + +kubectl get pods -n openslice + +NAME READY UP-TO-DATE AVAILABLE AGE +myopenslice-artemis 1/1 1 1 6m28s +myopenslice-blockdiag 1/1 1 1 6m28s +myopenslice-bugzilla 1/1 1 1 6m28s +myopenslice-centrallog 1/1 1 1 6m28s +myopenslice-cridge 1/1 1 1 6m28s +myopenslice-keycloak 1/1 1 1 6m28s +myopenslice-kroki 1/1 1 1 6m28s +myopenslice-manoclient 1/1 1 1 6m28s +myopenslice-oasapi 1/1 1 1 6m28s +myopenslice-osom 1/1 1 1 6m28s +myopenslice-osportalapi 1/1 1 1 6m28s +myopenslice-osscapi 1/1 1 1 6m28s +myopenslice-portalweb 1/1 1 1 6m28s +myopenslice-tmfweb 1/1 1 1 6m28s +``` +```bash +kubectl get deployments -n openslice + +NAME READY UP-TO-DATE AVAILABLE AGE +myopenslice-artemis 1/1 1 1 7m17s +myopenslice-blockdiag 1/1 1 1 7m17s +myopenslice-bugzilla 1/1 1 1 7m17s +myopenslice-centrallog 1/1 1 1 7m17s +myopenslice-cridge 1/1 1 1 7m17s +myopenslice-keycloak 1/1 1 1 7m17s +myopenslice-kroki 1/1 1 1 7m17s +myopenslice-manoclient 1/1 1 1 7m17s +myopenslice-oasapi 1/1 1 1 7m17s +myopenslice-osom 1/1 1 1 7m17s +myopenslice-osportalapi 1/1 1 1 7m17s +myopenslice-osscapi 1/1 1 1 7m17s +myopenslice-portalweb 1/1 1 1 7m17s +myopenslice-tmfweb 1/1 1 1 7m17s +``` +```bash +kubectl get services -n openslice + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +myopenslice-artemis ClusterIP 10.101.128.223 8161/TCP,61616/TCP,61613/TCP 7m43s +myopenslice-blockdiag ClusterIP 10.109.196.90 8001/TCP 7m43s +myopenslice-bugzilla ClusterIP 10.107.10.101 13010/TCP 7m43s +myopenslice-centrallog ClusterIP 10.109.84.33 13013/TCP 7m43s +myopenslice-keycloak ClusterIP 10.104.172.73 8080/TCP,8443/TCP 7m43s +myopenslice-kroki ClusterIP 10.106.92.111 8000/TCP 7m43s +myopenslice-manoclient ClusterIP 10.100.143.154 13011/TCP 7m43s +myopenslice-mysql ClusterIP 10.108.206.75 3306/TCP 7m43s +myopenslice-oasapi ClusterIP 10.100.107.66 13101/TCP 7m43s +myopenslice-osom ClusterIP 10.97.88.133 13100/TCP 7m43s +myopenslice-osportalapi ClusterIP 10.111.212.76 13000/TCP 7m43s +myopenslice-osscapi ClusterIP 10.101.84.220 13082/TCP 7m43s +myopenslice-portalweb ClusterIP 10.101.16.112 80/TCP 7m43s +myopenslice-tmfweb ClusterIP 10.101.157.185 80/TCP 7m43s +``` + +### Accessing Logs for Troubleshooting + +If a pod is not in the expected state, you can access its logs for troubleshooting: + +```bash +kubectl logs -n openslice +``` + +## Post installation steps + +After the successful deployment of OpenSlice, to ensure the E2E user experience, **this section is mandatory**. It contains crucial configuration in regard of authentication and user creation. + +### Configure Keycloak server + +The Keycloack server is managing authentication and running on a container at port 8080. It is also proxied to your host via the ingress resource under http://your-domain/auth. + +- Navigate to http://your-domain/auth/ or https://your-domain/auth/, (http://ipaddress:8080/auth/ or https://ipaddress:8443/auth/ which are directly accessible without proxy) + +- Navigate to Administration Console + +- Login with the credentials from section [Keycloak Configuration](#3-keycloak-configuration). Default values are: + - user: admin + - password: Pa55w0rd + +> This applies only if you are running in HTTP and get a message: HTTPS required. + +To resolve this issue when running in HTTP: + +- Select the master realm from top left corner +- Go to login Tab and select "Require SSL": None +- Repeat for realm Openslice + + +> If you are running in HTTPS, then "Require SSL" can be left unchanged to external requests. + +#### 1. Configure email + +Keycloak allows new users to register. Subsequently, this will also allow new users to register to the OpenSlice portal. + +Navigate to realm Openslice > Realm Settings > Login Tab > check User registration, Verify email, Forgot password etc. + +Finally, enter the details of the mail server at the Email Tab. + +> Email configuration is optional for test runs, but if not provided the above functionalities (e.g. external user registration) will not be possible. + + +#### 2. Add an OpenSlice admin user + +This step is mandatory so as to access the OpenSlice Web UI. To add an OpenSlice admin user you must: +- Navigate to realm Openslice > Users > Add user +- Set a password +- Upon creation, navigate to Role Mappings and add ADMIN to Assigned Roles list + +> That user is different from the Keycloak admin user. It is required to login and browse the OpenSlice Web UI. The Role ADMIN guarantee full access through the OpenSlice UI, thus such a user is always required. + +### NFV Orchestrator Configuration + +After successfully deploying and configuring OpenSlice, you may configure its environment (e.g. the NFVO) that will facilitate the deployment of NFV artifacts. + +See [NFV Orchestrator Configuration](./nfvoconfig.md). diff --git a/kubernetes/helm/openslice/.helmignore b/kubernetes/helm/openslice/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/kubernetes/helm/openslice/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/kubernetes/helm/openslice/Chart.yaml b/kubernetes/helm/openslice/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..18a24ba8dc405c6e9a6a28de01111afb5cea0697 --- /dev/null +++ b/kubernetes/helm/openslice/Chart.yaml @@ -0,0 +1,23 @@ +apiVersion: v2 +name: openslice +description: OpenSlice Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 1.0.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +appVersion: 2024Q2 diff --git a/kubernetes/helm/openslice/files/keycloak-init/realm-export.json b/kubernetes/helm/openslice/files/keycloak-init/realm-export.json new file mode 100644 index 0000000000000000000000000000000000000000..0be17ce27cf1cb144b41ee61b22c774305645a33 --- /dev/null +++ b/kubernetes/helm/openslice/files/keycloak-init/realm-export.json @@ -0,0 +1,2221 @@ +{ + "id": "openslice", + "realm": "openslice", + "displayName": "Openslice", + "notBefore": 1586721661, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 3600, + "accessTokenLifespanForImplicitFlow": 3600, + "ssoSessionIdleTimeout": 7200, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "1741dd77-ee50-4fd7-bec6-1a6d3d9d778a", + "name": "MENTOR", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "f61e8649-b003-42e2-8670-4116885a1e26", + "name": "NFV_DEVELOPER", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "379857ba-17b0-4299-9191-4df27ce9425b", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "a2685809-e874-4009-8435-92ded0c7180d", + "name": "ADMIN", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "af2ef7e2-d78a-4f4e-844c-174c64168316", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "8b544ccb-d0de-4550-b879-985c86b8d018", + "name": "USER", + "composite": false, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "0f367333-06dc-4740-931a-b2d6b3b06577", + "name": "EXPERIMENTER", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "ec900678-a7df-4955-a78d-a90b138a5121", + "name": "TESTBED_PROVIDER", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + } + ], + "client": { + "openslice-service": [], + "realm-management": [ + { + "id": "679a9d01-6d85-42f5-9c6b-f3d923dd1a0a", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "06f2873b-3926-4d97-9179-769e342f86e9", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "63f7b29c-c463-40d8-82de-4ae894de65ea", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "09422e3f-4358-466a-a46a-e887cb5f5189", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients", + "create-client", + "view-realm", + "manage-events", + "query-groups", + "manage-identity-providers", + "view-events", + "view-users", + "view-clients", + "manage-clients", + "impersonation", + "manage-authorization", + "manage-users", + "query-realms", + "query-users", + "manage-realm", + "view-authorization", + "view-identity-providers" + ] + } + }, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "2d6c5511-1cb7-4283-90f5-50d751c2eb92", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "dbb571cf-7d5e-418e-95d7-ca2160eceba6", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "31f02966-2fa2-479b-bcf1-fa2a000e7b0f", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "46c57172-f46d-466c-a73c-4b4f58eb23ce", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "006e604a-1915-4165-bf8a-709f77d07c99", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "22b0f1f4-b2de-4829-ae70-5b6a2ffb90c0", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "2ec8e15f-d086-4c49-a2dc-ccf1b85b645f", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "841fcb24-6965-4299-a2a8-2a0caf98b022", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "16a19114-7aa5-4c7c-a741-424e74b379b9", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "7c81140a-8b70-44fc-af0e-d6b83f6be914", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "1690c8e2-971a-4472-a21c-d2c403f46907", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "3b455fa3-45ce-4210-b138-c3a64b69271f", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "9cfae318-c817-428c-8a41-9f37fa3b8848", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "a085267a-ac93-4004-9899-b76b74d06c31", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "1dd16fc9-7abd-41fe-bb23-5887f01fa295", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "osapiWebClientId": [], + "account-console": [], + "broker": [ + { + "id": "be197fdb-fe78-4b10-87d3-9e17826b05c9", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "92128d63-9887-4e70-b5e2-9797756279d3", + "attributes": {} + } + ], + "account": [ + { + "id": "e2d74a05-f1a0-4fb1-8b03-a3e9b691d82b", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "f661e78f-1ce3-4af2-9a7c-a5cb7a09d4b5", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "3094e791-7572-4845-b64b-3dbbb763fdb7", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "05ddbf6c-7b93-4c49-83e9-154255ac877e", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "84bad9b3-a179-4700-84a4-fdcbf0ae2991", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "d3e32349-192a-464e-91f8-b73ed6a8f170", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRoles": [ + "uma_authorization", + "offline_access" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account" + ] + } + ] + }, + "clients": [ + { + "id": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/openslice/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": [ + "view-profile", + "manage-account" + ], + "redirectUris": [ + "/realms/openslice/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "7838e492-c9ce-4812-a9e9-629244fe1295", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/openslice/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/realms/openslice/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "48e276a8-68a7-45ef-929a-18d2afbab527", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "b233eb6d-e3df-4d8d-8b09-3666f043258f", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "92128d63-9887-4e70-b5e2-9797756279d3", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "41a307d8-9465-463e-89ad-8c30af4ad5c0", + "clientId": "openslice-service", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "40742f38-d000-431b-a0a5-f5101a730a5a", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "5115e3c5-8453-4c8b-a6a7-67e16f56eda9", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "a194cc8d-d541-42f8-8c3c-3553568b3d2c", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "40ec2a52-1033-4471-80a3-404167935e6f", + "clientId": "osapiWebClientId", + "rootUrl": "{{ .Values.rooturl }}", + "adminUrl": "{{ .Values.rooturl }}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "http://openslice.io/*", + "http://localhost:13000/osapi/webjars/springfox-swagger-ui/oauth2-redirect.html", + "http://localhost:13082/*", + "http://localhost:13000/*", + "{{ .Values.rooturl }}/*", + "http://localhost:13000/osapi/testweb/oauthresp.html" + ], + "webOrigins": [ + "http://localhost:13082", + "{{ .Values.rooturl }}", + "http://openslice.io", + "http://localhost:13000" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "37a4e3c2-48be-4ee0-b50f-6e439ed2cdb2", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/openslice/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/admin/openslice/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "d7eaa5b1-22be-4ab4-86b4-2e415aeca815", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "562b8e42-c857-4cf6-8241-28efb2642c4b", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "5a5001cb-4bd0-480f-a7a3-c0bcba80ad3a", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "f6653189-9761-4ef3-936c-38affde191d8", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "767ac64d-5809-4239-b406-edcdd9050e80", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "e8d8398b-37ea-43bb-9196-f934ac296014", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "09a290c7-2b47-4151-9bc5-157c74aca908", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "f00e6912-4087-4887-a322-28e138d4b39f", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + }, + { + "id": "b782ede1-459f-4e6a-bf8b-88b18a6772d6", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "a12e8651-599f-4ddb-b653-d8cb5b0184d7", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "0f2b29e9-8093-455c-a5a9-f0c1c928942f", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "f4ec14ee-b067-40bf-b7c0-6dd7df5a602f", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "65664f25-c82d-433d-bf36-c08ded829901", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "c712880d-9ef1-4ea2-86bf-810054d40b26", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "b18c9def-9b75-4706-9936-2d4178c7b5a6", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "dbef3b60-3c68-4bb7-9d2a-d8a85f6f7004", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "bdf07a0c-c5ca-4608-b494-b8a1ddc063c4", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "81e16a30-df1f-416b-80c3-6983101166d1", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "b44f4f26-6d0d-406e-9009-c5d8dfdd5d16", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "86c5c86e-cb21-4abd-a17a-85dc63617995", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "d78aedcd-828c-4773-ad70-22091d874bbd", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "95e1cb5d-4f42-4b2a-8e3a-69e39055b66d", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "id": "ac157f2a-50b9-404e-bde0-965910a47d05", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "4edc4427-0ebe-4825-89a8-0e8e80620f5a", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "6ce933f3-a5b4-4676-b5db-b6425d45021d", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "bd070586-ba31-42c4-b2fa-0614ad88e792", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "397b1ae7-6c83-4a4c-a97d-75102563ae57", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "a40de263-79e3-4adf-9dc6-584b1f537a06", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "6ca378b4-4e3b-4cc2-bee4-ef3479d59114", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "57d2d578-eb49-4756-8d41-c999c2849f1a", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "b322295e-fae9-4ade-9b0e-138a44732f3e", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "f24c94cb-8156-4f4e-b5f2-e7b3000f4f81", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "27c412ff-97ef-49d2-8a80-f42fd8649b7a", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "377da2df-94e7-43de-98f6-b3b4326cfa02", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "39e41a56-6439-40da-9aa7-fa3b8a57c759", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "bb450b68-fcda-4f82-b16c-6d83cd28aa8f", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "web-origins", + "roles", + "profile", + "email" + ], + "defaultOptionalClientScopes": [ + "microprofile-jwt", + "phone", + "address", + "offline_access" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "34e415a5-18a4-4e32-a17c-daf41c5cbf19", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "7d113054-e7c7-44cb-a6d8-d257195b1364", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "388b5ffd-ea57-48bc-b7af-43b21b529e8a", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper" + ] + } + }, + { + "id": "70080b90-b144-421e-9ec4-4106a6181d88", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "d556fcc1-038a-4ed2-992b-5803e4c599be", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "67803167-d874-41b2-970b-b2de89d0250b", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-address-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper", + "saml-user-attribute-mapper" + ] + } + }, + { + "id": "a4381728-f174-492f-9404-c8ecaddc8bd9", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "c60d614f-36b1-4a0f-b359-f2c4c7e7a2d5", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "472544bd-20bd-467d-8d5c-f71468017b90", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "56cdedf5-b827-4ca7-be55-8e12df78b974", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "9d0c7f22-b432-4223-baf1-83dbfbca38db", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "8357d622-c8b1-428d-b134-3315622f398d", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "f373c5c3-0467-47c7-8aa4-f6fe1acfe380", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "1647396e-5d80-47c0-9780-1b0601d81f55", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "4b75ca24-90fb-46da-ba2b-ba11e96b9cee", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "df72819f-b96b-47b9-88f5-bf0033798b40", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "241c2432-5771-4a42-90f3-4198b6e9fd62", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Account verification options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "fc2f23d5-003a-4e2a-947b-8f426c52694c", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c152dd74-8690-4c1f-b83f-2da74289cc1e", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "db2da225-e43a-42ad-977f-508895169efa", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "6bda8474-8636-4bff-9e86-b95552f5944a", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2dcccc92-8c58-4b18-9773-a991977fc829", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "34a83f8f-e241-412e-93c5-398495bc8f2a", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 30, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "d3849e68-145f-44ac-a360-d16930a6eb09", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "30ed0330-9d8a-4992-aa0c-56313cf60790", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "User creation or linking", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2521a30f-27ba-441e-821b-8515f63380c9", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "3f9984f5-a163-4b57-a947-1a7b72240dec", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Authentication Options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "273c03f3-8fc2-4e81-a9f7-fbf72158e129", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "07afd274-0910-43d8-b627-422d4d9e2ed8", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "7b72931e-ad78-41fd-add0-1e622e208d55", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 40, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2e95fbe8-90de-4ad0-af7c-b8a598456a19", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "0c8464aa-a2ea-479e-9f21-e3b4ba670b46", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "060e864c-a566-4551-ba54-2c280aafda02", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": {}, + "keycloakVersion": "9.0.2", + "userManagedAccessAllowed": false +} diff --git a/kubernetes/helm/openslice/files/mysql-init/01-databases.sql b/kubernetes/helm/openslice/files/mysql-init/01-databases.sql new file mode 100644 index 0000000000000000000000000000000000000000..aa16eecb933a0d47f811532a7fd8c7185800482c --- /dev/null +++ b/kubernetes/helm/openslice/files/mysql-init/01-databases.sql @@ -0,0 +1,11 @@ +# create databases +CREATE DATABASE IF NOT EXISTS `{{ .Values.oscreds.mysql.openslicedb | default "osdb" }}`; +CREATE DATABASE IF NOT EXISTS `{{ .Values.oscreds.mysql.keycloak.database | default "keycloak" }}`; + +# create portal user and grant rights +CREATE USER '{{ .Values.oscreds.mysql.portal.username | default "portaluser" }}'@'localhost' IDENTIFIED BY '{{ .Values.oscreds.mysql.portal.password | default "12345" }}'; +GRANT ALL PRIVILEGES ON *.* TO '{{ .Values.oscreds.mysql.portal.username | default "portaluser" }}'@'%' IDENTIFIED BY '{{ .Values.oscreds.mysql.portal.password | default "12345" }}'; + +# create keycloak user and grant rights +CREATE USER '{{ .Values.oscreds.mysql.keycloak.username | default "keycloak" }}'@'localhost' IDENTIFIED BY '{{ .Values.oscreds.mysql.keycloak.password | default "password" }}'; +GRANT ALL PRIVILEGES ON *.* TO '{{ .Values.oscreds.mysql.keycloak.username | default "keycloak" }}'@'%' IDENTIFIED BY '{{ .Values.oscreds.mysql.keycloak.password | default "password" }}'; diff --git a/kubernetes/helm/openslice/files/org.etsi.osl.cridge/kubeconfig.yaml b/kubernetes/helm/openslice/files/org.etsi.osl.cridge/kubeconfig.yaml new file mode 100644 index 0000000000000000000000000000000000000000..11764038afa4e39de82cc537994a03903690cde2 --- /dev/null +++ b/kubernetes/helm/openslice/files/org.etsi.osl.cridge/kubeconfig.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Config +clusters: +- name: development-cluster + cluster: + certificate-authority: path/to/ca.crt # Path to certificate authority file + server: https://123.45.67.89:6443 # Cluster API server address +contexts: +- name: dev-user@development-cluster + context: + cluster: development-cluster + namespace: development # Default namespace + user: dev-user +current-context: dev-user@development-cluster +users: +- name: dev-user + user: + client-certificate: path/to/cert.crt # Path to the client certificate + client-key: path/to/key.key # Path to the client key diff --git a/kubernetes/helm/openslice/files/org.etsi.osl.portal.web/src/js/config.js.default b/kubernetes/helm/openslice/files/org.etsi.osl.portal.web/src/js/config.js.default new file mode 100644 index 0000000000000000000000000000000000000000..be3cb6c45c945f14636252146d63010045a508a1 --- /dev/null +++ b/kubernetes/helm/openslice/files/org.etsi.osl.portal.web/src/js/config.js.default @@ -0,0 +1,14 @@ +var appConfig = angular.module('portalwebapp.config',[]); + +appConfig.factory('APIEndPointService', function() { + return { + TITLE: "OpenSlice by ETSI", + WIKI: "https://osl.etsi.org/documentation/", + BUGZILLA: "{{ .Values.rooturl }}/bugzilla", + STATUS: "{{ .Values.rooturl }}/status", + APIURL: "{{ .Values.rooturl }}", + WEBURL: "{{ .Values.rooturl }}/nfvportal", + APIOAUTHURL: "{{ .Values.rooturl }}/auth/realms/openslice", + APITMFURL: "{{ .Values.rooturl }}/tmf-api/serviceCatalogManagement/v4" + }; +}); diff --git a/kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config/config.prod.default.json b/kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config/config.prod.default.json new file mode 100644 index 0000000000000000000000000000000000000000..1d0bb9bae6fc33f8c2d2839da0a01f52bd836247 --- /dev/null +++ b/kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config/config.prod.default.json @@ -0,0 +1,31 @@ +{ + "TITLE": "OpenSlice by ETSI", + "PORTALVERSION":"2024Q2", + "WIKI": "https://osl.etsi.org/documentation", + "BUGZILLA": "{BASEURL}/bugzilla/", + "STATUS": "{BASEURL}/healthstatus/", + "WEBURL": "{BASEURL}", + "PORTAL_REPO_APIURL": "{BASEURL}/osapi", + "ASSURANCE_SERVICE_MGMT_APIURL": "{BASEURL}/oas-api", + "APITMFURL": "{BASEURL}/tmf-api", + "OAUTH_CONFIG" : { + "issuer": "{BASEURL}/auth/realms/openslice", + "loginUrl": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/auth", + "tokenEndpoint": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/token", + "userinfoEndpoint": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/userinfo", + "redirectUri": "{BASEURL}/redirect", + "logoutUrl": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/logout", + "postLogoutRedirectUri": "{BASEURL}", + + "responseType": "code", + "oidc": false, + "clientId": "osapiWebClientId", + "dummyClientSecret": "secret", + + "requireHttps": false, + "useHttpBasicAuth": true, + "clearHashAfterLogin": false, + + "showDebugInformation": true + } +} diff --git a/kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config/config.theming.default.json b/kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config/config.theming.default.json new file mode 100644 index 0000000000000000000000000000000000000000..0db3bf0e0708d7218a03f56c68434c7454345fd4 --- /dev/null +++ b/kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config/config.theming.default.json @@ -0,0 +1,9 @@ +{ +"THEME_ID":"default", +"DEPLOYMENT_LOGO_PATH":"assets/images/logo_clear.png", +"DEFAULT_SERVICE_LOGO_PATH":"assets/images/logo_icon_original.png", +"FAVICON_PATH":"favicon.ico", +"WHO_WE_ARE_HTML":"
ETSI SDG OpenSlice|https://osl.etsi.org
The ETSI Software Development Group for OpenSlice (SDG OSL) is developing an open source service based Operations Support System (OSS) to deliver Network Slice as a Service (NSaaS).
OpenSlice by ETSI|http://portal.openslice.io
A portal that allows 5G experimenters to design and deploy network services towards the infrastructure.
OpenSlice by ETSI wiki|https://osl.etsi.org/documentation
A wiki containing OpenSlice software documentation.
", +"CONNECT_WITH_US_HTML":"", +"FOOTER_HTML":"
OpenSlice has received funding from various projects under European Programmes for research, technological development and demonstration. You may refer to our extensive ecosystem for further details.
Openslice by ETSI running OSL version 2024Q2 | Terms and Conditions | © 2024 on behalf of osl.etsi.org
" +} diff --git a/kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config/theming.default.scss b/kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config/theming.default.scss new file mode 100644 index 0000000000000000000000000000000000000000..8e515db3e922c32fc2bbf203e8be8f8a1af0d2dc --- /dev/null +++ b/kubernetes/helm/openslice/files/org.etsi.osl.tmf.web/src/assets/config/theming.default.scss @@ -0,0 +1,22 @@ +/* Default theme */ + +$primary: #428bca; +$secondary: #6c6c6c; + +/* ------------------------------ */ +/* Predefined palette 1 theme */ + +/* $primary: rgba(0,45,126); */ +/* $secondary: #6c6c6c; */ + +/* ------------------------------ */ +/* Predefined palette 2 theme */ + +/* $primary: rgba(255, 124, 0); */ +/* $secondary: #6c6c6c; */ + +/* ------------------------------ */ +/* Predefined palette 3 theme */ + +/* $primary: rgba(247,1, 2); */ +/* $secondary: #6c6c6c; */ diff --git a/kubernetes/helm/openslice/templates/_helpers.tpl b/kubernetes/helm/openslice/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..89f9f71fba483f569751099ef78cdfb1da8a3f4c --- /dev/null +++ b/kubernetes/helm/openslice/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "openslice.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 "openslice.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 "openslice.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "openslice.labels" -}} +helm.sh/chart: {{ include "openslice.chart" . }} +{{ include "openslice.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "openslice.selectorLabels" -}} +app.kubernetes.io/name: {{ include "openslice.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "openslice.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "openslice.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/kubernetes/helm/openslice/templates/artemis.yaml b/kubernetes/helm/openslice/templates/artemis.yaml new file mode 100644 index 0000000000000000000000000000000000000000..87c75ea00d59459c65d068fce3d7f8eb62fa71bc --- /dev/null +++ b/kubernetes/helm/openslice/templates/artemis.yaml @@ -0,0 +1,70 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: artemis + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-artemis +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: artemis + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: artemis + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - image: "{{ .Values.image.artemis.repository }}:{{ .Values.image.artemis.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.artemis.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-artemis + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 8161 + - containerPort: 61616 + - containerPort: 61613 + volumeMounts: + - mountPath: /var/log/activemq + name: activemq-log + restartPolicy: Always + volumes: + - name: activemq-log + hostPath: + path: /var/log/activemq +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: artemis + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-artemis +spec: + ports: + - name: "8161" + port: 8161 + targetPort: 8161 + - name: "61616" + port: 61616 + targetPort: 61616 + - name: "61613" + port: 61613 + targetPort: 61613 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: artemis + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/blockdiag.yaml b/kubernetes/helm/openslice/templates/blockdiag.yaml new file mode 100644 index 0000000000000000000000000000000000000000..30b2025c27637392e801158d5ea496c11c8a03b2 --- /dev/null +++ b/kubernetes/helm/openslice/templates/blockdiag.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: blockdiag + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-blockdiag +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: blockdiag + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: blockdiag + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - image: "{{ .Values.image.blockdiag.repository }}:{{ .Values.image.blockdiag.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.blockdiag.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-blockdiag + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 8001 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: blockdiag + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-blockdiag +spec: + ports: + - name: "8001" + targetPort: 8001 + port: 8001 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: blockdiag + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/bugzilla.yaml b/kubernetes/helm/openslice/templates/bugzilla.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d759a2554c42af2abf6e209f2207b92cfc9ef7cb --- /dev/null +++ b/kubernetes/helm/openslice/templates/bugzilla.yaml @@ -0,0 +1,66 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: bugzilla + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-bugzilla +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: bugzilla + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: bugzilla + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - image: "{{ .Values.image.bugzilla.repository }}:{{ .Values.image.bugzilla.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.bugzilla.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-bugzilla + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.activemq.brokerUrl": "tcp://{{ include "openslice.fullname" . }}-artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "bugzillaurl":"{{ .Values.bugzillaurl }}", + "bugzillakey":"{{ .Values.bugzillakey }}", + "main_operations_product":"{{ .Values.main_operations_product }}" + } + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 13010 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: bugzilla + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-bugzilla +spec: + ports: + - name: "13010" + port: 13010 + targetPort: 13010 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: bugzilla + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/centrallog.yaml b/kubernetes/helm/openslice/templates/centrallog.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b8143fcd9f39869242c7192e96b1a55a08e94246 --- /dev/null +++ b/kubernetes/helm/openslice/templates/centrallog.yaml @@ -0,0 +1,65 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: centrallog + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-centrallog +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: centrallog + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: centrallog + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - image: "{{ .Values.image.centrallog.repository }}:{{ .Values.image.centrallog.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.centrallog.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-centrallog + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.activemq.brokerUrl": "tcp://{{ include "openslice.fullname" . }}-artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "centrallogurl": "{{ .Values.centrallogurl }}" + } + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 13013 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: centrallog + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-centrallog +spec: + ports: + - name: "13013" + targetPort: 13013 + port: 13013 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: centrallog + {{- include "openslice.selectorLabels" . | nindent 4 }} + diff --git a/kubernetes/helm/openslice/templates/cridge-config.yaml b/kubernetes/helm/openslice/templates/cridge-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2c62c9a4b728e1fbaef442af56fe08dd6a30d585 --- /dev/null +++ b/kubernetes/helm/openslice/templates/cridge-config.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: cridge + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-cridge-kubeconfig +data: + config: |- + {{- .Files.Get "files/org.etsi.osl.cridge/config" | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/cridge.yaml b/kubernetes/helm/openslice/templates/cridge.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5e558467581532ef544ef89545b3216cc76f99bf --- /dev/null +++ b/kubernetes/helm/openslice/templates/cridge.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: cridge + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-cridge +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: cridge + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: cridge + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + initContainers: + - name: init-osscapi + image: busybox:1.28 + command: ['sh', '-c', "until nslookup {{ include "openslice.fullname" . }}-osscapi; do echo waiting for osscapi; sleep 2; done"] + containers: + - image: "{{ .Values.image.cridge.repository }}:{{ .Values.image.cridge.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.cridge.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-cridge + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.activemq.brokerUrl": "tcp://{{ include "openslice.fullname" . }}-artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "logging.level.org.springframework" : "{{ .Values.cridge.spring.logLevel | default "INFO" }}", + "logging.level.org.etsi.osl.cridge" : "{{ .Values.cridge.logLevel | default "INFO" }}" + } + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: cridge-kubeconfig + readOnly: true + mountPath: /root/.kube + restartPolicy: Always + volumes: + - name: cridge-kubeconfig + configMap: + name: {{ include "openslice.fullname" . }}-cridge-kubeconfig diff --git a/kubernetes/helm/openslice/templates/keycloak-config.yaml b/kubernetes/helm/openslice/templates/keycloak-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..748008bbe0010d28024a746eeed9e485c8b5d3b5 --- /dev/null +++ b/kubernetes/helm/openslice/templates/keycloak-config.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: keycloak + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-keycloak-realm-config + namespace: {{ .Release.Namespace }} +data: + realm-export.json: | + {{- tpl (.Files.Get "files/keycloak-init/realm-export.json") . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/keycloak.yaml b/kubernetes/helm/openslice/templates/keycloak.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fca2bdbe8782e30adda9e4a54e3b0aa455f5a573 --- /dev/null +++ b/kubernetes/helm/openslice/templates/keycloak.yaml @@ -0,0 +1,98 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: keycloak + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-keycloak +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: keycloak + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: keycloak + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + initContainers: + - name: init-mysql-portal + image: busybox:1.28 + command: ['sh', '-c', "until nslookup {{ include "openslice.fullname" . }}-mysql; do echo waiting for mysql; sleep 2; done"] + hostNetwork: {{ .Values.hostNetwork }} + containers: + - image: "{{ .Values.image.keycloak.repository }}:{{ .Values.image.keycloak.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.keycloak.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-keycloak + env: + - name: DB_VENDOR + value: MYSQL + - name: DB_ADDR + value: {{ include "openslice.fullname" . }}-mysql + - name: DB_DATABASE + value: {{ .Values.oscreds.mysql.keycloak.database }} + - name: DB_PASSWORD + value: {{ .Values.oscreds.mysql.keycloak.password }} + - name: DB_USER + value: {{ .Values.oscreds.mysql.keycloak.username }} + - name: KEYCLOAK_USER + value: admin + - name: KEYCLOAK_PASSWORD + value: {{ .Values.oscreds.mysql.keycloak.adminpassword }} + - name: JDBC_PARAMS + value: useSSL=false + - name: JAVA_OPTS + value: "-server -Xms512m -Xmx2048m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -XX:+UseAdaptiveSizePolicy -XX:MaxMetaspaceSize=1024m -Djava.net.preferIPv4Stack=true -Djboss.as.management.blocking.timeout=3600" + - name: KEYCLOAK_IMPORT + value: /tmp/realm-export.json + - name: PROXY_ADDRESS_FORWARDING + value: "true" + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 8080 + - containerPort: 8443 + volumeMounts: + - name: "keycloak-configuration" + readOnly: true + mountPath: "/tmp" + readinessProbe: + httpGet: + path: /auth/realms/master + port: 8080 + volumes: + - name: "keycloak-configuration" + configMap: + name: {{ include "openslice.fullname" . }}-keycloak-realm-config +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: keycloak + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-keycloak +spec: + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + - name: "8443" + port: 8443 + targetPort: 8443 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: keycloak + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/kroki-ingress.yaml b/kubernetes/helm/openslice/templates/kroki-ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5127bdb12296565a01db48edf23d8da25c270674 --- /dev/null +++ b/kubernetes/helm/openslice/templates/kroki-ingress.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + annotations: + nginx.ingress.kubernetes.io/rewrite-target: "/$1" + name: {{ include "openslice.fullname" . }}-kroki-ingress +spec: + ingressClassName: nginx + rules: + - http: + paths: + - pathType: ImplementationSpecific + path: "/kroki/(.*)" + backend: + service: + name: {{ include "openslice.fullname" . }}-kroki + port: + number: 8000 diff --git a/kubernetes/helm/openslice/templates/kroki.yaml b/kubernetes/helm/openslice/templates/kroki.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5b34ae58df9ab87f202e7753f91e6423dc0beef3 --- /dev/null +++ b/kubernetes/helm/openslice/templates/kroki.yaml @@ -0,0 +1,58 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: kroki + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-kroki +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: kroki + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: kroki + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - image: "{{ .Values.image.kroki.repository }}:{{ .Values.image.kroki.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.kroki.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-kroki + resources: + {{- toYaml .Values.resources | nindent 12 }} + env: + - name: KROKI_BLOCKDIAG_HOST + value: {{ include "openslice.fullname" . }}-blockdiag + ports: + - containerPort: 8000 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: kroki + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-kroki +spec: + ports: + - name: "8000" + targetPort: 8000 + port: 8000 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: kroki + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/manoclient.yaml b/kubernetes/helm/openslice/templates/manoclient.yaml new file mode 100644 index 0000000000000000000000000000000000000000..064c0c18b043595834c087cdf909ba8a2111dcf8 --- /dev/null +++ b/kubernetes/helm/openslice/templates/manoclient.yaml @@ -0,0 +1,64 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: manoclient + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-manoclient +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: manoclient + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: manoclient + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - image: "{{ .Values.image.manoclient.repository }}:{{ .Values.image.manoclient.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.manoclient.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-manoclient + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.activemq.brokerUrl": "tcp://{{ include "openslice.fullname" . }}-artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "logging.level.org.springframework" : "{{ .Values.manoclient.spring.logLevel | default "INFO" }}" + } + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 13011 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: manoclient + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-manoclient +spec: + ports: + - name: "13011" + port: 13011 + targetPort: 13011 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: manoclient + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/mysql-config.yaml b/kubernetes/helm/openslice/templates/mysql-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0de0e5277807c43e82193fa44c53a07e386b9470 --- /dev/null +++ b/kubernetes/helm/openslice/templates/mysql-config.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mysql + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-mysql-initdb-config +data: + 01-databases.sql: | + {{- tpl (.Files.Get "files/mysql-init/01-databases.sql") . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/mysql-pv-pvc.yaml b/kubernetes/helm/openslice/templates/mysql-pv-pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2746bcf4262e2ec8b1315c6f0e2294a7059ccca6 --- /dev/null +++ b/kubernetes/helm/openslice/templates/mysql-pv-pvc.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mysql + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-mysql-portal-claim0 +spec: + storageClassName: {{ .Values.storageClass | default "mysql-manual" }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.mysql.storage }} +--- +{{- if or (not .Values.storageClass) (eq .Values.storageClass "manual") }} +apiVersion: v1 +kind: PersistentVolume +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mysql + type: local + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-mysql-pv-volume +spec: + storageClassName: "mysql-manual" + capacity: + storage: {{ .Values.mysql.storage }} + accessModes: + - ReadWriteOnce + hostPath: + path: "/dockerdata-nfs/osmysql" +{{- end }} diff --git a/kubernetes/helm/openslice/templates/mysql.yaml b/kubernetes/helm/openslice/templates/mysql.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b69a3f1e8cd3ecf222ed5aaa21f44feb52d2d950 --- /dev/null +++ b/kubernetes/helm/openslice/templates/mysql.yaml @@ -0,0 +1,88 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mysql + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-mysql +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + serviceName: {{ include "openslice.fullname" . }}-mysql + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mysql + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mysql + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - image: "{{ .Values.image.mysql.repository }}:{{ .Values.image.mysql.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.mysql.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-mysql + args: + - "--ignore-db-dir=lost+found" + env: + - name: MYSQL_ROOT_HOST + value: "%" + - name: MYSQL_ROOT_PASSWORD + value: {{ .Values.oscreds.mysql.password | default "letmein" }} + - name: MYSQL_DATABASE + value: {{ .Values.oscreds.mysql.openslicedb | default "osdb" }} + - name: MYSQL_USER + value: {{ .Values.oscreds.mysql.portal.username | default "portaluser" }} + - name: MYSQL_PASSWORD + value: "{{ .Values.oscreds.mysql.portal.password | default 12345 }}" + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 3306 + volumeMounts: + - mountPath: /var/lib/mysql + name: mysql-portal-claim0 + - mountPath: /docker-entrypoint-initdb.d + name: mysql-initdb + readinessProbe: + exec: + # Check we can execute queries over TCP (skip-networking is off). + command: ["mysql", "-h", "127.0.0.1", "-u", "{{ .Values.oscreds.mysql.username | default "root" }}", "-p{{ .Values.oscreds.mysql.password | default "letmein" }}", "-e", "SELECT 1"] + initialDelaySeconds: 5 + periodSeconds: 2 + timeoutSeconds: 1 + restartPolicy: Always + volumes: + - name: mysql-portal-claim0 + persistentVolumeClaim: + claimName: {{ include "openslice.fullname" . }}-mysql-portal-claim0 + - name: mysql-initdb + configMap: + name: {{ include "openslice.fullname" . }}-mysql-initdb-config +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mysql + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-mysql +spec: + ports: + - name: mysql + port: 3306 + targetPort: 3306 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: mysql + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/oasapi.yaml b/kubernetes/helm/openslice/templates/oasapi.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ea1ffac809c390158827a126f2b0773981ca252e --- /dev/null +++ b/kubernetes/helm/openslice/templates/oasapi.yaml @@ -0,0 +1,88 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: oasapi + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-oasapi +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: oasapi + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: oasapi + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + initContainers: + - name: init-keycloak + image: busybox:1.28 + command: ['sh', '-c', "until nslookup {{ include "openslice.fullname" . }}-keycloak; do echo waiting for keycloak; sleep 2; done"] + - name: init-mysql-portal + image: busybox:1.28 + command: ['sh', '-c', "until nslookup {{ include "openslice.fullname" . }}-mysql; do echo waiting for mysql; sleep 2; done"] + hostNetwork: {{ .Values.hostNetwork }} + containers: + - image: "{{ .Values.image.oasapi.repository }}:{{ .Values.image.oasapi.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.oasapi.pullPolicy | default "Always" }} + name: {{ .Release.Name }}-oasapi + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.datasource.url": "jdbc:mysql://{{ include "openslice.fullname" . }}-mysql/ostmfdb?createDatabaseIfNotExist=true&useUnicode=true&nullCatalogMeansCurrent=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", + "spring.datasource.username": "{{ .Values.oscreds.mysql.username }}", + "spring.datasource.password": "{{ .Values.oscreds.mysql.password }}", + "spring-addons.issuers[0].uri": "{{ .Values.rooturl }}/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "{{ .Values.rooturl }}/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "{{ .Values.rooturl }}/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "{{ .Values.rooturl }}/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id" : "osapiWebClientId", + "springdoc.oauth.clientsecret" : "{{ .Values.spring.oauthClientSecret }}", + "spring.activemq.brokerUrl": "tcp://{{ include "openslice.fullname" . }}-artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "logging.level.org.springframework" : "{{ .Values.oasapi.spring.logLevel | default "INFO" }}" + } + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 13101 + readinessProbe: + httpGet: + path: /oas-api/swagger-ui/index.html + port: 13101 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: oasapi + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-oasapi +spec: + ports: + - name: "13101" + targetPort: 13101 + port: 13101 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: oasapi + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/openslice-ingress.yaml b/kubernetes/helm/openslice/templates/openslice-ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a5f731485acad1a42297e77910cf176a152cc576 --- /dev/null +++ b/kubernetes/helm/openslice/templates/openslice-ingress.yaml @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + annotations: + {{- toYaml .Values.ingress.annotations | nindent 4 }} + name: {{ include "openslice.fullname" . }}-openslice-ingress +spec: + ingressClassName: nginx + rules: + - http: + paths: + {{- $root := . }} # Preserve the root context + {{- range .Values.ingress.paths }} + {{- if ne .path "/kroki/(.*)" }} + - pathType: ImplementationSpecific + path: "{{ .path }}" + backend: + service: + name: {{ include "openslice.fullname" $root }}-{{ .service }} + port: + number: {{ .port }} + {{- end }} + {{- end }} diff --git a/kubernetes/helm/openslice/templates/osom.yaml b/kubernetes/helm/openslice/templates/osom.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a7b758e9f0261aa75193f41faa349bd40a1a2b05 --- /dev/null +++ b/kubernetes/helm/openslice/templates/osom.yaml @@ -0,0 +1,65 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osom + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osom +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osom + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osom + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + containers: + - image: "{{ .Values.image.osom.repository }}:{{ .Values.image.osom.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.osom.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-osom + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.datasource.url" : "{{ .Values.osom.spring.datasource.url | default "jdbc:h2:~/tempdb;DB_CLOSE_DELAY=-1" }}", + "spring.activemq.brokerUrl": "tcp://{{ include "openslice.fullname" . }}-artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "logging.level.org.springframework" : "{{ .Values.osom.spring.logLevel | default "INFO" }}" + } + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 13100 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osom + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osom +spec: + ports: + - name: "13100" + targetPort: 13100 + port: 13100 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osom + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/osportalapi-pv-pvc.yaml b/kubernetes/helm/openslice/templates/osportalapi-pv-pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cb3bc42eb2db961bccc9f98146178072b46db9c3 --- /dev/null +++ b/kubernetes/helm/openslice/templates/osportalapi-pv-pvc.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osportalapi + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osportalapi-claim0 +spec: + storageClassName: {{ .Values.storageClass | default "osportalapi-pv-volume" }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "1Gi" +--- +{{- if or (not .Values.storageClass) (eq .Values.storageClass "osportalapi-pv-volume") }} +apiVersion: v1 +kind: PersistentVolume +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osportalapi + type: local + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osportalapi-pv-volume +spec: + storageClassName: "osportalapi-pv-volume" + capacity: + storage: "1Gi" + accessModes: + - ReadWriteOnce + hostPath: + path: "/dockerdata-nfs/osportalapi-pv-volume" +{{- end }} diff --git a/kubernetes/helm/openslice/templates/osportalapi.yaml b/kubernetes/helm/openslice/templates/osportalapi.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8c2927c3116af756659c34645cdcad957b7b0500 --- /dev/null +++ b/kubernetes/helm/openslice/templates/osportalapi.yaml @@ -0,0 +1,93 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osportalapi + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osportalapi +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osportalapi + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osportalapi + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + hostNetwork: {{ .Values.hostNetwork }} + initContainers: + - name: init-keycloak + image: busybox:1.28 + command: ['sh', '-c', "until nslookup {{ include "openslice.fullname" . }}-keycloak; do echo waiting for keycloak; sleep 2; done"] + - name: init-mysql-portal + image: busybox:1.28 + command: ['sh', '-c', "until nslookup {{ include "openslice.fullname" . }}-mysql; do echo waiting for mysql; sleep 2; done"] + containers: + - image: "{{ .Values.image.portalapi.repository }}:{{ .Values.image.portalapi.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.portalapi.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-osportalapi + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.datasource.url": "jdbc:mysql://{{ include "openslice.fullname" . }}-mysql/osdb?createDatabaseIfNotExist=true", + "spring.datasource.username": "{{ .Values.oscreds.mysql.username }}", + "spring.datasource.password": "{{ .Values.oscreds.mysql.password }}", + "spring-addons.issuers[0].uri": "{{ .Values.rooturl }}/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "{{ .Values.rooturl }}/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "{{ .Values.rooturl }}/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "{{ .Values.rooturl }}/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id" : "osapiWebClientId", + "springdoc.oauth.clientsecret" : "{{ .Values.spring.oauthClientSecret }}", + "spring.activemq.brokerUrl": "tcp://{{ include "openslice.fullname" . }}-artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "logging.level.org.springframework" : "{{ .Values.portalapi.spring.logLevel | default "INFO" }}", + "logging.level.org.etsi.osl.portal.api": "{{ .Values.portalapi.logLevel | default "INFO" }}" + } + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 13000 + volumeMounts: + - name: osportalapi-claim0 + mountPath: /root + restartPolicy: Always + volumes: + - name: osportalapi-claim0 + persistentVolumeClaim: + claimName: {{ include "openslice.fullname" . }}-osportalapi-claim0 +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osportalapi + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osportalapi +spec: + ports: + - name: "13000" + port: 13000 + targetPort: 13000 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osportalapi + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/osscapi-pv-pvc.yaml b/kubernetes/helm/openslice/templates/osscapi-pv-pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d8ce702d8723d359554be9e39f8ffdda0d91eb2a --- /dev/null +++ b/kubernetes/helm/openslice/templates/osscapi-pv-pvc.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osscapi + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osscapi-claim0 +spec: + storageClassName: {{ .Values.storageClass | default "osscapi-pv-manual" }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "1Gi" +--- +{{- if or (not .Values.storageClass) (eq .Values.storageClass "manual") }} +apiVersion: v1 +kind: PersistentVolume +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osscapi + type: local + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osscapi-pv-volume +spec: + storageClassName: "osscapi-pv-manual" + capacity: + storage: "1Gi" + accessModes: + - ReadWriteOnce + hostPath: + path: "/dockerdata-nfs/osscapi" +{{- end }} diff --git a/kubernetes/helm/openslice/templates/osscapi.yaml b/kubernetes/helm/openslice/templates/osscapi.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cf96f7d26268efc80d2d38e727ce98290028802b --- /dev/null +++ b/kubernetes/helm/openslice/templates/osscapi.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osscapi + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osscapi +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osscapi + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osscapi + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + hostNetwork: {{ .Values.hostNetwork }} + initContainers: + - name: init-keycloak + image: busybox:1.28 + command: ['sh', '-c', "until nslookup {{ include "openslice.fullname" . }}-keycloak; do echo waiting for keycloak; sleep 2; done"] + - name: init-mysql-portal + image: busybox:1.28 + command: ['sh', '-c', "until nslookup {{ include "openslice.fullname" . }}-mysql; do echo waiting for mysql; sleep 2; done"] + containers: + - image: "{{ .Values.image.osscapi.repository }}:{{ .Values.image.osscapi.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.osscapi.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-osscapi + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.datasource.url": "jdbc:mysql://{{ include "openslice.fullname" . }}-mysql/osdb?createDatabaseIfNotExist=true", + "spring.datasource.username": "{{ .Values.oscreds.mysql.username }}", + "spring.datasource.password": "{{ .Values.oscreds.mysql.password }}", + "spring-addons.issuers[0].uri":"{{ .Values.rooturl }}/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri":"{{ .Values.rooturl }}/auth/realms/openslice", + "spring.security.oauth2.resourceserver.jwt.jwk-set-uri":"{{ .Values.rooturl }}/auth/realms/openslice/.well-known/openid-configuration", + "springdoc.oAuthFlow.authorizationUrl":"{{ .Values.rooturl }}/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl":"{{ .Values.rooturl }}/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id":"osapiWebClientId", + "springdoc.oauth.clientsecret" : "{{ .Values.spring.oauthClientSecret }}", + "spring.activemq.brokerUrl": "tcp://{{ include "openslice.fullname" . }}-artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "{{ .Values.oscreds.activemq.user }}", + "spring.activemq.password": "{{ .Values.oscreds.activemq.password }}", + "logging.level.org.springframework": "{{ .Values.osscapi.spring.logLevel | default "INFO" }}", + "kroki.serverurl":"{{ .Values.rooturl }}/kroki" + } + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 13082 + volumeMounts: + - mountPath: /root + name: osscapi-claim0 + readinessProbe: + httpGet: + path: /tmf-api/serviceCatalogManagement/v4/serviceCatalog + port: 13082 + restartPolicy: Always + volumes: + - name: osscapi-claim0 + persistentVolumeClaim: + claimName: {{ include "openslice.fullname" . }}-osscapi-claim0 +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osscapi + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-osscapi +spec: + ports: + - name: "13082" + targetPort: 13082 + port: 13082 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: osscapi + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/portalweb-config.yaml b/kubernetes/helm/openslice/templates/portalweb-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0ce4191dedd8d634c51cc0781e1afbf03ca6534e --- /dev/null +++ b/kubernetes/helm/openslice/templates/portalweb-config.yaml @@ -0,0 +1,15 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: {{ include "openslice.fullname" . }}-portalweb-config + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: portalweb + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} +data: + config.js: | + {{- $configJs := .Files.Get "files/org.etsi.osl.portal.web/src/js/config.js" | required "config.js is required" }} + {{ tpl $configJs . | nindent 4 }} + \ No newline at end of file diff --git a/kubernetes/helm/openslice/templates/portalweb.yaml b/kubernetes/helm/openslice/templates/portalweb.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c2b22a10b01c00f22a850b9e951189c86e849fb4 --- /dev/null +++ b/kubernetes/helm/openslice/templates/portalweb.yaml @@ -0,0 +1,68 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: portalweb + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-portalweb +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: portalweb + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: portalweb + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + hostNetwork: {{ .Values.hostNetwork }} + containers: + - image: "{{ .Values.image.portalweb.repository }}:{{ .Values.image.portalweb.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.portalweb.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-portalweb + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 80 + volumeMounts: + - name: portalweb-configuration + mountPath: /usr/share/nginx/html/nfvportal/js/config.js + subPath: config.js + readinessProbe: + httpGet: + path: /tmf-api/serviceCatalogManagement/v4 + port: 80 + volumes: + - name: portalweb-configuration + configMap: + name: {{ include "openslice.fullname" . }}-portalweb-config + defaultMode: 420 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: portalweb + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-portalweb +spec: + ports: + - name: "portalwebport" + port: 80 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: portalweb + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/tmfweb-config.yaml b/kubernetes/helm/openslice/templates/tmfweb-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..badce4153c45a9aa610586a3b2b66bac6302fd46 --- /dev/null +++ b/kubernetes/helm/openslice/templates/tmfweb-config.yaml @@ -0,0 +1,19 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: tmfweb + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-tmfweb-config +data: + config.prod.json: | + {{- $prodJson := .Files.Get "files/org.etsi.osl.tmf.web/src/assets/config/config.prod.json" | required "config.prod.json is required" }} + {{ $prodJson | nindent 4 }} + config.theming.json: | + {{- .Files.Get "files/org.etsi.osl.tmf.web/src/assets/config/config.theming.json" | nindent 4 }} + theming.scss: | + {{- $themingScss := .Files.Get "files/org.etsi.osl.tmf.web/src/assets/config/theming.scss" | required "theming.scss is required" }} + {{ $themingScss | nindent 4 }} diff --git a/kubernetes/helm/openslice/templates/tmfweb.yaml b/kubernetes/helm/openslice/templates/tmfweb.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2d324ec79f2f34379c10d8b12ae10d3ad1cd493f --- /dev/null +++ b/kubernetes/helm/openslice/templates/tmfweb.yaml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: tmfweb + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-tmfweb +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: tmfweb + {{- include "openslice.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: tmfweb + {{- include "openslice.selectorLabels" . | nindent 8 }} + spec: + hostNetwork: {{ .Values.hostNetwork }} + containers: + - image: "{{ .Values.image.tmfweb.repository }}:{{ .Values.image.tmfweb.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.tmfweb.pullPolicy | default "Always" }} + name: {{ include "openslice.fullname" . }}-tmfweb + resources: + {{- toYaml .Values.resources | nindent 12 }} + ports: + - containerPort: 80 + volumeMounts: + - name: "tmfweb-configuration" + readOnly: true + mountPath: "/usr/share/nginx/html/services/assets/config" + volumes: + - name: "tmfweb-configuration" + configMap: + name: {{ include "openslice.fullname" . }}-tmfweb-config + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: tmfweb + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" + {{- include "openslice.labels" . | nindent 4 }} + name: {{ include "openslice.fullname" . }}-tmfweb +spec: + ports: + - name: "tmwebport" + port: 80 + selector: + app: {{ include "openslice.fullname" . }} + org.etsi.osl.service: tmfweb + {{- include "openslice.selectorLabels" . | nindent 4 }} diff --git a/kubernetes/helm/openslice/values.yaml b/kubernetes/helm/openslice/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..59e39e5b9701b38fe5fe6445b9ff4ad0caa94d18 --- /dev/null +++ b/kubernetes/helm/openslice/values.yaml @@ -0,0 +1,231 @@ +# Default values for openslice. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + artemis: + repository: apache/activemq-artemis + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2.30.0" + blockdiag: + repository: yuzutech/kroki-blockdiag + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "0.18.0" + bugzilla: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.bugzilla + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + centrallog: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.centrallog.service + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + keycloak: + repository: quay.io/keycloak/keycloak + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "16.1.1" + kroki: + repository: yuzutech/kroki + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "0.18.0" + manoclient: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.mano + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + osom: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.osom + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + portalapi: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.portal.api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + osscapi: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.tmf.api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + mysql: + repository: mysql + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "5.7.43" + oasapi: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.oas + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + portalweb: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.portal.web + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + tmfweb: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.tmf.web + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + cridge: + repository: labs.etsi.org:5050/osl/code/org.etsi.osl.cridge + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2024Q2_RC" + +bugzillaurl: example.com:443/bugzilla +bugzillakey: VH2Vw0iI5aYgALFFzVDWqhACwt6Hu3bXla9kSC1Z +main_operations_product: My Operations +centrallogurl: http://elk_ip:elk_port/index_name/_doc +rooturl: ~ # This is the ingress LB IP or domain - ex. http://openslice.com:port or http://3.15.198.35:8080 + +oscreds: + activemq: + user: artemis + password: artemis + mysql: + username: root + password: letmein + openslicedb: osdb + keycloak: + database: keycloak + username: keycloak + password: password + adminpassword: Pa55w0rd + portal: + database: osdb + username: portaluser + password: 12345 + +spring: + oauthClientSecret: secret + +mysql: + storage: 10Gi + +cridge: + logLevel: INFO + spring: + loglevel: INFO + +portalapi: + logLevel: INFO + spring: + loglevel: INFO + +manoclient: + spring: + loglevel: INFO + +oasapi: + spring: + loglevel: INFO + +osom: + spring: + loglevel: INFO + datasource: + url: "jdbc:h2:/tmp/tempdb;DB_CLOSE_DELAY=-1" + +osscapi: + spring: + loglevel: INFO + +# Storage class to be used for provisioning. Default is manual +# storageClass: ~ + +hostNetwork: false + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + paths: + - path: "/tmf-api" + service: "osscapi" + port: 13082 + - path: "/oas-api" + service: "oasapi" + port: 13101 + - path: "/auth" + service: "keycloak" + port: 8080 + - path: "/kroki/(.*)" + service: "kroki" + port: 8000 + - path: "/osapi" + service: "osportalapi" + port: 13000 + - path: "/nfvportal" + service: "portalweb" + port: 80 + - path: "/" + service: "tmfweb" + port: 80 + annotations: {} + + + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/kubernetes/k8sdeploy.sh b/kubernetes/k8sdeploy.sh new file mode 100644 index 0000000000000000000000000000000000000000..9eb34b1897fd7ea0dd8c77658d987bed857bf16e --- /dev/null +++ b/kubernetes/k8sdeploy.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +CURRENT_DIR="$(pwd)" +SCRIPT_DIR="$(dirname "$0")" +cd $SCRIPT_DIR + +# copy to a workingdir +cp -r ./template ./_apply + +kubectl create namespace openslice + +kubectl apply -f ./_apply/openslice-ingress.yaml + +# wait for ingress to get IP address +INGRESSADDR="" +while [ -z $INGRESSADDR ]; do + echo "Waiting for external IP" + INGRESSADDR=$(kubectl -n openslice get ingress openslice-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + if [ -z "$INGRESSADDR" ] + then + echo "\INGRESSADDR is empty trying hostname" + INGRESSADDR=$(kubectl -n openslice get ingress openslice-ingress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') + else + echo "\$INGRESSADDR found!" + fi + [ -z "$INGRESSADDR" ] && sleep 5 +done +echo 'Found external IP: '$INGRESSADDR +find ./_apply/ -type f -print0 | xargs -0 sed -i "s/INGRESSADDR/$INGRESSADDR/g" + +kubectl apply -f ./_apply/artemis.yaml +kubectl apply -f ./_apply/bugzilla.yaml +kubectl apply -f ./_apply/centrallog.yaml +kubectl apply -f ./_apply/manoclient.yaml +kubectl apply -f ./_apply/kroki.yaml +kubectl apply -f ./_apply/blockdiag.yaml + +kubectl apply -f ./_apply/portalweb-config.yaml +kubectl apply -f ./_apply/portalweb-config-nginx.yaml +kubectl apply -f ./_apply/portalweb.yaml + +kubectl apply -f ./_apply/tmfweb-config.yaml +kubectl apply -f ./_apply/tmfweb-config-nginx.yaml +kubectl apply -f ./_apply/tmfweb.yaml + +kubectl apply -f ./_apply/mysql-config.yaml +kubectl apply -f ./_apply/mysql-pv-pvc.yaml +kubectl apply -f ./_apply/mysql.yaml + +kubectl create configmap keycloak-realm-config --from-file=./_apply/realm-export.json --namespace=openslice +kubectl apply -f ./_apply/keycloak.yaml + +kubectl apply -f ./_apply/osom-pv-pvc.yaml +kubectl apply -f ./_apply/osom.yaml + +kubectl apply -f ./_apply/oasapi-pv-pvc.yaml +kubectl apply -f ./_apply/oasapi.yaml + +kubectl apply -f ./_apply/osportalapi-pv-pvc.yaml +kubectl apply -f ./_apply/osportalapi.yaml + +kubectl apply -f ./_apply/osscapi-pv-pvc.yaml +kubectl apply -f ./_apply/osscapi.yaml + +cd $CURRENT_DIR diff --git a/kubernetes/k8sremove.sh b/kubernetes/k8sremove.sh new file mode 100644 index 0000000000000000000000000000000000000000..1d5832aa0496894e1a5953ec43b00c0d98f8c341 --- /dev/null +++ b/kubernetes/k8sremove.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +CURRENT_DIR="$(pwd)" +SCRIPT_DIR="$(dirname "$0")" +cd $SCRIPT_DIR + +kubectl delete -f ./_apply/osscapi.yaml +kubectl delete -f ./_apply/osscapi-pv-pvc.yaml + +kubectl delete -f ./_apply/osportalapi.yaml +kubectl delete -f ./_apply/osportalapi-pv-pvc.yaml + +kubectl delete -f ./_apply/oasapi.yaml +kubectl delete -f ./_apply/oasapi-pv-pvc.yaml + +kubectl delete -f ./_apply/osom.yaml +kubectl delete -f ./_apply/osom-pv-pvc.yaml + +kubectl delete -f ./_apply/keycloak.yaml +kubectl delete configmap keycloak-realm-config -n openslice + +kubectl delete -f ./_apply/mysql.yaml +kubectl delete -f ./_apply/mysql-pv-pvc.yaml +kubectl delete -f ./_apply/mysql-config.yaml + +kubectl delete -f ./_apply/tmfweb-config.yaml +kubectl delete -f ./_apply/tmfweb-config-nginx.yaml +kubectl delete -f ./_apply/tmfweb.yaml + +kubectl delete -f ./_apply/portalweb-config.yaml +kubectl delete -f ./_apply/portalweb-config-nginx.yaml +kubectl delete -f ./_apply/portalweb.yaml + +kubectl delete -f ./_apply/blockdiag.yaml +kubectl delete -f ./_apply/kroki.yaml +kubectl delete -f ./_apply/manoclient.yaml +kubectl delete -f ./_apply/centrallog.yaml +kubectl delete -f ./_apply/bugzilla.yaml +kubectl delete -f ./_apply/artemis.yaml + +kubectl delete -f ./_apply/openslice-ingress.yaml + +kubectl delete ns openslice + +cd $CURRENT_DIR diff --git a/kubernetes/template/README.md b/kubernetes/template/README.md new file mode 100644 index 0000000000000000000000000000000000000000..83f6025e7085378ba3fcb5f47c2d9024ee16231c --- /dev/null +++ b/kubernetes/template/README.md @@ -0,0 +1,4 @@ +Install first an ingress controler +For docker desktop +https://kubernetes.github.io/ingress-nginx/deploy/#docker-desktop + diff --git a/kubernetes/template/artemis.yaml b/kubernetes/template/artemis.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a5e8f02539fbf3013f884a57ebe1e4cd4942dc83 --- /dev/null +++ b/kubernetes/template/artemis.yaml @@ -0,0 +1,54 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: artemis + name: artemis +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: artemis + template: + metadata: + labels: + org.etsi.osl.service: artemis + spec: + containers: + - image: apache/activemq-artemis:2.30.0 + name: artemis + ports: + - containerPort: 8161 + - containerPort: 61616 + - containerPort: 61613 + volumeMounts: + - mountPath: /var/log/activemq + name: activemq-log + restartPolicy: Always + volumes: + - name: activemq-log + hostPath: + path: /var/log/activemq +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + annotations: + labels: + org.etsi.osl.service: artemis + name: artemis +spec: + ports: + - name: "8161" + port: 8161 + targetPort: 8161 + - name: "61616" + port: 61616 + targetPort: 61616 + - name: "61613" + port: 61613 + targetPort: 61613 + selector: + org.etsi.osl.service: artemis diff --git a/kubernetes/template/blockdiag.yaml b/kubernetes/template/blockdiag.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0fdc41d62a0c02141024242b1a12b488b8d9e2da --- /dev/null +++ b/kubernetes/template/blockdiag.yaml @@ -0,0 +1,38 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: blockdiag + name: blockdiag +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: blockdiag + template: + metadata: + labels: + org.etsi.osl.service: blockdiag + spec: + containers: + - image: yuzutech/kroki-blockdiag + name: blockdiag + ports: + - containerPort: 8001 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: blockdiag + name: blockdiag +spec: + ports: + - name: "8001" + targetPort: 8001 + port: 8001 + selector: + org.etsi.osl.service: blockdiag diff --git a/kubernetes/template/bugzilla.yaml b/kubernetes/template/bugzilla.yaml new file mode 100644 index 0000000000000000000000000000000000000000..658d1028b6c1cbb39715af0dff019f28779e4c3a --- /dev/null +++ b/kubernetes/template/bugzilla.yaml @@ -0,0 +1,49 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: bugzilla + name: bugzilla +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: bugzilla + template: + metadata: + labels: + org.etsi.osl.service: bugzilla + spec: + containers: + - env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.activemq.brokerUrl": "tcp://artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "bugzillaurl":"", + "bugzillakey":"", + "main_operations_product":"" + } + image: labs.etsi.org:5050/osl/code/org.etsi.osl.bugzilla:develop + name: bugzilla + ports: + - containerPort: 13010 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: bugzilla + name: bugzilla +spec: + ports: + - name: "13010" + port: 13010 + targetPort: 13010 + selector: + org.etsi.osl.service: bugzilla diff --git a/kubernetes/template/centrallog.yaml b/kubernetes/template/centrallog.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2fa6b276b6fb3e5ff8b37c90e9ebe89c267d2b15 --- /dev/null +++ b/kubernetes/template/centrallog.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: centrallog + name: centrallog +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: centrallog + template: + metadata: + labels: + org.etsi.osl.service: centrallog + spec: + containers: + - env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.activemq.brokerUrl": "tcp://artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "centrallogurl":"http://elk_ip:elk_port/index_name/_doc" + } + image: labs.etsi.org:5050/osl/code/org.etsi.osl.centrallog.service:develop + name: centrallog + ports: + - containerPort: 13013 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: centrallog + name: centrallog +spec: + ports: + - name: "13013" + targetPort: 13013 + port: 13013 + selector: + org.etsi.osl.service: centrallog + diff --git a/kubernetes/template/keycloak.yaml b/kubernetes/template/keycloak.yaml new file mode 100644 index 0000000000000000000000000000000000000000..086a8951c409e300efeacd96a08a5be7508a1460 --- /dev/null +++ b/kubernetes/template/keycloak.yaml @@ -0,0 +1,82 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + org.etsi.osl.service: keycloak + name: keycloak + namespace: openslice +spec: + selector: + matchLabels: + org.etsi.osl.service: keycloak + strategy: + type: Recreate + template: + metadata: + labels: + org.etsi.osl.service: keycloak + spec: + initContainers: + - name: init-mysql-portal + image: busybox:1.28 + command: ['sh', '-c', "until nslookup mysql; do echo waiting for mysql; sleep 2; done"] + + containers: + - env: + - name: DB_VENDOR + value: MYSQL + - name: DB_ADDR + value: mysql + - name: DB_DATABASE + value: keycloak + - name: DB_PASSWORD + value: password + - name: DB_USER + value: keycloak + - name: KEYCLOAK_USER + value: admin + - name: KEYCLOAK_PASSWORD + value: keycloakadminpass + - name: JDBC_PARAMS + value: useSSL=false + - name: JAVA_OPTS + value: "-server -Xms512m -Xmx2048m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -XX:+UseAdaptiveSizePolicy -XX:MaxMetaspaceSize=1024m -Djava.net.preferIPv4Stack=true -Djboss.as.management.blocking.timeout=3600" + - name: KEYCLOAK_IMPORT + value: /tmp/realm-export.json + - name: PROXY_ADDRESS_FORWARDING + value: "true" + image: jboss/keycloak:16.1.1 + name: keycloak + ports: + - containerPort: 8080 + - containerPort: 8443 + volumeMounts: + - name: "keycloak-configuration" + readOnly: true + mountPath: "/tmp" + readinessProbe: + httpGet: + path: /auth/realms/master + port: 8080 + volumes: + - name: "keycloak-configuration" + configMap: + name: keycloak-realm-config +--- +apiVersion: v1 +kind: Service +metadata: + labels: + org.etsi.osl.service: keycloak + name: keycloak + namespace: openslice +spec: + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + - name: "8443" + port: 8443 + targetPort: 8443 + selector: + org.etsi.osl.service: keycloak diff --git a/kubernetes/template/kroki.yaml b/kubernetes/template/kroki.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d01f25ece8716d408415d6820eac5a67ba232680 --- /dev/null +++ b/kubernetes/template/kroki.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: kroki + name: kroki +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: kroki + template: + metadata: + labels: + org.etsi.osl.service: kroki + spec: + containers: + - image: yuzutech/kroki + name: kroki + env: + - name: KROKI_BLOCKDIAG_HOST + value: "blockdiag" + ports: + - containerPort: 8000 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: kroki + name: kroki +spec: + ports: + - name: "8000" + targetPort: 8000 + port: 8000 + selector: + org.etsi.osl.service: kroki diff --git a/kubernetes/template/manoclient.yaml b/kubernetes/template/manoclient.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5c181dc7ebca85f53707a39529548a9542b77ae0 --- /dev/null +++ b/kubernetes/template/manoclient.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: manoclient + name: manoclient +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: manoclient + template: + metadata: + labels: + org.etsi.osl.service: manoclient + spec: + containers: + - env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.activemq.brokerUrl": "tcp://artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO" + } + image: labs.etsi.org:5050/osl/code/org.etsi.osl.mano:develop + name: manoclient + ports: + - containerPort: 13011 + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: manoclient + name: manoclient +spec: + ports: + - name: "13011" + port: 13011 + targetPort: 13011 + selector: + org.etsi.osl.service: manoclient diff --git a/kubernetes/template/mysql-config.yaml b/kubernetes/template/mysql-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8ddccddb2e9aadb58d0881db6a229850a1ff78c0 --- /dev/null +++ b/kubernetes/template/mysql-config.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: openslice + name: mysql-initdb-config +data: + 01-databases.sql: | + # create databases + CREATE DATABASE IF NOT EXISTS `osdb`; + CREATE DATABASE IF NOT EXISTS `keycloak`; + + # create root user and grant rights + CREATE USER 'portaluser'@'localhost' IDENTIFIED BY '12345'; + GRANT ALL PRIVILEGES ON *.* TO 'portaluser'@'%' IDENTIFIED BY '12345'; + + # create root user and grant rights + CREATE USER 'keycloak'@'localhost' IDENTIFIED BY 'password'; + GRANT ALL PRIVILEGES ON *.* TO 'keycloak'@'%' IDENTIFIED BY 'password'; diff --git a/kubernetes/template/mysql-pv-pvc.yaml b/kubernetes/template/mysql-pv-pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b0fbdca3626f66b305ac1807003ebc83ee2f73ba --- /dev/null +++ b/kubernetes/template/mysql-pv-pvc.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + namespace: openslice + name: mysql-pv-volume + labels: + type: local +spec: + storageClassName: manual + capacity: + storage: 10Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/dockerdata-nfs/osmysql" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: openslice + creationTimestamp: null + labels: + org.etsi.osl.service: mysql + name: mysql-portal-claim0 +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi diff --git a/kubernetes/template/mysql.yaml b/kubernetes/template/mysql.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ef27f27981694a3c142b0a30597cebab1aae09ee --- /dev/null +++ b/kubernetes/template/mysql.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + namespace: openslice + labels: + org.etsi.osl.service: mysql + name: mysql +spec: + selector: + matchLabels: + org.etsi.osl.service: mysql + serviceName: mysql + replicas: 1 + template: + metadata: + labels: + org.etsi.osl.service: mysql + spec: + containers: + - env: + - name: MYSQL_ROOT_HOST + value: "%" + - name: MYSQL_ROOT_PASSWORD + value: letmein + - name: MYSQL_DATABASE + value: osdb + - name: MYSQL_USER + value: portaluser + - name: MYSQL_PASSWORD + value: "12345" + image: mysql:5.7.43 + name: mysql + ports: + - containerPort: 3306 + volumeMounts: + - mountPath: /var/lib/mysql + name: mysql-portal-claim0 + - mountPath: /docker-entrypoint-initdb.d + name: mysql-initdb + readinessProbe: + exec: + # Check we can execute queries over TCP (skip-networking is off). + command: ["mysql", "-h", "127.0.0.1", "-u", "root", "-pletmein", "-e", "SELECT 1"] + initialDelaySeconds: 5 + periodSeconds: 2 + timeoutSeconds: 1 + restartPolicy: Always + volumes: + - name: mysql-portal-claim0 + persistentVolumeClaim: + claimName: mysql-portal-claim0 + - name: mysql-initdb + configMap: + name: mysql-initdb-config +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: mysql + name: mysql +spec: + ports: + - name: mysql + port: 3306 + targetPort: 3306 + selector: + org.etsi.osl.service: mysql diff --git a/kubernetes/template/oasapi-pv-pvc.yaml b/kubernetes/template/oasapi-pv-pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6a675bb6fe37835c5886ec027de0ff38ba602cee --- /dev/null +++ b/kubernetes/template/oasapi-pv-pvc.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + namespace: openslice + name: oasapi-pv-volume + labels: + type: local +spec: + storageClassName: oasapi-pv-manual + capacity: + storage: 1Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/dockerdata-nfs/oasapi" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: openslice + creationTimestamp: null + labels: + org.etsi.osl.service: oasapi-claim0 + name: oasapi-claim0 +spec: + storageClassName: oasapi-pv-manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/kubernetes/template/oasapi.yaml b/kubernetes/template/oasapi.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f494e3e748766750dd0f1c011f8f72e973d9ad44 --- /dev/null +++ b/kubernetes/template/oasapi.yaml @@ -0,0 +1,79 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: oasapi + name: oasapi +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: oasapi + strategy: + type: Recreate + template: + metadata: + labels: + org.etsi.osl.service: oasapi + spec: + initContainers: + - name: init-keycloak + image: busybox:1.28 + command: ['sh', '-c', "until nslookup keycloak; do echo waiting for keycloak; sleep 2; done"] + - name: init-mysql-portal + image: busybox:1.28 + command: ['sh', '-c', "until nslookup mysql; do echo waiting for mysql; sleep 2; done"] + containers: + - env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.datasource.url": "jdbc:mysql://mysql/ostmfdb?createDatabaseIfNotExist=true&useUnicode=true&nullCatalogMeansCurrent=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", + "spring.datasource.username":"root", + "spring.datasource.password":"letmein", + "spring-addons.issuers[0].uri": "http://INGRESSADDR/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "http://INGRESSADDR/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "http://INGRESSADDR/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "http://INGRESSADDR/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id" : "osapiWebClientId", + "springdoc.oauth.clientsecret" : "secret", + "spring.activemq.brokerUrl": "tcp://artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO" + } + image: labs.etsi.org:5050/osl/code/org.etsi.osl.oas:develop + name: openslice-oasapi + ports: + - containerPort: 13101 + volumeMounts: + - mountPath: /root + name: oasapi-claim0 + readinessProbe: + httpGet: + path: /oas-api/swagger-ui/index.html + port: 13101 + restartPolicy: Always + volumes: + - name: oasapi-claim0 + persistentVolumeClaim: + claimName: oasapi-claim0 +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: oasapi + name: oasapi +spec: + ports: + - name: "13101" + targetPort: 13101 + port: 13101 + selector: + org.etsi.osl.service: oasapi diff --git a/kubernetes/template/openslice-ingress.yaml b/kubernetes/template/openslice-ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..67cb54299daec0414cdd5eb0201d6ed36e982770 --- /dev/null +++ b/kubernetes/template/openslice-ingress.yaml @@ -0,0 +1,52 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: openslice-ingress + namespace: openslice +spec: + ingressClassName: nginx + rules: + - http: + paths: + - pathType: Prefix + path: "/tmf-api" + backend: + service: + name: osscapi + port: + number: 13082 + - pathType: Prefix + path: "/oas-api" + backend: + service: + name: oasapi + port: + number: 13101 + - pathType: Prefix + path: "/auth" + backend: + service: + name: keycloak + port: + number: 8080 + - pathType: Prefix + path: "/osapi" + backend: + service: + name: osportalapi + port: + number: 13000 + - pathType: Prefix + path: "/nfvportal" + backend: + service: + name: portalweb + port: + number: 80 + - pathType: Prefix + path: "/" + backend: + service: + name: tmfweb + port: + number: 80 diff --git a/kubernetes/template/osom-pv-pvc.yaml b/kubernetes/template/osom-pv-pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..da3f75b97c6a01c6c557d48025b8cdc2975b4dcd --- /dev/null +++ b/kubernetes/template/osom-pv-pvc.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + namespace: openslice + name: osom-pv-volume + labels: + type: local +spec: + storageClassName: osom-pv-manual + capacity: + storage: 100Mi + accessModes: + - ReadWriteOnce + hostPath: + path: "/dockerdata-nfs/osom" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: openslice + creationTimestamp: null + labels: + org.etsi.osl.service: osom-claim0 + name: osom-claim0 +spec: + storageClassName: osom-pv-manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Mi diff --git a/kubernetes/template/osom.yaml b/kubernetes/template/osom.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d05010e79e60c15c6de465eff9e73a1255f7682d --- /dev/null +++ b/kubernetes/template/osom.yaml @@ -0,0 +1,56 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: osom + name: osom +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: osom + strategy: + type: Recreate + template: + metadata: + labels: + org.etsi.osl.service: osom + spec: + containers: + - env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.activemq.brokerUrl": "tcp://artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO" + } + image: labs.etsi.org:5050/osl/code/org.etsi.osl.osom:develop + name: openslice-osom + ports: + - containerPort: 13100 + volumeMounts: + - mountPath: /root + name: osom-claim0 + restartPolicy: Always + volumes: + - name: osom-claim0 + persistentVolumeClaim: + claimName: osom-claim0 +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: osom + name: osom +spec: + ports: + - name: "13100" + targetPort: 13100 + port: 13100 + selector: + org.etsi.osl.service: osom diff --git a/kubernetes/template/osportalapi-pv-pvc.yaml b/kubernetes/template/osportalapi-pv-pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bd15ddce3e27e4037deaf1e23665b60c20c7dccc --- /dev/null +++ b/kubernetes/template/osportalapi-pv-pvc.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + namespace: openslice + name: osportalapi-pv-volume + labels: + type: local +spec: + storageClassName: osportalapi-pv-volume + capacity: + storage: 100Mi + accessModes: + - ReadWriteOnce + hostPath: + path: "/dockerdata-nfs/osportalapi-pv-volume" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: openslice + creationTimestamp: null + labels: + org.etsi.osl.service: osportalapi-claim0 + name: osportalapi-claim0 +spec: + storageClassName: osportalapi-pv-volume + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Mi diff --git a/kubernetes/template/osportalapi.yaml b/kubernetes/template/osportalapi.yaml new file mode 100644 index 0000000000000000000000000000000000000000..16995791bf30b2358e88ea0cf2385e137c9e898b --- /dev/null +++ b/kubernetes/template/osportalapi.yaml @@ -0,0 +1,76 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: osportalapi + name: osportalapi +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: osportalapi + strategy: + type: Recreate + template: + metadata: + labels: + org.etsi.osl.service: osportalapi + spec: + initContainers: + - name: init-keycloak + image: busybox:1.28 + command: ['sh', '-c', "until nslookup keycloak; do echo waiting for keycloak; sleep 2; done"] + - name: init-mysql-portal + image: busybox:1.28 + command: ['sh', '-c', "until nslookup mysql; do echo waiting for mysql; sleep 2; done"] + containers: + - name: openslice-portalapi + image: labs.etsi.org:5050/osl/code/org.etsi.osl.portal.api:develop + ports: + - containerPort: 13000 + volumeMounts: + - name: osportalapi-claim0 + mountPath: /root + env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.datasource.url": "jdbc:mysql://mysql/osdb?createDatabaseIfNotExist=true", + "spring.datasource.username": "root", + "spring.datasource.password": "letmein", + "spring-addons.issuers[0].uri": "http://INGRESSADDR/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri": "http://INGRESSADDR/auth/realms/openslice", + "springdoc.oAuthFlow.authorizationUrl": "http://INGRESSADDR/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl": "http://INGRESSADDR/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id" : "osapiWebClientId", + "springdoc.oauth.clientsecret" : "secret", + "spring.activemq.brokerUrl": "tcp://artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user": "artemis", + "spring.activemq.password": "artemis", + "logging.level.org.springframework" : "INFO" + } + restartPolicy: Always + volumes: + - name: osportalapi-claim0 + persistentVolumeClaim: + claimName: osportalapi-claim0 +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: osportalapi + name: osportalapi +spec: + ports: + - name: "13000" + port: 13000 + targetPort: 13000 + selector: + org.etsi.osl.service: osportalapi diff --git a/kubernetes/template/osscapi-pv-pvc.yaml b/kubernetes/template/osscapi-pv-pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..57b661bfcf41f8bee98e64ba89f6d41661663d45 --- /dev/null +++ b/kubernetes/template/osscapi-pv-pvc.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + namespace: openslice + name: osscapi-pv-volume + labels: + type: local +spec: + storageClassName: osscapi-pv-manual + capacity: + storage: 1Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/dockerdata-nfs/osscapi" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + namespace: openslice + creationTimestamp: null + labels: + org.etsi.osl.service: osscapi-claim0 + name: osscapi-claim0 +spec: + storageClassName: osscapi-pv-manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/kubernetes/template/osscapi.yaml b/kubernetes/template/osscapi.yaml new file mode 100644 index 0000000000000000000000000000000000000000..720c922066b04b91fab1358ce28997630907ad01 --- /dev/null +++ b/kubernetes/template/osscapi.yaml @@ -0,0 +1,81 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: osscapi + name: osscapi +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: osscapi + strategy: + type: Recreate + template: + metadata: + labels: + org.etsi.osl.service: osscapi + spec: + initContainers: + - name: init-keycloak + image: busybox:1.28 + command: ['sh', '-c', "until nslookup keycloak; do echo waiting for keycloak; sleep 2; done"] + - name: init-mysql-portal + image: busybox:1.28 + command: ['sh', '-c', "until nslookup mysql; do echo waiting for mysql; sleep 2; done"] + containers: + - env: + - name: SPRING_APPLICATION_JSON + value: >- + { + "spring.datasource.url":"jdbc:mysql://mysql/ostmfdb?createDatabaseIfNotExist=true&useSSL=false&requireSSL=false&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", + "spring.datasource.username":"root", + "spring.datasource.password":"letmein", + "spring-addons.issuers[0].uri":"http://INGRESSADDR/auth/realms/openslice", + "spring-addons.issuers[0].username-json-path":"$.preferred_username", + "spring-addons.issuers[0].claims[0].jsonPath":"$.realm_access.roles", + "spring-addons.issuers[0].claims[1].jsonPath":"$.resource_access.*.roles", + "spring.security.oauth2.resourceserver.jwt.issuer-uri":"http://INGRESSADDR/auth/realms/openslice", + "spring.security.oauth2.resourceserver.jwt.jwk-set-uri":"http://INGRESSADDR/auth/realms/openslice/.well-known/openid-configuration", + "springdoc.oAuthFlow.authorizationUrl":"http://INGRESSADDR/auth/realms/openslice/protocol/openid-connect/auth", + "springdoc.oAuthFlow.tokenUrl":"http://INGRESSADDR/auth/realms/openslice/protocol/openid-connect/token", + "springdoc.oauth.client-id":"osapiWebClientId", + "springdoc.oauth.clientsecret":"secret", + "spring.activemq.brokerUrl":"tcp://artemis:61616?jms.watchTopicAdvisories=false", + "spring.activemq.user":"artemis", + "spring.activemq.password":"artemis", + "logging.level.org.springframework":"INFO", + "kroki.serverurl":"http://INGRESSADDR/kroki" + } + image: labs.etsi.org:5050/osl/code/org.etsi.osl.tmf.api:develop + name: openslice-scapi + ports: + - containerPort: 13082 + volumeMounts: + - mountPath: /root + name: osscapi-claim0 + readinessProbe: + httpGet: + path: /tmf-api/serviceCatalogManagement/v4/serviceCatalog + port: 13082 + restartPolicy: Always + volumes: + - name: osscapi-claim0 + persistentVolumeClaim: + claimName: osscapi-claim0 +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: osscapi + name: osscapi +spec: + ports: + - name: "13082" + targetPort: 13082 + port: 13082 + selector: + org.etsi.osl.service: osscapi diff --git a/kubernetes/template/portalweb-config-nginx.yaml b/kubernetes/template/portalweb-config-nginx.yaml new file mode 100644 index 0000000000000000000000000000000000000000..17a60e90ac599b8a6188c4674a36245cadddd1fc --- /dev/null +++ b/kubernetes/template/portalweb-config-nginx.yaml @@ -0,0 +1,31 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: portalweb-config-nginx + namespace: openslice +data: + default.conf: |+ + # Expires map + map $sent_http_content_type $expires { + default off; + text/html epoch; + text/css max; + application/json max; + application/javascript max; + ~image/ max; + } + + server { + listen 80; + include /etc/nginx/mime.types; + + server_name INGRESSADDR; + location / { + root /usr/share/nginx/html/; + index index.html index.htm; + try_files $uri $uri/ /index.html =404; + } + + expires $expires; + gzip on; + } diff --git a/kubernetes/template/portalweb-config.yaml b/kubernetes/template/portalweb-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f7c12aa6f28db7997d8b185fd98a57414e82dde9 --- /dev/null +++ b/kubernetes/template/portalweb-config.yaml @@ -0,0 +1,8 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + namespace: openslice + name: portalweb-config +data: + config.js: "var appConfig = angular.module('portalwebapp.config',[]);\n\n\nappConfig.factory('APIEndPointService', function() {\n\t return {\t \n\t\tTITLE: \"Openslice demo\",\n\t\tWIKI: \"http://INGRESSADDR\",\n\t\tBUGZILLA: \"https://INGRESSADDR/bugzilla/\",\n\t\tSTATUS: \"http://INGRESSADDR/\",\n\t\tAPIURL: \"http://INGRESSADDR\",\n\t\tWEBURL: \"http://INGRESSADDR/nfvportal\",\n\t\tAPIOAUTHURL: \"http://INGRESSADDR/auth/realms/openslice\",\n\t\tAPITMFURL: \"http://INGRESSADDR/tmf-api/serviceCatalogManagement/v4\"\n\t\t\n\t };\n});\n\n\n" + diff --git a/kubernetes/template/portalweb.yaml b/kubernetes/template/portalweb.yaml new file mode 100644 index 0000000000000000000000000000000000000000..92106a9a65c0fbeb4cba44a833f228d799a1e804 --- /dev/null +++ b/kubernetes/template/portalweb.yaml @@ -0,0 +1,54 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: portalweb + name: portalweb +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: portalweb + strategy: + type: Recreate + template: + metadata: + labels: + org.etsi.osl.service: portalweb + spec: + containers: + - name: openslice-portalweb + image: labs.etsi.org:5050/osl/code/org.etsi.osl.portal.web:develop + ports: + - containerPort: 80 + volumeMounts: + - name: "portalweb-configuration" + mountPath: /usr/share/nginx/html/nfvportal/js/config.js + subPath: config.js + - name: "portalweb-configuration-nginx" + readOnly: true + mountPath: "/etc/nginx/conf.d" + volumes: + - name: "portalweb-configuration" + configMap: + name: portalweb-config + defaultMode: 420 + - name: "portalweb-configuration-nginx" + configMap: + name: portalweb-config-nginx + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: portalweb + name: portalweb +spec: + ports: + - name: "portalwebport" + port: 80 + selector: + org.etsi.osl.service: portalweb diff --git a/kubernetes/template/realm-export.json b/kubernetes/template/realm-export.json new file mode 100644 index 0000000000000000000000000000000000000000..16ea845afd790243e4f51ca622815c54bbea36ac --- /dev/null +++ b/kubernetes/template/realm-export.json @@ -0,0 +1,2221 @@ +{ + "id": "openslice", + "realm": "openslice", + "displayName": "Openslice", + "notBefore": 1586721661, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "1741dd77-ee50-4fd7-bec6-1a6d3d9d778a", + "name": "MENTOR", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "f61e8649-b003-42e2-8670-4116885a1e26", + "name": "NFV_DEVELOPER", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "379857ba-17b0-4299-9191-4df27ce9425b", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "a2685809-e874-4009-8435-92ded0c7180d", + "name": "ADMIN", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "af2ef7e2-d78a-4f4e-844c-174c64168316", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "8b544ccb-d0de-4550-b879-985c86b8d018", + "name": "USER", + "composite": false, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "0f367333-06dc-4740-931a-b2d6b3b06577", + "name": "EXPERIMENTER", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + }, + { + "id": "ec900678-a7df-4955-a78d-a90b138a5121", + "name": "TESTBED_PROVIDER", + "composite": true, + "composites": { + "realm": [ + "USER" + ] + }, + "clientRole": false, + "containerId": "openslice", + "attributes": {} + } + ], + "client": { + "openslice-service": [], + "realm-management": [ + { + "id": "679a9d01-6d85-42f5-9c6b-f3d923dd1a0a", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "06f2873b-3926-4d97-9179-769e342f86e9", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "63f7b29c-c463-40d8-82de-4ae894de65ea", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "09422e3f-4358-466a-a46a-e887cb5f5189", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients", + "create-client", + "view-realm", + "manage-events", + "query-groups", + "manage-identity-providers", + "view-events", + "view-users", + "view-clients", + "manage-clients", + "impersonation", + "manage-authorization", + "manage-users", + "query-realms", + "query-users", + "manage-realm", + "view-authorization", + "view-identity-providers" + ] + } + }, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "2d6c5511-1cb7-4283-90f5-50d751c2eb92", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "dbb571cf-7d5e-418e-95d7-ca2160eceba6", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "31f02966-2fa2-479b-bcf1-fa2a000e7b0f", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "46c57172-f46d-466c-a73c-4b4f58eb23ce", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "006e604a-1915-4165-bf8a-709f77d07c99", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "22b0f1f4-b2de-4829-ae70-5b6a2ffb90c0", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "2ec8e15f-d086-4c49-a2dc-ccf1b85b645f", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "841fcb24-6965-4299-a2a8-2a0caf98b022", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "16a19114-7aa5-4c7c-a741-424e74b379b9", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "7c81140a-8b70-44fc-af0e-d6b83f6be914", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "1690c8e2-971a-4472-a21c-d2c403f46907", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "3b455fa3-45ce-4210-b138-c3a64b69271f", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "9cfae318-c817-428c-8a41-9f37fa3b8848", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "a085267a-ac93-4004-9899-b76b74d06c31", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + }, + { + "id": "1dd16fc9-7abd-41fe-bb23-5887f01fa295", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "osapiWebClientId": [], + "account-console": [], + "broker": [ + { + "id": "be197fdb-fe78-4b10-87d3-9e17826b05c9", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "92128d63-9887-4e70-b5e2-9797756279d3", + "attributes": {} + } + ], + "account": [ + { + "id": "e2d74a05-f1a0-4fb1-8b03-a3e9b691d82b", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "f661e78f-1ce3-4af2-9a7c-a5cb7a09d4b5", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "3094e791-7572-4845-b64b-3dbbb763fdb7", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "05ddbf6c-7b93-4c49-83e9-154255ac877e", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "84bad9b3-a179-4700-84a4-fdcbf0ae2991", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + }, + { + "id": "d3e32349-192a-464e-91f8-b73ed6a8f170", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRoles": [ + "uma_authorization", + "offline_access" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account" + ] + } + ] + }, + "clients": [ + { + "id": "d30c8b0b-4d20-4dd7-876a-21ee1ae2c028", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/openslice/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": [ + "view-profile", + "manage-account" + ], + "redirectUris": [ + "/realms/openslice/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "7838e492-c9ce-4812-a9e9-629244fe1295", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/openslice/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/realms/openslice/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "48e276a8-68a7-45ef-929a-18d2afbab527", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "b233eb6d-e3df-4d8d-8b09-3666f043258f", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "92128d63-9887-4e70-b5e2-9797756279d3", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "41a307d8-9465-463e-89ad-8c30af4ad5c0", + "clientId": "openslice-service", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "40742f38-d000-431b-a0a5-f5101a730a5a", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "5115e3c5-8453-4c8b-a6a7-67e16f56eda9", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "a194cc8d-d541-42f8-8c3c-3553568b3d2c", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "40ec2a52-1033-4471-80a3-404167935e6f", + "clientId": "osapiWebClientId", + "rootUrl": "http://INGRESSADDR", + "adminUrl": "http://INGRESSADDR", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "http://openslice.io/*", + "http://localhost:13000/osapi/webjars/springfox-swagger-ui/oauth2-redirect.html", + "http://localhost:13082/*", + "http://localhost:13000/*", + "http://INGRESSADDR/*", + "http://localhost:13000/osapi/testweb/oauthresp.html" + ], + "webOrigins": [ + "http://localhost:13082", + "http://INGRESSADDR", + "http://openslice.io", + "http://localhost:13000" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "380ac4d6-6105-495d-873c-6e85983fcfeb", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "37a4e3c2-48be-4ee0-b50f-6e439ed2cdb2", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/openslice/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/admin/openslice/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "d7eaa5b1-22be-4ab4-86b4-2e415aeca815", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "562b8e42-c857-4cf6-8241-28efb2642c4b", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "5a5001cb-4bd0-480f-a7a3-c0bcba80ad3a", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "f6653189-9761-4ef3-936c-38affde191d8", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "767ac64d-5809-4239-b406-edcdd9050e80", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "e8d8398b-37ea-43bb-9196-f934ac296014", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "09a290c7-2b47-4151-9bc5-157c74aca908", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "f00e6912-4087-4887-a322-28e138d4b39f", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + }, + { + "id": "b782ede1-459f-4e6a-bf8b-88b18a6772d6", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "a12e8651-599f-4ddb-b653-d8cb5b0184d7", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "0f2b29e9-8093-455c-a5a9-f0c1c928942f", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "f4ec14ee-b067-40bf-b7c0-6dd7df5a602f", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "65664f25-c82d-433d-bf36-c08ded829901", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "c712880d-9ef1-4ea2-86bf-810054d40b26", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "b18c9def-9b75-4706-9936-2d4178c7b5a6", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "dbef3b60-3c68-4bb7-9d2a-d8a85f6f7004", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "bdf07a0c-c5ca-4608-b494-b8a1ddc063c4", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "81e16a30-df1f-416b-80c3-6983101166d1", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "b44f4f26-6d0d-406e-9009-c5d8dfdd5d16", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "86c5c86e-cb21-4abd-a17a-85dc63617995", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "d78aedcd-828c-4773-ad70-22091d874bbd", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "95e1cb5d-4f42-4b2a-8e3a-69e39055b66d", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "id": "ac157f2a-50b9-404e-bde0-965910a47d05", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "4edc4427-0ebe-4825-89a8-0e8e80620f5a", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "6ce933f3-a5b4-4676-b5db-b6425d45021d", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "bd070586-ba31-42c4-b2fa-0614ad88e792", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "397b1ae7-6c83-4a4c-a97d-75102563ae57", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "a40de263-79e3-4adf-9dc6-584b1f537a06", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "6ca378b4-4e3b-4cc2-bee4-ef3479d59114", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "57d2d578-eb49-4756-8d41-c999c2849f1a", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "b322295e-fae9-4ade-9b0e-138a44732f3e", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "f24c94cb-8156-4f4e-b5f2-e7b3000f4f81", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "27c412ff-97ef-49d2-8a80-f42fd8649b7a", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "377da2df-94e7-43de-98f6-b3b4326cfa02", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "39e41a56-6439-40da-9aa7-fa3b8a57c759", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "bb450b68-fcda-4f82-b16c-6d83cd28aa8f", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "web-origins", + "roles", + "profile", + "email" + ], + "defaultOptionalClientScopes": [ + "microprofile-jwt", + "phone", + "address", + "offline_access" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "34e415a5-18a4-4e32-a17c-daf41c5cbf19", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "7d113054-e7c7-44cb-a6d8-d257195b1364", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "388b5ffd-ea57-48bc-b7af-43b21b529e8a", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper" + ] + } + }, + { + "id": "70080b90-b144-421e-9ec4-4106a6181d88", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "d556fcc1-038a-4ed2-992b-5803e4c599be", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "67803167-d874-41b2-970b-b2de89d0250b", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-address-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper", + "saml-user-attribute-mapper" + ] + } + }, + { + "id": "a4381728-f174-492f-9404-c8ecaddc8bd9", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "c60d614f-36b1-4a0f-b359-f2c4c7e7a2d5", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "472544bd-20bd-467d-8d5c-f71468017b90", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "56cdedf5-b827-4ca7-be55-8e12df78b974", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "9d0c7f22-b432-4223-baf1-83dbfbca38db", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS256" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "8357d622-c8b1-428d-b134-3315622f398d", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "f373c5c3-0467-47c7-8aa4-f6fe1acfe380", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "1647396e-5d80-47c0-9780-1b0601d81f55", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "4b75ca24-90fb-46da-ba2b-ba11e96b9cee", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "df72819f-b96b-47b9-88f5-bf0033798b40", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "241c2432-5771-4a42-90f3-4198b6e9fd62", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Account verification options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "fc2f23d5-003a-4e2a-947b-8f426c52694c", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c152dd74-8690-4c1f-b83f-2da74289cc1e", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "db2da225-e43a-42ad-977f-508895169efa", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "6bda8474-8636-4bff-9e86-b95552f5944a", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2dcccc92-8c58-4b18-9773-a991977fc829", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "34a83f8f-e241-412e-93c5-398495bc8f2a", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 30, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "d3849e68-145f-44ac-a360-d16930a6eb09", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "30ed0330-9d8a-4992-aa0c-56313cf60790", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "User creation or linking", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2521a30f-27ba-441e-821b-8515f63380c9", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "3f9984f5-a163-4b57-a947-1a7b72240dec", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Authentication Options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "273c03f3-8fc2-4e81-a9f7-fbf72158e129", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "07afd274-0910-43d8-b627-422d4d9e2ed8", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "7b72931e-ad78-41fd-add0-1e622e208d55", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 40, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2e95fbe8-90de-4ad0-af7c-b8a598456a19", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "0c8464aa-a2ea-479e-9f21-e3b4ba670b46", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "060e864c-a566-4551-ba54-2c280aafda02", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": {}, + "keycloakVersion": "9.0.2", + "userManagedAccessAllowed": false +} diff --git a/kubernetes/template/tmfweb-config-nginx.yaml b/kubernetes/template/tmfweb-config-nginx.yaml new file mode 100644 index 0000000000000000000000000000000000000000..04de3cd2e43ba639939edbd605a57af6ac8c6d00 --- /dev/null +++ b/kubernetes/template/tmfweb-config-nginx.yaml @@ -0,0 +1,31 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: tmfweb-config-nginx + namespace: openslice +data: + default.conf: |+ + # Expires map + map $sent_http_content_type $expires { + default off; + text/html epoch; + text/css max; + application/json max; + application/javascript max; + ~image/ max; + } + + server { + listen 80; + include /etc/nginx/mime.types; + + server_name INGRESSADDR; + location / { + root /usr/share/nginx/html/services; + index index.html index.htm; + try_files $uri $uri/ /index.html =404; + } + + expires $expires; + gzip on; + } diff --git a/kubernetes/template/tmfweb-config.yaml b/kubernetes/template/tmfweb-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3d7442823c785ca893c30030c894c7dd0ef2c1f8 --- /dev/null +++ b/kubernetes/template/tmfweb-config.yaml @@ -0,0 +1,47 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: tmfweb-config + namespace: openslice +data: + config.prod.json: |+ + { + "TITLE": "Openslice demo", + "PORTALVERSION":"2023-Q3 1.2.0-SNAPSHOT", + "WIKI": "https://openslice.readthedocs.io/en/stable/", + "BUGZILLA": "{BASEURL}/bugzilla/", + "STATUS": "http://INGRESSADDR/", + "WEBURL": "{BASEURL}", + "PORTAL_REPO_APIURL": "{BASEURL}/osapi", + "ASSURANCE_SERVICE_MGMT_APIURL": "{BASEURL}/oas-api", + "APITMFURL": "{BASEURL}/tmf-api", + "OAUTH_CONFIG" : { + "issuer": "{BASEURL}/auth/realms/openslice", + "loginUrl": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/auth", + "tokenEndpoint": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/token", + "redirectUri": "{BASEURL}/redirect", + "logoutUrl": "{BASEURL}/auth/realms/openslice/protocol/openid-connect/logout", + "postLogoutRedirectUri": "{BASEURL}", + + "responseType": "code", + "oidc": false, + "clientId": "osapiWebClientId", + "dummyClientSecret": "secret", + + "requireHttps": false, + "useHttpBasicAuth": true, + "clearHashAfterLogin": false, + + "showDebugInformation": true + } + } + config.theming.json: |+ + { + "THEME_ID":"default", + "DEPLOYMENT_LOGO_PATH":"assets/images/logo_clear.png", + "DEFAULT_SERVICE_LOGO_PATH":"assets/images/logo_icon_original.png", + "FAVICON_PATH":"favicon.ico", + "WHO_WE_ARE_HTML":"
openslice.io project | openslice.io
openslice.io an opensource OSS
Openslice demo | http://portal.openslice.io
A portal that allows 5G experimenters to deploy experiment descriptors towards the infrastructure.
Openslice demo wiki | https://openslice.readthedocs.io/en/stable/
A wiki containing project documentation.
Openslice demo Report Issues | http://portal.openslice.io/bugzilla/
Our issue tracking system.
", + "CONNECT_WITH_US_HTML":"", + "FOOTER_HTML":"
openslice.io has received funding from
5GinFIRE | https://5ginfire.eu/ project from the European Horizon 2020 Programme for research, technological development and demonstration under grant agreement number 732497.
5G-VINNI project | https://5g-vinni.eu/ 5G-VINNI project has received funding from the European Horizon 2020 Programme for research, technological development and demonstration under grant agreement number 815279
Openslice demo running openslice.io version 1.1.0-SNAPSHOT| Data Protection Declaration | © 2019-2021 on behalf of openslice.io
" + } diff --git a/kubernetes/template/tmfweb.yaml b/kubernetes/template/tmfweb.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a07b188fd8caf794695234f2cd8c8cfe29d935fa --- /dev/null +++ b/kubernetes/template/tmfweb.yaml @@ -0,0 +1,53 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openslice + labels: + org.etsi.osl.service: tmfweb + name: tmfweb +spec: + replicas: 1 + selector: + matchLabels: + org.etsi.osl.service: tmfweb + strategy: + type: Recreate + template: + metadata: + labels: + org.etsi.osl.service: tmfweb + spec: + containers: + - name: openslice-tmfweb + image: labs.etsi.org:5050/osl/code/org.etsi.osl.tmf.web:develop + ports: + - containerPort: 80 + volumeMounts: + - name: "tmfweb-configuration" + readOnly: true + mountPath: "/usr/share/nginx/html/services/assets/config" + - name: "tmfweb-configuration-nginx" + readOnly: true + mountPath: "/etc/nginx/conf.d" + volumes: + - name: "tmfweb-configuration" + configMap: + name: tmfweb-config + - name: "tmfweb-configuration-nginx" + configMap: + name: tmfweb-config-nginx + restartPolicy: Always +--- +apiVersion: v1 +kind: Service +metadata: + namespace: openslice + labels: + org.etsi.osl.service: tmfweb + name: tmfweb +spec: + ports: + - name: "tmwebport" + port: 80 + selector: + org.etsi.osl.service: tmfweb diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000000000000000000000000000000000000..c0a559547b9b26d5c0c0dd15b938f8ba6e5669b6 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,76 @@ +# Project information +site_name: Openslice +site_description: Openslice - Open source OSS +site_author: Openslice.io +site_url: http://openslice.io + +# Repository +repo_name: openslice +repo_url: https://github.com/openslice +edit_uri: "" +docs_dir: doc + +# edit_uri: edit/docs-revamp/docs/ +# edit_uri: blob/docs-revamp/docs/ + +# remote_name: origin +# remote_branch: gh-pages + +# Theme and overrides, i.e. language partial +theme: + name: mkdocs + + # Don't include MkDocs' JavaScript + include_search_page: false + search_index_only: true + + # Default values, taken from mkdocs_theme.yml + language: en + feature: + tabs: true + palette: + primary: 'teal' + accent: 'light blue' + logo: 'images/openslice_logo.png' + +# Copyright +copyright: "Copyright © 2019-2023 Openslice Project" + +# Options +extra: + search: + languages: "en" + social: + - type: globe + link: http://openslice.io + - type: github-alt + link: https://github.com/openslice + - type: twitter + link: https://twitter.com/OpensliceOSS + +# Page tree +nav: + - Overview: + - Introduction: index.md + - Getting Started: + - Deployment/Installation: deployment.md + - NFV Orchestrator Configuration: nfvoconfig.md + - Service Catalogs: catalogs.md + - NFV Catalogs: nfvcatalogs.md + - LCM Rules: lcm.md + - Consuming Services From External OSS: ./architecture/consumingServicesFromExternalPartners.md + - Service Inventory: service_inventory.md + - Alarms and Actions: alarms_actions.md + - Design & Architecture: + - Architecture: ./architecture/architecture.md + - Message bus: ./architecture/messagebus.md + - OSOM: ./architecture/osom.md + - Authentication: ./architecture/oauth.md + - TMF API: ./architecture/tmfapi.md + - NFV API: ./architecture/nfvapi.md + - TMF WEB: ./architecture/tmfweb.md + - NFV WEB: ./architecture/nfvweb.md + - Issue management: ./architecture/issuemgt.md + - Central logging: ./architecture/centrallog.md + - Contributing: + - Developing: ./contributing/developing.md diff --git a/openslice-install.sh b/openslice-install.sh new file mode 100644 index 0000000000000000000000000000000000000000..226ca3b122a3b9602ad6f25c236af2e372ce67df --- /dev/null +++ b/openslice-install.sh @@ -0,0 +1,149 @@ +#!/bin/bash + +# Exit on error +set -e + +# Function to log messages +log() { + echo "[INFO] $1" +} + +# Temporarily remove needrestart +if dpkg -l | grep needrestart; then + log "Temporarily removing needrestart..." + sudo apt-get remove -y needrestart > /dev/null +fi + +# Update OS +log "Updating OS..." +sudo apt-get update -y > /dev/null +sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" > /dev/null +log "OS updated successfully." + +# Install Docker if it's not already installed +if ! command -v docker &> /dev/null; then + log "Installing Docker..." + sudo apt-get install -y docker.io > /dev/null + sudo systemctl enable docker > /dev/null + sudo systemctl start docker > /dev/null + log "Docker installed successfully." +fi + +# Install kubectl if it's not already installed +if ! command -v kubectl &> /dev/null; then + log "Installing kubectl..." + sudo apt-get update && sudo apt-get install -y apt-transport-https > /dev/null + curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - > /dev/null + echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list > /dev/null + sudo apt-get update > /dev/null + sudo apt-get install -y kubectl > /dev/null + log "kubectl installed successfully." +fi + +# Install kind if it's not already installed +if ! command -v kind &> /dev/null; then + log "Installing kind..." + curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.12.0/kind-linux-amd64 > /dev/null + chmod +x ./kind + sudo mv ./kind /usr/local/bin/ > /dev/null + log "kind installed successfully." +fi + +# Check if a kind cluster already exists and create if it doesn't +if ! kind get clusters | grep -q 'kind'; then + log "Creating kind cluster..." + kind create cluster > /dev/null + log "Kind cluster created successfully." +else + log "Kind cluster already exists. Skipping creation." +fi + +# Install helm if it's not already installed +if ! command -v helm &> /dev/null; then + log "Installing helm..." + curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 > /dev/null + chmod 700 get_helm.sh + ./get_helm.sh > /dev/null + rm get_helm.sh + log "Helm installed successfully." +fi + +# Install ingress-nginx with helm +log "Installing ingress-nginx..." +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx > /dev/null +helm repo update > /dev/null +helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx --create-namespace --set controller.hostNetwork=true,controller.service.type="" > /dev/null + +# Wait for ingress-nginx to be ready +log "Waiting for ingress-nginx to be ready..." +kubectl wait --namespace ingress-nginx \ + --for=condition=ready pod \ + --selector=app.kubernetes.io/component=controller \ + --timeout=120s > /dev/null +log "ingress-nginx is ready." + +################################################################################################### +# # Fetch the ClusterIP and Port of the ingress controller service +# CLUSTER_IP=$(kubectl get svc -n ingress-nginx ingress-nginx-controller -o=jsonpath='{.spec.clusterIP}') +# PORT=$(kubectl get svc -n ingress-nginx ingress-nginx-controller -o=jsonpath='{.spec.ports[?(@.name=="http")].port}') + +# # Set up iptables rules +# sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination $CLUSTER_IP:$PORT +# sudo iptables -t nat -A POSTROUTING -j MASQUERADE +################################################################################################### + +# Clone the repository +if [ ! -d "org.etsi.osl.main" ]; then + log "Cloning repository..." + git clone -b kubernetes https://github.com/openslice/org.etsi.osl.main.git > /dev/null + log "Repository cloned successfully." +else + log "Repository already exists. Switching to kubernetes branch and pulling latest changes..." + cd org.etsi.osl.main + git fetch origin > /dev/null + git checkout -B kubernetes origin/kubernetes > /dev/null + git pull origin kubernetes > /dev/null + cd .. + log "Latest changes pulled successfully." +fi + +# Find the host's IP address automatically +DEFAULT_IFACE=$(ip route show default | awk '/default/ {print $5}') +HOST_IP=$(ip -4 addr show $DEFAULT_IFACE | grep -oP '(?<=inet\s)\d+(\.\d+){3}') + +# Define the release name +RELEASE_NAME="my-openslice" + +# Define a specific port for Keycloak +KEYCLOAK_PORT=31000 + +# Change directory and run helm install +cd org.etsi.osl.main/kubernetes/helm/openslice +log "Installing my-openslice..." +# change this +# helm upgrade --install $RELEASE_NAME . -n openslice --create-namespace --set rooturl=http://$HOST_IP:$KEYCLOAK_PORT,mysql.storage="500Mi" > /dev/null +helm upgrade --install $RELEASE_NAME . -n openslice --create-namespace --set rooturl=http://$HOST_IP,mysql.storage="500Mi" > /dev/null + +# Update services to NodePort +# full_svc_name="${RELEASE_NAME}-${svc_suffix}" +# log "Updating $full_svc_name service to use NodePort..." +# kubectl patch svc ${RELEASE_NAME}-keycloak -n openslice --type='json' -p="[{'op': 'replace', 'path': '/spec/type', 'value': 'NodePort'}, {'op': 'replace', 'path': '/spec/ports/0/nodePort', 'value': $KEYCLOAK_PORT}]" + +# for svc_suffix in "keycloak" "portalweb" "tmfweb"; do +# full_svc_name="${RELEASE_NAME}-${svc_suffix}" +# log "Updating $full_svc_name service to use NodePort..." +# kubectl patch svc $full_svc_name -n openslice --type='json' -p="[{'op': 'replace', 'path': '/spec/type', 'value': 'NodePort'}]" +# done + +cd - > /dev/null +log "my-openslice installed successfully." + +# # Display the summary +# log "=== Access Information ===" + +# # Fetch and display NodePorts for each service +# for svc_suffix in "keycloak" "portalweb" "tmfweb"; do +# full_svc_name="${RELEASE_NAME}-${svc_suffix}" +# NODE_PORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services $full_svc_name -n openslice) +# log "You can access $svc_suffix on ${HOST_IP}:${NODE_PORT}" +# done diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..b22ca3a80a9b3bb430d1024fae9c3513dc099d4d --- /dev/null +++ b/pom.xml @@ -0,0 +1,143 @@ + + 4.0.0 + + org.etsi.osl + org.etsi.osl.main + 1.0.0 + pom + + org.etsi.osl.main + + openslice.io + http://openslice.io + + + 2019 + + + 2.8.11 + 2.0.0 + apache_v2 + UTF-8 + UTF-8 + 4.0.0-RC2 + 3.1.2 + 3.0.0 + 2.1.0 + 17 + 22.0.1 + 7.0.0.M1 + 1.7.0 + 1.7.0 + + + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + 1.0.0 + + + + 2.4.0.RELEASE + 1.0.10.RELEASE + 2.1.1.RELEASE + 2.2.4.RELEASE + + + + + utf-8 + ${encoding} + ${encoding} + ${encoding} + ${encoding} + 8.0.33 + + + + + + + + gitlab-maven + https://labs.etsi.org/rep/api/v4/groups/260/-/packages/maven + + + + + gitlab-maven + ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven + + + gitlab-maven + ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + org.codehaus.mojo + license-maven-plugin + ${maven-license-plugin.version} + + false + ========================LICENSE_START================================= + =========================LICENSE_END================================== + *.json + src/main/java,src/test/java + + + + + generate-license-headers + + update-file-header + + process-sources + + ${license.licenseName} + + + + + download-licenses + + download-licenses + + + + + + + + + +