diff --git a/.github/workflows/detect-secrets.yml b/.github/workflows/detect-secrets.yml new file mode 100644 index 00000000..693b3215 --- /dev/null +++ b/.github/workflows/detect-secrets.yml @@ -0,0 +1,34 @@ +name: detect secrets + +on: push + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "detect-secrets" + detect-secrets: + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + + # Checks-out your repository under ${{github.workspace}}, so your job can access it + - uses: actions/checkout@v4 + + - name: scan all the files (not just the ones committed), generate a report, and check that there are no actual or potential secret + run: | + docker run --pull=always -a stdout \ + -v ${{github.workspace}}:/code \ + --entrypoint /bin/sh \ + icr.io/git-defenders/detect-secrets:0.13.1.ibm.61.dss-redhat-ubi \ + -c "detect-secrets --version; + detect-secrets scan --all-files --exclude-files "^.git/.*" --update .secrets.baseline; + detect-secrets audit --report --fail-on-unaudited --fail-on-live --fail-on-audited-real .secrets.baseline" + + - name: Report Status + if: always() + uses: ravsamhq/notify-slack-action@master + with: + status: ${{ job.status }} + notify_when: 'failure' + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/.gitignore b/.gitignore index 3044f462..c6e4597b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,17 @@ *.iml output /.vscode + + +# Local .terraform directories +**/.terraform/* +# .tfstate files +*.tfstate +*.tfstate.* +*.terraform.lock.hcl +# Exclude all .tfvars files, which are likely to contain sentitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +# +# *.tfvars \ No newline at end of file diff --git a/.md_check_config.json b/.md_check_config.json index a59c004f..17934a02 100644 --- a/.md_check_config.json +++ b/.md_check_config.json @@ -1,5 +1,10 @@ { - "replacementPatterns": [ + "ignorePatterns": [ + { + "pattern": "^http://localhost" + } + ], + "replacementPatterns": [ { "pattern": "^/LICENSE", "replacement": "{{BASEURL}}/LICENSE" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ec308043..50c1a6ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: # You are encouraged to use static refs such as tags, instead of branch name # # Running "pre-commit autoupdate" automatically updates rev to latest tag - rev: 0.13.1+ibm.61.dss + rev: 0.13.1+ibm.62.dss hooks: - id: detect-secrets # pragma: whitelist secret # Add options for detect-secrets-hook binary. You can run `detect-secrets-hook --help` to list out all possible options. diff --git a/.secrets.baseline b/.secrets.baseline index 4905011d..2500cd3e 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -1,9 +1,9 @@ { "exclude": { - "files": "openldap-customldif.yaml|ldap-custom-ssl-secret.yaml|^.secrets.baseline$", + "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2024-08-09T09:14:16Z", + "generated_at": "2024-11-13T08:35:31Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -100,7 +100,7 @@ "hashed_secret": "5a2ea68e9ea943ea31948fe51388c798e13346a9", "is_secret": false, "is_verified": false, - "line_number": 221, + "line_number": 234, "type": "Secret Keyword", "verified_result": null }, @@ -108,7 +108,7 @@ "hashed_secret": "fa9beb99e4029ad5a6615399e7bbae21356086b3", "is_secret": false, "is_verified": false, - "line_number": 442, + "line_number": 495, "type": "Secret Keyword", "verified_result": null }, @@ -116,7 +116,7 @@ "hashed_secret": "076a042dcb8e3b7be55cbbe95e1f18f577ef1ba5", "is_secret": false, "is_verified": false, - "line_number": 488, + "line_number": 541, "type": "Secret Keyword", "verified_result": null } @@ -134,7 +134,7 @@ "hashed_secret": "5a2ea68e9ea943ea31948fe51388c798e13346a9", "is_secret": false, "is_verified": false, - "line_number": 145, + "line_number": 152, "type": "Secret Keyword", "verified_result": null }, @@ -142,7 +142,7 @@ "hashed_secret": "fa9beb99e4029ad5a6615399e7bbae21356086b3", "is_secret": false, "is_verified": false, - "line_number": 387, + "line_number": 394, "type": "Secret Keyword", "verified_result": null } @@ -254,11 +254,19 @@ } ], "authentication/Keycloak/README.md": [ + { + "hashed_secret": "d033e22ae348aeb5660fc2140aec35850c4da997", + "is_secret": false, + "is_verified": false, + "line_number": 107, + "type": "Secret Keyword", + "verified_result": null + }, { "hashed_secret": "5a2ea68e9ea943ea31948fe51388c798e13346a9", "is_secret": false, "is_verified": false, - "line_number": 361, + "line_number": 374, "type": "Secret Keyword", "verified_result": null }, @@ -266,7 +274,7 @@ "hashed_secret": "fa9beb99e4029ad5a6615399e7bbae21356086b3", "is_secret": false, "is_verified": false, - "line_number": 560, + "line_number": 580, "type": "Secret Keyword", "verified_result": null }, @@ -274,7 +282,7 @@ "hashed_secret": "076a042dcb8e3b7be55cbbe95e1f18f577ef1ba5", "is_secret": false, "is_verified": false, - "line_number": 605, + "line_number": 625, "type": "Secret Keyword", "verified_result": null } @@ -284,7 +292,7 @@ "hashed_secret": "d033e22ae348aeb5660fc2140aec35850c4da997", "is_secret": false, "is_verified": false, - "line_number": 104, + "line_number": 113, "type": "Secret Keyword", "verified_result": null }, @@ -292,7 +300,7 @@ "hashed_secret": "c94cfbe098fb5c2eedde2bb22c78fe2cd7e9a0e8", "is_secret": false, "is_verified": false, - "line_number": 162, + "line_number": 171, "type": "Secret Keyword", "verified_result": null } @@ -307,6 +315,42 @@ "verified_result": null } ], + "authentication/Keycloak/openldap/ldap-custom-ssl-secret.yaml": [ + { + "hashed_secret": "470bf8b666f65eb413930e55a2153b2e6d6334b0", + "is_secret": false, + "is_verified": false, + "line_number": 8, + "type": "Base64 High Entropy String", + "verified_result": null + }, + { + "hashed_secret": "641ad3b66231e0f477088e711306cd1fdf1e5626", + "is_secret": false, + "is_verified": false, + "line_number": 11, + "type": "Base64 High Entropy String", + "verified_result": null + }, + { + "hashed_secret": "03b4a6482aeaf6e6aa3c2639db6e1c9b728e7b49", + "is_secret": false, + "is_verified": false, + "line_number": 13, + "type": "Base64 High Entropy String", + "verified_result": null + } + ], + "authentication/Keycloak/openldap/openldap-customldif.yaml": [ + { + "hashed_secret": "3e6e3eece5e10a4c903489f501c049b2c54094c4", + "is_secret": false, + "is_verified": false, + "line_number": 8, + "type": "Base64 High Entropy String", + "verified_result": null + } + ], "authentication/Keycloak/openldap/openldap-secret.yaml": [ { "hashed_secret": "e6c016ec485da2332894dc2ec7a6dc51274329ca", @@ -360,7 +404,7 @@ "hashed_secret": "5a2ea68e9ea943ea31948fe51388c798e13346a9", "is_secret": false, "is_verified": false, - "line_number": 225, + "line_number": 250, "type": "Secret Keyword", "verified_result": null }, @@ -368,7 +412,7 @@ "hashed_secret": "fa9beb99e4029ad5a6615399e7bbae21356086b3", "is_secret": false, "is_verified": false, - "line_number": 379, + "line_number": 405, "type": "Secret Keyword", "verified_result": null }, @@ -376,7 +420,7 @@ "hashed_secret": "076a042dcb8e3b7be55cbbe95e1f18f577ef1ba5", "is_secret": false, "is_verified": false, - "line_number": 425, + "line_number": 451, "type": "Secret Keyword", "verified_result": null } @@ -709,72 +753,6 @@ "verified_result": null } ], - "contrib/authentication/openid/README.md": [ - { - "hashed_secret": "d7f9728ec689ecd3fd50058a04802f459b83173e", - "is_secret": false, - "is_verified": false, - "line_number": 107, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "02ce1f4be51daf5cd47c57197dc61a5fe2eba473", - "is_secret": false, - "is_verified": false, - "line_number": 110, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "3849133aa19d6e8902e4a1f0c7c465ac1c09d431", - "is_secret": false, - "is_verified": false, - "line_number": 131, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "c673da365bbd9dd8e6f92d3154b80aea2ff4f881", - "is_secret": false, - "is_verified": false, - "line_number": 182, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "b23331241177ae0c97f6cb8fc4e1a095922768be", - "is_secret": false, - "is_verified": false, - "line_number": 190, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "4340fd2b47019e2ccb89f8bb9d0ec64eea4d91cf", - "is_secret": false, - "is_verified": false, - "line_number": 227, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "59c41b55cd0186e10b7e9bfb92d127f827d20d37", - "is_secret": false, - "is_verified": false, - "line_number": 234, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "fd1daf2e350a06b865f4a1e17bb39183b806c1e9", - "is_secret": false, - "is_verified": false, - "line_number": 287, - "type": "Secret Keyword", - "verified_result": null - } - ], "contrib/monitor/mpmetrics/README.md": [ { "hashed_secret": "5a2ea68e9ea943ea31948fe51388c798e13346a9", @@ -1133,38 +1111,152 @@ "verified_result": null } ], - "platform/azure/README-Azure-SQL-MI.md": [ + "platform/azure/README.md": [ + { + "hashed_secret": "07596f183f5e91b1778d5e47b2752b8d42aa763d", + "is_secret": false, + "is_verified": false, + "line_number": 174, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "3ea3f9802accf8817bacd6f3df46a73b93ccddec", + "is_secret": false, + "is_verified": false, + "line_number": 175, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "12d57965bd88277e9e9d69dc2b36aae2c0b7e316", + "is_secret": false, + "is_verified": false, + "line_number": 274, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "41b864c967d31ed0bf10562e22faa36324405048", + "is_secret": false, + "is_verified": false, + "line_number": 292, + "type": "Secret Keyword", + "verified_result": null + } + ], + "platform/azure/aks-nginx-values.yaml": [ { "hashed_secret": "547ef58bd39c2e3cc6ff7e61ea31e3d23e6382f1", "is_secret": false, "is_verified": false, - "line_number": 62, + "line_number": 21, "type": "Secret Keyword", "verified_result": null } ], - "platform/azure/README.md": [ + "platform/azure/aks-sqlmi-values.yaml": [ { - "hashed_secret": "12d57965bd88277e9e9d69dc2b36aae2c0b7e316", + "hashed_secret": "547ef58bd39c2e3cc6ff7e61ea31e3d23e6382f1", + "is_secret": false, + "is_verified": false, + "line_number": 14, + "type": "Secret Keyword", + "verified_result": null + } + ], + "platform/azure/aks-values.yaml": [ + { + "hashed_secret": "547ef58bd39c2e3cc6ff7e61ea31e3d23e6382f1", + "is_secret": false, + "is_verified": false, + "line_number": 14, + "type": "Secret Keyword", + "verified_result": null + } + ], + "platform/ecs/README.md": [ + { + "hashed_secret": "f7a650098d23ab9e1348956a181ad78def09fff4", "is_secret": false, "is_verified": false, - "line_number": 227, + "line_number": 105, "type": "Secret Keyword", "verified_result": null }, { - "hashed_secret": "41b864c967d31ed0bf10562e22faa36324405048", + "hashed_secret": "1d064a26284fe7e4a9162b75bc4910c073b6f20c", "is_secret": false, "is_verified": false, - "line_number": 245, + "line_number": 124, "type": "Secret Keyword", "verified_result": null }, { - "hashed_secret": "547ef58bd39c2e3cc6ff7e61ea31e3d23e6382f1", + "hashed_secret": "ee6d75b0e9dd89083901685b135e7221f66acffe", "is_secret": false, "is_verified": false, - "line_number": 406, + "line_number": 139, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "e460a102a85c6b2ad4ba7d0d03f87a59748c2967", + "is_secret": false, + "is_verified": false, + "line_number": 228, + "type": "Secret Keyword", + "verified_result": null + } + ], + "platform/ecs/docker-compose-http.yaml": [ + { + "hashed_secret": "fd1daf2e350a06b865f4a1e17bb39183b806c1e9", + "is_secret": false, + "is_verified": false, + "line_number": 115, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "e460a102a85c6b2ad4ba7d0d03f87a59748c2967", + "is_secret": false, + "is_verified": false, + "line_number": 254, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "be77c8f0e58f35545f8075bbdaf8893bfb8f03fe", + "is_secret": false, + "is_verified": false, + "line_number": 272, + "type": "Secret Keyword", + "verified_result": null + } + ], + "platform/ecs/docker-compose-https.yaml": [ + { + "hashed_secret": "fd1daf2e350a06b865f4a1e17bb39183b806c1e9", + "is_secret": false, + "is_verified": false, + "line_number": 126, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "e460a102a85c6b2ad4ba7d0d03f87a59748c2967", + "is_secret": false, + "is_verified": false, + "line_number": 267, + "type": "Secret Keyword", + "verified_result": null + }, + { + "hashed_secret": "be77c8f0e58f35545f8075bbdaf8893bfb8f03fe", + "is_secret": false, + "is_verified": false, + "line_number": 285, "type": "Secret Keyword", "verified_result": null } @@ -1174,7 +1266,7 @@ "hashed_secret": "8b712744eee080d5fe6048e4f589235d00435559", "is_secret": false, "is_verified": false, - "line_number": 132, + "line_number": 133, "type": "Secret Keyword", "verified_result": null }, @@ -1182,7 +1274,7 @@ "hashed_secret": "b11974a9da0d56698df935ab86e19b127804d6d4", "is_secret": false, "is_verified": false, - "line_number": 156, + "line_number": 157, "type": "Secret Keyword", "verified_result": null } @@ -1248,7 +1340,7 @@ "hashed_secret": "dc081999b19ee322ee45e3d4451246b7c449db0a", "is_secret": false, "is_verified": false, - "line_number": 134, + "line_number": 143, "type": "Secret Keyword", "verified_result": null }, @@ -1256,7 +1348,7 @@ "hashed_secret": "5a2ea68e9ea943ea31948fe51388c798e13346a9", "is_secret": false, "is_verified": false, - "line_number": 181, + "line_number": 185, "type": "Secret Keyword", "verified_result": null } @@ -1271,7 +1363,7 @@ "verified_result": null }, { - "hashed_secret": "8ce7feb4d1c89d5611541bafa8f7ea83a4039665", + "hashed_secret": "e6a8430b6dc3747f44d258a127b11f4705d9ee01", "is_secret": false, "is_verified": false, "line_number": 20, @@ -1284,7 +1376,7 @@ "hashed_secret": "b11974a9da0d56698df935ab86e19b127804d6d4", "is_secret": false, "is_verified": false, - "line_number": 71, + "line_number": 72, "type": "Secret Keyword", "verified_result": null } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ad4cf69c..f7072c4d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -248,4 +248,4 @@ request. [Fork a Repo]: https://help.github.com/articles/fork-a-repo [coding guidelines]: https://github.com/ibm-js/sdk/blob/master/GUIDELINES.md [interactive rebase]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages -[rebasing]: http://git-scm.com/book/en/Git-Branching-Rebasing +[rebasing]: https://git-scm.com/book/en/v2/Git-Branching-Rebasing diff --git a/README.md b/README.md index e5f18867..f289e1d4 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,22 @@ The ODM Docker material is used here, which is available in the [odm-ondocker](h ![Flow](images/ODMinKubernetes-DeploymentOverview.png) +## Supported Versions + +This repository provides materials for the following versions of IBM ODM: + +| ODM Version | +|--------------| +| **[9.0.0.1 (Latest)](README.md)** | +| **[8.12.0.1](https://github.com/DecisionsDev/odm-docker-kubernetes/tree/8.12.0.1)** | +| **[8.11.0.1](https://github.com/DecisionsDev/odm-docker-kubernetes/tree/8.11.0.1)** | + +Each version has dedicated deployment instructions and materials tailored to its release. Select the version that matches your requirements for compatibility and features. ### Deploying ODM Rules on a specific platform - [Amazon EKS](platform/eks/README.md) +- [Amazon ECS Fargate](platform/ecs/README.md) (BETA) - [Azure AKS](platform/azure/README.md) - [Google Cloud GKE](platform/gcloud/README.md) - [Redhat OpenShift Kubernetes Service on IBM Cloud (ROKS)](platform/roks/README.md) diff --git a/authentication/AzureAD/Dockerfile b/authentication/AzureAD/Dockerfile new file mode 100644 index 00000000..9405f6c9 --- /dev/null +++ b/authentication/AzureAD/Dockerfile @@ -0,0 +1,8 @@ +FROM alpine + +RUN set -e; \ + apk update; \ + apk upgrade; \ + apk add bash curl jq; \ + apk cache purge; \ + set +e diff --git a/authentication/AzureAD/README_WITH_CLIENT_SECRET.md b/authentication/AzureAD/README_WITH_CLIENT_SECRET.md index a72c7c0d..0c393613 100644 --- a/authentication/AzureAD/README_WITH_CLIENT_SECRET.md +++ b/authentication/AzureAD/README_WITH_CLIENT_SECRET.md @@ -26,7 +26,7 @@ 1. Create the *ODM application*. - In **Azure Active Directory** / **App registration**, click **New Registration**: + In **Microsoft Entra Id** / **Manage** / **App registration**, click **New Registration**: * Name: **ODM Application** * Supported account types / Who can use this application or access this API?: select `Accounts in this organizational directory only (Default Directory only - Single tenant)` @@ -36,7 +36,7 @@ 2. Retrieve Tenant and Client information. - In **Azure Active Directory** / **App Registration**, select **ODM Application** and click **Overview**: + In **Microsoft Entra Id** / **Manage** / **App Registration**, select **ODM Application** and click **Overview**: * Application (client) ID: **Client ID**. It will be referenced as `CLIENT_ID` in the next steps. * Directory (tenant) ID: **Your Tenant ID**. It will be referenced as `TENANT_ID` in the next steps. @@ -45,7 +45,7 @@ 3. Generate an OpenID client secret. - In **Azure Active Directory** / **App registrations**, select **ODM Application**: + In **Microsoft Entra Id** / **Manage** / **App registrations**, select **ODM Application**: * From the Overview page, click on the link Client credentials: **Add a certificate or secret** or on the **Manage / Certificates & secrets** tab * Click + New Client Secret @@ -58,24 +58,24 @@ 4. Add Claims. - In **Azure Active Directory** / **App registrations**, select **ODM Application**, and in **Manage / Token Configuration**: + In **Microsoft Entra Id** / **Manage** / **App registrations**, select **ODM Application**, and in **Manage / Token Configuration**: - * Add Optional Email ID Claim + * Add Optional **email** ID Claim * Click +Add optional claim * Select ID - * Check Email - * Click Add - - * Add Optional Email Access Claim - * Click +Add optional claim - * Select Access - * Check Email + * Check **email** * Click Add * Turn on Microsoft Graph email permission * Check Turn on the Microsoft Graph email permission * Click Add + * Add Optional **email** Access Claim + * Click +Add optional claim + * Select Access + * Check **email** + * Click Add + * Add Group Claim * Click +Add groups claim * Check Security Groups @@ -85,11 +85,11 @@ To allow ODM rest-api to use the password flow with email as user identifier and the client-credentials flow with client_id as user identifier, we need to create a new claim named "identity" that will take the relevant value according to the flow: - In **Azure Active Directory** / **Enterprise applications**, select **ODM Application**, and in **Manage / Single sign-on**: + In **Microsoft Entra Id** / **Manage** / **Enterprise applications**, select **ODM Application**, and in **Manage / Single sign-on**: * Click Edit in the "Attributes & Claims" section * Click + Add new claim - * Name: identity + * Name: **identity** * Fill 2 Claim conditions in the exact following order: 1. User Type: Any / Scoped Groups: 0 / Source: Attribute / Value: 2. User Type: Members / Scoped Groups: 0 / Source: Attribute / Value: user.mail @@ -97,13 +97,22 @@ 6. API Permissions. - In **Azure Active Directory** / **App Registration**, select **ODM Application**, and then click **API Permissions**. + In **Microsoft Entra Id** / **Manage** / **App Registration**, select **ODM Application**, and then click **API Permissions**. * Click Grant Admin Consent for Default Directory + [Optional] If you are interested by the groups and users synchronization in the Business Console, you have to add some specific permission to allow Microsoft Graph Rest API Usage like : + + * Click on **Add a permission**, select **Application permissions** and choose **Group.Read.All**, **User.Read.All** + * Don't forget to **Grant Admin Consent for Default Directory** on these API permissions + + 7. Manifest change. - In **Azure Active Directory** / **App Registration**, select **ODM Application**, and then click **Manifest**. + In **Microsoft Entra Id** / **Manage** / **App Registration**, select **ODM Application**, and then click **Manifest**. + + The Manifest feature (a JSON representation of an app registration) is currently in transition. + [**AAD Graph app manifest**](https://learn.microsoft.com/en-us/entra/identity-platform/azure-active-directory-graph-app-manifest-deprecation) will be deprecated soon and not editable anymore starting 12/2/2024. It will be replaced by the **Microsoft Graph App Manifest** As explained in [accessTokenAcceptedVersion attribute explanation](https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-app-manifest#accesstokenacceptedversion-attribute), change the value to 2. @@ -111,6 +120,10 @@ It is also necessary to set **acceptMappedClaims** to true to manage claims. Without this setting, you get the exception **AADSTS50146: This application is required to be configured with an application-specific signing key. It is either not configured with one, or the key has expired or is not yet valid.** when requesting a token. + With **Microsoft Graph App Manifest**: + * **acceptMappedClaims** is relocated as a property of the **api** attribute + * **accessTokenAcceptedVersion** is relocated as a property of the **api** attribute and renamed **requestedAccessTokenVersion** + Then, click Save. 8. Check the configuration. @@ -290,6 +303,36 @@ --from-file=webSecurity.xml=./output/webSecurity.xml ``` +4. Create the secret allowing to synchronize Decision Center Users and Groups with Entra ID. + + This section is optional. + + ODM Decision Center allows to [manage users and groups from the Business console](https://www.ibm.com/docs/en/odm/9.0.0?topic=center-enabling-users-groups) in order to set access security on specific projects. + The Groups and Users import can be done using an LDAP connection. + But, if the openId server also provides a SCIM server, then it can also be managed using a SCIM connection. + + However, in some context, it's not possible to use LDAP or SCIM to import groups and users inside Decision Center. + We will explain here how to synchronize Decision Center Groups and Users with Entra ID by leveraging Entra ID and Decision Center rest-api. + + A script will be responsible to get groups and users located in the EntraID tenant using the Microsoft Graph API : + - [for users](https://learn.microsoft.com/en-us/graph/api/resources/users?view=graph-rest-1.0&preserve-view=true) + - [for groups](https://learn.microsoft.com/en-us/graph/api/resources/groups-overview?view=graph-rest-1.0&tabs=http) + + Then, it will generate a [group-security-configurations.xml](https://www.ibm.com/docs/en/odm/9.0.0?topic=access-optional-user-liberty-configurations#reference_w1b_xhq_2rb__title__3) file that will be consumed using the [Decision Center rest-api](https://www.ibm.com/docs/en/odm/9.0.0?topic=mufdc-creating-users-groups-roles-by-using-rest-api) to populate Groups and Users in the Administration Tab. + + In a kubernetes context, this script can be called by a CRON job. + Using the new ODM sidecar container mechanism, it can also be managed by the Decision Center pod himself. + + ```shell + kubectl create secret generic users-groups-synchro-secret \ + --from-file=./output/sidecar-start.sh \ + --from-file=generate-user-group-mgt.sh + ``` + > **Note** + > The scripts will be used inside a container using the Decision Center image. It's possible to use a dedicated lighter image instead + > by setting the helm chart parameter **--set decisionCenter.sidecar.image** + > You can find a [Dockerfile](Dockerfile) containing the minimal tooling (bash,curl,jq) to execute the scripts. + ## Install your ODM Helm release ### Add the public IBM Helm charts repository @@ -304,7 +347,7 @@ ```shell helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION - ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager + ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### Run the `helm install` command @@ -316,7 +359,7 @@ You can now install the product. We will use the PostgreSQL internal database an See the [Preparing to install](https://www.ibm.com/docs/en/odm/9.0.0?topic=production-preparing-install-operational-decision-manager) documentation for additional information. ```shell - helm install my-odm-release ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ + helm install my-odm-release ibm-helm/ibm-odm-prod --version 24.1.0 \ --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ --set oidc.enabled=true \ --set license=true \ @@ -326,6 +369,11 @@ You can now install the product. We will use the PostgreSQL internal database an --set internalDatabase.runAsUser='' --set customization.runAsUser='' --set service.enableRoute=true ``` +> **Note** +> If you want the optional synchronization of groups and users with Entra ID, you have to add to the helm install command: +> +> --set decisionCenter.sidecar.enabled=true --set decisionCenter.sidecar.confSecretRef=users-groups-synchro-secret + #### b. Installation using Ingress Refer to the following documentation to install an NGINX Ingress Controller on: @@ -336,7 +384,7 @@ You can now install the product. We will use the PostgreSQL internal database an When the NGINX Ingress Controller is ready, you can install the ODM release with: ``` - helm install my-odm-release ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ + helm install my-odm-release ibm-helm/ibm-odm-prod --version 24.1.0 \ --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ --set oidc.enabled=true \ --set license=true \ @@ -350,6 +398,11 @@ You can now install the product. We will use the PostgreSQL internal database an > **Note** > By default, NGINX does not enable sticky session. If you want to use sticky session to connect to DC, refer to [Using sticky session for Decision Center connection](../../contrib/sticky-session/README.md) +> **Note** +> If you want the optional synchronization of groups and users with Entra ID, you have to add to the helm install command: +> +> --set decisionCenter.sidecar.enabled=true --set decisionCenter.sidecar.confSecretRef=users-groups-synchro-secret + ## Complete post-deployment tasks ### Register the ODM redirect URLs @@ -403,7 +456,7 @@ You can now install the product. We will use the PostgreSQL internal database an - Decision Server Runtime redirect URI: `https:///DecisionService/openid/redirect/odm` - Rule Designer redirect URI: `https://127.0.0.1:9081/oidcCallback` - From the Azure console, in **Azure Active Directory** / **App Registrations** / **ODM Application**: + From the Microsoft Azure console, in **Microsoft Entra Id** / **Manage** / **App Registrations** / **ODM Application**: - Click the `Add a Redirect URI` link - Click `Add Platform` @@ -461,11 +514,11 @@ To manage ODM runtime call on the next steps, we used the [Loan Validation Decis Import the **Loan Validation Service** in Decision Center connected using *myodmuser*@YOURDOMAIN created at step 2 -![Import project](../Keycloak/images/import_project.png) +![Import project](images/import_project.png) Deploy the **Loan Validation Service** production_deployment ruleapps using the **production deployment** deployment configuration in the Deployments>Configurations tab. -![Deploy project](../Keycloak/images/deploy_project.png) +![Deploy project](images/deploy_project.png) You can retrieve the payload.json from the ODM Decision Server Console or use [the provided payload](payload.json). @@ -474,7 +527,7 @@ As explained in the ODM on Certified Kubernetes documentation [Configuring user You can realize a basic authentication ODM runtime call the following way: ```shell -$ curl -H "Content-Type: application/json" -k --data @payload.json \ +curl -H "Content-Type: application/json" -k --data @payload.json \ -H "Authorization: Basic b2RtQWRtaW46b2RtQWRtaW4=" \ https:///DecisionService/rest/production_deployment/1.0/loan_validation_production/1.0 ``` @@ -484,7 +537,7 @@ Where b2RtQWRtaW46b2RtQWRtaW4= is the base64 encoding of the current username:pa But if you want to execute a bearer authentication ODM runtime call using the Client Credentials flow, you have to get a bearer access token: ```shell -$ curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded" \ +curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded" \ -d 'client_id=&scope=%2F.default&client_secret=&grant_type=client_credentials' \ 'https://login.microsoftonline.com//oauth2/v2.0/token' ``` @@ -492,7 +545,7 @@ $ curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded" \ And use the retrieved access token in the following way: ```shell -$ curl -H "Content-Type: application/json" -k --data @payload.json \ +curl -H "Content-Type: application/json" -k --data @payload.json \ -H "Authorization: Bearer " \ https:///DecisionService/rest/production_deployment/1.0/loan_validation_production/1.0 ``` diff --git a/authentication/AzureAD/README_WITH_PRIVATE_KEY_JWT.md b/authentication/AzureAD/README_WITH_PRIVATE_KEY_JWT.md index c862f52a..8720dfa7 100644 --- a/authentication/AzureAD/README_WITH_PRIVATE_KEY_JWT.md +++ b/authentication/AzureAD/README_WITH_PRIVATE_KEY_JWT.md @@ -32,7 +32,7 @@ For additional information regarding the implement in Liberty, please refer to t 1. Create the *ODM application*. - In **Identity** / **Applications** / **App registration**, click **New Registration**: + In **Microsoft Entra Id** / **Manage** / **App registration**, click **New Registration**: * Name: **ODM Application** * Supported account types / Who can use this application or access this API?: select `Accounts in this organizational directory only (Default Directory only - Single tenant)` @@ -42,7 +42,7 @@ For additional information regarding the implement in Liberty, please refer to t 2. Retrieve Tenant and Client information. - In **Identity** / **Applications** / **App Registration**, select **ODM Application** and click **Overview**: + In **Microsoft Entra Id** / **Manage** / **App Registration**, select **ODM Application** and click **Overview**: * Application (client) ID: **Client ID**. It will be referenced as `CLIENT_ID` in the next steps. * Directory (tenant) ID: **Your Tenant ID**. It will be referenced as `TENANT_ID` in the next steps. @@ -57,12 +57,12 @@ For additional information regarding the implement in Liberty, please refer to t The expiration is set to 1000 days: ```shell - $ openssl req -x509 -nodes -days 1000 -newkey rsa:2048 -keyout myodmcompany.key \ + openssl req -x509 -nodes -days 1000 -newkey rsa:2048 -keyout myodmcompany.key \ -out myodmcompany.crt -subj "/CN=myodmcompany.com/OU=it/O=myodmcompany/L=Paris/C=FR" \ -addext "subjectAltName = DNS:myodmcompany.com" ``` - In **Identity** / **Applications** / **App registrations**, select **ODM Application**: + In **Microsoft Entra Id** / **Manage** / **App registrations**, select **ODM Application**: * From the Overview page, click on the link Client credentials: **Add a certificate or secret** or on the **Manage / Certificates & secrets** tab * Select the **Certificates** tab @@ -73,24 +73,24 @@ For additional information regarding the implement in Liberty, please refer to t 4. Add Claims. - In **Identity** / **Applications** / **App registrations**, select **ODM Application**, and in **Manage / Token Configuration**: + In **Microsoft Entra Id** / **Manage** / **App registrations**, select **ODM Application**, and in **Manage / Token Configuration**: - * Add Optional Email ID Claim + * Add Optional **email** ID Claim * Click **+ Add optional claim** * Select **ID** - * Check **Email** - * Click **Add** - - * Add Optional Email Access Claim - * Click **+ Add optional claim** - * Select **Access** - * Check **Email** + * Check **email** * Click **Add** * Turn on Microsoft Graph email permission * Check **Turn on the Microsoft Graph email permission** * Click **Add** + * Add Optional **email** Access Claim + * Click **+ Add optional claim** + * Select **Access** + * Check **email** + * Click **Add** + * Add Group Claim * Click **+ Add groups claim** * Check **Security Groups** @@ -99,7 +99,7 @@ For additional information regarding the implement in Liberty, please refer to t 5. Create a custom claim named "identity" To enable the ODM REST API to use both the 'Password Credentials' flow with email as the user identifier and the 'Client Credentials' flow with client_id as the user identifier, we must establish a new claim named "identity" that will dynamically capture the appropriate value based on the chosen flow: - In **Identity** / **Applications** / **Enterprise applications**, select **ODM Application**, and in **Manage / Single sign-on**: + In **Microsoft Entra Id** / **Manage** / **Enterprise applications**, select **ODM Application**, and in **Manage / Single sign-on**: * Click on Edit of the "Attributes & Claims" section * Click **+ Add new claim** @@ -110,21 +110,28 @@ For additional information regarding the implement in Liberty, please refer to t 6. API Permissions. - In **Identity** / **Applications** / **App Registration**, select **ODM Application**, and then click **API Permissions**. + In **Microsoft Entra Id** / **Manage** / **App Registration**, select **ODM Application**, and then click **API Permissions**. * Click **Grant Admin Consent for ** 7. Manifest change. - In **Identity** / **Applications** / **App Registration**, select **ODM Application**, and then click **Manifest**. + In **Microsoft Entra Id** / **Manage** / **App Registration**, select **ODM Application**, and then click **Manifest**. - As explained in [accessTokenAcceptedVersion attribute explanation](https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-app-manifest#accesstokenacceptedversion-attribute), change the value of **accessTokenAcceptedVersion** to `2`. + The Manifest feature (a JSON representation of an app registration) is currently in transition. + [**AAD Graph app manifest**](https://learn.microsoft.com/en-us/entra/identity-platform/azure-active-directory-graph-app-manifest-deprecation) will be deprecated soon and not editable anymore starting 12/2/2024. It will be replaced by the **Microsoft Graph App Manifest** + + As explained in [accessTokenAcceptedVersion attribute explanation](https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-app-manifest#accesstokenacceptedversion-attribute), change the value to 2. ODM OpenID Liberty configuration needs version 2.0 for the issuerIdentifier. See the [openIdWebSecurity.xml](templates/openIdWebSecurity.xml) file. - It is also necessary to set **acceptMappedClaims** to `true` to manage claims. Without this setting, you get the exception `AADSTS50146: This application is required to be configured with an application-specific signing key. It is either not configured with one, or the key has expired or is not yet valid.` when requesting a token. + It is also necessary to set **acceptMappedClaims** to true to manage claims. Without this setting, you get the exception **AADSTS50146: This application is required to be configured with an application-specific signing key. It is either not configured with one, or the key has expired or is not yet valid.** when requesting a token. + + With **Microsoft Graph App Manifest**: + * **acceptMappedClaims** is relocated as a property of the **api** attribute + * **accessTokenAcceptedVersion** is relocated as a property of the **api** attribute and renamed **requestedAccessTokenVersion** - Then, click Save. + Then, click Save. # Deploy ODM on a container configured with Microsoft Entra ID (Part 2) @@ -235,7 +242,7 @@ For additional information regarding the implement in Liberty, please refer to t ```shell helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION - ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager + ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### Run the `helm install` command @@ -247,7 +254,7 @@ You can now install the product. We will use the PostgreSQL internal database an See the [Preparing to install](https://www.ibm.com/docs/en/odm/9.0.0?topic=production-preparing-install-operational-decision-manager) documentation for additional information. ```shell - helm install my-odm-release ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ + helm install my-odm-release ibm-helm/ibm-odm-prod --version 24.1.0 \ --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ --set oidc.enabled=true \ --set license=true \ @@ -268,7 +275,7 @@ You can now install the product. We will use the PostgreSQL internal database an When the NGINX Ingress Controller is ready, you can install the ODM release with: ``` - helm install my-odm-release ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ + helm install my-odm-release ibm-helm/ibm-odm-prod --version 24.1.0 \ --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ --set oidc.enabled=true \ --set license=true \ @@ -334,7 +341,7 @@ You can now install the product. We will use the PostgreSQL internal database an - Decision Server Console redirect URI: `https:///res/openid/redirect/odm` - Decision Server Runtime redirect URI: `https:///DecisionService/openid/redirect/odm` - From the Azure console, in **Identity** / **Applications** / **App Registrations** / **ODM Application**: + From the Azure console, in **Microsoft Entra Id** / **Manage** / **App Registrations** / **ODM Application**: - Click`Add Redirect URIs link` - Click `Add Platform` @@ -352,7 +359,7 @@ You can now install the product. We will use the PostgreSQL internal database an The ODM Rule Designer will use the [PKCE authorization code flow](https://oauth.net/2/pkce/) to connect to Decision Center and Decision Server Console. - From the Azure console, in **Identity** / **Applications** / **App Registrations** / **ODM Application**: + From the Azure console, in **Microsoft Entra Id** / **Manage** / **App Registrations** / **ODM Application**: - Click`Add Redirect URIs link` - Click `Add Platform` @@ -406,11 +413,11 @@ To manage ODM runtime call on the next steps, we used the [Loan Validation Decis Import the **Loan Validation Service** in Decision Center connected using *myodmuser*@YOURDOMAIN created at step 2 -![Import project](../Keycloak/images/import_project.png) +![Import project](images/import_project.png) Deploy the **Loan Validation Service** production_deployment ruleapps using the **production deployment** deployment configuration in the Deployments>Configurations tab. -![Deploy project](../Keycloak/images/deploy_project.png) +![Deploy project](images/deploy_project.png) You can retrieve the payload.json from the ODM Decision Server Console or use [the provided payload](payload.json). @@ -419,7 +426,7 @@ As explained in the ODM on Certified Kubernetes documentation [Configuring user You can realize a basic authentication ODM runtime call the following way: ```shell -$ curl -H "Content-Type: application/json" -k --data @payload.json \ +curl -H "Content-Type: application/json" -k --data @payload.json \ -H "Authorization: Basic b2RtQWRtaW46b2RtQWRtaW4=" \ https:///DecisionService/rest/production_deployment/1.0/loan_validation_production/1.0 ``` @@ -431,20 +438,20 @@ But if you want to execute a bearer authentication ODM runtime call using the Cl Before to generate the client_assertion, you need a keystore.jks that will be build using the previously generated myodmcompany.key private key and myodmcompany.crt public key PEM files with the commands: ```shell -$ openssl pkcs12 -export -out myodmcompany.p12 -inkey myodmcompany.key -in myodmcompany.crt -passout pass:changeme +openssl pkcs12 -export -out myodmcompany.p12 -inkey myodmcompany.key -in myodmcompany.crt -passout pass:changeme keytool -importkeystore -srckeystore myodmcompany.p12 -srcstoretype pkcs12 -srcalias 1 -srcstorepass changeme -destkeystore myodmcompany.jks -deststoretype jks -deststorepass changeme -destalias myalias ``` Now you can generate the client_assertion following the [ODM documentation](https://www.ibm.com/docs/en/odm/9.0.0?topic=900-generating-json-web-token-client-assertion). ```shell -java -cp $DCLIB/jrules-teamserver.jar:$DCLIB/jose4j-0.9.3.jar:$DCLIB/slf4j-api-1.7.25.jar com.ibm.rules.oauth.ClientAssertionHelper -clientId -tokenEndpoint https://login.microsoftonline.com//oauth2/v2.0/token -keyAliasName myalias -keyStorePwd changeme -keyStoreLocation ./myodmcompany.jks +java -cp $DCLIB/jrules-teamserver.jar:$DCLIB/jose4j-0.9.5.jar:$DCLIB/slf4j-api-1.7.25.jar com.ibm.rules.oauth.ClientAssertionHelper -clientId -tokenEndpoint https://login.microsoftonline.com//oauth2/v2.0/token -keyAliasName myalias -keyStorePwd changeme -keyStoreLocation ./myodmcompany.jks ``` Now, generate the access token using the client_assertion: ```shell -$ curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded" \ +curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded" \ -d 'client_id=&scope=%2F.default&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=&grant_type=client_credentials' \ 'https://login.microsoftonline.com//oauth2/v2.0/token' ``` @@ -452,7 +459,7 @@ $ curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded" \ And use the retrieved access token in the following way: ```shell -$ curl -H "Content-Type: application/json" -k --data @payload.json \ +curl -H "Content-Type: application/json" -k --data @payload.json \ -H "Authorization: Bearer " \ https:///DecisionService/rest/production_deployment/1.0/loan_validation_production/1.0 ``` diff --git a/authentication/AzureAD/azuread-odm-script.zip b/authentication/AzureAD/azuread-odm-script.zip index bd8a47e4..6f5b6676 100644 Binary files a/authentication/AzureAD/azuread-odm-script.zip and b/authentication/AzureAD/azuread-odm-script.zip differ diff --git a/authentication/AzureAD/generate-user-group-mgt.sh b/authentication/AzureAD/generate-user-group-mgt.sh new file mode 100755 index 00000000..307d261f --- /dev/null +++ b/authentication/AzureAD/generate-user-group-mgt.sh @@ -0,0 +1,161 @@ +#!/bin/bash + +# Function to display help message +usage() { + echo "Usage: $0 -t TENANT_ID -i CLIENT_ID -x CLIENT_SECRET [-v]" + echo "Options:" + echo " -t Azure AD Tenant ID" + echo " -i Azure AD Client ID" + echo " -x Azure AD Client Secret" + echo " -v Enable verbose output to display extracted users and groups" + echo " -h Display this help message" + exit 1 +} + +# Initialize verbose flag +VERBOSE=false + +# Check if no arguments are passed +if [ "$#" -eq 0 ]; then + usage +fi + +# Parse command-line options +while getopts ":t:i:x:vh" opt; do + case $opt in + t) + TENANT_ID="$OPTARG" + ;; + i) + CLIENT_ID="$OPTARG" + ;; + x) + CLIENT_SECRET="$OPTARG" + ;; + v) + VERBOSE=true + ;; + h) + usage + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + usage + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + usage + ;; + esac +done + +# Check if all required parameters are provided +if [ -z "$TENANT_ID" ] || [ -z "$CLIENT_ID" ] || [ -z "$CLIENT_SECRET" ]; then + echo "Error: Missing required parameters." + usage +fi + +# Function to URL encode the data +urlencode() { + local length="${#1}" + for (( i = 0; i < length; i++ )); do + local c="${1:i:1}" + case $c in + [a-zA-Z0-9.~_-]) printf "$c" ;; + *) printf '%%%02X' "'$c" + esac + done +} + +# Step 1: Get Access Token +echo "Getting access token..." +ACCESS_TOKEN=$(curl -s --location --request POST "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \ +--header "Content-Type: application/x-www-form-urlencoded" \ +--data-urlencode "client_id=$CLIENT_ID" \ +--data-urlencode "scope=https://graph.microsoft.com/.default" \ +--data-urlencode "client_secret=$CLIENT_SECRET" \ +--data-urlencode "grant_type=client_credentials" | jq -r '.access_token') + +if [ -z "$ACCESS_TOKEN" ]; then + echo "Failed to obtain access token." + exit 1 +fi +echo $ACCESS_TOKEN + +# Step 2: Get User Data +echo "Fetching user data..." +USER_NAMES=$(curl -s --location --request GET "https://graph.microsoft.com/v1.0/users?\$select=mail,displayName,id" \ +--header "Authorization: Bearer $ACCESS_TOKEN") + +# Display users if verbose mode is enabled +if [ "$VERBOSE" = true ]; then + echo "Extracted Users:" + echo "$USER_NAMES" | jq -r '.value[] | "\(.displayName) (\(.mail))"' +fi + +# Step 3: Get Group Data +echo "Fetching group data..." +GROUP_ENTRAID=$(curl -s --location --request GET "https://graph.microsoft.com/v1.0/groups?\$select=displayName" --header "Authorization: Bearer $ACCESS_TOKEN") +GROUP_NAMES=$(echo $GROUP_ENTRAID | jq -r '.value[] | .displayName') +# Display groups if verbose mode is enabled +if [ "$VERBOSE" = true ]; then + echo "Extracted Groups:" + echo "Groups : $GROUP_NAMES" +fi + + +# Initialize the XML content +XML_CONTENT="" + +# Generate role and group XML +echo "Generating XML for roles and groups..." + +for group_name in $GROUP_NAMES; do + XML_CONTENT+="\n " +done + +# Process users +echo "Generating XML for users..." +USER_ENTRIES=$(echo $USER_NAMES | jq -c '.value[] | { id: .id , mail: .mail}') +for user in $USER_ENTRIES; do +# NAME=$(echo $user | jq -r '.name') + EMAIL=$(echo $user | jq -r '.mail') + ID=$(echo $user | jq -r '.id') + + GROUPS_FOR_USER=$(curl -s --location --request GET "https://graph.microsoft.com/v1.0/users/$ID/memberOf" \ +--header "Authorization: Bearer $ACCESS_TOKEN") + + # Use jq to extract displayName values, excluding "Global Administrator" + group_names_bis=$(echo "$GROUPS_FOR_USER" | jq -r '.value[].displayName' | grep -v "Global Administrator") + + # Join the group names with commas + commasGroups=$(echo "$group_names_bis" | paste -sd "," -) + # Iterate over the extracted displayName values + if [ "$VERBOSE" = true ]; then + echo "GROUPS FOR USER : $EMAIL --> $commasGroups" + fi + + + # Add user XML entry + XML_CONTENT+="\n " +done + +# Close the XML +XML_CONTENT+="\n" + +# Output the XML to a file +echo "Writing XML to output file..." +echo -e "$XML_CONTENT" > /tmp/group-security-configurations.xml + +echo "Script completed. XML file 'group-security-configurations.xml' generated successfully." + +echo "Getting ODM access token..." +ODM_ACCESS_TOKEN=$(curl -s --location --request POST "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \ +--header "Content-Type: application/x-www-form-urlencoded" \ +--data-urlencode "client_id=$CLIENT_ID" \ +--data-urlencode "scope=$CLIENT_ID/.default" \ +--data-urlencode "client_secret=$CLIENT_SECRET" \ +--data-urlencode "grant_type=client_credentials" | jq -r '.access_token') + +echo "Calling /v1/repository/users-roles-registry Decision Center Endpoint..." +curl -X 'POST' 'http://localhost:9060/decisioncenter-api/v1/repository/users-roles-registry?eraseAllUsersAndGroups=true' -H 'accept: */*' -H 'Content-Type: multipart/form-data' -F 'file=@/tmp/group-security-configurations.xml;type=text/xml' -H "Authorization: Bearer $ODM_ACCESS_TOKEN" diff --git a/authentication/AzureAD/generateTemplate.sh b/authentication/AzureAD/generateTemplate.sh index c8f3d5e6..f7b38401 100755 --- a/authentication/AzureAD/generateTemplate.sh +++ b/authentication/AzureAD/generateTemplate.sh @@ -28,10 +28,10 @@ Options: -g : AZUREAD ODM Group ID -i : Client ID --n : AZUREAD domain (AZUREAD server name) +-n : Tenant ID -x : Cient Secret -a : Allow others domains (Optional) -Usage example: $0 -i AzureADClientId -x AzureADClientSecret -n -g [-a ]" +Usage example: $0 -i AzureADClientId -x AzureADClientSecret -n AzureADTenantId -g [-a ]" EOF } @@ -39,7 +39,7 @@ while getopts "x:i:n:s:g:ha:" option; do case "${option}" in g) AZUREAD_ODM_GROUP_ID=${OPTARG};; i) AZUREAD_CLIENT_ID=${OPTARG};; - n) AZUREAD_SERVER_NAME=${OPTARG};; + n) AZUREAD_TENANT_ID=${OPTARG};; x) AZUREAD_CLIENT_SECRET=${OPTARG};; a) ALLOW_DOMAIN=${OPTARG};; h) usage; exit 0;; @@ -55,8 +55,8 @@ if [[ -z ${AZUREAD_CLIENT_ID} ]]; then echo "AZUREAD_CLIENT_ID has to be provided, either as in environment or with -i." exit 1 fi -if [[ -z ${AZUREAD_SERVER_NAME} ]]; then - echo "AZUREAD_SERVER_NAME has to be provided, either as in environment or with -n." +if [[ -z ${AZUREAD_TENANT_ID} ]]; then + echo "AZUREAD_TENANT_ID has to be provided, either as in environment or with -n." exit 1 fi if [[ -z ${AZUREAD_CLIENT_SECRET} ]]; then @@ -64,10 +64,10 @@ if [[ -z ${AZUREAD_CLIENT_SECRET} ]]; then exit 1 fi -if [[ ${AZUREAD_SERVER_NAME} != "https://.*" ]]; then - AZUREAD_SERVER_URL=https://login.microsoftonline.com/${AZUREAD_SERVER_NAME} +if [[ ${AZUREAD_TENANT_ID} != "https://.*" ]]; then + AZUREAD_SERVER_URL=https://login.microsoftonline.com/${AZUREAD_TENANT_ID} else - AZUREAD_SERVER_URL=${AZUREAD_SERVER_NAME} + AZUREAD_SERVER_URL=${AZUREAD_TENANT_ID} fi mkdir -p $OUTPUT_DIR && cp $TEMPLATE_DIR/* $OUTPUT_DIR @@ -76,6 +76,7 @@ sed -i.bak 's|AZUREAD_CLIENT_ID|'$AZUREAD_CLIENT_ID'|g' $OUTPUT_DIR/* sed -i.bak 's|AZUREAD_CLIENT_SECRET|'$AZUREAD_CLIENT_SECRET'|g' $OUTPUT_DIR/* sed -i.bak 's|AZUREAD_ODM_GROUP_ID|'$AZUREAD_ODM_GROUP_ID'|g' $OUTPUT_DIR/* sed -i.bak 's|AZUREAD_SERVER_URL|'$AZUREAD_SERVER_URL'|g' $OUTPUT_DIR/* +sed -i.bak 's|AZUREAD_TENANT_ID|'$AZUREAD_TENANT_ID'|g' $OUTPUT_DIR/* # Claim replacement sed -i.bak 's|AZUREAD_CLAIM_GROUPS|'$AZUREAD_CLAIM_GROUPS'|g' $OUTPUT_DIR/* sed -i.bak 's|AZUREAD_CLAIM_LOGIN|'$AZUREAD_CLAIM_LOGIN'|g' $OUTPUT_DIR/* diff --git a/authentication/AzureAD/generateTemplateForPrivateKeyJWT.sh b/authentication/AzureAD/generateTemplateForPrivateKeyJWT.sh index 4b71dd83..217fd74f 100755 --- a/authentication/AzureAD/generateTemplateForPrivateKeyJWT.sh +++ b/authentication/AzureAD/generateTemplateForPrivateKeyJWT.sh @@ -28,9 +28,9 @@ Options: -g : AZUREAD ODM Group ID -i : Client ID --n : AZUREAD domain (AZUREAD server name) +-n : Tenant ID -a : Allow others domains (Optional) -Usage example: $0 -i AzureADClientId -n -g [-a ]" +Usage example: $0 -i AzureADClientId -n TenantId -g [-a ]" EOF } @@ -38,7 +38,7 @@ while getopts "x:i:n:s:g:ha:" option; do case "${option}" in g) AZUREAD_ODM_GROUP_ID=${OPTARG};; i) AZUREAD_CLIENT_ID=${OPTARG};; - n) AZUREAD_SERVER_NAME=${OPTARG};; + n) AZUREAD_TENANT_ID=${OPTARG};; a) ALLOW_DOMAIN=${OPTARG};; h) usage; exit 0;; *) usage; exit 1;; @@ -53,15 +53,15 @@ if [[ -z ${AZUREAD_CLIENT_ID} ]]; then echo "AZUREAD_CLIENT_ID has to be provided, either as in environment or with -i." exit 1 fi -if [[ -z ${AZUREAD_SERVER_NAME} ]]; then - echo "AZUREAD_SERVER_NAME has to be provided, either as in environment or with -n." +if [[ -z ${AZUREAD_TENANT_ID} ]]; then + echo "AZUREAD_TENANT_ID has to be provided, either as in environment or with -n." exit 1 fi -if [[ ${AZUREAD_SERVER_NAME} != "https://.*" ]]; then - AZUREAD_SERVER_URL=https://login.microsoftonline.com/${AZUREAD_SERVER_NAME} +if [[ ${AZUREAD_TENANT_ID} != "https://.*" ]]; then + AZUREAD_SERVER_URL=https://login.microsoftonline.com/${AZUREAD_TENANT_ID} else - AZUREAD_SERVER_URL=${AZUREAD_SERVER_NAME} + AZUREAD_SERVER_URL=${AZUREAD_TENANT_ID} fi mkdir -p $OUTPUT_DIR && cp $TEMPLATE_DIR/* $OUTPUT_DIR @@ -69,6 +69,7 @@ echo "Generating files for AZUREAD" sed -i.bak 's|AZUREAD_CLIENT_ID|'$AZUREAD_CLIENT_ID'|g' $OUTPUT_DIR/* sed -i.bak 's|AZUREAD_ODM_GROUP_ID|'$AZUREAD_ODM_GROUP_ID'|g' $OUTPUT_DIR/* sed -i.bak 's|AZUREAD_SERVER_URL|'$AZUREAD_SERVER_URL'|g' $OUTPUT_DIR/* +sed -i.bak 's|AZUREAD_TENANT_ID|'$AZUREAD_TENANT_ID'|g' $OUTPUT_DIR/* # Claim replacement sed -i.bak 's|AZUREAD_CLAIM_GROUPS|'$AZUREAD_CLAIM_GROUPS'|g' $OUTPUT_DIR/* sed -i.bak 's|AZUREAD_CLAIM_LOGIN|'$AZUREAD_CLAIM_LOGIN'|g' $OUTPUT_DIR/* diff --git a/authentication/AzureAD/images/deploy_project.png b/authentication/AzureAD/images/deploy_project.png new file mode 100644 index 00000000..686a2f46 Binary files /dev/null and b/authentication/AzureAD/images/deploy_project.png differ diff --git a/authentication/AzureAD/images/import_project.png b/authentication/AzureAD/images/import_project.png new file mode 100644 index 00000000..a2205ac3 Binary files /dev/null and b/authentication/AzureAD/images/import_project.png differ diff --git a/authentication/AzureAD/templates/openIdWebSecurity.xml b/authentication/AzureAD/templates/openIdWebSecurity.xml index d7b92fba..0362a326 100644 --- a/authentication/AzureAD/templates/openIdWebSecurity.xml +++ b/authentication/AzureAD/templates/openIdWebSecurity.xml @@ -6,7 +6,7 @@ @@ -19,7 +19,7 @@ clientId="AZUREAD_CLIENT_ID" signatureAlgorithm="RS256" inboundPropagation="required" jwkEndpointUrl="${ServerHost}/discovery/v2.0/keys" - issuerIdentifier="${ServerHost}/v2.0" + issuerIdentifier="${ServerHost}/v2.0" tokenReuse="true" authorizationEndpointUrl="${ServerHost}/oauth2/v2.0/authorize" tokenEndpointUrl="${ServerHost}/oauth2/v2.0/token" userIdentifier="identity" groupIdentifier="groups" audiences="ALL_AUDIENCES"/> diff --git a/authentication/Cognito/README.md b/authentication/Cognito/README.md index 86c5f3ca..fb8a87d7 100644 --- a/authentication/Cognito/README.md +++ b/authentication/Cognito/README.md @@ -505,7 +505,7 @@ In the **Container software library** tile, verify your entitlement on the **Vie ```shell helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION - ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager + ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### 3. Run the `helm install` command @@ -516,7 +516,7 @@ In the **Container software library** tile, verify your entitlement on the **Vie See the [Preparing to install](https://www.ibm.com/docs/en/odm/9.0.0?topic=production-preparing-install-operational-decision-manager) documentation for more information. ```shell - helm install my-odm-release ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ + helm install my-odm-release ibm-helm/ibm-odm-prod --version 24.1.0 \ --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ --set oidc.enabled=true \ --set license=true \ @@ -536,7 +536,7 @@ In the **Container software library** tile, verify your entitlement on the **Vie When the NGINX Ingress Controller is ready, you can install the ODM release with: ``` - helm install my-odm-release ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ + helm install my-odm-release ibm-helm/ibm-odm-prod --version 24.1.0 \ --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ --set oidc.enabled=true \ --set license=true \ diff --git a/authentication/Keycloak/README.md b/authentication/Keycloak/README.md index 9703f53a..c43a189f 100644 --- a/authentication/Keycloak/README.md +++ b/authentication/Keycloak/README.md @@ -38,8 +38,8 @@ In the context of the Operational Decision Manager (ODM) on Certified Kubernetes offering, ODM for production can be configured with an external OpenID Connect server (OIDC provider), such as the Keycloak cloud service. -This tutorial is showing how to realize an integration of ODM with Keycloak to manage classic authentication and authorization. -An other tutorial explains how to manage [fine grain permission with Decision Center by using a Keycloak SCIM Server](README_FINE_GRAIN_PERMISSION.md). +This tutorial shows how to integrate ODM with Keycloak to manage classic authentication and authorization. +Another tutorial explains how to manage [fine grain permission with Decision Center by using a Keycloak SCIM Server](README_FINE_GRAIN_PERMISSION.md). ## What is Keycloak? @@ -92,7 +92,7 @@ You need the following elements: ### Install a Keycloak instance -We have tested with a Keycloak instance (version 24.0.3) that is installed on Openshift. The installation procedure can be found at [Get started with Keycloak on Openshift](https://www.keycloak.org/getting-started/getting-started-openshift). +This tutorial has been tested with a Keycloak instance version 26.0.5 installed on Openshift. The installation procedure can be found at [Get started with Keycloak on Openshift](https://www.keycloak.org/getting-started/getting-started-openshift). If you already have an Openshift cluster, you can skip the section [Before you start](https://www.keycloak.org/getting-started/getting-started-openshift#_before_you_start) and use the following steps: - oc login to your cluster @@ -100,7 +100,14 @@ If you already have an Openshift cluster, you can skip the section [Before you s ```shell oc new-project keycloak ``` -- Continue from the section [Start Keycloak](https://www.keycloak.org/getting-started/getting-started-openshift#_start_keycloak) +- Continue from the section [Start Keycloak](https://www.keycloak.org/getting-started/getting-started-openshift#_start_keycloak) using the file [keycloak.yaml](keycloak.yaml) instead of the one online as suggested at the first step (which may prevent from accessing the console behind a proxy), ie.: + ```shell + oc process -f keycloak.yaml \ + -p KEYCLOAK_ADMIN=admin \ + -p KEYCLOAK_ADMIN_PASSWORD=admin \ + -p NAMESPACE=keycloak \ + | oc create -f - + ``` If you want to install on another Kubernetes platform, follow these instructions: [Get started with Keycloak on Kubernetes](https://www.keycloak.org/getting-started/getting-started-kube). @@ -143,10 +150,9 @@ But to avoid getting mixing up with existing configurations, it is preferable to ## Manage roles, groups, and users -As explained in [Keycloak documentation](https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-using-roles-and-groups), roles and groups have a similar purpose, which is to give users access and permissions to use applications. Groups are collections of users to which you apply roles and attributes. Roles define specific application permissions and access control. -To manage permissions inside the ODM application, the ID token and access token contain all the roles that are gather in a property named groups. -So, you can only create roles and provide these roles to a user. -You can also create groups and do a mapping between groups and roles. This way, adding a user to a group will grant them the roles mapped to this group. This is what we are applying here. +As explained in [Keycloak documentation](https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-using-roles-and-groups), groups and roles enables to give users access and permissions to use applications. Groups are collections of users to which you apply roles and attributes. Roles define specific application permissions and access control. +To manage permissions inside the ODM application, the ID token and access token contain a property (aka claim) named 'groups' listing all the roles granted to the identified user. +You can create roles and grant these roles directly to an individual user, or even better to a group. This way, all the users of the group are granted the roles of the group. 1. Create a role for ODM administrators. @@ -181,6 +187,7 @@ You can also create groups and do a mapping between groups and roles. This way, * Click **Create odm-admin** * Click the **Role mapping** tab * Click **Assign role** + * Select "Filter by realm roles" * Select all previously created ODM roles * Click **Assign** @@ -203,12 +210,12 @@ You can also create groups and do a mapping between groups and roles. This way, ![Create User](images/create_user.png) * In User Details, select the **Credentials** tab - * Click **Set password** + * Click **Set password** * Fill the Password and Password confirmation fields with **johndoe** - * Temporary: Off - * Click *Save Password* - * Click Details tab - * Click **Save** + * Temporary: Off + * Click *Save Password* + * Click the **Details** tab + * Click **Save** (Optional) Every user is created with a predefined role named **default-roles-**. This role has no interest. So, here is the way to unassign this role. @@ -217,10 +224,12 @@ You can also create groups and do a mapping between groups and roles. This way, * Select **default-roles-** * Click **Unassign** * Click **Remove** + * Click the **Details** tab + * Click **Save** ![Unassign default role](images/unassign_default_role.png) - Repeat this step for each user you want to add. + Repeat those steps for each user you want to add. ## Set up the client @@ -230,34 +239,38 @@ You can also create groups and do a mapping between groups and roles. This way, * Client type: **OpenID Connect** * Client ID: **odm** * Name: **ODM Application** - * Always display in UI: On + * Always display in console: On + * Click **Next** ![Create Client 1](images/create_client_1.png) - * Click **Next** * Client Authentication: On * Authorization: On + * Click **Next** or **Save** ![Create Client 2](images/create_client_2.png) - * Click *Save*. For newer version of Keycloak with an addition *Login settings* page, click **Next** to go to this third page, and then click *Save* + * Newer versions of Keycloak display the additional *Login settings* page below. If you can see it, just click **Save**. ![Create Client 3](images/create_client_3.png) - * Click **Credentials** tab + * Click the **Credentials** tab * Take a note of the **Client secret** value. It will be referenced as ``CLIENT_SECRET`` in the next steps. ![Get Client Secret](images/client_secret.png) - * Click **Service Account Roles** tab - * Click the **Assign role** button. Select all res* and rts* roles in the list and click on "Assign" button. + * Click the **Service account roles** tab + * Click the **Assign role** button. + * Select **Filter by realm roles** + * Select all res* and rts* roles in the list and click the **Assign** button. ![Set Service Account Roles](images/assign_service_account_roles.png) 2. Add the GROUPS predefined mapper on the ROLES client scope - In Menu **Manage** / **Client scopes**, click the existing **roles** scope: + * Select the **Manage** / **Client scopes** menu + * click the **roles** scope * Select the **Mappers** tab * Click **Add mapper>From predefined mappers** * Search for mapper : **groups** @@ -277,13 +290,13 @@ You can also create groups and do a mapping between groups and roles. This way, Download the [keycloak-odm-script.zip](keycloak-odm-script.zip) file to your machine and unzip it in your working directory. This .zip file contains scripts and templates to verify and set up ODM. - 7.1 Verify the Client Credentials Token + 4.1 Verify the Client Credentials Token You can request an access token using the Client-Credentials flow to verify the format of the token. This token is used for the deployment between Decision Center and the Decision Server Console: ```shell - $ ./get-client-credential-token.sh -i -x -n + ./get-client-credential-token.sh -i $CLIENT_ID -x $CLIENT_SECRET -n $KEYCLOAK_SERVER_URL ``` Where: @@ -304,21 +317,21 @@ You can also create groups and do a mapping between groups and roles. This way, } ``` - 7.2 Verify the Client Password Token + 4.2 Verify the Client Password Token To check that it has been correctly taken into account, you can request an access token using the Client password flow. This token is used for the invocation of the ODM components like the Decision Center, Decision Server console, and the invocation of the Decision Server Runtime REST API. ```shell - $ ./get-user-password-token.sh -i -x -n -u -p + ./get-user-password-token.sh -i $CLIENT_ID -x $CLIENT_SECRET -n $KEYCLOAK_SERVER_URL -u -p ``` Where: - *CLIENT_ID* is your ODM Application, default is odm, can be retrieved in the **Manage** / **Clients** menu - *CLIENT_SECRET* is listed in your ODM Application, in the **Credentials** tab - *KEYCLOAK_SERVER_URL* is the issuer that can be retrieved using the **OpenID Endpoint Configuration** link of the **General** tab in the **Configure**/**Realm settings** menu - - *USERNAME* *PASSWORD* have been created from 'Create at least one user that belongs to this new group.' section. + - *USERNAME* and *PASSWORD* have been created from 'Create at least one user that belongs to this new group.' section. By introspecting the id_token value with the online tool [https://jwt.io](https://jwt.io), you should get: @@ -355,7 +368,7 @@ You can also create groups and do a mapping between groups and roles. This way, 2. Create a pull secret by running a `kubectl create secret` command. ```shell - $ kubectl create secret docker-registry icregistry-secret \ + kubectl create secret docker-registry icregistry-secret \ --docker-server=cp.icr.io \ --docker-username=cp \ --docker-password="" \ @@ -384,20 +397,22 @@ You can also create groups and do a mapping between groups and roles. This way, kubectl create secret generic keycloak-secret --from-file=tls.crt=keycloak.crt ``` Where: - - KEYCLOAK_SERVER_URL_WITHOUT_HTTPS is KEYCLOAK_SERVER_URL by removing https:// prefix + - KEYCLOAK_SERVER_URL_WITHOUT_HTTPS is KEYCLOAK_SERVER_URL without the leading `https://` 2. Generate the ODM configuration file for Keycloak. - If you have not yet done so, download the [keycloak-odm-script.zip](keycloak-odm-script.zip) file to your machine. This .zip file contains the [script](generateTemplate.sh) and the content of the [templates](templates) directory. + If you have not done it yet, download the [keycloak-odm-script.zip](keycloak-odm-script.zip) file to your machine. This .zip file contains the [script](generateTemplate.sh) and the content of the [templates](templates) directory. The [script](generateTemplate.sh) allows you to generate the necessary configuration files. Generate the files with the following command: ```shell - ./generateTemplate.sh -i -x -n [-r -u ] + ./generateTemplate.sh -i $CLIENT_ID -x $CLIENT_SECRET -n $KEYCLOAK_SERVER_URL [-r $REALM_NAME -u $USERID_CLAIM] ``` Where: - *CLIENT_SECRET* is listed in your ODM Application, section **General** / **Client Credentials** + - *REALM_NAME* is optional (**odm** by default) + - *USERID_CLAIM* is optional (**preferred_username** by default). This is the name of the claim (ie. parameter) in the token that holds the name of the user. The following files are generated into the `output` directory: @@ -432,8 +447,11 @@ You can also create groups and do a mapping between groups and roles. This way, ```shell helm search repo ibm-odm-prod + ``` + The output should look like: + ```shell NAME CHART VERSION APP VERSION DESCRIPTION - ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager + ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### 3. Run the `helm install` command @@ -445,15 +463,16 @@ You can now install the product. We will use the PostgreSQL internal database an See the [Preparing to install](https://www.ibm.com/docs/en/odm/9.0.0?topic=production-preparing-install-operational-decision-manager) documentation for more information. ```shell - helm install my-odm-release ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ - --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ - --set oidc.enabled=true \ - --set license=true \ - --set internalDatabase.persistence.enabled=false \ - --set decisionCenter.disableAllAuthenticatedUser=true \ - --set customization.trustedCertificateList={"keycloak-secret"} \ - --set customization.authSecretRef=keycloak-auth-secret \ - --set internalDatabase.runAsUser='' --set customization.runAsUser='' --set service.enableRoute=true + helm install my-odm-release ibm-helm/ibm-odm-prod \ + --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ + --set oidc.enabled=true \ + --set license=true \ + --set internalDatabase.persistence.enabled=false \ + --set internalDatabase.populateSampleData=true \ + --set decisionCenter.disableAllAuthenticatedUser=true \ + --set customization.trustedCertificateList={"keycloak-secret"} \ + --set customization.authSecretRef=keycloak-auth-secret \ + --set internalDatabase.runAsUser='' --set customization.runAsUser='' --set service.enableRoute=true ``` #### b. Installation using Ingress @@ -466,16 +485,17 @@ You can now install the product. We will use the PostgreSQL internal database an When the NGINX Ingress Controller is ready, you can install the ODM release with: ```shell - helm install my-odm-release ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ - --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ - --set oidc.enabled=true \ - --set license=true \ - --set internalDatabase.persistence.enabled=false \ - --set customization.trustedCertificateList={"keycloak-secret"} \ - --set customization.authSecretRef=keycloak-auth-secret \ - --set service.ingress.enabled=true \ - --set decisionCenter.disableAllAuthenticatedUser=true \ - --set service.ingress.annotations={"kubernetes.io/ingress.class: nginx"\,"nginx.ingress.kubernetes.io/backend-protocol: HTTPS"\,"nginx.ingress.kubernetes.io/affinity: cookie"} + helm install my-odm-release ibm-helm/ibm-odm-prod \ + --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ + --set oidc.enabled=true \ + --set license=true \ + --set internalDatabase.persistence.enabled=false \ + --set internalDatabase.populateSampleData=true \ + --set customization.trustedCertificateList={"keycloak-secret"} \ + --set customization.authSecretRef=keycloak-auth-secret \ + --set service.ingress.enabled=true \ + --set decisionCenter.disableAllAuthenticatedUser=true \ + --set service.ingress.annotations={"kubernetes.io/ingress.class: nginx"\,"nginx.ingress.kubernetes.io/backend-protocol: HTTPS"\,"nginx.ingress.kubernetes.io/affinity: cookie"} ``` ## Complete post-deployment tasks @@ -591,7 +611,7 @@ As explained in the ODM on Certified Kubernetes documentation [Configuring user You perform a basic authentication ODM runtime call in the following way: ``` - $ curl -H "Content-Type: application/json" -k --data @payload.json \ + curl -H "Content-Type: application/json" -k --data @payload.json \ -H "Authorization: Basic b2RtQWRtaW46b2RtQWRtaW4=" \ https:///DecisionService/rest/production_deployment/1.0/loan_validation_production/1.0 ``` @@ -601,7 +621,7 @@ You perform a basic authentication ODM runtime call in the following way: If you want to perform a bearer authentication ODM runtime call using the Client Credentials flow, you must get a bearer access token: ``` - $ curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded" \ + curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded" \ -d 'client_id=&scope=openid&client_secret=&grant_type=client_credentials' \ '/protocol/openid-connect/token' ``` @@ -609,7 +629,7 @@ If you want to perform a bearer authentication ODM runtime call using the Client And use the retrieved access token in the following way: ``` - $ curl -H "Content-Type: application/json" -k --data @payload.json \ + curl -H "Content-Type: application/json" -k --data @payload.json \ -H "Authorization: Bearer " \ https:///DecisionService/rest/production_deployment/1.0/loan_validation_production/1.0 ``` diff --git a/authentication/Keycloak/README_FINE_GRAIN_PERMISSION.md b/authentication/Keycloak/README_FINE_GRAIN_PERMISSION.md index 4d8c4b1d..fe052bd3 100644 --- a/authentication/Keycloak/README_FINE_GRAIN_PERMISSION.md +++ b/authentication/Keycloak/README_FINE_GRAIN_PERMISSION.md @@ -4,7 +4,7 @@ - [Introduction](#introduction) - [Deploy on OpenShift a custom Keycloak service with a SCIM Server](#deploy-on-openShift-a-custom-keycloak-service-with-a-scim-server) - - [Build the Keycloak docker image embbeding the open source SCIM plug-in](#build-the-keycloak-docker-image-embbeding-the-open-source-scim-plug-in) + - [Build the Keycloak docker image embedding the open source SCIM plug-in](#build-the-keycloak-docker-image-embedding-the-open-source-scim-plug-in) - [Push the image on the OpenShift Cluster](#push-the-image-on-the-openShift-cluster) - [Deploy Keycloak Service using the keycloak-scim image](#deploy-keycloak-service-using-the-keycloak-scim-image) - [Configure an ODM Application with Keycloak dashboard](#configure-an-odm-application-with-keycloak-dashboard) @@ -21,7 +21,7 @@ - [Import Groups and Users](#import-groups-and-users) - [Set the project security](#set-the-project-security) - [Check the project security](#check-the-project-security) -- [Synchonize Decision Center when updating Keycloak](#synchonize-decision-center-when-updating-keycloak) +- [Synchronize Decision Center when updating Keycloak](#synchronize-decision-center-when-updating-keycloak) @@ -32,56 +32,65 @@ The Groups and Users import can be done using an LDAP connection. But, if the openId server also provides a SCIM server, then it can also be managed using a SCIM connection. Keycloak server doesn't provide a SCIM server by default. But, it's possible to manage it using the following opensource contribution [https://github.com/Captain-P-Goldfish/scim-for-keycloak](https://github.com/Captain-P-Goldfish/scim-for-keycloak). -As the project [https://scim-for-keycloak.de/](https://scim-for-keycloak.de) will become Enterprise ready soon, we realized this tutorial using the last available open source version : kc-20-b1 for Keycloak 20.0.5. +As the project [https://scim-for-keycloak.de/](https://scim-for-keycloak.de) will become Enterprise ready soon, this tutorial was performed using the last available open source version : kc-20-b1 for Keycloak 20.0.5. # Deploy on OpenShift a custom Keycloak service with a SCIM Server -## Build the Keycloak docker image embbeding the open source SCIM plug-in +## Build the Keycloak docker image embedding the open source SCIM plug-in - Get the [SCIM for Keycloak scim-for-keycloak-kc-20-b1.jar file](https://github.com/Captain-P-Goldfish/scim-for-keycloak/releases/download/kc-20-b1/scim-for-keycloak-kc-20-b1.jar) - Get the [Dockerfile](Dockerfile) - Build the image locally: -```shell - docker build . --build-arg KEYCLOAK_IMAGE=quay.io/keycloak/keycloak:20.0.5 --build-arg SCIM_JAR_FILE=scim-for-keycloak-kc-20-b1.jar -t keycloak-scim:latest -``` + ```shell + docker build . --build-arg KEYCLOAK_IMAGE=quay.io/keycloak/keycloak:20.0.5 --build-arg SCIM_JAR_FILE=scim-for-keycloak-kc-20-b1.jar -t keycloak-scim:latest + ``` + + > Note: + > The build command produces an image suitable to the architecture (amd64, ...) of the machine where the build is performed. + > + > Make sure that the architecture of the cluster is the same. + > If not, you may consider using `docker buildx build --platform=linux/${ARCH} ...` to build an image suitable to the target architecture. + ## Push the image on the OpenShift Cluster - Log on your OCP Cluster - Expose the Docker image registry: -```shell - oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge -``` + ```shell + oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge + ``` - Log into it: -```shell - REGISTRY_HOST=$(oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}') - docker login -u kubeadmin -p $(oc whoami -t) $REGISTRY_HOST -``` + ```shell + REGISTRY_HOST=$(oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}') + docker login -u kubeadmin -p $(oc whoami -t) $REGISTRY_HOST + ``` - Upload the keycloak-scim:latest on the wanted : -```shell - docker tag keycloak-scim:latest $REGISTRY_HOST//keycloak-scim:latest - docker push $REGISTRY_HOST//keycloak-scim:latest -``` - -Note: To avoid an error on the image push, perhaps you will have to add $REGISTRY_HOST to your Docker insecure-registries list configuration. - With podman, you have to create a myregistry.conf file in the /etc/containers/registries.conf.d folder like: + ```shell + docker tag keycloak-scim:latest $REGISTRY_HOST//keycloak-scim:latest + docker push $REGISTRY_HOST//keycloak-scim:latest + ``` - [[registry]] - location = "$REGISTRY_HOST" - insecure = true +>Note: To avoid an error on the image push, perhaps you will have to add $REGISTRY_HOST to your Docker insecure-registries list configuration. +> +> For instance, if you use podman, you have to create a myregistry.conf file in the /etc/containers/registries.conf.d folder (inside the virtual machine on Windows or Mac) with the content below: +> ``` +> [[registry]] +> location = "$REGISTRY_HOST" +> insecure = true +> ``` ## Deploy Keycloak Service using the keycloak-scim image -- Get the [keycloak.yaml](https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/latest/openshift/keycloak.yaml) file +- Get the [keycloak.yaml](https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/refs/heads/main/openshift/keycloak.yaml) file - Replace the provided image: input using image-registry.openshift-image-registry.svc:5000/\/keycloak-scim:latest -```shell + ```shell ... spec: containers: @@ -94,17 +103,17 @@ Note: To avoid an error on the image push, perhaps you will have to add $REGISTR value: 'edge' image: image-registry.openshift-image-registry.svc:5000//keycloak-scim:latest ... -``` + ``` - Deploy keycloak: -```shell + ```shell oc process -f ./keycloak.yaml \ -p KEYCLOAK_ADMIN=admin \ -p KEYCLOAK_ADMIN_PASSWORD=admin \ -p NAMESPACE= \ -| oc create -f - -``` + | oc create -f - + ``` # Configure an ODM Application with Keycloak dashboard You must start with the configuration of Keycloak with ODM roles as instructed in [Keycloak instance for ODM (Part 1)](README.md#configure-a-keycloak-instance-for-odm-part-1). @@ -112,7 +121,7 @@ You must start with the configuration of Keycloak with ODM roles as instructed i # Deploy an Open LDAP Service -- Create a Service Account with the anyuid policy +- Create a Service Account with the `anyuid` policy ```shell oc apply -f ./openldap/service-account-for-anyuid.yaml @@ -136,31 +145,31 @@ oc apply -f ./openldap/ldap-service.yaml The following command should return the OpenLDAP Schema : ```shell -oc exec -ti bash -- ldapsearch -x -Z -H ldap://ldap-service..svc:389 -D 'cn=admin,dc=example,dc=org' -b 'dc=example,dc=org' -w xNxICc74qG24x3GoW03n +oc exec -ti bash -- ldapsearch -x -Z -H ldap://ldap-service..svc:389 -D 'cn=admin,dc=example,dc=org' -b 'dc=example,dc=org' -w xNxICc74qG24x3GoW03n ``` Where: - OPENLDAP_POD is the name of the OpenLDAP pod - - PROJECT is the name of the current project + - OPENLDAP_PROJECT is the name of the project in which the OpenLDAP pod has been deployed # Add an LDAP User Federation to Keycloak -- Connect at the Keycloak Admin Dashboard using the odm realm with login/pass `admin/admin` -- Select "User federation" and click Add Provider > LDAP +- Connect at the Keycloak Admin Dashboard using the odm realm with username/password `admin/admin` +- Select **Configure > User federation** and click **Add Provider > Add Ldap providers** -- Fill "Add LDAP provider" dialog +- Fill the **Add LDAP provider** dialog * General options * Console display name: openldap * Vendor: "Red Hat Directory Server" * Connection and authentication settings - * Connection URL should be: ldap://ldap-service.\.svc:389 (PROJECT is the name of the current project) + * Connection URL should be: ldap://ldap-service.\.svc:389 (when OPENLDAP_PROJECT is the project in which OpenLdap has been deployed) * Bind type: simple * Bind DN: cn=admin,dc=example,dc=org * Bind credentials: xNxICc74qG24x3GoW03n -- Click on the "Test authentication" button => "Successfully connected to LDAP" message is displayed +- Click the **Test authentication** button => "Successfully connected to LDAP" message is displayed * LDAP searching and updating * Edit mode: READ_ONLY @@ -195,14 +204,14 @@ Where: - Click on the "Save" button - At this step, all openldap users have been imported. You can check it by clicking on the "Users" tab, put "*" in the Search user box and click on the search button. + At this step, all openldap users have been imported. You can check it by clicking on the **Users** tab, put "*" in the Search user box and click on the search button. You should see: ![OpenLdap Users Import](images/import_openldap_users.png) - Now, we will import groups. + Now let's import groups. - - Edit the "openldap" User federation + - In **User federation**, click **openldap** - Click on the "Mappers" tab - Click "Add mapper" * Name: groups @@ -223,10 +232,10 @@ Where: * Drop non-existing groups during sync: Off * Groups Path: / - - Click the "Save" button - - Click on Action>Sync All users + - Click the **Save** button + - Click **Action > Sync All users** - Now you can check the openldap groups have been imported using the Groups tab. You should see : + Now you can check the openldap groups have been imported in the **Groups** tab. You should see : ![OpenLdap Groups Import](images/import_openldap_groups.png) @@ -236,13 +245,13 @@ Where: ## Enable the SCIM Console Theme To access the SCIM Configuration User Interface, you have to change the Admin Console Theme. - If you are in the "odm" realm, you need to go back to the "master" realm before to do: - - Select the "Realm settings" Menu - - Select the "Themes" Tab - - Select "scim" for the "Admin console theme" - - Click the "Save" button => the "Realm sucessfully updated" message is displayed + If you are in the **odm** realm, you need to switch to the **master** realm beforehand. Then: + - Select the **Realm settings** Menu + - Select the **Themes** Tab + - Select **scim** for the **Admin console theme** + - Click the **Save** button => the "Realm successfully updated" message is displayed - Refresh the browser page => a "Page not found..." message is displayed - - Click on the "Go to the home page >>" hyperlink + - Click the "Go to the home page >>" hyperlink Now, the Admin console theme has changed and you should be able to access the SCIM Configuration tab : @@ -250,14 +259,14 @@ Where: ## Configure the odm client application authorization - - Select the "Service Provider" tab + - Select the **Service Provider** tab - - Select "Settings" - - Set "SCIM enabled" to "ON" - - Click on the "Save" Button + - Select the **Settings** sub-tab + - Set **SCIM enabled** to **ON** + - Click the **Save** Button - - Select "Authorization" - - Select **odm** (clientId of the application) in the "Available Clients" list and click on "Add selected" to move it to the "Assigned Clients" list + - Select the **Authorization** sub-tab + - Select **odm** (clientId of the application) in the **Available Clients** list and click **Add selected >** to move it to the **Assigned Clients** list By default, the SCIM Groups and Users Endpoints require authentication. @@ -265,21 +274,21 @@ Where: ![SCIM Resources Tab](images/scim_resources.png) - Now, we will configure these endpoints to authorize authenticated users that have the rtsAdministrators role. In the ODM client application, we will use the client_credentials flow using the "service-account-odm" service account having assigned the rtsAdministrators role. We just have to configure authorization for the "Get" endpoint as the ODM SCIM Import is a read only mode and doesn't need the other endpoints (Create, Update, Delete) + Now, let's configure these endpoints to authorize authenticated users that have the rtsAdministrators role. In the ODM client application, we will use the client_credentials flow using the "service-account-odm" service account having assigned the rtsAdministrators role. We just have to configure authorization for the "Get" endpoint as the ODM SCIM Import is a read only mode and doesn't need the other endpoints (Create, Update, Delete). - - Select the "Resource Type" tab - - Click on "Group" inside the table - - Click on the "Authorization" tab - - Expand "Common Roles", select "rtsAdministrators" in the "Available Roles" and click on "Add selected" to move it to the "Assigned Roles" list - - Expand "Roles for Get", select "rtsAdministrators" in the "Available Roles" and click on "Add selected" to move it to the "Assigned Roles" list + - Select the **Resource Type** tab + - Click **Group** inside the table + - Select the **Authorization** sub-tab + - Expand **Common Roles**, select **rtsAdministrators** in the **Available Roles** list and click **Add selected >** to move it to the **Assigned Roles** list + - Expand **Roles for Get**, select **rtsAdministrators** in the **Available Roles** list and click **Add selected >** to move it to the **Assigned Roles** list ![SCIM Group Authorization Tab](images/scim_groups_authorization.png) - - Select the "Resource Type" tab again - - Click on "User" inside the table - - Click on the "Authorization" tab - - Expand "Common Roles", select "rtsAdministrators" in the "Available Roles" and click on "Add selected" to move it to the "Assigned Roles" list - - Expand "Roles for Get", select "rtsAdministrators" in the "Available Roles" and click on "Add selected" to move it to the "Assigned Roles" list + - Select the **Resource Type** tab again + - Click **User** inside the table + - Click the **Authorization** sub-tab + - Expand **Common Roles**, select **rtsAdministrators** in the **Available Roles** list and click **Add selected >** to move it to the **Assigned Roles** list + - Expand **Roles for Get**, select **rtsAdministrators** in the **Available Roles** list and click **Add selected >** to move it to the **Assigned Roles** list ![SCIM User Authorization Tab](images/scim_user_authorization.png) @@ -291,33 +300,33 @@ Where: Request an access token using the Client-Credentials flow ```shell - $ ./get-client-credential-token.sh -i -x -n + ./get-client-credential-token.sh -i $CLIENT_ID -x $CLIENT_SECRET -n $KEYCLOAK_SERVER_URL ``` Call the SCIM Group endpoint using this ```shell - $ curl -k -H "Authorization: Bearer " /scim/v2/Groups + curl -k -H "Authorization: Bearer $ACCESS_TOKEN" $KEYCLOAK_SERVER_URL/scim/v2/Groups ``` Result should looks like : ```shell -{"schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],"totalResults":10,"itemsPerPage":10,"startIndex":1,"Resources":[{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Group"],"id":"ef20202e-20e3-44f3-8d70-b1cf2d2c2d7d","displayName":"ADPEnvironmentOwners","members":[{"value":"35560439-88a3-4a56-bb67-384f024bfd7a","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/35560439-88a3-4a56-bb67-384f024bfd7a","type":"User"},{"value":"7d995178-294a-4175-91f4-43cd9f5906aa","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/7d995178-294a-4175-91f4-43cd9f5906aa","type":"User"},{"value":"6c74e271-ae1c-4849-aa67-8351f1c816c5","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/6c74e271-ae1c-4849-aa67-8351f1c816c5","type":"User"}],"meta":{"resourceType":"Group","created":"2023-08-09T13:09:44.164Z","lastModified":"2023-08-09T13:09:44.164Z","location":"https://9.46.78.129:8443/realms/odm/scim/v2/Groups/ef20202e-20e3-44f3-8d70-b1cf2d2c2d7d"}},{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Group"],"id":"f671e618-ef45-41d4-bd0b-c134536edf45","displayName":"CE_EnvironmentOwners","members":[{"value":"35560439-88a3-4a56-bb67-384f024bfd7a","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/35560439-88a3-4a56-bb67-384f024bfd7a","type":"User"}],"meta":{"resourceType":"Group","created":"2023-08-09T13:09:44.207Z","lastModified":"2023-08-09T13:09:44.207Z","location":"https://9.46.78.129:8443/realms/odm/scim/v2/Groups/f671e618-ef45-41d4-bd0b-c134536edf45"}},{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Group"],"id":"7f767eac-0950-4e71-b2ec-b9e04a10be04","displayName":"GeneralUsers","members":[{"value":"88094536-a059-4383-8bf4-1dcb65457bb9","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/88094536-a059-4383-8bf4-1dcb65457bb9","type":"User"},{"value":"94a6b972-04aa-4394-89b8-f16a875fe54d","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/94a6b972-04aa-4394-89b8-f16a875fe54d","type":"User"},{"value":"9a37726a-2a69-4f97-a892-ef38d566c94f","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/9a37726a-2a69-4f97-a892-ef38d566c94f","type":"User"},{"value":"35774b15-42bc-4c05-bcc9-145fbf075ace","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/35774b15-42bc-4c05-bcc9-145fbf075ace","type":"User"}, - ... + {"schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],"totalResults":10,"itemsPerPage":10,"startIndex":1,"Resources":[{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Group"],"id":"ef20202e-20e3-44f3-8d70-b1cf2d2c2d7d","displayName":"ADPEnvironmentOwners","members":[{"value":"35560439-88a3-4a56-bb67-384f024bfd7a","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/35560439-88a3-4a56-bb67-384f024bfd7a","type":"User"},{"value":"7d995178-294a-4175-91f4-43cd9f5906aa","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/7d995178-294a-4175-91f4-43cd9f5906aa","type":"User"},{"value":"6c74e271-ae1c-4849-aa67-8351f1c816c5","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/6c74e271-ae1c-4849-aa67-8351f1c816c5","type":"User"}],"meta":{"resourceType":"Group","created":"2023-08-09T13:09:44.164Z","lastModified":"2023-08-09T13:09:44.164Z","location":"https://9.46.78.129:8443/realms/odm/scim/v2/Groups/ef20202e-20e3-44f3-8d70-b1cf2d2c2d7d"}},{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Group"],"id":"f671e618-ef45-41d4-bd0b-c134536edf45","displayName":"CE_EnvironmentOwners","members":[{"value":"35560439-88a3-4a56-bb67-384f024bfd7a","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/35560439-88a3-4a56-bb67-384f024bfd7a","type":"User"}],"meta":{"resourceType":"Group","created":"2023-08-09T13:09:44.207Z","lastModified":"2023-08-09T13:09:44.207Z","location":"https://9.46.78.129:8443/realms/odm/scim/v2/Groups/f671e618-ef45-41d4-bd0b-c134536edf45"}},{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Group"],"id":"7f767eac-0950-4e71-b2ec-b9e04a10be04","displayName":"GeneralUsers","members":[{"value":"88094536-a059-4383-8bf4-1dcb65457bb9","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/88094536-a059-4383-8bf4-1dcb65457bb9","type":"User"},{"value":"94a6b972-04aa-4394-89b8-f16a875fe54d","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/94a6b972-04aa-4394-89b8-f16a875fe54d","type":"User"},{"value":"9a37726a-2a69-4f97-a892-ef38d566c94f","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/9a37726a-2a69-4f97-a892-ef38d566c94f","type":"User"},{"value":"35774b15-42bc-4c05-bcc9-145fbf075ace","$ref":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/35774b15-42bc-4c05-bcc9-145fbf075ace","type":"User"}, + ... ``` Call the SCIM Group endpoint using this ```shell - $ curl -k -H "Authorization: Bearer " /scim/v2/Users + curl -k -H "Authorization: Bearer $ACCESS_TOKEN" $KEYCLOAK_SERVER_URL/scim/v2/Users ``` Result should looks like : ```shell -{"schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],"totalResults":23,"itemsPerPage":23,"startIndex":1,"Resources":[{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"id":"def4784e-7b1d-460b-86b3-8cf4d95e47e2","userName":"caserviceuser","name":{"familyName":"caServiceUser","givenName":"caServiceUser"},"active":true,"emails":[{"value":"caserviceuser@example.org","primary":true}],"meta":{"resourceType":"User","created":"2022-12-09T14:07:02.529Z","lastModified":"2022-12-09T14:07:02.529Z","location":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/def4784e-7b1d-460b-86b3-8cf4d95e47e2"}},{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"id":"7d995178-294a-4175-91f4-43cd9f5906aa","userName":"cp4admin","name":{"familyName":"cp4admin","givenName":"cp4admin"},"active":true,"emails":[{"value":"cp4admin@example.org","primary":true}],"groups":[{"value":"da45f301-9b11-4367-be98-ecf63b677c45","display":"TaskAdmins","type":"direct"},{"value":"ef20202e-20e3-44f3-8d70-b1cf2d2c2d7d","display":"ADPEnvironmentOwners","type":"direct"},{"value":"8a0a6948-1c07-4c5c-8e17-c445a12572b8","display":"P8Administrators","type":"direct"},{"value":"ee18a23d-ba39-466a-a4f6-8d7ebc53825b","display":"TeamsAdmins","type":"direct"}],"meta":{"resourceType":"User","created":"2022-12-09T14:06:54.231Z","lastModified":"2022-12-09T14:06:54.231Z","location":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/7d995178-294a-4175-91f4-43cd9f5906aa"}},{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"id":"35560439-88a3-4a56-bb67-384f024bfd7a","userName":"environmentowner","name":{"familyName":"environmentOwner","givenName":"environmentOwner"},"active":true,"emails":[{"value":"environmentowner@example.org","primary":true}],"groups":[{"value":"f671e618-ef45-41d4-bd0b-c134536edf45","display":"CE_EnvironmentOwners","type":"direct"},{"value":"ef20202e-20e3-44f3-8d70-b1cf2d2c2d7d","display":"ADPEnvironmentOwners","type":"direct"}, - ... + {"schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],"totalResults":23,"itemsPerPage":23,"startIndex":1,"Resources":[{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"id":"def4784e-7b1d-460b-86b3-8cf4d95e47e2","userName":"caserviceuser","name":{"familyName":"caServiceUser","givenName":"caServiceUser"},"active":true,"emails":[{"value":"caserviceuser@example.org","primary":true}],"meta":{"resourceType":"User","created":"2022-12-09T14:07:02.529Z","lastModified":"2022-12-09T14:07:02.529Z","location":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/def4784e-7b1d-460b-86b3-8cf4d95e47e2"}},{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"id":"7d995178-294a-4175-91f4-43cd9f5906aa","userName":"cp4admin","name":{"familyName":"cp4admin","givenName":"cp4admin"},"active":true,"emails":[{"value":"cp4admin@example.org","primary":true}],"groups":[{"value":"da45f301-9b11-4367-be98-ecf63b677c45","display":"TaskAdmins","type":"direct"},{"value":"ef20202e-20e3-44f3-8d70-b1cf2d2c2d7d","display":"ADPEnvironmentOwners","type":"direct"},{"value":"8a0a6948-1c07-4c5c-8e17-c445a12572b8","display":"P8Administrators","type":"direct"},{"value":"ee18a23d-ba39-466a-a4f6-8d7ebc53825b","display":"TeamsAdmins","type":"direct"}],"meta":{"resourceType":"User","created":"2022-12-09T14:06:54.231Z","lastModified":"2022-12-09T14:06:54.231Z","location":"https://9.46.78.129:8443/realms/odm/scim/v2/Users/7d995178-294a-4175-91f4-43cd9f5906aa"}},{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"id":"35560439-88a3-4a56-bb67-384f024bfd7a","userName":"environmentowner","name":{"familyName":"environmentOwner","givenName":"environmentOwner"},"active":true,"emails":[{"value":"environmentowner@example.org","primary":true}],"groups":[{"value":"f671e618-ef45-41d4-bd0b-c134536edf45","display":"CE_EnvironmentOwners","type":"direct"},{"value":"ef20202e-20e3-44f3-8d70-b1cf2d2c2d7d","display":"ADPEnvironmentOwners","type":"direct"}, + ... ``` # Deploy ODM on a container configured with Keycloak @@ -326,13 +335,13 @@ Follow - [Deploy ODM on a container configured with Keycloak (Part 2)](README.md But replace the previous step "3. Create the Keycloak authentication secret" of the section [Create secrets to configure ODM with Keycloak](README.md#create-secrets-to-configure-odm-with-keycloak) by: - ``` - kubectl create secret generic keycloak-auth-secret \ - --from-file=ldap-configurations.xml=./output/ldap-configurations.xml \ - --from-file=openIdParameters.properties=./output/openIdParameters.properties \ - --from-file=openIdWebSecurity.xml=./output/openIdWebSecurity.xml \ - --from-file=webSecurity.xml=./output/webSecurity.xml - ``` + ``` + kubectl create secret generic keycloak-auth-secret \ + --from-file=ldap-configurations.xml=./output/ldap-configurations.xml \ + --from-file=openIdParameters.properties=./output/openIdParameters.properties \ + --from-file=openIdWebSecurity.xml=./output/openIdWebSecurity.xml \ + --from-file=webSecurity.xml=./output/webSecurity.xml + ``` Make sure that you finish [Complete post-deployment tasks](README.md#complete-post-deployment-tasks). # Manage Security on ODM Decision Service Project @@ -344,28 +353,32 @@ We will only provide access to the "Miniloan Service" project for users belongin ## Provide the relevant roles on groups -The first step is to declare groups of users that will be Decision Center Administrators, having access to the Business Console Administration Tab. +The first step is to declare the groups of users that will be Decision Center Administrators, and therefore have access to the Business Console Administration Tab. - - In Keycloak admin console of **odm** realm, select the `Manage>Groups` Tab - - Double-click on "TaskAdmins" - - Select the "Role Mappings" Tab - - Select all rts*** roles in the "Available Roles" list and click on "Add selected" to move it to the "Assigned Roles" list + - In Keycloak admin console, select the **odm** realm + - Select the **Manage > Groups** Tab + - Double-click **TaskAdmins** + - Select the **Role Mappings** Tab + - Select all rts*** roles in the **Available Roles** list and click **Add selected >** to move them to the **Assigned Roles** list ![Assign Admin Roles](images/assign_rtsadministrators_role.png) -We also need to declare "TaskAuditors" and "TaskUsers" groups having rtsUSers roles. If you don't do this, users are not authorized to login into the Business Console. +Let's also assign the **rtsUsers** role to the **TaskAuditors** and **TaskUsers** groups. If you do not do this, users are not authorized to login into the Business Console. - - Select the `Manage>Groups` Tab - - Double-click on "TaskAuditors" - - Select the "Role Mappings" Tab - - Select the "rtsUsers" role in the "Available Roles" list and click on "Add selected" to move it to the "Assigned Roles" list - - Repeat the same for the "TaskUsers" group + - Select the **Manage > Groups** Tab + - Double-click on **TaskAuditors** + - Select the **Role Mappings** Tab + - Select the **rtsUsers** role in the **Available Roles** list and click **Add selected >** to move it to the **Assigned Roles** list + - Repeat the same for the **TaskUsers** group ![Assign User Roles](images/assign_rtsusers_role.png) ## Load projects - For all the coming steps, the users' password can be found in the `ldap_user.ldif` file of the `openldap-customldif` secret. + For the next steps, the users password can be found in the `ldap_user.ldif` file of the `openldap-customldif` secret, by running the commmand: + ``` + oc get secret openldap-customldif -o jsonpath={.data."ldap_user\.ldif"} | base64 -d + ``` - Log into the ODM Decision Center Business Console using the `cp4admin` user - Select the **LIBRARY** tab @@ -376,35 +389,35 @@ We also need to declare "TaskAuditors" and "TaskUsers" groups having rtsUSers ro ## Import Groups and Users - Select the **ADMINISTRATION** tab - - Select the "Connection Settings" sub-tab + - Select the **Connection Settings** sub-tab - Check the KEYCLOAK_SCIM connection status is green - - Select the "Groups" sub-tab - - Click the "Import Groups from directories" button - - Select the "TaskAuditors" and "TaskUsers" groups - - Click on the "Import groups and users" button + - Select the **Groups** sub-tab + - Click the **Import Groups from directories** button + - Select the **TaskAuditors** and **TaskUsers** groups + - Click on the **Import groups and users** button ![DC Import Groups and Users](images/dc_import_groups_users.png) ## Set the project security - - Select the "Project Security" sub-tab - - Click on the "Edit decision service security" of the "Loan Validation Service" project - - Below the Security section, select "Enforce Security" - - Below the Groups section, select the TaskAuditors group - - Click on the Done button + - Select the **Project Security** sub-tab + - Click on the **Edit decision service security** of the "Loan Validation Service" project + - Below the Security section, select **Enforce Security** + - Below the Groups section, select the **TaskAuditors** group + - Click the **Done** button ![Set Loan Validation Service Security](images/set_loan_validation_service_security.png) - - Click on the "Edit decision service security" of the "Miniloan Service" project - - Below the Security section, select "Enforce Security" - - Below the Groups section, select the TaskUsers group - - Click on the Done button + - Click the **Edit decision service security** of the "Miniloan Service" project + - Below the Security section, select **Enforce Security** + - Below the Groups section, select the **TaskUsers** group + - Click the **Done** button ![Security Results](images/security_results.png) ## Check the project security - - Click on top right "cp4admin" user + - Click on top right **cp4admin** user - Click the "Log out" link - Click the Keycloak Logout button diff --git a/authentication/Keycloak/generateTemplate.sh b/authentication/Keycloak/generateTemplate.sh index f81d0c4a..adaec092 100755 --- a/authentication/Keycloak/generateTemplate.sh +++ b/authentication/Keycloak/generateTemplate.sh @@ -15,7 +15,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -export KEYCLOAK_USERID="preferred_username" OUTPUT_DIR=./output TEMPLATE_DIR=./templates @@ -29,18 +28,18 @@ Options: -n : KEYCLOAK URL (KEYCLOAK server name) -x : Cient Secret -r : Realm Name --u : UserID -Usage example: $0 -i KeycloakClientId -x KeycloakClientSecret -n KeycloakURL [-r KeycloakRealm -u KeycloakUserID]" +-u : UserID claim +Usage example: $0 -i CLIENT_ID -x CLIENT_SECRET -n KEYCLOAK_SERVER_URL [-r REALM_NAME -u USERID_CLAIM]" EOF } -while getopts "x:i:n:r:u:ha:" option; do +while getopts "x:i:n:r:u:h:" option; do case "${option}" in i) KEYCLOAK_CLIENT_ID=${OPTARG};; - n) KEYCLOAK_SERVER_URL=${OPTARG};; x) KEYCLOAK_CLIENT_SECRET=${OPTARG};; + n) KEYCLOAK_SERVER_URL=${OPTARG};; r) KEYCLOAK_REALM=${OPTARG};; - u) KEYCLOAK_USERID=${OPTARG};; + u) KEYCLOAK_USERID_CLAIM=${OPTARG};; h) usage; exit 0;; *) usage; exit 1;; esac @@ -62,9 +61,9 @@ if [[ -z ${KEYCLOAK_REALM} ]]; then echo "REALM not provided, using odm as realm name." KEYCLOAK_REALM=odm fi -if [[ -z ${KEYCLOAK_USERID} ]]; then - echo "USERID not provided, using preferred_username as user_id." - KEYCLOAK_USERID=preferred_username +if [[ -z ${KEYCLOAK_USERID_CLAIM} ]]; then + echo "USERID_CLAIM not provided, using preferred_username as user_id claim." + KEYCLOAK_USERID_CLAIM=preferred_username fi mkdir -p $OUTPUT_DIR && cp $TEMPLATE_DIR/* $OUTPUT_DIR @@ -72,7 +71,7 @@ echo "Generating files for KEYCLOAK" sed -i.bak 's|KEYCLOAK_CLIENT_ID|'$KEYCLOAK_CLIENT_ID'|g' $OUTPUT_DIR/* sed -i.bak 's|KEYCLOAK_CLIENT_SECRET|'$KEYCLOAK_CLIENT_SECRET'|g' $OUTPUT_DIR/* sed -i.bak 's|KEYCLOAK_SERVER_URL|'$KEYCLOAK_SERVER_URL'|g' $OUTPUT_DIR/* -sed -i.bak 's|KEYCLOAK_USERID|'$KEYCLOAK_USERID'|g' $OUTPUT_DIR/* +sed -i.bak 's|KEYCLOAK_USERID_CLAIM|'$KEYCLOAK_USERID_CLAIM'|g' $OUTPUT_DIR/* # Claim replacement ALLOW_DOMAIN=$(echo $KEYCLOAK_SERVER_URL | sed -e "s/\/realms\/$KEYCLOAK_REALM//" -e "s/https:\/\///") sed -i.bak 's|KEYCLOAK_DOMAIN|'$ALLOW_DOMAIN'|g' $OUTPUT_DIR/* diff --git a/authentication/Keycloak/images/assign_rtsadministrators_role.png b/authentication/Keycloak/images/assign_rtsadministrators_role.png index 48eebc67..9c1634a7 100644 Binary files a/authentication/Keycloak/images/assign_rtsadministrators_role.png and b/authentication/Keycloak/images/assign_rtsadministrators_role.png differ diff --git a/authentication/Keycloak/images/create_client_1.png b/authentication/Keycloak/images/create_client_1.png index c7f3c90b..7b72a90a 100644 Binary files a/authentication/Keycloak/images/create_client_1.png and b/authentication/Keycloak/images/create_client_1.png differ diff --git a/authentication/Keycloak/keycloak-odm-script.zip b/authentication/Keycloak/keycloak-odm-script.zip index b4b76ef8..fd75aacb 100644 Binary files a/authentication/Keycloak/keycloak-odm-script.zip and b/authentication/Keycloak/keycloak-odm-script.zip differ diff --git a/authentication/Keycloak/keycloak.yaml b/authentication/Keycloak/keycloak.yaml new file mode 100644 index 00000000..856abead --- /dev/null +++ b/authentication/Keycloak/keycloak.yaml @@ -0,0 +1,130 @@ +kind: Template +apiVersion: template.openshift.io/v1 +metadata: + name: keycloak + annotations: + description: An example template for trying out Keycloak on OpenShift + iconClass: icon-sso + openshift.io/display-name: Keycloak + tags: keycloak + version: 26.0.5 +objects: + - apiVersion: v1 + kind: Service + metadata: + annotations: + description: The web server's http port. + labels: + application: '${APPLICATION_NAME}' + name: '${APPLICATION_NAME}' + spec: + ports: + - port: 8080 + targetPort: 8080 + selector: + deploymentConfig: '${APPLICATION_NAME}' + - apiVersion: v1 + id: '${APPLICATION_NAME}' + kind: Route + metadata: + annotations: + description: Route for application's service. + labels: + application: '${APPLICATION_NAME}' + name: '${APPLICATION_NAME}' + spec: + host: '${HOSTNAME}' + tls: + termination: edge + to: + name: '${APPLICATION_NAME}' + - apiVersion: v1 + kind: DeploymentConfig + metadata: + labels: + application: '${APPLICATION_NAME}' + name: '${APPLICATION_NAME}' + spec: + replicas: 1 + selector: + deploymentConfig: '${APPLICATION_NAME}' + strategy: + type: Recreate + template: + metadata: + labels: + application: '${APPLICATION_NAME}' + deploymentConfig: '${APPLICATION_NAME}' + name: '${APPLICATION_NAME}' + spec: + containers: + - env: + - name: KEYCLOAK_ADMIN + value: '${KEYCLOAK_ADMIN}' + - name: KEYCLOAK_ADMIN_PASSWORD + value: '${KEYCLOAK_ADMIN_PASSWORD}' + - name: KC_PROXY + value: 'edge' + - name: KC_PROXY_HEADERS + value: 'forwarded' + image: quay.io/keycloak/keycloak:26.0.5 + livenessProbe: + failureThreshold: 100 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 60 + name: '${APPLICATION_NAME}' + ports: + - containerPort: 8080 + protocol: TCP + readinessProbe: + failureThreshold: 300 + httpGet: + path: / + port: 8080 + scheme: HTTP + initialDelaySeconds: 30 + securityContext: + privileged: false + volumeMounts: + - mountPath: /opt/keycloak/data + name: empty + args: ["start-dev"] + volumes: + - name: empty + emptyDir: {} + triggers: + - type: ConfigChange +parameters: + - name: APPLICATION_NAME + displayName: Application Name + description: The name for the application. + value: keycloak + required: true + - name: KEYCLOAK_ADMIN + displayName: Keycloak Administrator Username + description: Keycloak Server administrator username + generate: expression + from: '[a-zA-Z0-9]{8}' + required: true + - name: KEYCLOAK_ADMIN_PASSWORD + displayName: Keycloak Administrator Password + description: Keycloak Server administrator password + generate: expression + from: '[a-zA-Z0-9]{8}' + required: true + - name: HOSTNAME + displayName: Custom Route Hostname + description: >- + Custom hostname for the service route. Leave blank for default hostname, + e.g.: -. + - name: NAMESPACE + displayName: Namespace used for DNS discovery + description: >- + This namespace is a part of DNS query sent to Kubernetes API. This query + allows the DNS_PING protocol to extract cluster members. This parameter + might be removed once https://issues.jboss.org/browse/JGRP-2292 is + implemented. + required: true diff --git a/authentication/Keycloak/templates/openIdWebSecurity.xml b/authentication/Keycloak/templates/openIdWebSecurity.xml index 48a1bc13..c745613c 100644 --- a/authentication/Keycloak/templates/openIdWebSecurity.xml +++ b/authentication/Keycloak/templates/openIdWebSecurity.xml @@ -9,7 +9,7 @@ signatureAlgorithm="RS256" inboundPropagation="supported" audiences="ALL_AUDIENCES" httpsRequired="false" tokenReuse="true" - userIdentifier="KEYCLOAK_USERID" groupIdentifier="groups" + userIdentifier="KEYCLOAK_USERID_CLAIM" groupIdentifier="groups" issuerIdentifier="${ServerHost}" jwkEndpointUrl="${ServerHost}/protocol/openid-connect/certs" authorizationEndpointUrl="${ServerHost}/protocol/openid-connect/auth" @@ -22,7 +22,7 @@ signatureAlgorithm="RS256" inboundPropagation="required" audiences="ALL_AUDIENCES" httpsRequired="false" tokenReuse="true" - userIdentifier="KEYCLOAK_USERID" groupIdentifier="groups" + userIdentifier="KEYCLOAK_USERID_CLAIM" groupIdentifier="groups" issuerIdentifier="${ServerHost}" jwkEndpointUrl="${ServerHost}/protocol/openid-connect/certs" authorizationEndpointUrl="${ServerHost}/protocol/openid-connect/auth" diff --git a/authentication/Okta/README.md b/authentication/Okta/README.md index 225c90a8..ed6f5233 100644 --- a/authentication/Okta/README.md +++ b/authentication/Okta/README.md @@ -108,10 +108,10 @@ After activating your account by email, you should have access to your Okta inst In Menu **Directory** / **People**: * Click **Add Person** button * User type: *User* - * First name: ```` - * Last name: ```` - * Username: ```` - * Primary email: ```` + * First name: `` + * Last name: `` + * Username: `` + * Primary email: `` * Groups (optional): ***odm-admin*** * Click **Save** @@ -166,21 +166,46 @@ In this step, we augment the token with meta-information that is required by the In **Claims** tab, create the following claims: - * Click **Add claim** - * *groups - Access Token* claim: + * Click **Add claim** and set the fields: * Name: *groups* * Include in token type: *Access Token* * Value type: *Groups* * Filter: **Equals**: *odm-admin* - * *groups - Id Token* claim: + * Click **Create** + * Click **Add claim** and set the fields: * Name: *groups* - * Include in token type: *Id Token* + * Include in token type: *ID Token* (Always) * Value type: *Groups* * Filter: **Equals**: odm-admin + * Click **Create** ![Add Claim Result](images/ResultAddClaims.png) -4. Verify the content of the token. +4. Add an Access Policy and Rule. + + Access Policies are containers for Rules. + Rules define particular token lifetimes for a given combination of grant type, user, and scope. If no matching rule is found, then the authorization request fails. + + Let's create an Access Policy and rule for the *ODM Application*. + + In the **Access Policies** tab: + * Click **Add New Access Policy** + * Name: *ODM Application policy* + * Description: *ODM Application policy* + * Assign to: **The following clients** and enter: *ODM Application* + * Click **Create Policy** + * Click **Add Rule** + * Rule Name: *default rule* + * In **grant type**: + * Check **Client Credentials** + * Check **Authorization Code** + * Check **Device Authorization** + * Check **Implicit (hybrid)** + * Click **Create rule** + + ![Add Policy and Rule Result](images/ResultAddAccessPolicy.png) + +5. Verify the content of the token. Check that the login name and groups meta-information are available in the ID token. @@ -293,8 +318,10 @@ In this step, we augment the token with meta-information that is required by the ``` helm search repo ibm-odm-prod + ``` + ``` NAME CHART VERSION APP VERSION DESCRIPTION - ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager + ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` 3. Run the `helm install` command. @@ -302,10 +329,11 @@ In this step, we augment the token with meta-information that is required by the You can now install the product. We will use the PostgreSQL internal database and disable the data persistence (`internalDatabase.persistence.enabled=false`) to avoid any platform complexity concerning persistent volume allocation. ``` - helm install my-odm-release ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ + helm install my-odm-release ibm-helm/ibm-odm-prod --version 24.1.0 \ --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets=icregistry-secret \ --set oidc.enabled=true \ --set internalDatabase.persistence.enabled=false \ + --set internalDatabase.populateSampleData=true \ --set customization.trustedCertificateList={"okta-secret"} \ --set customization.authSecretRef=okta-auth-secret \ --set license=true @@ -352,15 +380,13 @@ In this step, we augment the token with meta-information that is required by the - In the **General** tab, click **Edit** on the **General Settings** section. - In the **LOGIN** section, click **+ Add URI** in the **Sign-in redirect URIs** section and add the Decision Center redirect URI you got earlier (`https:///decisioncenter/openid/redirect/odm` -- do not forget to replace by your actual host name!) - Repeat the previous step for all other redirect URIs. - - Click **Save** at the bottom of the LOGIN section. + - Click **Save** at the bottom of the **General Settings** section. ![Sign-in redirect URIs](images/Sign-in_redirect_URIs.png) ### Access the ODM services -Well done! You can now connect to ODM using the endpoints you got [earlier](#register-the-odm-redirect-url), and log in as an ODM admin with the account you created in [the first step](#manage-groups-and-users). - ->Note: Logout in ODM components using Okta authentication raises an error for the time being. This is a known issue. We recommend you to use a private window in your browser to log in, so that logout is done just by closing this window. +Well done! You can now connect to ODM using the endpoints you got [earlier](#register-the-odm-redirect-urls), and log in as an ODM admin with the account you created in [the first step](#manage-groups-and-users). ### Set up Rule Designer diff --git a/authentication/Okta/images/ResultAddAccessPolicy.png b/authentication/Okta/images/ResultAddAccessPolicy.png new file mode 100644 index 00000000..7303d330 Binary files /dev/null and b/authentication/Okta/images/ResultAddAccessPolicy.png differ diff --git a/authentication/Okta/images/add_person.png b/authentication/Okta/images/add_person.png index 53520d24..e0e8ec7a 100644 Binary files a/authentication/Okta/images/add_person.png and b/authentication/Okta/images/add_person.png differ diff --git a/authentication/README.md b/authentication/README.md index 0ee65ecc..99caad01 100644 --- a/authentication/README.md +++ b/authentication/README.md @@ -74,14 +74,14 @@ The URL that provides the dedicated OpenID Server syntax group depends on the Op If you encounter issues to be authorized, follow this advice: * To debug the Liberty authorization mechanism when accessing Decision Center, choose one of the following options: * Edit the Decision Center logging configmap of the current release by adding: - **com.ibm.ws.security.*=all:com.ibm.ws.webcontainer.security.*=all** to the Liberty logging. + **com.ibm.ws.security.\*=all:com.ibm.ws.webcontainer.security.\*=all** to the Liberty logging. * Create the **my-dc-logging-configmap** Decision Center configmap using [dc-logging.yaml](./dc-logging.yaml) with the command: **kubectl apply -f dc-logging.xml** and attach it to the Helm deployment using **-set decisionCenter.loggingRef=my-dc-logging-configmap** * To debug the Liberty authorization mechanism when accessing Decision Server Console, choose one of the following options: * Edit the Decision Server Console logging configmap of the current release by adding: - **com.ibm.ws.security.*=all:com.ibm.ws.webcontainer.security.*=all** to the Liberty logging. + **com.ibm.ws.security.\*=all:com.ibm.ws.webcontainer.security.\*=all** to the Liberty logging. * Create the **my-dsc-logging-configmap** Decision Server configmap using [dsc-logging.yaml](./dsc-logging.yaml) with the command: **kubectl apply -f dsc-logging.xml** and attach it to the Helm deployment using diff --git a/contrib/authentication/openid/README.md b/contrib/authentication/openid/README.md deleted file mode 100644 index 5a47faec..00000000 --- a/contrib/authentication/openid/README.md +++ /dev/null @@ -1,331 +0,0 @@ -# Configuring user access with external OIDC providers - -In the context of the IBM Cloud Pak for Business Automation, Operational Decision Manager for production can be configured with an external OpenID Connect server (OIDC Provider). You must set `oidc.external_server` to true, in your custom resource file. - -## Before you begin - -You must configure a basic or LDAP authentication registry for your ODM services before you can configure ODM with an OIDC provider. To understand better ODM roles, see [Understanding user roles and user groups](https://www.ibm.com/docs/cloud-paks/cp-biz-automation/21.0.x?topic=access-understanding-user-roles-user-groups). - -ODM uses hardcoded roles with three users and three groups for each role. All authenticated users have by default the `rtsUser` role. - -The following lines show the ODM configuration. - -```xml -rtsAdministrators: - - - - - - -``` - -Similar users and groups exist for the other roles `rtsConfigManagers`, `resAdministrators`, `resExecutors`, `resMonitors`, and `resDeployers`. You can find an example in the [configuration](../../../configuration/security) folder. - -## About this task - -You need to create a number of secrets before you can install an ODM instance with an external OIDC provider and use web application single sign-on (SSO). The following diagram shows the ODM services with an external OIDC provider after a successful installation. - -![ODM web application SSO](images/diag_oidc_interaction.jpg) - -The following procedure describes how to manually configure ODM with an external OpenID Connect server. You must define the mapping between the liberty roles and the LDAP groups by creating a secret and reference it in the customization.authSecretRef parameter. - -## Procedure - -1. Create a secret that maps groups to the ODM roles. - - This secret grants user access to the ODM services with an external OIDC provider. - - - Create a webSecurity.xml file to define the mapping to the OIDC groups. - - See the [configuration](../../../configuration/security) folder on how to put all of the definitions that your environment needs into the webSecurity.xml file. - - - Create a secret for the webSecurity.xml file. - - > Note: The secret must be registered with the webSecurity.xml key. If you did use a different file name, for example sample-webSecurity-OIDC.xml, you can still register it by specifying your file name when you create the secret. - >``` - >kubectl create secret generic \ - > --from-file=webSecurity.xml=/sample-webSecurity-OIDC.xml - > ``` - - Make sure that you create the secret in the same namespace as the namespace that you use for the ODM instance. To create the secret, use the following command. - - ``` - kubectl create secret generic --from-file=webSecurity.xml - ``` - - Where is the name that you give to the secret. - - Make a note of the secret name so that you can set the customization.authSecretRef parameter in the configuration of your ODM instance. - - When the custom resource is deployed, you can edit this file in the secret `-odm-oidc-auth-operator-secret` to change the authorization configuration. - -2. Set the external OpenID provider parameters in the custom resource to true. - - ```yaml - odm_configuration: - oidc: - enabled: true - external_server: true - ``` - -3. Provide the certificate of the OpenID server. - - For more information, see [Importing the certificate of an external service](https://www.ibm.com/docs/cloud-paks/cp-biz-automation/21.0.x?topic=services-importing-certificate-external-service). - -4. Provide the URL of the external OpenID server. - - ```yaml - odm_configuration: - oidc: - serverUrl: my-openid-serverUrl - ``` - -5. To protect Decision Center and Decision Server Console against CSRF attacks, provide the allowed domains list (separated by a comma) that can be used to access ODM consoles. Generally, the minimal domain contains the OpenID server URL (without https://). - - ```yaml - odm_configuration: - oidc: - allowedDomains: my-openid-alloweddomains - ``` - -6. Provide the name of the OpenID provider. - - > Note: If not provided, "`ums`" is set. - - ``` { .prettyprint .language-yaml} - odm_configuration: - oidc: - provider: my-openid-provider - ``` - -7. Create a secret with an OpenID client ID and password to request the authentication token from the OpenID instance. - - ``` - kubectl create secret generic my_openid_clientid_secret \ - --from-literal=clientId=MY-OPENID-CLIENT-ID \ - --from-literal=clientSecret=MY-OPENID-CLIENT-SECRET - ``` - - If not provided, a secret is generated by using some default values: `clientId=-odm-oidc-client-id-secret` and `clientSecret=-odm-oidc-client-id-secret-value`. - - ```yaml - odm_configuration: - oidc: - clientRef: my_openid_clientid_secret - ``` - -8. To make the ODM URLs accessible, a list of URLs must be registered to the OpenID server. - - For more information, see [OpenID Connect Dynamic Client Registration](https://openid.net/specs/openid-connect-registration-1_0-17.html). - - A job automatically registers the redirect URL on the OpenID server when UMS is the provider (`oidc.provider: "ums"`). The job contains some cURL scripts that are compatible only with a UMS provider. If you are using Okta, Keycloak, or another OpenID provider, you need to register the redirect manually. To manage the registration, you must create an OpenID administrator secret. - - The administrator secret is used to call the OpenID REST API to register the URLs of the ODM services. The registration process can provide useful information for the ODM services, including the OAuth 2.0 client ID and client secret. - - You create a secret by running the following command. - - ``` - kubectl create secret generic my_openid_admin_secret \ - --from-literal=adminUser=OPENID-ADMIN-USERNAME \ - --from-literal=adminPassword=OPENID-ADMIN-PASSWORD - ``` - - Then, set the secret name in the CR file. - - ```yaml - odm_configuration: - oidc: - adminRef: my_openid_admin_secret - ``` - -## Advanced configuration -### [Optional] Configure OIDC endpoints -If you need to modify the OIDC endpoints or the token format, because the template is not compatible, you can create your own openIdParameters.properties file and provide it to the ODM instance. - - * Create the properties file with the following formatting. - - ``` - OPENID_SERVER_URL= - OPENID_PROVIDER= - OPENID_CLIENT_ID=OPENID_CLIENT_ID # provided or generated - OPENID_CLIENT_SECRET=OPENID_CLIENT_SECRET # provided or generated - OPENID_ALLOWED_DOMAINS= - OPENID_AUTHORIZATION_URL=/oidc/endpoint//authorize - OPENID_TOKEN_URL=/oidc/endpoint//token - OPENID_INTROSPECTION_URL=/oidc/endpoint//introspect - OPENID_LOGOUT_URL=/oidc/endpoint//logout - OPENID_TOKEN_FORMAT=NON-JWT - ``` - - > Note: If OPENID_CLIENT_ID and OPENID_CLIENT_SECRET are left blank, the values are replaced by the oidc.clientRef secret values. - - * Re-create the secret with the openIdParameters.properties file, and apply the change. - - ``` - kubectl create secret generic - --from-file=webSecurity.xml=webSecurity.xml - --from-file=openIdParameters.properties=openIdParameters.properties - - kubectl apply -f custom_resource.yaml - ``` - -### [Optional] Changing Liberty Openid configuration -If you need to add or modify a parameter to the `openidConnectClient` tag in the openIdWebSecurity.xml file, you can write your own file and provide it to the ODM instance. - - * Create the XML file with the following formatting. - - ```xml - -   -   -   - - ``` - - > Note: The **authFilterRef**, **id**, and **inboundPropagation** values must not be modified, as they are used internally. If **clientId** and **clientSecret** are left blank, the values are replaced by the oidc.clientRef secret values. - - * Re-create the secret , add the openIdWebSecurity.xml file, and apply the change. - - ``` - kubectl create secret generic - --from-file=webSecurity.xml=webSecurity.xml - --from-file=openIdWebSecurity.xml=openIdWebSecurity.xml - - kubectl apply -f custom_resource.yaml - ``` - - For more information about Liberty endpoints, see [OpenID Connect endpoint URLs](https://www.ibm.com/docs/en/was-liberty/base?topic=connect-openid-endpoint-urls). - - -## Results - -- [Optional] To use an external OIDC provider with Rule Designer, see [Configuring Rule Designer](https://www.ibm.com/docs/en/odm/9.0.0?topic=parties-configuring-rule-designer). - - You must import the security certificate that is used in the ODM instance into Rule Designer. For more information, see [Importing a security certificate in Rule Designer](https://www.ibm.com/docs/en/cloud-paks/cp-biz-automation/21.0.x?topic=designer-importing-security-certificate-in-rule). To provide the truststore.jks file to the eclipse.ini, you can identify the ODM pods with the `oc get pods | grep odm` command, and then copy the file by running the `oc cp` command. - - ``` - oc cp /:/config/security/truststore.jks ./truststore.jks - ``` - - The default password of the provided truststore.jks file is `changeit`. The clientId and clientSecret parameters can be set in Step 7 of the procedure. - - If you did not provide client credentials, an ID and password is created for you with the values `clientId=-odm-oidc-client-id` and `clientSecret=-odm-oidc-client-id-secret-value`. You need these values so that you can connect Rule Designer as a client. - -> Note: The access token is validated for all requests. The validation process has an impact on the Decision Server Runtime performance. To improve the performance, `LtpaToken` cookies are enabled in the `openidConnectClient` Liberty configuration to manage the token. However, for demanding applications that require high performance, `LtpaToken` cookies are sometimes not enough. In this case, use basic authentication to call the Decision Server Runtime. -> The Liberty OpenID configuration contains a parameter that manages basic authentication. The default configuration in webSecurity.xml provides a basic registry with a resExecutor user that has the resExecutors role, as illustrated in the following code sample. -> ```xml -> -> -> -> -> -> -> -> -> -> ``` -> So you can call a decision service like this: -> ``` -> curl -H "Content-Type: application/json" -k --data @loanvalidation.json \ -> -H "Authorization: Basic cmVzRXhlY3V0b3I6cmVzRXhlY3V0b3I=" \ -> https://DecisionServerRuntime:Port/DecisionService/rest/LoanValidationDS/1.0/loan_validation_with_score_and_grade/1.0 -> ``` -> Where `cmVzRXhlY3V0b3I6cmVzRXhlY3V0b3I=` is the base64 encoding of the current username:password resExecutor:resExecutor -> -> You can modify the default basic registry, users, and groups by modifying the webSecurity.xml file. - -- If you want to call the REST API, you must get an access token by running a cURL command with the following endpoint: -`https:///oidc/endpoint//token`. - - You can then authenticate with the "Bearer ". For more information, see How a Liberty-based application obtains an access token from UMS SSO. - - The following diagram shows the API invocations with an external OIDC provider. - - ![ODM service API invocations](images/diag_oidc_other_interaction_api.jpg) - - For more information, see [Invoking the Token Endpoint for OpenID Connect](https://www.ibm.com/docs/en/was-liberty/zos?topic=liberty-invoking-token-endpoint-openid-connect). - -- The following OIDC groups provide an example of how to map these ODM roles. - - oidcFullAccess, a group to manage all ODM roles. - - oidcRtsAdministrator, a group for the `rtsAdministrators` role. - - oidcRtsConfigManager, a group for the `rtsConfigManagers` role. - - oidcRtsInstaller, a group for the `rtsInstallers` role. - - oidcResAdministrator, a group for the `resAdministrators` role. - - oidcResMonitor, a group for the `resMonitors` role. - - oidcResExecutor, a group for the `resExecutors` role. - - oidcResDeployer, a group for the `resDeployers` role. - - The users and groups must be defined in the OpenID server. The names that you intend to use must exist in an associated registry so that they can be mapped to an ODM user or group. - -- The following OpenID server definition shows an example of this mapping with a group `group:o=defaultWIMFileBasedRealm/oidcAllRoles` defined in a basic registry, and a group `group:o=defaultWIMFileBasedRealm/cn=oidcRtsAdministrator,ou=memberlist,ou=examplegroups,o=example.org` defined in an LDAP registry. - - ```xml - - - - - - - - - - - - - - - - - - mycompanyPerson - ou=mydomain,o=example.org - - - groupOfUniqueNames - ou=memberlist,ou=examplegroups,o=example.org - - - - - ``` - - The mapping itself is done with variable definitions and key-value pairs. A cert-kubernetes/ODM/configuration/security/sample-webSecurity-OIDC.xml file can be used as a starting point to map your ODM users and groups to the users and groups. For more information about downloading cert-kubernetes, see "Preparing for an Enterprise deployment". The variable definitions in the sample file use the following scenario: - - - A user `generalAdmin` (defined through an LDAP registry). A user that has access to all applications. - - A group `oidcAllRoles` (defined through a basic registry). A group of users that has access to all applications. - - A group `oidcRtsAdministrator` (defined through an LDAP registry). A group of users that has admin access to Decision Center. - - A group `oidcRtsConfigmanager` (defined through an LDAP registry). A group of users that can configure deployments in Decision Center. - - A group `oidcResAdministrator` (defined through an LDAP registry). A group of users that has admin access to Decision Server console. - - A group `oidcResDeployer` (defined through an LDAP registry). A group of users that can deploy in Decision Server console. - - A group `oidcResMonitor` (defined through an LDAP registry). A group of users that can monitor Decision Server console. - - A group `oidcResExecutor` (defined through an LDAP registry). A group of users that can execute decisions in Decision Server Runtime. - -## Related information - -- [Configuring user access with UMS](https://www.ibm.com/docs/cloud-paks/cp-biz-automation/21.0.x?topic=access-configuring-user-ums) - -- [Configuring user access](https://www.ibm.com/docs/cloud-paks/cp-biz-automation/21.0.x?topic=manager-configuring-user-access) - -- [ODM configuration parameters](https://www.ibm.com/docs/cloud-paks/cp-biz-automation/21.0.x?topic=parameters-operational-decision-manager) - -- [Preparing to install ODM](https://www.ibm.com/docs/cloud-paks/cp-biz-automation/21.0.x?topic=capabilities-preparing-install-operational-decision-manager) - -- [User Management Services](https://www.ibm.com/docs/en/cloud-paks/cp-biz-automation/21.0.x?topic=services-ums-single-sign) diff --git a/contrib/authentication/openid/images/diag_oidc_interaction.jpg b/contrib/authentication/openid/images/diag_oidc_interaction.jpg deleted file mode 100644 index e8bd1816..00000000 Binary files a/contrib/authentication/openid/images/diag_oidc_interaction.jpg and /dev/null differ diff --git a/contrib/authentication/openid/images/diag_oidc_other_interaction_api.jpg b/contrib/authentication/openid/images/diag_oidc_other_interaction_api.jpg deleted file mode 100644 index 815d982a..00000000 Binary files a/contrib/authentication/openid/images/diag_oidc_other_interaction_api.jpg and /dev/null differ diff --git a/contrib/file-server/README.md b/contrib/file-server/README.md new file mode 100644 index 00000000..6dc8851b --- /dev/null +++ b/contrib/file-server/README.md @@ -0,0 +1,108 @@ +# Setup an Httpd file server + +For several ODM on k8s use-cases, there is the need to provide some downloadable material. +It's the case if you want to download a different driver than the one provided by default. + +It's also needed when you want to customize Decision Center using the **decisionCenter.downloadUrl** helm chart parameter. + +If you don't have on your kubernetes environment an available FTP server, or an other solution in order to propose to your ODM instance some downloadable URL, we explain below how to setup an Apache HTTP Server with upload/download capabilities using the [Bitnami HTTP Server Helm Chart](https://artifacthub.io/packages/helm/bitnami/apache) + +Obviously the following solution is a proposition and can be modified according to the real use-case. + +![File Server](images/FileServerUpload.png) + +Install the Bitnami Helm Chart + +```bash +helm repo add bitnami https://charts.bitnami.com/bitnami +helm repo update +``` + +Get the [httpd.conf](./httpd.conf) file and create the configmap to provide the httpd.conf configuration file that activate the Dav module. + +```bash +kubectl create configmap httpd-cm --from-file=httpd.conf +``` + +It's the default Apache **httpd.conf** file with the following modifications : + +- 1/ Activation of the Dav module with : + +``` +LoadModule dav_module modules/mod_dav.so +LoadModule dav_fs_module modules/mod_dav_fs.so +``` + +- 2/ Creation of a Dav lock DB directory : + +``` +DavLockDB /tmp/lock +``` + +- 3/ Enabling Dav in the default root directory : + +``` +DocumentRoot "/opt/bitnami/apache/htdocs" + +Dav On +... + +``` + +Get the [httpd-pvc.yaml](./httpd-pvc.yaml) file and create a PVC to persist all the downloads, by adapting the storage. + +```bash +kubectl create -f httpd-pvc.yaml +``` + +Get the [httpd-values.yaml](./httpd-values.yaml) file and instanciate the Apache Http file server : + +```bash +helm install fileserver bitnami/apache -f httpd-values.yaml +``` + +[Optional] Expose the service + +The service exposition is optional. It's only needed if you want to manage an upload on the file server using an external URL. +On several platform like AWS EKS, a cluster external access is provided. +For OCP, if you want to create a route providing a public URL, you have to do : + +```bash +oc expose svc fileserver-apache +``` + +If you are on OCP, you can get the fileserver route URL to upload the sample jar or zip file : + +```bash +curl -T http:// +``` + +It must generates the following output when the file is correctly uploaded. + +```bash + + + +201 Created + +

Created

+

Resource / has been created.

+ +``` + +If, for security reason, it's not allowed to expose the service, you can directly copy the **sample-file** on the file server pod after a cluster login : + +```bash +kubectl cp /:/opt/bitnami/apache/htdocs/ -n +``` + +You can check the download URL from a container inside the same cluster : + +```bash +curl http://fileserver-apache..svc.cluster.local:80/ -o +``` + +> [!IMPORTANT] +> Pay attention to manage downloads with a size adapted to the Decision Center ephemeral storage to avoid a pod eviction. + + diff --git a/contrib/file-server/httpd-pvc.yaml b/contrib/file-server/httpd-pvc.yaml new file mode 100644 index 00000000..0c8decd9 --- /dev/null +++ b/contrib/file-server/httpd-pvc.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: httpd-pvc +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 2Gi diff --git a/contrib/file-server/httpd-values.yaml b/contrib/file-server/httpd-values.yaml new file mode 100644 index 00000000..2381cb77 --- /dev/null +++ b/contrib/file-server/httpd-values.yaml @@ -0,0 +1,4 @@ +containerSecurityContext: + readOnlyRootFilesystem: false +httpdConfConfigMap: httpd-cm +htdocsPVC: httpd-pvc diff --git a/contrib/file-server/httpd.conf b/contrib/file-server/httpd.conf new file mode 100644 index 00000000..a19e96e8 --- /dev/null +++ b/contrib/file-server/httpd.conf @@ -0,0 +1,522 @@ +# +# This is the main Apache HTTP server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information. +# In particular, see +# +# for a discussion of each configuration directive. +# +# Do NOT simply read the instructions in here without understanding +# what they do. They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path. If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so "logs/access_log" +# with ServerRoot set to "/usr/local/apache2" will be interpreted by the +# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log" +# will be interpreted as '/logs/access_log'. + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# Do not add a slash at the end of the directory path. If you point +# ServerRoot at a non-local disk, be sure to specify a local disk on the +# Mutex directive, if file-based mutexes are used. If you wish to share the +# same ServerRoot for multiple httpd daemons, you will need to change at +# least PidFile. +# +ServerRoot "/opt/bitnami/apache" + +# +# Mutex: Allows you to set the mutex mechanism and mutex file directory +# for individual mutexes, or change the global defaults +# +# Uncomment and change the directory if mutexes are file-based and the default +# mutex file directory is not on a local disk or is not appropriate for some +# other reason. +# +# Mutex default:logs + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, instead of the default. See also the +# directive. +# +# Change this to Listen on specific IP addresses as shown below to +# prevent Apache from glomming onto all bound IP addresses. +# +#Listen 12.34.56.78:80 +Listen 8080 + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Statically compiled modules (those listed by `httpd -l') do not need +# to be loaded here. +# +# Example: +# LoadModule foo_module modules/mod_foo.so +# +#LoadModule mpm_event_module modules/mod_mpm_event.so +LoadModule mpm_prefork_module modules/mod_mpm_prefork.so +#LoadModule mpm_worker_module modules/mod_mpm_worker.so +LoadModule authn_file_module modules/mod_authn_file.so +#LoadModule authn_dbm_module modules/mod_authn_dbm.so +#LoadModule authn_anon_module modules/mod_authn_anon.so +#LoadModule authn_dbd_module modules/mod_authn_dbd.so +#LoadModule authn_socache_module modules/mod_authn_socache.so +LoadModule authn_core_module modules/mod_authn_core.so +LoadModule authz_host_module modules/mod_authz_host.so +LoadModule authz_groupfile_module modules/mod_authz_groupfile.so +LoadModule authz_user_module modules/mod_authz_user.so +#LoadModule authz_dbm_module modules/mod_authz_dbm.so +#LoadModule authz_owner_module modules/mod_authz_owner.so +#LoadModule authz_dbd_module modules/mod_authz_dbd.so +LoadModule authz_core_module modules/mod_authz_core.so +#LoadModule authnz_ldap_module modules/mod_authnz_ldap.so +LoadModule access_compat_module modules/mod_access_compat.so +LoadModule auth_basic_module modules/mod_auth_basic.so +#LoadModule auth_form_module modules/mod_auth_form.so +#LoadModule auth_digest_module modules/mod_auth_digest.so +#LoadModule allowmethods_module modules/mod_allowmethods.so +#LoadModule file_cache_module modules/mod_file_cache.so +#LoadModule cache_module modules/mod_cache.so +#LoadModule cache_disk_module modules/mod_cache_disk.so +#LoadModule cache_socache_module modules/mod_cache_socache.so +LoadModule socache_shmcb_module modules/mod_socache_shmcb.so +#LoadModule socache_dbm_module modules/mod_socache_dbm.so +#LoadModule socache_memcache_module modules/mod_socache_memcache.so +#LoadModule socache_redis_module modules/mod_socache_redis.so +#LoadModule watchdog_module modules/mod_watchdog.so +#LoadModule macro_module modules/mod_macro.so +#LoadModule dbd_module modules/mod_dbd.so +#LoadModule dumpio_module modules/mod_dumpio.so +#LoadModule buffer_module modules/mod_buffer.so +#LoadModule ratelimit_module modules/mod_ratelimit.so +LoadModule reqtimeout_module modules/mod_reqtimeout.so +#LoadModule ext_filter_module modules/mod_ext_filter.so +#LoadModule request_module modules/mod_request.so +#LoadModule include_module modules/mod_include.so +LoadModule filter_module modules/mod_filter.so +#LoadModule substitute_module modules/mod_substitute.so +#LoadModule sed_module modules/mod_sed.so +LoadModule deflate_module modules/mod_deflate.so +#LoadModule proxy_html_module modules/mod_proxy_html.so +LoadModule mime_module modules/mod_mime.so +#LoadModule ldap_module modules/mod_ldap.so +LoadModule log_config_module modules/mod_log_config.so +#LoadModule log_debug_module modules/mod_log_debug.so +#LoadModule logio_module modules/mod_logio.so +LoadModule env_module modules/mod_env.so +#LoadModule expires_module modules/mod_expires.so +LoadModule headers_module modules/mod_headers.so +#LoadModule unique_id_module modules/mod_unique_id.so +LoadModule setenvif_module modules/mod_setenvif.so +LoadModule version_module modules/mod_version.so +#LoadModule remoteip_module modules/mod_remoteip.so +LoadModule proxy_module modules/mod_proxy.so +LoadModule proxy_connect_module modules/mod_proxy_connect.so +LoadModule proxy_ftp_module modules/mod_proxy_ftp.so +LoadModule proxy_http_module modules/mod_proxy_http.so +LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so +#LoadModule proxy_scgi_module modules/mod_proxy_scgi.so +#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so +#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so +#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so +LoadModule proxy_ajp_module modules/mod_proxy_ajp.so +LoadModule proxy_balancer_module modules/mod_proxy_balancer.so +#LoadModule proxy_express_module modules/mod_proxy_express.so +#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so +#LoadModule session_module modules/mod_session.so +#LoadModule session_cookie_module modules/mod_session_cookie.so +#LoadModule session_dbd_module modules/mod_session_dbd.so +LoadModule slotmem_shm_module modules/mod_slotmem_shm.so +LoadModule ssl_module modules/mod_ssl.so +#LoadModule http2_module modules/mod_http2.so +#LoadModule proxy_http2_module modules/mod_proxy_http2.so +#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so +#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so +#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so +#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so +LoadModule unixd_module modules/mod_unixd.so +LoadModule dav_module modules/mod_dav.so +LoadModule status_module modules/mod_status.so +LoadModule autoindex_module modules/mod_autoindex.so +#LoadModule info_module modules/mod_info.so +#LoadModule cgid_module modules/mod_cgid.so +LoadModule dav_fs_module modules/mod_dav_fs.so +#LoadModule vhost_alias_module modules/mod_vhost_alias.so +LoadModule negotiation_module modules/mod_negotiation.so +LoadModule dir_module modules/mod_dir.so +#LoadModule actions_module modules/mod_actions.so +#LoadModule speling_module modules/mod_speling.so +#LoadModule userdir_module modules/mod_userdir.so +LoadModule alias_module modules/mod_alias.so +LoadModule rewrite_module modules/mod_rewrite.so +#LoadModule security3_module modules/mod_security3.so + + +# +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. +# +# User/Group: The name (or #number) of the user/group to run httpd as. +# It is usually good practice to create a dedicated user and group for +# running httpd, as with most system services. +# +User daemon +Group daemon + + + +# 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. e.g. admin@your-domain.com +# +ServerAdmin you@example.com + +# +# ServerName gives the name and port that the server uses to identify itself. +# This can often be determined automatically, but we recommend you specify +# it explicitly to prevent problems during startup. +# +# If your host doesn't have a registered DNS name, enter its IP address here. +# +ServerName www.example.com:8080 + +# +# Deny access to the entirety of your server's filesystem. You must +# explicitly permit access to web content directories in other +# blocks below. +# + + AllowOverride All + Require all granted + + +DavLockDB /tmp/lock + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "/opt/bitnami/apache/htdocs" + + # + # Possible values for the Options directive are "None", "All", + # or any combination of: + # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews + # + # Note that "MultiViews" must be named *explicitly* --- "Options All" + # doesn't give it to you. + # + # The Options directive is both complicated and important. Please see + # http://httpd.apache.org/docs/2.4/mod/core.html#options + # for more information. + # + Options Indexes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews + + # + # AllowOverride controls what directives may be placed in .htaccess files. + # It can be "All", "None", or any combination of the keywords: + # AllowOverride FileInfo AuthConfig Limit + # +# AllowOverride All + Dav On + # + # Controls who can get stuff from this server. + # + Require all granted + + +# +# DirectoryIndex: sets the file that Apache will serve if a directory +# is requested. +# + + DirectoryIndex index.html + + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all granted + + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog "logs/error_log" + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + + + # + # The following directives define some format nicknames for use with + # a CustomLog directive (see below). + # + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + # You need to enable mod_logio.c to use %I and %O + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + # + # The location and format of the access logfile (Common Logfile Format). + # If you do not define any access logfiles within a + # container, they will be logged here. Contrariwise, if you *do* + # define per- access logfiles, transactions will be + # logged therein and *not* in this file. + # + CustomLog "logs/access_log" common + + # + # If you prefer a logfile with access, agent, and referer information + # (Combined Logfile Format) you can use the following directive. + # + #CustomLog "logs/access_log" combined + + + + # + # Redirect: Allows you to tell clients about documents that used to + # exist in your server's namespace, but do not anymore. The client + # will make a new request for the document at its new location. + # Example: + # Redirect permanent /foo http://www.example.com/bar + + # + # Alias: Maps web paths into filesystem paths and is used to + # access content that does not live under the DocumentRoot. + # Example: + # Alias /webpath /full/filesystem/path + # + # If you include a trailing / on /webpath then the server will + # require it to be present in the URL. You will also likely + # need to provide a section to allow access to + # the filesystem path. + + # + # ScriptAlias: This controls which directories contain server scripts. + # ScriptAliases are essentially the same as Aliases, except that + # documents in the target directory are treated as applications and + # run by the server when requested rather than as documents sent to the + # client. The same rules about trailing "/" apply to ScriptAlias + # directives as to Alias. + # + ScriptAlias /cgi-bin/ "/opt/bitnami/apache/cgi-bin/" + + + + + # + # ScriptSock: On threaded servers, designate the path to the UNIX + # socket used to communicate with the CGI daemon of mod_cgid. + # + #Scriptsock cgisock + + +# +# "/opt/bitnami/apache/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# + + AllowOverride None + Options None + Require all granted + + + + # + # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied + # backend servers which have lingering "httpoxy" defects. + # 'Proxy' request header is undefined by the IETF, not listed by IANA + # + RequestHeader unset Proxy early + + + + # + # TypesConfig points to the file containing the list of mappings from + # filename extension to MIME-type. + # + TypesConfig conf/mime.types + + # + # AddType allows you to add to or override the MIME configuration + # file specified in TypesConfig for specific file types. + # + #AddType application/x-gzip .tgz + # + # AddEncoding allows you to have certain browsers uncompress + # information on the fly. Note: Not all browsers support this. + # + #AddEncoding x-compress .Z + #AddEncoding x-gzip .gz .tgz + # + # If the AddEncoding directives above are commented-out, then you + # probably should define those extensions to indicate media types: + # + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + + # + # AddHandler allows you to map certain file extensions to "handlers": + # actions unrelated to filetype. These can be either built into the server + # or added with the Action directive (see below) + # + # To use CGI scripts outside of ScriptAliased directories: + # (You will also need to add "ExecCGI" to the "Options" directive.) + # + #AddHandler cgi-script .cgi + + # For type maps (negotiated resources): + #AddHandler type-map var + + # + # Filters allow you to process content before it is sent to the client. + # + # To parse .shtml files for server-side includes (SSI): + # (You will also need to add "Includes" to the "Options" directive.) + # + #AddType text/html .shtml + #AddOutputFilter INCLUDES .shtml + + +# +# The mod_mime_magic module allows the server to use various hints from the +# contents of the file itself to determine its type. The MIMEMagicFile +# directive tells the module where the hint definitions are located. +# +#MIMEMagicFile conf/magic + +# +# Customizable error responses come in three flavors: +# 1) plain text 2) local redirects 3) external redirects +# +# Some examples: +#ErrorDocument 500 "The server made a boo boo." +#ErrorDocument 404 /missing.html +#ErrorDocument 404 "/cgi-bin/missing_handler.pl" +#ErrorDocument 402 http://www.example.com/subscription_info.html +# + +# +# MaxRanges: Maximum number of Ranges in a request before +# returning the entire resource, or one of the special +# values 'default', 'none' or 'unlimited'. +# Default setting is to accept 200 Ranges. +#MaxRanges unlimited + +# +# EnableMMAP and EnableSendfile: On systems that support it, +# memory-mapping or the sendfile syscall may be used to deliver +# files. This usually improves server performance, but must +# be turned off when serving from networked-mounted +# filesystems or if support for these functions is otherwise +# broken on your system. +# Defaults: EnableMMAP On, EnableSendfile Off +# +#EnableMMAP off +#EnableSendfile on + +# Supplemental configuration +# +# The configuration files in the conf/extra/ directory can be +# included to add extra features or to modify the default configuration of +# the server, or you may simply copy their contents here and change as +# necessary. + +# Server-pool management (MPM specific) +#Include conf/extra/httpd-mpm.conf + +# Multi-language error messages +#Include conf/extra/httpd-multilang-errordoc.conf + +# Fancy directory listings +#Include conf/extra/httpd-autoindex.conf + +# Language settings +#Include conf/extra/httpd-languages.conf + +# User home directories +#Include conf/extra/httpd-userdir.conf + +# Real-time info on requests and configuration +#Include conf/extra/httpd-info.conf + +# Virtual hosts +#Include conf/extra/httpd-vhosts.conf + +# Local access to the Apache HTTP Server Manual +#Include conf/extra/httpd-manual.conf + +# Distributed authoring and versioning (WebDAV) +#Include conf/extra/httpd-dav.conf + +# Various default settings +#Include conf/extra/httpd-default.conf + +# Configure mod_proxy_html to understand HTML4/XHTML1 + +Include conf/extra/proxy-html.conf + + +# Secure (SSL/TLS) connections +#Include conf/extra/httpd-ssl.conf +# +# Note: The following must must be present to support +# starting without SSL on platforms with no /dev/random equivalent +# but a statically compiled-in mod_ssl. +# + +SSLRandomSeed startup builtin +SSLRandomSeed connect builtin + +Include "/opt/bitnami/apache/conf/extra/httpd-default.conf" +PidFile "/opt/bitnami/apache/var/run/httpd.pid" +TraceEnable Off +ServerTokens Prod +Include "/opt/bitnami/apache/conf/deflate.conf" +IncludeOptional "/opt/bitnami/apache/conf/vhosts/*.conf" +Include "/opt/bitnami/apache/conf/bitnami/bitnami.conf" diff --git a/contrib/file-server/images/FileServerUpload.png b/contrib/file-server/images/FileServerUpload.png new file mode 100644 index 00000000..aa3cfda9 Binary files /dev/null and b/contrib/file-server/images/FileServerUpload.png differ diff --git a/contrib/kustomize/ds-console-dedicated-node/README.md b/contrib/kustomize/ds-console-dedicated-node/README.md index 26fb1027..ae2f2ead 100644 --- a/contrib/kustomize/ds-console-dedicated-node/README.md +++ b/contrib/kustomize/ds-console-dedicated-node/README.md @@ -6,7 +6,7 @@ Use `kustomize` to scope the Decision Server Console to a dedicated node defined - [`kustomize`](https://kubectl.docs.kubernetes.io/installation/kustomize/) 3.5+ installed in your PATH - Helm 3.1 -- A running Kubernetes cluster with an annotated node. You can add a label to a node with the following command: +- In a running Kubernetes cluster with an annotated node. You can add a label to a node with the following command: ``` kubectl label nodes = ``` diff --git a/contrib/monitor/mpmetrics/README.md b/contrib/monitor/mpmetrics/README.md index ab084eb0..3195fe32 100644 --- a/contrib/monitor/mpmetrics/README.md +++ b/contrib/monitor/mpmetrics/README.md @@ -70,7 +70,7 @@ Create the monitor-secret ```shell helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION - ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager + ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### 3. Run the `helm install` command diff --git a/contrib/monitor/opentelemetry/README.md b/contrib/monitor/opentelemetry/README.md index f7f383ec..655131b9 100644 --- a/contrib/monitor/opentelemetry/README.md +++ b/contrib/monitor/opentelemetry/README.md @@ -20,15 +20,13 @@ For installations on other platforms, refer to the [Jaeger documentation](https: ## Deploy the OpenTelemetry Collector -We used the following [descriptor](https://github.com/open-telemetry/opentelemetry-go/blob/main/example/otel-collector/otel-collector.yaml) as the basis for the OTEL Collector deployment. +We used the following [descriptor](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/examples/otel-collector/otel-collector.yaml) as the basis for the OTEL Collector deployment. However, it's likely that you will encounter an error similar to: ```console 2023-07-06T17:28:37.520Z debug jaegerexporter@v0.80.0/exporter.go:106 failed to push trace data to Jaeger {"kind": "exporter", "data_type": "traces", "name": "jaeger", "error": "rpc error: code = Unimplemented desc = unknown service jaeger.api_v2.CollectorService"} ``` -A solution is provided in the following [article](https://cloudbyt.es/blog/switching-to-jaeger-otel-collector). - You can also utilize the [otel-collector.yaml](./otel-collector.yaml) file we used for this tutorial by applying it with: ```bash @@ -90,7 +88,7 @@ helm repo update ```bash $ helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION -ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager +ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### Install an IBM Operational Decision Manager release (10 min) diff --git a/contrib/secrets-store/README.md b/contrib/secrets-store/README.md index 6b599027..ba5a89ee 100644 --- a/contrib/secrets-store/README.md +++ b/contrib/secrets-store/README.md @@ -60,7 +60,7 @@ HashiCorp Vault must be up and running. An [on-prem installation description](RE - [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) already installed. - [HashiCorp Vault provider driver](https://developer.hashicorp.com/vault/tutorials/kubernetes/kubernetes-secret-store-driver) already installed - [Helm](https://helm.sh/docs/intro/install/) -- Access to Operational Decision Manager on Container 9.0.0.0 images +- Access to Operational Decision Manager on Container 9.0.0.1 images > Note: The first and second steps are described in the [companion document](README-External_Vault.md) when you use OCP. @@ -160,7 +160,7 @@ Check that you can access ODM charts: ```bash helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION -ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager +ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` #### Data to be injected in the pods diff --git a/contrib/secrets-store/values-default-vault.yaml b/contrib/secrets-store/values-default-vault.yaml index c5bd02a1..9b4ce091 100644 --- a/contrib/secrets-store/values-default-vault.yaml +++ b/contrib/secrets-store/values-default-vault.yaml @@ -3,7 +3,7 @@ license: true image: repository: cp.stg.icr.io/cp/cp4a/odm/ - tag: 9.0.0.0 + tag: 9.0.0.1 ## Optionally specify an list of imagePullSecrets. ## Secrets must be manually created in the namespace. ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ diff --git a/contrib/sticky-session/README.md b/contrib/sticky-session/README.md index c24b9331..c2cf611e 100644 --- a/contrib/sticky-session/README.md +++ b/contrib/sticky-session/README.md @@ -41,6 +41,12 @@ envsubst < ingress-ds.yaml | kubectl apply -f - The [ingress-dc.yaml](ingress-dc.yaml) configuration file uses the `nginx.ingress.kubernetes.io/affinity: cookie` annotation that enable sticky sessions. +> **Note** +> If you are on AWS/EKS and that your are using the ALB instead of NGINX Ingress Controller, [ALB annotations to manage sticky session](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/ingress/annotations/) will be : +> +> alb.ingress.kubernetes.io/target-group-attributes: stickiness.enabled=true,stickiness.lb_cookie.duration_seconds=60 +> alb.ingress.kubernetes.io/target-type: ip + ### 6. Access the ODM services   After a couple of minutes, the Ingress configuration is updated. You can then access the ODM services by retrieving the URLs with this command: diff --git a/contrib/sticky-session/ingress-dc.yaml b/contrib/sticky-session/ingress-dc.yaml index 0fefeec3..113e5d57 100644 --- a/contrib/sticky-session/ingress-dc.yaml +++ b/contrib/sticky-session/ingress-dc.yaml @@ -6,11 +6,11 @@ metadata: app: ibm-odm-prod ingressroutes: ${RELEASE_NAME} annotations: - kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/backend-protocol: https nginx.ingress.kubernetes.io/affinity: cookie spec: + ingressClassName: nginx rules: - http: paths: diff --git a/contrib/sticky-session/ingress-ds.yaml b/contrib/sticky-session/ingress-ds.yaml index d9a674c3..975eb4c8 100644 --- a/contrib/sticky-session/ingress-ds.yaml +++ b/contrib/sticky-session/ingress-ds.yaml @@ -6,10 +6,10 @@ metadata: app: ibm-odm-prod ingressroutes: ${RELEASE_NAME} annotations: - kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/backend-protocol: https spec: + ingressClassName: nginx rules: - http: paths: diff --git a/contrib/vault-initcontainer/README.md b/contrib/vault-initcontainer/README.md index 45c0db72..ea679acf 100644 --- a/contrib/vault-initcontainer/README.md +++ b/contrib/vault-initcontainer/README.md @@ -58,7 +58,7 @@ The diagram visually represents the secure flow of secrets data from the central * [Vault client](https://developer.hashicorp.com/vault/install) * [Helm v3](https://helm.sh/docs/intro/install/) * [Kustomize](https://github.com/kubernetes-sigs/kustomize/releases) - * Operational Decision Manager on Container 9.0.0.0 + * Operational Decision Manager on Container 9.0.0.1 > Note: This documentation has been tested with a HashiCorp evaluation instance. We assume that the procedure will remain the same for the commercial product. diff --git a/contrib/vault-initcontainer/openid/values-default-vault.yaml b/contrib/vault-initcontainer/openid/values-default-vault.yaml index b3fabf73..eb015cf5 100644 --- a/contrib/vault-initcontainer/openid/values-default-vault.yaml +++ b/contrib/vault-initcontainer/openid/values-default-vault.yaml @@ -11,7 +11,7 @@ usersPassword: "odmAdmin" image: repository: "cp.stg.icr.io/cp/cp4a/odm/" - tag: 9.0.0.0 + tag: 9.0.0.1 pullPolicy: IfNotPresent ## Optionally specify an list of imagePullSecrets. ## Secrets must be manually created in the namespace. diff --git a/contrib/vault-initcontainer/values-default-vault.yaml b/contrib/vault-initcontainer/values-default-vault.yaml index d05a7266..d33e3785 100644 --- a/contrib/vault-initcontainer/values-default-vault.yaml +++ b/contrib/vault-initcontainer/values-default-vault.yaml @@ -11,7 +11,7 @@ usersPassword: "odmAdmin" image: repository: "cp.stg.icr.io/cp/cp4a/odm/" - tag: 9.0.0.0 + tag: 9.0.0.1 pullPolicy: IfNotPresent ## Optionally specify an list of imagePullSecrets. ## Secrets must be manually created in the namespace. diff --git a/platform/azure/README-Azure-SQL-MI.md b/platform/azure/README-Azure-SQL-MI.md index 0bd4ec0b..d6439ae2 100644 --- a/platform/azure/README-Azure-SQL-MI.md +++ b/platform/azure/README-Azure-SQL-MI.md @@ -51,20 +51,21 @@ kubectl create secret generic --from-literal=db-user= Then you can deploy ODM with: -```bash -helm install ibmcharts/ibm-odm-prod \ - --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets= \ - --set image.tag=${ODM_VERSION:-9.0.0.0} --set service.type=LoadBalancer \ - --set externalDatabase.type=sqlserver \ - --set externalDatabase.serverName=.public..database.windows.net \ - --set externalDatabase.databaseName=odmdb \ - --set externalDatabase.port=3342 \ - --set externalDatabase.secretCredentials= \ - --set customization.securitySecretRef= \ - --set license=true --set usersPassword= +You can now install the product. +- Get the [aks-sqlmi-values.yaml](./aks-sqlmi-values.yaml) file and replace the following keys: + - `` is your registry secret name + - `` is your flexible postgres server name + - `` is the database credentials secret name + - `` is the container certificate + - `` is the password to login with the basic registry users like `odmAmin` + - `` is the name of the SQL managed instance + - `` is the identifier of the dnsZone of the SQL managed instance + +```shell +helm install ibmcharts/ibm-odm-prod --version 24.1.0 -f aks-sqlmi-values.yaml ``` -Other deployment options (especially using NGINX) and IBM License Service usage are explained in the main [README](README.md). +Other deployment options (especially using NGINX) and IBM License Service usage are explained in the [NGINX README](README-NGINX.md). ## Troubleshooting diff --git a/platform/azure/README-NGINX.md b/platform/azure/README-NGINX.md new file mode 100644 index 00000000..bf6bb972 --- /dev/null +++ b/platform/azure/README-NGINX.md @@ -0,0 +1,155 @@ +# Deploying IBM Operational Decision Manager with NGINX Ingress Controller on Azure AKS + +The aim of this complementary documentation is to explain how to replace the **AKS default Load Balancer** usage with an **NGINX Ingress Controller**. + +## Prerequisites + +You must have created an AKS cluster and set up your environment by following steps : +- [Prepare your AKS instance 30 min](README.md#prepare-your-aks-instance-30-min) +- [Create the PostgreSQL Azure instance 10 min](README.md#create-the-postgresql-azure-instance-10-min) +- [Prepare your environment for the ODM installation](README.md#prepare-your-environment-for-the-odm-installation) + +## Provision an NGINX Ingress Controller + +Installing an NGINX Ingress controller allows you to access ODM components through a single external IP address instead of the different IP addresses as seen above. It is also mandatory to retrieve license usage through the IBM License Service. + +1. Use the official YAML manifest: + + ```shell + kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0-beta.0/deploy/static/provider/cloud/deploy.yaml + ``` + +> [!NOTE] +> The version will probably change after the publication of our documentation so please refer to the actual [documentation](https://kubernetes.github.io/ingress-nginx/deploy/#azure)! + +2. Get the Ingress controller external IP address (it will appear 80 seconds or so after the resource application above): + + ```shell + kubectl get service --selector app.kubernetes.io/name=ingress-nginx --namespace ingress-nginx + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + ingress-nginx-controller LoadBalancer 10.0.78.246 20.19.105.130 80:32208/TCP,443:30249/TCP 2m12s + ingress-nginx-controller-admission ClusterIP 10.0.229.164 443/TCP 2m12s + ``` + +3. Verify the name of the new IngressClass: + + ```shell + kubectl get ingressclass + NAME CONTROLLER PARAMETERS AGE + nginx k8s.io/ingress-nginx 5h38m + ``` + + It should be "nginx" but if different please update the next command accordingly. + +## Install an ODM release with NGINX Ingress Controller + +You can reuse the secret with TLS certificate created [above](README.md#manage-adigital-certificate-10-min): + +You can now install the product. +- Get the [aks-nginx-values.yaml](./aks-nginx-values.yaml) file and replace the following keys: + - `` is your registry secret name + - `` is your flexible postgres server name + - `` is the database credentials secret name + - `` is the container certificate + - `` is the password to login with the basic registry users like `odmAmin` + +```shell +helm install ibmcharts/ibm-odm-prod --version 24.1.0 -f aks-nginx-values.yaml +``` + +> [!NOTE] +> By default, the NGINX Ingress controller does not enable sticky session. If you want to use sticky session to connect to DC, refer to [Using sticky session for Decision Center connection](../../contrib/sticky-session/README.md) + + +### Edit the file /etc/hosts on your host + +```shell +# vi /etc/hosts + mynicecompany.com +``` + +### Access the ODM services + +Check that ODM services are in NodePort type: + +```shell +kubectl get services --selector release= +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +release-odm-decisioncenter NodePort 10.0.178.43 9453:32720/TCP 16m +release-odm-decisionrunner NodePort 10.0.171.46 9443:30223/TCP 16m +release-odm-decisionserverconsole NodePort 10.0.106.222 9443:30280/TCP 16m +release-odm-decisionserverconsole-notif ClusterIP 10.0.115.118 1883/TCP 16m +release-odm-decisionserverruntime NodePort 10.0.232.212 9443:30082/TCP 16m +``` + +ODM services are available through the following URLs: + + +| SERVICE NAME | URL | USERNAME/PASSWORD +| --- | --- | --- +| Decision Server Console | https://mynicecompany.com/res | odmAdmin/\ +| Decision Center | https://mynicecompany.com/decisioncenter | odmAdmin/\ +| Decision Server Runtime | https://mynicecompany.com/DecisionService | odmAdmin/\ +| Decision Runner | https://mynicecompany.com/DecisionRunner | odmAdmin/\ + + +Where: + +* \ is the password provided to the **usersPassword** helm chart parameter + +## Install the IBM License Service and retrieve license usage + +This section explains how to track ODM usage with the IBM License Service. + +Follow the **Installation** section of the [Manual installation without the Operator Lifecycle Manager (OLM)](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.9?topic=ils-installing-license-service-without-operator-lifecycle-manager-olm) documentation. + +### Patch the IBM Licensing instance with Nginx configuration + +Get the [licensing-instance-nginx.yaml](./licensing-instance-nginx.yaml) file and run the command: + +```bash +kubectl patch IBMLicensing instance --type merge --patch-file licensing-instance-nginx.yaml -n ibm-licensing +``` + +Wait a couple of minutes for the changes to be applied. + +Run the following command to see the status of Ingress instance: + +```bash +kubectl get ingress -n ibm-licensing +``` + +You should be able to see the address and other details about `ibm-licensing-service-instance`. +``` +NAME CLASS HOSTS ADDRESS PORTS AGE +ibm-licensing-service-instance nginx * xxx.xxx.xxx.xxx 80 11m +``` + +You will be able to access the IBM License Service by retrieving the URL with this command: + +```bash +export LICENSING_URL=$(kubectl get ingress ibm-licensing-service-instance -n ibm-licensing -o jsonpath='{.status.loadBalancer.ingress[0].ip}')/ibm-licensing-service-instance +export TOKEN=$(kubectl get secret ibm-licensing-token -n ibm-licensing -o jsonpath='{.data.token}' |base64 -d) +``` + +You can access the `http://${LICENSING_URL}/status?token=${TOKEN}` URL to view the licensing usage. + +Otherwise, you can also retrieve the licensing report .zip file by running: + +```bash +curl "http://${LICENSING_URL}/snapshot?token=${TOKEN}" --output report.zip +``` + +If your IBM License Service instance is not running properly, refer to this [troubleshooting page](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.9?topic=service-troubleshooting-license). + +## Troubleshooting + +If your ODM instances are not running properly, refer to [our dedicated troubleshooting page](https://www.ibm.com/docs/en/odm/9.0.0?topic=900-troubleshooting-support). + +## Getting Started with IBM Operational Decision Manager for Containers + +Get hands-on experience with IBM Operational Decision Manager in a container environment by following this [Getting started tutorial](https://github.com/DecisionsDev/odm-for-container-getting-started/blob/master/README.md). + +# License + +[Apache 2.0](/LICENSE) diff --git a/platform/azure/README.md b/platform/azure/README.md index ff5a079d..aef3e0b6 100644 --- a/platform/azure/README.md +++ b/platform/azure/README.md @@ -43,8 +43,6 @@ Then, [create an Azure account and pay as you go](https://azure.microsoft.com/en - [Create the PostgreSQL Azure instance 10 min](#create-the-postgresql-azure-instance-10-min) - [Prepare your environment for the ODM installation](#prepare-your-environment-for-the-odm-installation) - [Install an ODM Helm release and expose it with the service type LoadBalancer 10 min](#install-an-odm-helm-release-and-expose-it-with-the-service-type-loadbalancer-10-min) -- [Create an NGINX Ingress controller](#create-an-nginx-ingress-controller) -- [Optional Install an ODM Helm release and expose it with the NGINX Ingress controller 10 min](#optional-install-an-odm-helm-release-and-expose-it-with-the-nginx-ingress-controller-10-min) - [Install the IBM License Service and retrieve license usage](#install-the-ibm-license-service-and-retrieve-license-usage) - [Troubleshooting](#troubleshooting) - [Getting Started with IBM Operational Decision Manager for Containers](#getting-started-with-ibm-operational-decision-manager-for-containers) @@ -105,14 +103,14 @@ Use the `az aks create` command to create an AKS cluster. The following example ```shell az aks create --name --resource-group --node-count 2 \ - --enable-cluster-autoscaler --min-count 2 --max-count 4 + --enable-cluster-autoscaler --min-count 2 --max-count 4 --generate-ssh-keys ``` After a few minutes, the command completes and returns JSON-formatted information about the cluster. Make a note of the newly-created Resource Group that is displayed in the JSON output (e.g. "nodeResourceGroup": "") if you have to tag it, for example: ```shell az group update --name \ - --tags Owner= Team=DBA Usage=demo Usage_desc="Azure customers support" Delete_date=2023-12-31 + --tags Owner= Team=DBA Usage=demo Usage_desc="Azure customers support" Delete_date=2024-12-31 ```         ### Set up your environment to this cluster @@ -139,21 +137,21 @@ The following example output shows the single node created in the previous steps ``` NAME STATUS ROLES AGE VERSION -aks-nodepool1-27504729-vmss000000 Ready agent 21m v1.28.5 -aks-nodepool1-27504729-vmss000001 Ready agent 21m v1.28.5 +aks-nodepool1-27504729-vmss000000 Ready agent 21m v1.29.9 +aks-nodepool1-27504729-vmss000001 Ready agent 21m v1.29.9 ``` ## Create the PostgreSQL Azure instance (10 min) ### Create an Azure Database for PostgreSQL -Create an Azure Database for PostgreSQL server by running the `az postgres server create` command. A server can contain multiple databases. +Create an Azure Database for PostgreSQL flexible server by running the `az postgres flexible-server create` command. A server can contain multiple databases. To get a good bandwidth between ODM containers and the database, choose the same location for the PostgreSQL server and for the AKS cluster. ```shell -az postgres server create --name --resource-group \ +az postgres flexible-server create --name --resource-group \ --admin-user myadmin --admin-password 'passw0rd!' \ - --sku-name GP_Gen5_2 --version 11 + --sku-name Standard_D2s_v3 --version 15 ``` > [!NOTE] @@ -163,7 +161,7 @@ Verify the database. To connect to your server, you need to provide host information and access credentials. ```shell -az postgres server show --name --resource-group +az postgres flexible-server show --name --resource-group ``` Result: @@ -171,39 +169,88 @@ Result: ```json { "administratorLogin": "myadmin", - "byokEnforcement": "Disabled", - "earliestRestoreDate": "2022-01-06T09:15:54.563000+00:00", + "administratorLoginPassword": null, + "authConfig": { + "activeDirectoryAuth": "Disabled", + "passwordAuth": "Enabled", + "tenantId": null + }, + "availabilityZone": "2", + "backup": { + "backupRetentionDays": 7, + "earliestRestoreDate": "2024-11-21T10:10:16.007641+00:00", + "geoRedundantBackup": "Disabled" + }, + "cluster": null, + "createMode": null, + "dataEncryption": { + "geoBackupEncryptionKeyStatus": null, + "geoBackupKeyUri": null, + "geoBackupUserAssignedIdentityId": null, + "primaryEncryptionKeyStatus": null, + "primaryKeyUri": null, + "primaryUserAssignedIdentityId": null, + "type": "SystemManaged" + }, "fullyQualifiedDomainName": ".postgres.database.azure.com", - "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-5242e4507709/resourceGroups//providers/Microsoft.DBforPostgreSQL/servers/", + "highAvailability": { + "mode": "Disabled", + "standbyAvailabilityZone": null, + "state": "NotEnabled" + }, + "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-cb6e4a84fda1/resourceGroups//providers/Microsoft.DBforPostgreSQL/flexibleServers/", "identity": null, - "infrastructureEncryption": "Disabled", "location": "", - "masterServerId": "", - "minimalTlsVersion": "TLSEnforcementDisabled", + "maintenanceWindow": { + "customWindow": "Disabled", + "dayOfWeek": 0, + "startHour": 0, + "startMinute": 0 + }, + "minorVersion": "8", "name": "", + "network": { + "delegatedSubnetResourceId": null, + "privateDnsZoneArmResourceId": null, + "publicNetworkAccess": "Enabled" + }, + "pointInTimeUtc": null, "privateEndpointConnections": [], - "publicNetworkAccess": "Enabled", + "replica": { + "capacity": 5, + "promoteMode": null, + "promoteOption": null, + "replicationState": null, + "role": "Primary" + }, "replicaCapacity": 5, - "replicationRole": "None", + "replicationRole": "Primary", "resourceGroup": "", "sku": { - "capacity": 2, - "family": "Gen5", - "name": "GP_Gen5_2", - "size": null, + "name": "Standard_D2s_v3", "tier": "GeneralPurpose" }, - "sslEnforcement": "Enabled", - "storageProfile": { - "backupRetentionDays": 7, - "geoRedundantBackup": "Disabled", - "storageAutogrow": "Enabled", - "storageMb": 51200 + "sourceServerResourceId": null, + "state": "Ready", + "storage": { + "autoGrow": "Disabled", + "iops": 500, + "storageSizeGb": 128, + "throughput": null, + "tier": "P10", + "type": "" + }, + "systemData": { + "createdAt": "2024-11-21T10:05:19.405443+00:00", + "createdBy": null, + "createdByType": null, + "lastModifiedAt": null, + "lastModifiedBy": null, + "lastModifiedByType": null }, "tags": null, - "type": "Microsoft.DBforPostgreSQL/servers", - "userVisibleState": "Ready", - "version": "11" + "type": "Microsoft.DBforPostgreSQL/flexibleServers", + "version": "15" } ``` @@ -214,8 +261,8 @@ Make a note of the server name that is displayed in the JSON output (e.g. "fully To make sure your database and your AKS cluster can communicate, put in place firewall rules with the following command: ```shell -az postgres server firewall-rule create --resource-group --server-name \ - --name --start-ip-address 0.0.0.0 --end-ip-address 255.255.255.255 +az postgres flexible-server firewall-rule create --resource-group --name \ + --rule-name --start-ip-address 0.0.0.0 --end-ip-address 255.255.255.255 ``` ### Create the database credentials secret for Azure PostgreSQL @@ -223,7 +270,7 @@ az postgres server firewall-rule create --resource-group --serve To secure the access to the database, create a secret that encrypts the database user and password before you install the Helm release. ```shell -kubectl create secret generic --from-literal=db-user=myadmin@ \ +kubectl create secret generic --from-literal=db-user=myadmin \ --from-literal=db-password='passw0rd!' ``` @@ -269,7 +316,7 @@ Check that you can access the ODM charts: ```shell helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION -ibmcharts/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager License By in... +ibmcharts/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager License By in... ``` ### Manage a digital certificate (10 min) @@ -305,19 +352,19 @@ az aks update --name --resource-group --load-balancer- ### Install the ODM release -You can now install the product: +> **Note** +> If you prefer to use the NGINX Ingress Controller instead of the default AKS Load Balancer, refer to [Deploying IBM Operational Decision Manager with NGINX Ingress Controller on Azure AKS](README-NGINX.md) + +You can now install the product. +- Get the [aks-values.yaml](./aks-values.yaml) file and replace the following keys: + - `` is your registry secret name + - `` is your flexible postgres server name + - `` is the database credentials secret name + - `` is the container certificate + - `` is the password to login with the basic registry users like `odmAmin` ```shell -helm install ibmcharts/ibm-odm-prod \ - --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets= \ - --set image.tag=${ODM_VERSION:-9.0.0.0} --set service.type=LoadBalancer \ - --set externalDatabase.type=postgres \ - --set externalDatabase.serverName=.postgres.database.azure.com \ - --set externalDatabase.databaseName=postgres \ - --set externalDatabase.port=5432 \ - --set externalDatabase.secretCredentials= \ - --set customization.securitySecretRef= \ - --set license=true --set usersPassword= +helm install ibmcharts/ibm-odm-prod --version 24.1.0 -f aks-values.yaml ``` Where: @@ -355,131 +402,60 @@ NAME TYPE CLUSTER-IP EXTERN You can then open a browser on `https://xxx.xxx.xxx.xxx:9453` to access Decision Center, and on `https://xxx.xxx.xxx.xxx:9443` to access Decision Server console, Decision Server Runtime, and Decision Runner. -## Create an NGINX Ingress controller - -Installing an NGINX Ingress controller allows you to access ODM components through a single external IP address instead of the different IP addresses as seen above. It is also mandatory to retrieve license usage through the IBM License Service. - -1. Use the official YAML manifest: - - ```shell - kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.6/deploy/static/provider/cloud/deploy.yaml - ``` - - > [!NOTE] - > The version will probably change after the publication of our documentation so please refer to the actual [documentation](https://kubernetes.github.io/ingress-nginx/deploy/#azure)! - -2. Get the Ingress controller external IP address (it will appear 80 seconds or so after the resource application above): - - ```shell - kubectl get service --selector app.kubernetes.io/name=ingress-nginx --namespace ingress-nginx - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - ingress-nginx-controller LoadBalancer 10.0.78.246 20.19.105.130 80:32208/TCP,443:30249/TCP 2m12s - ingress-nginx-controller-admission ClusterIP 10.0.229.164 443/TCP 2m12s - ``` - -3. Verify the name of the new IngressClass: - - ```shell - kubectl get ingressclass - NAME CONTROLLER PARAMETERS AGE - nginx k8s.io/ingress-nginx 5h38m - ``` - - It should be "nginx" but if different please update the next command accordingly. +## Install the IBM License Service and retrieve license usage -## (Optional) Install an ODM Helm release and expose it with the NGINX Ingress controller (10 min) +This section explains how to track ODM usage with the IBM License Service. -You might want to access ODM components through a single external IP address. +Follow the **Installation** section of the [Installation License Service without Operator Lifecycle Manager (OLM)](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.9?topic=ils-installing-license-service-without-operator-lifecycle-manager-olm) documentation. -### Install the product +#### a. Expose the licensing service using the AKS LoadBalancer -You can reuse the secret with TLS certificate created [above](#manage-adigital-certificate-10-min): +To expose the licensing service using the AKS LoadBalancer, run the command: -```shell -helm install ibmcharts/ibm-odm-prod \ - --set image.repository=cp.icr.io/cp/cp4a/odm --set image.pullSecrets= \ - --set image.tag=${ODM_VERSION:-9.0.0.0} \ - --set externalDatabase.type=postgres \ - --set externalDatabase.serverName=.postgres.database.azure.com \ - --set externalDatabase.databaseName=postgres \ - --set externalDatabase.port=5432 \ - --set externalDatabase.secretCredentials= \ - --set service.ingress.enabled=true --set service.ingress.tlsSecretRef= \ - --set service.ingress.tlsHosts={mynicecompany.com} --set service.ingress.host=mynicecompany.com \ - --set service.ingress.annotations={"nginx.ingress.kubernetes.io/backend-protocol: HTTPS"} \ - --set service.ingress.class=nginx \ - --set license=true --set usersPassword= +```bash +kubectl patch svc ibm-licensing-service-instance -p '{"spec": { "type": "LoadBalancer"}}' -n ibm-licensing ``` -> [!NOTE] -> By default, the NGINX Ingress controller does not enable sticky session. If you want to use sticky session to connect to DC, refer to [Using sticky session for Decision Center connection](../../contrib/sticky-session/README.md) - - -### Edit the file /etc/hosts on your host +Wait a couple of minutes for the changes to be applied. +Then, you should see an EXTERNAL-IP available for the exposed licensing service. ```shell -# vi /etc/hosts - mynicecompany.com +oc get service -n ibm-licensing +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +ibm-licensing-service-instance LoadBalancer 10.0.58.142 xxx.xxx.xxx.xxx 8080:32301/TCP 10m ``` -### Access the ODM services +#### b. Patch the IBM Licensing instance -Check that ODM services are in NodePort type: +Get the [licensing-instance.yaml](./licensing-instance.yaml) file and run the command: -```shell -kubectl get services --selector release= -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -release-odm-decisioncenter NodePort 10.0.178.43 9453:32720/TCP 16m -release-odm-decisionrunner NodePort 10.0.171.46 9443:30223/TCP 16m -release-odm-decisionserverconsole NodePort 10.0.106.222 9443:30280/TCP 16m -release-odm-decisionserverconsole-notif ClusterIP 10.0.115.118 1883/TCP 16m -release-odm-decisionserverruntime NodePort 10.0.232.212 9443:30082/TCP 16m +```bash +kubectl patch IBMLicensing instance --type merge --patch-file licensing-instance.yaml -n ibm-licensing ``` -ODM services are available through the following URLs: +Wait a couple of minutes for the changes to be applied. - -| SERVICE NAME | URL | USERNAME/PASSWORD -| --- | --- | --- -| Decision Server Console | https://mynicecompany.com/res | odmAdmin/\ -| Decision Center | https://mynicecompany.com/decisioncenter | odmAdmin/\ -| Decision Server Runtime | https://mynicecompany.com/DecisionService | odmAdmin/\ -| Decision Runner | https://mynicecompany.com/DecisionRunner | odmAdmin/\ - - -Where: - -* \ is the password provided to the **usersPassword** helm chart parameter +You can find more information and use cases on [this page](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.9?topic=configuration-configuring-kubernetes-ingress). -## Install the IBM License Service and retrieve license usage - -This section explains how to track ODM usage with the IBM License Service. - -Follow the **Installation** section of the [Manual installation without the Operator Lifecycle Manager (OLM)](https://www.ibm.com/docs/en/cpfs?topic=software-manual-installation-without-operator-lifecycle-manager-olm) documentation. Do not follow the **Creating an IBM Licensing instance** part! - -### Create the Licensing instance - -Just run: - -```shell -kubectl create -f licensing-instance.yml -n ibm-common-services -``` - -(More information and use cases on [this page](https://www.ibm.com/docs/en/cpfs?topic=software-configuration).) +> **Note** +> If you choose to use the NGINX Ingress Controller, you must use the [licensing-instance-nginx.yaml](./licensing-instance-nginx.yaml) file. Refer to [Track ODM usage with the IBM License Service with NGINX Ingress Controller](README-NGINX.md#track-odm-usage-with-the-ibm-license-service-with-nginx-ingress-controller). ### Retrieve license usage -After a couple of minutes, the NGINX load balancer reflects the Ingress configuration and you will be able to access the IBM License Service by retrieving the URL with this command: +You will be able to access the IBM License Service by retrieving the URL with this command: -```shell -export LICENSING_URL=$(kubectl get ingress ibm-licensing-service-instance --namespace ibm-common-services --no-headers | awk '{print $4}')/ibm-licensing-service-instance -export TOKEN=$(kubectl get secret ibm-licensing-token --output jsonpath={.data.token} --namespace ibm-common-services | base64 -d) +```bash +export LICENSING_URL=$(kubectl get service ibm-licensing-service-instance -n ibm-licensing -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +export TOKEN=$(kubectl get secret ibm-licensing-token -n ibm-licensing -o jsonpath='{.data.token}' |base64 -d) ``` -You can access the `http://${LICENSING_URL}/status?token=${TOKEN}` URL to view the licensing usage, or retrieve the licensing report .zip file by running: +> **Note** +> If `LICENSING_URL` is empty, take a look at the [troubleshooting](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.9?topic=service-troubleshooting-license) page. + +You can access the `http://${LICENSING_URL}:8080/status?token=${TOKEN}` URL to view the licensing usage or retrieve the licensing report .zip file by running: ```shell -curl "http://${LICENSING_URL}/snapshot?token=${TOKEN}" --output report.zip +curl "http://${LICENSING_URL}:8080/snapshot?token=${TOKEN}" --output report.zip ``` If your IBM License Service instance is not running properly, refer to this [troubleshooting page](https://www.ibm.com/docs/en/cpfs?topic=software-troubleshooting). diff --git a/platform/azure/aks-nginx-values.yaml b/platform/azure/aks-nginx-values.yaml new file mode 100644 index 00000000..f8c0a53e --- /dev/null +++ b/platform/azure/aks-nginx-values.yaml @@ -0,0 +1,27 @@ +license: true +usersPassword: + +image: + repository: cp.icr.io/cp/cp4a/odm + pullSecrets: + - + +service: + ingress: + enabled: true + class: nginx + host: mynicecompany.com + tlsHosts: + - mynicecompany.com + annotations: + nginx.ingress.kubernetes.io/backend-protocol: HTTPS + +externalDatabase: + type: postgres + secretCredentials: + port: 5432 + serverName: .postgres.database.azure.com + databaseName: postgres + +customization: + securitySecretRef: diff --git a/platform/azure/aks-sqlmi-values.yaml b/platform/azure/aks-sqlmi-values.yaml new file mode 100644 index 00000000..fb522bd5 --- /dev/null +++ b/platform/azure/aks-sqlmi-values.yaml @@ -0,0 +1,20 @@ +license: true +usersPassword: + +image: + repository: cp.icr.io/cp/cp4a/odm + pullSecrets: + - + +service: + type: LoadBalancer + +externalDatabase: + type: sqlserver + secretCredentials: + port: 3342 + serverName: .public..database.windows.net + databaseName: odmdb + +customization: + securitySecretRef: diff --git a/platform/azure/aks-values.yaml b/platform/azure/aks-values.yaml new file mode 100644 index 00000000..724649a4 --- /dev/null +++ b/platform/azure/aks-values.yaml @@ -0,0 +1,20 @@ +license: true +usersPassword: + +image: + repository: cp.icr.io/cp/cp4a/odm + pullSecrets: + - + +service: + type: LoadBalancer + +externalDatabase: + type: postgres + secretCredentials: + port: 5432 + serverName: .postgres.database.azure.com + databaseName: postgres + +customization: + securitySecretRef: diff --git a/platform/azure/licensing-instance.yml b/platform/azure/licensing-instance-nginx.yaml similarity index 100% rename from platform/azure/licensing-instance.yml rename to platform/azure/licensing-instance-nginx.yaml diff --git a/platform/azure/licensing-instance.yaml b/platform/azure/licensing-instance.yaml new file mode 100644 index 00000000..db37e81a --- /dev/null +++ b/platform/azure/licensing-instance.yaml @@ -0,0 +1,8 @@ +apiVersion: operator.ibm.com/v1alpha1 +kind: IBMLicensing +metadata: + name: instance +spec: + apiSecretToken: ibm-licensing-token + datasource: datacollector + httpsEnable: false diff --git a/platform/ecs/README.md b/platform/ecs/README.md new file mode 100644 index 00000000..795f48e5 --- /dev/null +++ b/platform/ecs/README.md @@ -0,0 +1,386 @@ +# Deploying IBM Operational Decision Manager on Amazon ECS Fargate (BETA) + +This tutorial demonstrates how to deploy an IBM® Operational Decision Manager (ODM) topology on Amazon ECS Fargate with the help of ECS Compose-x tool. + +

+**Table of Contents** + + +- [Deploying IBM Operational Decision Manager on Amazon ECS Fargate BETA](#deploying-ibm-operational-decision-manager-on-amazon-ecs-fargate-beta) + - [Pre-requisite](#1-pre-requisite) + - [Prepare your environment for the ODM installation](#2-prepare-your-environment-for-the-odm-installation) + - [Login to AWS](#21-login-to-aws) + - [Create RDS Database](#22-create-rds-database) + - [Create a secret for the Entitled registry access](#23-create-a-secret-for-the-entitled-registry-access) + - [Retrieve your entitled registry key](#231-retrieve-your-entitled-registry-key) + - [Create a JSON file](#232-create-a-json-file) + - [Create the secret in ASW Secrets Manager:](#233-create-the-secret-in-asw-secrets-manager) + - [Create S3 bucket and IAM policy for IBM licensing service](#24-create-s3-bucket-and-iam-policy-for-ibm-licensing-service) + - [Add Outbound rule to Load balancer's security group](#25-add-outbound-rule-to-load-balancers-security-group) + - [Initialize ECS Compose-X](#26-initialize-ecs-compose-x) + - [Store Amazon Root CA For HTTPS mode only](#27-store-amazon-root-ca-for-https-mode-only) + - [Deploy ODM to AWS ECS Fargate](#3-deploy-odm-to-aws-ecs-fargate) + - [Edit docker-compose file](#31-edit-docker-compose-file) + - [HTTP mode](#311-http-mode) + - [HTTPS mode](#312-https-mode) + - [Create the AWS CloudFormation stacks](#32-create-the-aws-cloudformation-stacks) + - [Configure inbound rule on RES security group:](#33-configure-inbound-rule-on-res-security-group) + - [Access ODM services:](#34-access-odm-services) + - [Edit Server configurations in Decision Center](#35-edit-server-configurations-in-decision-center) + - [Cleaup AWS CloudFormation stack](#4-cleaup-aws-cloudformation-stack) + - [AWS CloudFormation console:](#41-aws-cloudformation-console) + - [AWS Cli command](#42-aws-cli-command) + + + + +## 1. Pre-requisite + +To deploy ODM containers on AWS ECS Fargate from [docker-compose](docker-compose-http.yaml) file, you must meet the following requirements: + + * Install the latest version of [AWS Cli](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). + * Install the latest version of Podman. + * Install python3.6+ and later version. + * Ensure you have an [AWS Account](https://aws.amazon.com/getting-started/). + * Install [ECS Compose-x](https://github.com/compose-x/ecs_composex?tab=readme-ov-file#installation), preferably in a virtual environment. + * Ensure that you have an existing internet-facing Application Elastic Load balancer and a VPC with public subnets [setup](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-manage-subnets.html) on Amazon Web Services(AWS). + * If you want to run ODM Decision services in HTTPS mode, you need to have an [ACM public certificate](https://console.aws.amazon.com/acm/home). + +*Note*: The commands and tools have been tested on macOS. + +## 2. Prepare your environment for the ODM installation + +### 2.1 Login to AWS + +``` +export REGION= +export AWSACCOUNTID= +aws ecr get-login-password --region ${REGION} | podman login --username AWS --password-stdin ${AWSACCOUNTID}.dkr.ecr.${REGION}.amazonaws.com +``` +where +- `REGION`: AWS Regions where you want to deploy your services +- `AWSACCOUNTID`: your AWS account ID + +### 2.2 Create RDS Database + +In this tutorial, we will create an Amazon RDS database instance that can be used by ODM. + +- Run the following command to create the postgres database instance: +``` +aws rds create-db-instance \ + --db-instance-identifier "odm-rds" \ + --db-name "odmdb" \ + --engine 'postgres' \ + --engine-version '13' \ + --auto-minor-version-upgrade \ + --allocated-storage 50 \ + --max-allocated-storage 100 \ + --db-instance-class 'db.t3.large' \ + --master-username "odmusername" \ + --master-user-password "odmpassword" \ + --port "5432" \ + --publicly-accessible \ + --storage-encrypted \ + --tags Key=project,Value=odm +``` +- Note down the RDS instance endpoint, you will assign it to the `DB_SERVER_NAME` parameter under `environment` section of each ODM service in the docker-compose file. + +### 2.3 Create a secret for the Entitled registry access + +To get access to the ODM material, you must have an IBM entitlement registry key to pull the images from the IBM Entitled registry. +It will be used in the next step of this tutorial. + +#### 2.3.1 Retrieve your entitled registry key + +- Log in to [MyIBM Container Software Library](https://myibm.ibm.com/products-services/containerlibrary) with the IBMid and password that are associated with the entitled software. + +- In the Container software library tile, verify your entitlement on the View library page, and then go to *Get entitlement key* to retrieve the key. + +#### 2.3.2 Create a JSON file + +- Create a `token.json` file with that format. +```json +{ + "username":"cp", + "password":"" +} +``` + +#### 2.3.3 Create the secret in ASW Secrets Manager + +You can proceed to create an AWS Secret containing the `token.json` file. The secret with the pull credential will be assigned in the docker-compose file. + +- Create the secret using the following AWS Cli command. For more information, see [Create an AWS Secrets Manager secret](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html). + +``` +aws secretsmanager create-secret \ + --name IBMCPSecret \ + --secret-string file://token.json +``` + +*Result*: +``` +{ + "ARN": "arn:aws:secretsmanager:::secret:IBMCPSecret-YYYYY", + "Name": "IBMCPSecret", + "VersionId": "..." +} +``` + +- Note down the secret's ARN. You will assign it to the `x-aws-pull_credentials` custom extension along with the image URI of each ODM service in the docker-compose file. +For example: +``` + odm-decisioncenter: + image: cp.icr.io/cp/cp4a/odm/odm-decisioncenter:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-YYYYY" + ... + odm-decisionserverruntime: + image: cp.icr.io/cp/cp4a/odm/odm-decisionserverruntime:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-YYYYY" + ... +``` + +### 2.4 Create S3 bucket and IAM policy for IBM licensing service + +In this tutorial, we have included IBM Licensing service for tracking license usage of ODM that is deployed on AWS ECS Fargate. + +The following steps are needed by IBM Licensing service: + +- Create a S3 bucket in AWS for storing the IBM software license usage data. The name of the bucket must follow the `ibm-license-service-` pattern. + +- Add a IAM policy with read and write access, and define it on the S3 bucket. + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "Statement1", + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObject" + ], + "Resource": "arn:aws:s3:::ibm-license-service-/*" + } + ] +} +``` + +- You will assign this policy to the `x-aws-policies` custom extension of each service in the docker-compose file. +``` + x-aws-policies: + - arn:aws:iam:::policy/ +``` + +For more information, see [Tracking license usage on AWS ECS Fargate](https://www.ibm.com/docs/en/cloud-paks/foundational-services/3.23?topic=platforms-tracking-license-usage-aws-ecs-fargate). + +### 2.5 Add Outbound rule to Load balancer's security group + +Verify that the outbound configuration of the security group of your existing loadbalancer is having "Allow all outbound traffic". However, if you have restricted outbound security group settings, then you must add an addition outbound rule to allow "Custom TCP" port range of `9060 - 9082` . These ports are for ODM Decision services in HTTP mode. For HTTPS mode, the port range should be `9653 - 9953`. + +- Access to [EC2 Loadbalancer](https://console.aws.amazon.com/ec2/home?#LoadBalancers:) console. +- Click on the load balancer that you want to define in the docker-compose file. +- Click `Security` tab and then click on the security group. +- Click `Outbound rules` tab, `Edit outbound rules` button and add the outbound rule as shown below: +
+ +### 2.6 Initialize ECS Compose-X + +You will need to setup some permissions to validate the AWS CloudFormation (CFN) templates, Lookup AWS resources and etc when using ECS Compose-X commands. For more information about the configuration, see [AWS Account configuration](https://github.com/compose-x/ecs_composex/blob/main/docs/requisites.rst#aws-account-configuration) and [Permissions to upload files to S3](https://github.com/compose-x/ecs_composex/blob/main/docs/requisites.rst#permissions-to-upload-files-to-s3). If your AWS account has administrator permissions, then it is not required to do so. + +Upon setting up the appropriate permissions, run this `ecs-compose-x` command which enables some ECS settings and create a default S3 bucket [required by ECS Compose-X](https://github.com/compose-x/ecs_composex/blob/main/docs/requisites.rst#aws-ecs-settings): +``` +ecs-compose-x init +``` + +Result: +``` +2024-06-19 11:39:37 [ INFO] ECS Setting awsvpcTrunking set to 'enabled' +2024-06-19 11:39:37 [ INFO] ECS Setting serviceLongArnFormat set to 'enabled' +2024-06-19 11:39:37 [ INFO] ECS Setting taskLongArnFormat set to 'enabled' +2024-06-19 11:39:37 [ INFO] ECS Setting containerInstanceLongArnFormat set to 'enabled' +2024-06-19 11:39:37 [ INFO] ECS Setting containerInsights set to 'enabled' +2024-06-19 11:39:38 [ INFO] Bucket ecs-composex-- successfully created. +``` + +*NOTE*: A S3 bucket will automatically be created. It is used to store the generated CFN templates when running `ecs-compose-x` commands. + +### 2.7 Store Amazon Root CA (For HTTPS mode only) + +If you want to run ODM Decision services in HTTPS mode, it is required to provide the Amazon Root CA to ODM Decision Center for authentication purposes during ruleApp deployments and also running `Test and Simulation`. + +- Go to [Amazon Trust Services](https://www.amazontrust.com/repository/) and download [Amazon Root CA 1](https://www.amazontrust.com/repository/AmazonRootCA1.pem) in `PEM` format. +- Rename the downloaded `AmazonRootCA1.pem` file to `AmazonRootCA1.crt`. +- In the S3 bucket created by `ecs-compose-x init`, create a folder named `certificate`. +- Upload this `AmazonRootCA1.crt` file into this folder.
+- Create a new file system name `odm-filesystem` in [Amazon EFS](https://console.aws.amazon.com/efs/home) using the same VPC where you plan to create ECS Fargate cluster with ODM services. This file system will be used as a volume for Decision Center. See : +``` +volumes: + app: + x-efs: + Lookup: + Tags: + Name: odm-filesystem +... + odm-decisioncenter: + image: cp.icr.io/cp/cp4a/odm/odm-decisioncenter:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-XXXXXX" + volumes: + - app:/config/security/trusted-cert-volume +``` +- At [AWS DataSync](https://console.aws.amazon.com/datasync), create a new task for data transfer and synchronization between the S3 bucket `certificate` folder and `odm-filesystem`. + - Step 1: Configure source location. + - Select *Location type*: `Amazon S3`, *Region*, *S3 bucket*. In *Folder* field, and enter `/certificate`. Auto-generate the IAM role. Click `Next`. +
+ + - Step 2: Configure destination location. + - Select *Location type*: `Amazon EFS file system`, *Region*, *File System*: `odm-filesystem` and *Mount path*: `/`. Choose the appropriate subnet (that this filesystem will be accessed) and the security group (that can access this file system). Click `Next`. +
+ + - Step 3: Configure settings. + - Give a name to the datasync. Use the default options and click `Next` to `Review` page. +
+ - Step 4: Review + - Verify the details and click `Create Task` to create the task. + +- After the task is created, you can launch data synchronising using `Start with defaults`. +
+ - Wait for a few minutes and check the status at `Task history`. It should be successful.
+ - If the task failed with this following error, the security group that you configured at Step 2 does not allow ingress and egress on port 2049.
+ - Make sure to add an inbound and outbound rule with NFS type at port 2049 to this security group. For example:
+ +## 3. Deploy ODM to AWS ECS Fargate + +ODM can be deployed either in [HTTP](docker-compose-http.yaml) or [HTTPS](docker-compose-https.yaml) mode. Each of the ODM components are configured to be deployed as separate ECS task due to IBM licensing service which logs CPU usage per ECS task. The IBM Licensing service will be deployed to each ECS task for tracking purpose. Inspect the docker-compose file for more details. + +### 3.1 Edit docker-compose file + +#### 3.1.1 HTTP mode + +- Download the [docker-compose-http.yaml](docker-compose-http.yaml) and save this file in your working dir. +- Edit the file and assign the appropriate values in the all ``. +- For the parameter `RES_URL` that is defined in `environment` section of `odm-decisionrunner` service, look for the DNS value of your [load balancer](https://console.aws.amazon.com/ec2/home?#LoadBalancers:) and assign it to the parameter as `http://your_loadbalancer_dns/res`. This is required for running Testing and Simulation in Decision Center under ECS Fargate network. + +#### 3.1.2 HTTPS mode + +- Download the [docker-compose-https.yaml](docker-compose-https.yaml) and save this file in your working dir. +- Edit the file and assign the appropriate values in the all ``. +- In this mode, HTTPS listeners for each ODM service will be added to the load balancer. You need to assign the arn of the [ACM public certificate](https://console.aws.amazon.com/acm/home) at `x-elbv2` custom extension. The ssl policy is set to TLS1.3 `ELBSecurityPolicy-TLS13-1-2-2021-06` policy. For more information, see [Create an HTTPS listener for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies). + +``` +x-elbv2: + public-alb: + Lookup: + loadbalancer: + Tags: + : +... + Listeners: + # Declare to use port=443, protocal=HTTPS and the access paths for each ODM components + # If the port is used, change it to another value. + - Port: 443 + Protocol: HTTPS + # Make sure there is ACM public certificate that can be applied on ELB for HTTPS purpose + Certificates: + - CertificateArn: arn:aws:acm:::certificate/XXXX-YYYY + SslPolicy: ELBSecurityPolicy-TLS13-1-2-2021-06 + ``` +- For the parameter `RES_URL` that is defined in `environment` section of `odm-decisionrunner` service, look for the DNS value of your [load balancer](https://console.aws.amazon.com/ec2/home?#LoadBalancers:) and assign it to the parameter as `https://your_loadbalancer_dns/res`. This is required for running `Testing and Simulation` in Decision Center. + + +### 3.2 Create the AWS CloudFormation stacks + +- Run the following command to generate the CFN templates, validate the templates, and create the stacks in CFN. + +``` +ecs-compose-x up -n odm-stack -b -f docker-compose-http.yaml -d outputdir +``` + +- Sign in to the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation/home?) to monitor the stacks (root, CloudMap, IAM, elbv2, service networking, and odm services) creation status. +
+- If all the stacks complete without error, go to [Elastic Container Service](https://console.aws.amazon.com/ecs/v2/home?) to look for the newly created cluster named `odm-stack`. + +### 3.3 Configure inbound rule on RES security group + +- Click on the cluster and you will find 4 services with their respective tasks starting up : +
+ +As Decision Server Console and Decision Server Runtime are deployed as separate services for IBM license tracking and scalability, an addition setup is required to allow Decision Server Runtime to connect to the notification server of Decision Server Console. + +- Under the `Services` tab, click on `odm-stack-res-XXX` service. + +- At the `odm-stack-res-XXX` page, click the `Configuration and networking` tab. + +- Under `Network configuration` section, click on the security group `sg-YYYYY`. The security group configuration of the RES service will be displayed. + +- Click the `Edit inbound rules` button, and update the rule that defines custom TCP port:1883. + - Change the default security group to the security group of Decision Server Runtime. + - Update the description to `From runtime to res on port 1883`. + - Save the rules. +

+*Tips:* Enter `runtime` in the *Source* field to filter the list of existing security groups + +After saving the inbound rules, wait for all the services to be `Active` and that their respective tasks are in running state. Check the logs of the `odm-decisionserverruntime` containers. If the following exception persists, restart the Decision Server Runtime `odm-stack-runtime-YYY` service to be sure that the changes to the security rules are well taken into account. + +``` +com.ibm.rules.res.notificationserver.internal.ClientConnectionHandler$1 operationComplete GBRXX0102W: Rule Execution Server console : Client 66325de3-3537-4f56-8cc4-ede3460d6427 was unable to perform handshake with the notification server. It will disconnect and then try to reconnect. For details, see the exception trace.... +``` + +Follow these steps to restart: + +- Go back to `odm-stack`, click on `odm-stack-runtime-YYY` service. + +- Click the `Update service` button and check the `Force new deployment` checkbox on the top of the page. + +- Click the `Update` button to restart the service. You should see that the service is updated and a new deployment with `In progress` state as such: +
+ +- When the deployment is complete, verify in the runtime log that the client is connected to the notification server: + +``` +[10/7/24, 17:17:49:451 CEST] 00000040 mbean I com.ibm.rules.res.notificationserver.internal.DefaultNotificationServerClient$1 serviceActivated GBRXX0119I: Rule Execution Server console : Client d6bcf2c5-26e3-4373-9e3f-3e33baf36b52 is connected to server odm-decisionserverconsole:1883. +... + +[10/7/24, 17:17:50:592 CEST] 00000042 mbean I com.ibm.rules.res.notificationserver.internal.ClientConnectionHandler$1 operationComplete GBRXX0103I: Rule Execution Server console : Client d6bcf2c5-26e3-4373-9e3f-3e33baf36b52 performed handshake with the notification server. +``` + +### 3.4 Access ODM services + +- Access to [EC2 Loadbalancer](https://console.aws.amazon.com/ec2/home?#LoadBalancers:) console. +- Click on the load balancer that you have defined in your [docker-compose](docker-compose-http.yaml) file. +- Verify that the listener rules for the ODM services are added and the target groups are in healthy state. +- Copy the load balancer's DNS name. +- Depending on HTTP or HTTPS mode, the URLs for the ODM components are as follows: + - `http:///decisioncenter` or `https:///decisioncenter` + - `http:///res` or `https:///res` + - `http:///DecisionService` or `https:///DecisionService` + - `http:///DecisionRunner` or `https:///DecisionRunner` + +### 3.5 Edit Server configurations in Decision Center + +- Login to Decision Center with `odmAdmin` user. +- Click on `Administration` tab and then `Servers` tab. +- Edit `Decision Service Execution` configuration and update the `Server URL` to `http:///res`. If HTTPS mode, use `https://`. +- Test the connection. If the test is successful, save the changes. +
+- Repeat the same for `Test and Simulation Execution` configuration. Update the `Server URL` to `http:///DecisionRunner`. If HTTPS mode, use `https://`. Test and then save the changes. + +## 4. Cleaup AWS CloudFormation stack + +To remove the base stack and its nested stacks, there are 2 options. + +### 4.1 AWS CloudFormation console +- Access to the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation/home?). +- Select the base stack `odm-stack` and click `Delete` button. + +### 4.2 AWS Cli command + +```console +aws --region cloudformation delete-stack \ +--stack-name odm-stack +``` + +## License + +[Apache 2.0](/LICENSE) diff --git a/platform/ecs/docker-compose-http.yaml b/platform/ecs/docker-compose-http.yaml new file mode 100644 index 00000000..b9b023bf --- /dev/null +++ b/platform/ecs/docker-compose-http.yaml @@ -0,0 +1,327 @@ +# Docker-compose file with ECS-compose-x extensions to create a ECS Fargate stack with ODM deployment in HTTP +version: "3.8" + +# To create a namespace in CloudMap required by Service Connect +x-cloudmap: + PrivateNamespace: + Name: odm-namespace + +# To declare that the network for the ODM applications is via PublicSubnets +networks: + application: + x-vpc: PublicSubnets + +# To lookup and use an existing VPC in AWS +x-vpc: + Lookup: + VpcId: + Tags: + - Name: + AppSubnets: {} + PublicSubnets: + Tags: + - : + PrivateSubnets: {} + StorageSubnets: {} + +# To lookup an existing internet-facing Application Load balancer and setup Listener rules on it +x-elbv2: + public-alb: + Lookup: + loadbalancer: + Tags: + : + MacroParameters: + Ingress: + ExtSources: + - IPv4: "0.0.0.0/0" + Description: ANY + Properties: + Scheme: internet-facing + Type: application + Listeners: + # Declare to use port=80, protocol=HTTP and the access paths for each ODM components + # If the port is used, change it to another value. + - Port: 80 + Protocol: HTTP + Targets: + - name: res:odm-decisionserverconsole + access: /res + - name: res:odm-decisionserverconsole + access: /res/* + - name: rts:odm-decisioncenter + access: /decisioncenter + - name: rts:odm-decisioncenter + access: /decisioncenter/* + - name: rts:odm-decisioncenter + access: /decisioncenter-api/* + - name: test:odm-decisionrunner + access: /DecisionRunner + - name: test:odm-decisionrunner + access: /DecisionRunner/* + - name: runtime:odm-decisionserverruntime + access: /DecisionService + - name: runtime:odm-decisionserverruntime + access: /DecisionService/* + # Target groups + Services: + res:odm-decisionserverconsole: + port: 9080 + protocol: HTTP + healthcheck: 9080:HTTP:/res/login.jsf:200 + rts:odm-decisioncenter: + port: 9060 + protocol: HTTP + healthcheck: 9060:HTTP:/decisioncenter/healthCheck:200 + # Enable session stickiness + TargetGroupAttributes: + stickiness.enabled: "true" + test:odm-decisionrunner: + port: 9081 + protocol: HTTP + healthcheck: 9081:HTTP:/DecisionRunner:302 + runtime:odm-decisionserverruntime: + port: 9082 + protocol: HTTP + healthcheck: 9082:HTTP:/DecisionService:302 + # Set Least outstanding requests (LOR) algorithm + TargetGroupAttributes: + load_balancing.algorithm.type: least_outstanding_requests + +services: + odm-decisionserverconsole: + image: cp.icr.io/cp/cp4a/odm/odm-decisionserverconsole:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-XXXXXX" + # Optional: Set to true, to enable execute command and access the container + x-ecs: + EnableExecuteCommand: true + # To enable Service Connect with "Client and server" option + x-network: + AssignPublicIp: true + x-ecs_connect: + MacroParameters: + service_ports: + tcp_1883: + DnsName: odm-decisionserverconsole + CloudMapServiceName: odm-decisionserverconsole + x-cloudmap: PrivateNamespace + restart: always + networks: + - application + ports: + - 9080 + - 1883/tcp + environment: + - USERS_PASSWORD=odmAdmin + - HTTP_PORT=9080 + - DB_TYPE=postgres + - DB_USER= + - DB_PASSWORD= + - DB_NAME=odmdb + # Amazon RDS instance created for ODM. An example of the endpoint: odm-rds.XXXXXXX.eu-central-1.rds.amazonaws.com + - DB_SERVER_NAME= + labels: + - productName=IBM Operational Decision Manager + - productID=e32af5770e06427faae142993c691048 + - productVersion=9.0.0.1 + - productMetric=FREE + - productChargedContainers=decisionserverconsole + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + deploy: + resources: + limits: + cpus: '1' + memory: 512M + reservations: + cpus: '0.5' + memory: 512M + labels: + ecs.task.family: res + healthcheck: + test: ["CMD", "curl", "-k", "-f", "http://localhost:9080/res/login.jsf"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 50s + + odm-decisionserverruntime: + image: cp.icr.io/cp/cp4a/odm/odm-decisionserverruntime:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-XXXXXX" + x-ecs: + EnableExecuteCommand: true + # To enable Service Connect with "Client side only" option + x-network: + AssignPublicIp: true + x-ecs_connect: + MacroParameters: + x-cloudmap: PrivateNamespace + restart: always + networks: + - application + environment: + - DECISIONSERVERCONSOLE_NAME=odm-decisionserverconsole + - HTTP_PORT=9082 + - DB_TYPE=postgres + - DB_USER= + - DB_PASSWORD= + - DB_NAME=odmdb + # Amazon RDS instance created for ODM. An example of the endpoint: odm-rds.XXXXXXX.eu-central-1.rds.amazonaws.com + - DB_SERVER_NAME= + labels: + - productName=IBM Operational Decision Manager + - productID=b1a07d4dc0364452aa6206bb6584061d + - productVersion=9.0.0.1 + - productMetric=PROCESSOR_VALUE_UNIT + - productChargedContainers=decisionserverruntime + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + ports: + - 9082 + deploy: + replicas: 1 + resources: + limits: + cpus: '1' + memory: 1G + reservations: + cpus: '1' + memory: 1G + labels: + ecs.task.family: runtime + healthcheck: + test: ["CMD", "curl", "-k", "-f", "http://localhost:9082/DecisionService"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 50s + + odm-decisioncenter: + image: cp.icr.io/cp/cp4a/odm/odm-decisioncenter:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-XXXXXX" + x-ecs: + EnableExecuteCommand: true + restart: always + networks: + - application + environment: + - DECISIONSERVERCONSOLE_PORT=9080 + - DECISIONRUNNER_PORT=9081 + - HTTP_PORT=9060 + - DECISION_MODEL_DISABLED=true + - DB_TYPE=postgres + - DB_USER= + - DB_PASSWORD= + - DB_NAME=odmdb + # Amazon RDS instance created for ODM. An example of the endpoint: odm-rds.XXXXXXX.eu-central-1.rds.amazonaws.com + - DB_SERVER_NAME= + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + ports: + - 9060 + labels: + - productName=IBM Operational Decision Manager + - productID=b1a07d4dc0364452aa6206bb6584061d + - productVersion=9.0.0.1 + - productMetric=PROCESSOR_VALUE_UNIT + - productChargedContainers=decisioncenter + deploy: + replicas: 1 + resources: + limits: + cpus: '2' + memory: 4G + reservations: + cpus: '1' + memory: 1G + labels: + ecs.task.family: rts + healthcheck: + test: ["CMD", "curl", "-k", "-f", "http://localhost:9060/decisioncenter/healthCheck"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 50s + + odm-decisionrunner: + image: cp.icr.io/cp/cp4a/odm/odm-decisionrunner:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-XXXXXX" + x-ecs: + EnableExecuteCommand: true + restart: always + networks: + - application + labels: + - productName=IBM Operational Decision Manager - Non Prod + - productID=e32af5770e06427faae142993c691048 + - productVersion=9.0.0.1 + - productMetric=PROCESSOR_VALUE_UNIT + - productChargedContainers=decisionrunner + environment: + # An example of loadbalancer's DNS: loadbalancer-name-XXXXXXXX.eu-west-3.elb.amazonaws.com + - RES_URL=http:///res + - HTTP_PORT=9081 + - DB_TYPE=postgres + - DB_USER= + - DB_PASSWORD= + - DB_NAME=odmdb + # Amazon RDS instance created for ODM. An example of the endpoint: odm-rds.XXXXXXX.eu-central-1.rds.amazonaws.com + - DB_SERVER_NAME= + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + ports: + - 9081 + deploy: + replicas: 1 + resources: + limits: + cpus: '1' + memory: 1G + reservations: + cpus: '1' + memory: 1G + labels: + ecs.task.family: test + healthcheck: + test: ["CMD", "curl", "-k", "-f", "http://localhost:9081/DecisionRunner"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 50s + + # IBM License Service to track ODM license usage + # For information, see https://www.ibm.com/docs/en/was-liberty/base?topic=container-tracking-liberty-license-use-aws-ecs-fargate + ibm-license-usage-logger-for-fargate: + image: quay.io/opencloudio/ibm-license-usage-logger-for-fargate:latest + restart: always + networks: + - application + labels: + - productID=33687f02f10b4475aa7236f4cd2f94e6 + - productMetric=FREE + - productName="IBM License Usage Logger for Fargate" + environment: + - AWS_S3_BUCKET_NAME=ibm-license-service- + - AWS_S3_HTTPS_ENABLED=true + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + deploy: + replicas: 1 + labels: + ecs.task.family: res,rts,test,runtime + healthcheck: + test: ["CMD-SHELL", "./check-health.sh || exit 1"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 300s \ No newline at end of file diff --git a/platform/ecs/docker-compose-https.yaml b/platform/ecs/docker-compose-https.yaml new file mode 100644 index 00000000..28cdbf48 --- /dev/null +++ b/platform/ecs/docker-compose-https.yaml @@ -0,0 +1,339 @@ +# Docker-compose file with ECS-compose-x extensions to create a ECS Fargate stack with ODM deployment in HTTPS +version: "3.8" + +volumes: + app: + x-efs: + Lookup: + Tags: + Name: odm-filesystem + +# To create a namespace in CloudMap required by Service Connect +x-cloudmap: + PrivateNamespace: + Name: odm-https-namespace + +# To declare that the network for the ODM applications is via PublicSubnets +networks: + application: + x-vpc: PublicSubnets + +# To lookup and use an existing VPC in AWS +x-vpc: + Lookup: + VpcId: + Tags: + - Name: + AppSubnets: {} + PublicSubnets: + Tags: + - : + PrivateSubnets: {} + StorageSubnets: {} + +# To lookup an existing internet-facing Application Load balancer and setup Listener rules on it +x-elbv2: + public-alb: + Lookup: + loadbalancer: + Tags: + : + MacroParameters: + Ingress: + ExtSources: + - IPv4: "0.0.0.0/0" + Description: ANY + Properties: + Scheme: internet-facing + Type: application + Listeners: + # Declare to use port=443, protocal=HTTPS and the access paths for each ODM components + # If the port is used, change it to another value. + - Port: 443 + Protocol: HTTPS + # Make sure there is an ACM public certificate that can be applied on ELB for HTTPS purpose + Certificates: + - CertificateArn: arn:aws:acm:::certificate/XXXX-YYYY + SslPolicy: ELBSecurityPolicy-TLS13-1-2-2021-06 + Targets: + - name: res:odm-decisionserverconsole + access: /res + - name: res:odm-decisionserverconsole + access: /res/* + - name: rts:odm-decisioncenter + access: /decisioncenter + - name: rts:odm-decisioncenter + access: /decisioncenter/* + - name: rts:odm-decisioncenter + access: /decisioncenter-api/* + - name: test:odm-decisionrunner + access: /DecisionRunner + - name: test:odm-decisionrunner + access: /DecisionRunner/* + - name: runtime:odm-decisionserverruntime + access: /DecisionService + - name: runtime:odm-decisionserverruntime + access: /DecisionService/* + # Target groups + Services: + res:odm-decisionserverconsole: + port: 9853 + protocol: HTTPS + healthcheck: 9853:HTTPS:/res/login.jsf:200 + rts:odm-decisioncenter: + port: 9653 + protocol: HTTPS + healthcheck: 9653:HTTPS:/decisioncenter/healthCheck:200 + # Enable session stickiness + TargetGroupAttributes: + stickiness.enabled: "true" + test:odm-decisionrunner: + port: 9753 + protocol: HTTPS + healthcheck: 9753:HTTPS:/DecisionRunner:302 + runtime:odm-decisionserverruntime: + port: 9953 + protocol: HTTPS + healthcheck: 9953:HTTPS:/DecisionService:302 + # Set Least outstanding requests (LOR) algorithm + TargetGroupAttributes: + load_balancing.algorithm.type: least_outstanding_requests + +services: + odm-decisionserverconsole: + image: cp.icr.io/cp/cp4a/odm/odm-decisionserverconsole:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-XXXXXX" + # Optional: Set to true, to enable execute command and access the container + x-ecs: + EnableExecuteCommand: true + # To enable Service Connect with "Client and server" option + x-network: + AssignPublicIp: true + x-ecs_connect: + MacroParameters: + service_ports: + tcp_1883: + DnsName: odm-decisionserverconsole + CloudMapServiceName: odm-decisionserverconsole + x-cloudmap: PrivateNamespace + restart: always + networks: + - application + ports: + - 9853 + - 1883/tcp + environment: + - USERS_PASSWORD=odmAdmin + - HTTPS_PORT=9853 + - DB_TYPE=postgres + - DB_USER= + - DB_PASSWORD= + - DB_NAME=odmdb + # Amazon RDS instance created for ODM. An example of the endpoint: odm-rds.XXXXXXX.eu-central-1.rds.amazonaws.com + - DB_SERVER_NAME= + labels: + - productName=IBM Operational Decision Manager + - productID=e32af5770e06427faae142993c691048 + - productVersion=9.0.0.1 + - productMetric=FREE + - productChargedContainers=decisionserverconsole + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + deploy: + resources: + limits: + cpus: '1' + memory: 512M + reservations: + cpus: '0.5' + memory: 512M + labels: + ecs.task.family: res + healthcheck: + test: ["CMD", "curl", "-k", "-f", "https://localhost:9853/res/login.jsf"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 50s + + odm-decisionserverruntime: + image: cp.icr.io/cp/cp4a/odm/odm-decisionserverruntime:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-XXXXXX" + x-ecs: + EnableExecuteCommand: true + # To enable Service Connect with "Client side only" option + x-network: + AssignPublicIp: true + x-ecs_connect: + MacroParameters: + x-cloudmap: PrivateNamespace + restart: always + networks: + - application + environment: + - DECISIONSERVERCONSOLE_NAME=odm-decisionserverconsole + - HTTPS_PORT=9953 + - DB_TYPE=postgres + - DB_USER= + - DB_PASSWORD= + - DB_NAME=odmdb + # Amazon RDS instance created for ODM. An example of the endpoint: odm-rds.XXXXXXX.eu-central-1.rds.amazonaws.com + - DB_SERVER_NAME= + labels: + - productName=IBM Operational Decision Manager + - productID=b1a07d4dc0364452aa6206bb6584061d + - productVersion=9.0.0.1 + - productMetric=PROCESSOR_VALUE_UNIT + - productChargedContainers=decisionserverruntime + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + ports: + - 9953 + deploy: + replicas: 1 + resources: + limits: + cpus: '1' + memory: 1G + reservations: + cpus: '1' + memory: 1G + labels: + ecs.task.family: runtime + healthcheck: + test: ["CMD", "curl", "-k", "-f", "https://localhost:9953/DecisionService"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 50s + + odm-decisioncenter: + image: cp.icr.io/cp/cp4a/odm/odm-decisioncenter:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-XXXXXX" + volumes: + - app:/config/security/trusted-cert-volume + x-ecs: + EnableExecuteCommand: true + restart: always + networks: + - application + environment: + - DECISIONSERVERCONSOLE_PORT=9853 + - DECISIONRUNNER_PORT=9753 + - HTTPS_PORT=9653 + - DECISION_MODEL_DISABLED=true + - DB_TYPE=postgres + - DB_USER= + - DB_PASSWORD= + - DB_NAME=odmdb + # Amazon RDS instance created for ODM. An example of the endpoint: odm-rds.XXXXXXX.eu-central-1.rds.amazonaws.com + - DB_SERVER_NAME= + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + ports: + - 9653 + labels: + - productName=IBM Operational Decision Manager + - productID=b1a07d4dc0364452aa6206bb6584061d + - productVersion=9.0.0.1 + - productMetric=PROCESSOR_VALUE_UNIT + - productChargedContainers=decisioncenter + deploy: + replicas: 1 + resources: + limits: + cpus: '2' + memory: 4G + reservations: + cpus: '1' + memory: 1G + labels: + ecs.task.family: rts + healthcheck: + test: ["CMD", "curl", "-k", "-f", "https://localhost:9653/decisioncenter/healthCheck"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 50s + + odm-decisionrunner: + image: cp.icr.io/cp/cp4a/odm/odm-decisionrunner:9.0.0.1-amd64 + x-aws-pull_credentials: "arn:aws:secretsmanager:::secret:IBMCPSecret-XXXXXX" + x-ecs: + EnableExecuteCommand: true + restart: always + networks: + - application + labels: + - productName=IBM Operational Decision Manager - Non Prod + - productID=e32af5770e06427faae142993c691048 + - productVersion=9.0.0.1 + - productMetric=PROCESSOR_VALUE_UNIT + - productChargedContainers=decisionrunner + environment: + # An example of loadbalancer's DNS: loadbalancer-name-XXXXXXXX.eu-west-3.elb.amazonaws.com + - RES_URL=http:///res + - HTTPS_PORT=9753 + - DB_TYPE=postgres + - DB_USER= + - DB_PASSWORD= + - DB_NAME=odmdb + - DB_SERVER_NAME=odm-rds.cn8urma5pdl6.eu-west-3.rds.amazonaws.com + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + ports: + - 9753 + deploy: + replicas: 1 + resources: + limits: + cpus: '1' + memory: 1G + reservations: + cpus: '1' + memory: 1G + labels: + ecs.task.family: test + healthcheck: + test: ["CMD", "curl", "-k", "-f", "https://localhost:9753/DecisionRunner"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 50s + + # IBM License Service to track ODM license usage + # For information, see https://www.ibm.com/docs/en/was-liberty/base?topic=container-tracking-liberty-license-use-aws-ecs-fargate + ibm-license-usage-logger-for-fargate: + image: quay.io/opencloudio/ibm-license-usage-logger-for-fargate:latest + restart: always + networks: + - application + labels: + - productID=33687f02f10b4475aa7236f4cd2f94e6 + - productMetric=FREE + - productName="IBM License Usage Logger for Fargate" + environment: + - AWS_S3_BUCKET_NAME=ibm-license-service- + - AWS_S3_HTTPS_ENABLED=true + logging: + driver: "awslogs" + x-aws-policies: + - arn:aws:iam:::policy/ + deploy: + replicas: 1 + labels: + ecs.task.family: res,rts,test,runtime + healthcheck: + test: ["CMD-SHELL", "./check-health.sh || exit 1"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 300s \ No newline at end of file diff --git a/platform/ecs/images/ODM-ECS.drawio b/platform/ecs/images/ODM-ECS.drawio new file mode 100644 index 00000000..f4d3e9ae --- /dev/null +++ b/platform/ecs/images/ODM-ECS.drawio @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/ecs/images/ODM-ECS.png b/platform/ecs/images/ODM-ECS.png new file mode 100644 index 00000000..fb07f6bd Binary files /dev/null and b/platform/ecs/images/ODM-ECS.png differ diff --git a/platform/ecs/images/S3-certificate.png b/platform/ecs/images/S3-certificate.png new file mode 100644 index 00000000..1ad9e9df Binary files /dev/null and b/platform/ecs/images/S3-certificate.png differ diff --git a/platform/ecs/images/data-sync-ko.png b/platform/ecs/images/data-sync-ko.png new file mode 100644 index 00000000..f112fcfb Binary files /dev/null and b/platform/ecs/images/data-sync-ko.png differ diff --git a/platform/ecs/images/data-sync-ok.png b/platform/ecs/images/data-sync-ok.png new file mode 100644 index 00000000..83e96f4f Binary files /dev/null and b/platform/ecs/images/data-sync-ok.png differ diff --git a/platform/ecs/images/data-sync1.png b/platform/ecs/images/data-sync1.png new file mode 100644 index 00000000..5e11a242 Binary files /dev/null and b/platform/ecs/images/data-sync1.png differ diff --git a/platform/ecs/images/data-sync2.png b/platform/ecs/images/data-sync2.png new file mode 100644 index 00000000..90c0735e Binary files /dev/null and b/platform/ecs/images/data-sync2.png differ diff --git a/platform/ecs/images/data-sync3.png b/platform/ecs/images/data-sync3.png new file mode 100644 index 00000000..48c97933 Binary files /dev/null and b/platform/ecs/images/data-sync3.png differ diff --git a/platform/ecs/images/data-sync4.png b/platform/ecs/images/data-sync4.png new file mode 100644 index 00000000..835fc7dd Binary files /dev/null and b/platform/ecs/images/data-sync4.png differ diff --git a/platform/ecs/images/odm-stack-cfn.png b/platform/ecs/images/odm-stack-cfn.png new file mode 100644 index 00000000..49fcebb6 Binary files /dev/null and b/platform/ecs/images/odm-stack-cfn.png differ diff --git a/platform/ecs/images/odm-stack-ecs.png b/platform/ecs/images/odm-stack-ecs.png new file mode 100644 index 00000000..a635342c Binary files /dev/null and b/platform/ecs/images/odm-stack-ecs.png differ diff --git a/platform/ecs/images/res-inbound-rules.png b/platform/ecs/images/res-inbound-rules.png new file mode 100644 index 00000000..bce5f71f Binary files /dev/null and b/platform/ecs/images/res-inbound-rules.png differ diff --git a/platform/ecs/images/restart-runtime.png b/platform/ecs/images/restart-runtime.png new file mode 100644 index 00000000..63d5c0d8 Binary files /dev/null and b/platform/ecs/images/restart-runtime.png differ diff --git a/platform/ecs/images/security-group-nfs-2049.png b/platform/ecs/images/security-group-nfs-2049.png new file mode 100644 index 00000000..634eb746 Binary files /dev/null and b/platform/ecs/images/security-group-nfs-2049.png differ diff --git a/platform/ecs/images/security-group-outbound.png b/platform/ecs/images/security-group-outbound.png new file mode 100644 index 00000000..def1f91b Binary files /dev/null and b/platform/ecs/images/security-group-outbound.png differ diff --git a/platform/ecs/images/test-res-configuration.png b/platform/ecs/images/test-res-configuration.png new file mode 100644 index 00000000..19ba6f30 Binary files /dev/null and b/platform/ecs/images/test-res-configuration.png differ diff --git a/platform/eks/README-ECR.md b/platform/eks/README-ECR.md index 250359cd..8bdaa875 100644 --- a/platform/eks/README-ECR.md +++ b/platform/eks/README-ECR.md @@ -11,6 +11,7 @@ The related instructions in the online documentation are: ## Prerequisites: - Install the following tools on your bastion host (if needed, refer to [Setting up a host to mirror images to a private registry](https://www.ibm.com/docs/en/odm/9.0.0?topic=installation-setting-up-host-mirror-images-private-registry)): + - [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) - Docker or Podman - OCP CLI (oc) - [IBM ibm-pak plugin](https://github.com/IBM/ibm-pak) @@ -21,6 +22,12 @@ The related instructions in the online documentation are: - github.com for CASE files and tools - Amazon ECR +- Configure the `aws` CLI environment by running the following command: + ```bash + aws configure  + ``` + You will be prompted to provide your AWS Access Key ID, AWS Secret Access Key and the Default region name. + - Export the following environment variables (replace the placeholders ``, ``, `` and `` with actual values): ```bash @@ -65,34 +72,11 @@ The related instructions in the online documentation are: This command generates the files `images-mapping.txt` and `image-content-source-policy.yaml` at `~/.ibm-pak/data/mirror/${CASE_NAME}/${CASE_VERSION}`. The `~/.ibm-pak/mirror` directory is also created. -- For CASE versions up to 1.7.x (included), append `-` at the end of each line in `~/.ibm-pak/data/mirror/${CASE_NAME}/${CASE_VERSION}/images-mapping.txt` (where `` can be `amd64`, `ppc64le`, or `s390x`). - - - either manually, - - or by running the command below (on Linux only, not for MacOS): - - ```bash - sed -i "s/$/-${ARCHITECTURE}/" ~/.ibm-pak/data/mirror/${CASE_NAME}/${CASE_VERSION}/images-mapping.txt - ``` - - Here is an example of such a file after this modification: - - ``` - cp.icr.io/cp/cp4a/odm/dbserver@sha256:bde14b68043370e9a4e49b1f3394978c202e0d5495e0121bd7972b37a7d99c35=194826081736.dkr.ecr.eu-west-3.amazonaws.com/cp/cp4a/odm/dbserver:9.0.0.0-amd64 - cp.icr.io/cp/cp4a/odm/odm-decisioncenter@sha256:869a6a47b5c49865086242e60228eaba7292b8d2e8e56ee4b67ea4fc07d591ad=194826081736.dkr.ecr.eu-west-3.amazonaws.com/cp/cp4a/odm/odm-decisioncenter9.0.0.0-amd64 - cp.icr.io/cp/cp4a/odm/odm-decisionrunner@sha256:70824d9aa218c0b768e42a35f6dcc5f424779d1f54540a885fc9395a7a9e07c3=194826081736.dkr.ecr.eu-west-3.amazonaws.com/cp/cp4a/odm/odm-decisionrunner:9.0.0.0-amd64 - cp.icr.io/cp/cp4a/odm/odm-decisionserverconsole@sha256:9a2f71ab6b62ffc2adf84d68b9d5fcee54d91ab76b62661265a6842479f4388b=194826081736.dkr.ecr.eu-west-3.amazonaws.com/cp/cp4a/odm/odm-decisionserverconsole:9.0.0.0-amd64 - cp.icr.io/cp/cp4a/odm/odm-decisionserverruntime@sha256:b5539e7efbe410d1a874abcd20d170dabf073d91a0ad58ae69ee03b7acea92d3=194826081736.dkr.ecr.eu-west-3.amazonaws.com/cp/cp4a/odm/odm-decisionserverruntime:9.0.0.0-amd64 - ``` - - > WARNING: - For some interim fixes, the file `images-mapping.txt` need to be modified differently. The instructions can be found in the readme page of the interim fix. - - - Store authentication credentials of the source Docker registry `cp.icr.io` and the target Amazon ECR. > NOTE: You must specify the user as `cp` to log in to `cp.icr.io`. The password is your Entitlement key from the [IBM Cloud Container Registry](https://myibm.ibm.com/products-services/containerlibrary). - + - If you use Podman: > Note: by default Podman reads and stores credentials in `${XDG_RUNTIME_DIR}/containers/auth.json`. Read more [here](https://docs.podman.io/en/stable/markdown/podman-login.1.html). @@ -170,9 +154,9 @@ The related instructions in the online documentation are: - Find the Helm Chart version related to your CASE version: - For instance, if you choose the CASE version `1.8.0`, then the Helm chart version should be `24.0.0` and you should set: + For instance, if you choose the CASE version `1.9.0`, then the Helm chart version should be `24.1.0` and you should set: ```bash - export CHART_VERSION=24.0.0 + export CHART_VERSION=24.1.0 ``` You can find the Helm chart version related to a given CASE version: @@ -181,23 +165,23 @@ The related instructions in the online documentation are: - For an interim fix: click the link for your version of ODM in the page [Operational Decision Manager Interim Fixes](https://www.ibm.com/support/pages/operational-decision-manager-interim-fixes) and then check the table "Interim fix for ODM on Certified Kubernetes". - - Alternatively, you can also run the command `tree ~/.ibm-pak/data/cases/ibm-odm-prod/` (on the bastion host), and you can find the chart version number in the name of the file `ibm-odm-prod-.tgz` located in `/charts/` : + - Alternatively, you can also run the command `tree ~/.ibm-pak/data/cases/ibm-odm-prod/` (on the bastion host), and you can find the chart version number corresponding to the file `ibm-odm-prod-.tgz`. Below is an example for CASE version `1.9.0` that corresponds to Helm chart version `24.1.0` : ```bash /home/user/.ibm-pak/data/cases/ibm-odm-prod/ - └── 1.8.0 + └── 1.9.0 ├── caseDependencyMapping.csv ├── charts - │   └── ibm-odm-prod-24.0.0.tgz + │   └── ibm-odm-prod-24.1.0.tgz ├── component-set-config.yaml - ├── ibm-odm-prod-1.8.0-airgap-metadata.yaml - ├── ibm-odm-prod-1.8.0-charts.csv - ├── ibm-odm-prod-1.8.0-images.csv - ├── ibm-odm-prod-1.8.0.tgz + ├── ibm-odm-prod-1.9.0-airgap-metadata.yaml + ├── ibm-odm-prod-1.9.0-charts.csv + ├── ibm-odm-prod-1.9.0-images.csv + ├── ibm-odm-prod-1.9.0.tgz └── resourceIndexes └── ibm-odm-prod-resourcesIndex.yaml ``` -- Run the `helm install` command below: +- Run the `helm install` command below to install ODM: ```bash helm install mycompany ibm-helm/ibm-odm-prod --version ${CHART_VERSION} \ @@ -205,3 +189,6 @@ The related instructions in the online documentation are: --set image.repository=${TARGET_REGISTRY}/cp/cp4a/odm \ --values eks-values.yaml ``` + + > **Note:** + > By using `eks-values.yaml`, ODM with a PostgreSQL internal database will be installed. It requires an ALB ingress controller and a server certificate. For more information, see [Provision an AWS Load Balancer Controller](README.md#d-provision-an-aws-load-balancer-controller) and [Manage a digital certificate](README.md#4-manage-a-digital-certificate-10-min). diff --git a/platform/eks/README-NGINX.md b/platform/eks/README-NGINX.md index 03a9393d..47e24276 100644 --- a/platform/eks/README-NGINX.md +++ b/platform/eks/README-NGINX.md @@ -6,6 +6,10 @@ The aim of this complementary documentation is to explain how to replace the **A You must have created an EKS cluster and set up your environment by following step 1 of [Deploying IBM Operational Decision Manager on Amazon EKS](README.md#1-prepare-your-environment-20-min). +> **Note**: +> Make sure that AWS Load Balancer Controller is not provisioned in this cluster. + + ## Provision an NGINX Ingress Controller You can replace the [Provision an AWS Load Balancer Controller](README.md#d-provision-an-aws-load-balancer-controller) step by provisioning an NGINX Ingress Controller with the following commands. @@ -13,7 +17,7 @@ You can replace the [Provision an AWS Load Balancer Controller](README.md#d-prov ```bash helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update -helm install my-odm-nginx ingress-nginx/ingress-nginx +helm install my-odm-nginx ingress-nginx/ingress-nginx --set controller.service.annotations."service\.beta\.kubernetes\.io/aws-load-balancer-type"=nlb ``` For more information, refer to the [ingress-nginx readme](https://github.com/kubernetes/ingress-nginx/tree/main/charts/ingress-nginx#install-chart). @@ -24,11 +28,11 @@ The `my-odm-nginx` service should have an available `External-IP` when you run t kubectl get service my-odm-nginx-ingress-nginx-controller ``` -You can then go back to the [main documentation](README.md#2-create-an-rds-database-10-min). +You can then go back to the main documentation to continue [Step 2: Create an RDS database](README.md#2-create-an-rds-database-10-min) and [Step 3: Prepare your environment for the ODM installation](README.md#3-prepare-your-environment-for-the-odm-installation-5-min). ## Install an ODM release with NGINX Ingress Controller -During the helm install, you just have to replace [eks-values.yaml](./eks-values.yaml) with [eks-nginx-values.yaml](./eks-nginx-values.yaml) that contains the relevant Ingress class: `nginx` and annotation: `nginx.ingress.kubernetes.io/backend-protocol: https` +In this tutorial, you will use [eks-nginx-values.yaml](./eks-nginx-values.yaml) or [eks-rds-nginx-values.yaml](./eks-rds-nginx-values.yaml) file that contains the relevant Ingress class: `nginx` and annotation: `nginx.ingress.kubernetes.io/backend-protocol: https` for the installation. To install ODM with the AWS RDS PostgreSQL database created in [step 2](README.md#2-create-an-rds-database-10-min): @@ -37,7 +41,7 @@ To install ODM with the AWS RDS PostgreSQL database created in [step 2](README.m - ``: the initial database name defined when creating the RDS database ```bash -helm install mycompany ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 -f eks-rds-nginx-values.yaml +helm install mycompany ibm-helm/ibm-odm-prod --version 24.1.0 -f eks-rds-nginx-values.yaml ``` > **Note** @@ -49,30 +53,49 @@ helm install mycompany ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 -f eks-rds- > - Get the [eks-nginx-values.yaml](./eks-nginx-values.yaml) file: > > ```bash -> helm install mycompany ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 -f eks-nginx-values.yaml +> helm install mycompany ibm-helm/ibm-odm-prod --version 24.1.0 -f eks-nginx-values.yaml > ``` + ## Track ODM usage with the IBM License Service with NGINX Ingress Controller -Install the IBM License Service following a. section of [Track ODM usage with the IBM License Service](README.md#7-track-odm-usage-with-the-ibm-license-service) step of the documentation. +Install the IBM License Service following *7a.* section of [Track ODM usage with the IBM License Service](README.md#7-track-odm-usage-with-the-ibm-license-service) step of the documentation. + +### Patch the IBM Licensing instance with Nginx configuration -To create the IBM Licensing instance using NGINX, get the [licensing-instance-nginx.yaml](./licensing-instance-nginx.yaml) file and run the command: +Get the [licensing-instance-nginx.yaml](./licensing-instance-nginx.yaml) file and run the command: ```bash -kubectl create -f licensing-instance-nginx.yaml +kubectl patch IBMLicensing instance --type merge --patch-file licensing-instance-nginx.yaml -n ibm-licensing +``` + +Wait a couple of minutes for the changes to be applied. + +Run the following command to see the status of Ingress instance: + +```bash +kubectl get ingress -n ibm-licensing +``` + +You should be able to see the address and other details about `ibm-licensing-service-instance`. +``` +NAME CLASS HOSTS ADDRESS PORTS AGE +ibm-licensing-service-instance nginx * abcdefghijklmnopqrstuvqxyz-xxxxxxxyyyyyyzzzzzz.elb..amazonaws.com 80 11m ``` You will be able to access the IBM License Service by retrieving the URL with this command: ```bash -export LICENSING_URL=$(kubectl get ingress ibm-licensing-service-instance -n ibm-common-services -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/ibm-licensing-service-instance -export TOKEN=$(kubectl get secret ibm-licensing-token -n ibm-common-services -o jsonpath='{.data.token}' |base64 -d) +export LICENSING_URL=$(kubectl get ingress ibm-licensing-service-instance -n ibm-licensing -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')/ibm-licensing-service-instance +export TOKEN=$(kubectl get secret ibm-licensing-token -n ibm-licensing -o jsonpath='{.data.token}' |base64 -d) ``` -You can access the `http://${LICENSING_URL}/status?token=${TOKEN}` URL to view the licensing usage or retrieve the licensing report .zip file by running: +You can access the `http://${LICENSING_URL}/status?token=${TOKEN}` URL to view the licensing usage. + +Otherwise, you can also retrieve the licensing report .zip file by running: ```bash curl "http://${LICENSING_URL}/snapshot?token=${TOKEN}" --output report.zip ``` -If your IBM License Service instance is not running properly, refer to this [troubleshooting page](https://www.ibm.com/docs/en/cpfs?topic=software-troubleshooting). +If your IBM License Service instance is not running properly, refer to this [troubleshooting page](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.9?topic=service-troubleshooting-license). diff --git a/platform/eks/README.md b/platform/eks/README.md index ad645925..704c274c 100644 --- a/platform/eks/README.md +++ b/platform/eks/README.md @@ -4,6 +4,7 @@ This project demonstrates how to deploy an IBM® Operational Decision Manager (O Flow + The ODM on Kubernetes Docker images are available in the [IBM Cloud Container Registry](https://www.ibm.com/cloud/container-registry). The ODM Helm chart is available in the [IBM Helm charts repository](https://github.com/IBM/charts). ## Included components @@ -49,16 +50,16 @@ Set up your environment by [configuring the AWS CLI](https://docs.aws.amazon.com ```bash aws configure  ``` +Where you provide your `AWS Access Key ID`, `AWS Secret Access Key` and the `Default region name`. #### b. Create an EKS cluster (20 min) ```bash -eksctl create cluster --version 1.28 --alb-ingress-access - +eksctl create cluster --version 1.30 --alb-ingress-access ``` > **Note** -> The tutorial has been tested with the Kubernetes version 1.28. Check the supported kubernetes version in the [system requirement](https://www.ibm.com/support/pages/ibm-operational-decision-manager-detailed-system-requirements) page. +> The tutorial has been tested with the Kubernetes version 1.30. Check the supported kubernetes version in the [system requirement](https://www.ibm.com/support/pages/ibm-operational-decision-manager-detailed-system-requirements) page. > **Warning** > If you prefer to use the NGINX Ingress Controller instead of the ALB Load Balancer to expose ODM services, don't use the --alb-ingress-access option during the creation of the cluster ! @@ -177,7 +178,7 @@ helm repo update ```bash $ helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION -ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager +ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### 4. Manage a  digital certificate (10 min) @@ -229,7 +230,7 @@ To install ODM with the AWS RDS PostgreSQL database created in [step 2](#2-creat - `` is the initial database name defined when creating the RDS database ```bash -helm install mycompany ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 -f eks-rds-values.yaml +helm install mycompany ibm-helm/ibm-odm-prod --version 24.1.0 -f eks-rds-values.yaml ``` > **Note** @@ -239,7 +240,7 @@ helm install mycompany ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 -f eks-rds- > - `` is your AWS Account Id > >```bash ->helm install mycompany ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 -f eks-values.yaml +>helm install mycompany ibm-helm/ibm-odm-prod --version 24.1.0 -f eks-values.yaml >``` > **Note** @@ -267,6 +268,7 @@ After a couple of minutes, the ALB reflects the Ingress configuration. You can ```bash export ROOTURL=$(kubectl get ingress mycompany-odm-ingress --no-headers |awk '{print $4}') +echo $ROOTURL ``` > **Note** @@ -288,31 +290,41 @@ The ODM services are accessible from the following URLs: #### a. Install the IBM License Service -Follow the **Installation** section of the [Manual installation without the Operator Lifecycle Manager (OLM)](https://www.ibm.com/docs/en/cpfs?topic=software-manual-installation-without-operator-lifecycle-manager-olm) documentation. - -> **Warning** -> Make sure you do not follow the **Creating an IBM Licensing instance** part! +Follow the **Installation** section of the [Installation License Service without Operator Lifecycle Manager (OLM)](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.9?topic=ils-installing-license-service-without-operator-lifecycle-manager-olm) documentation. -#### b. Create the IBM Licensing instance +#### b. Patch the IBM Licensing instance Get the [licensing-instance.yaml](./licensing-instance.yaml) file and run the command: ```bash -kubectl create -f licensing-instance.yaml +kubectl patch IBMLicensing instance --type merge --patch-file licensing-instance.yaml -n ibm-licensing ``` -You can find more information and use cases on [this page](https://www.ibm.com/docs/en/cpfs?topic=software-configuration). +Wait a couple of minutes for the changes to be applied. + +Run the following command to see the status of Ingress instance: + +```bash +kubectl get ingress -n ibm-licensing +``` + +You should be able to see the address and other details about `ibm-licensing-service-instance`. +``` +NAME CLASS HOSTS ADDRESS PORTS AGE +ibm-licensing-service-instance alb * k8s-ibmlicen-ibmlicen-xxxxxxxx-yyyyyyy..elb.amazonaws.com 80 44m +``` +You can find more information and use cases on [this page](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.9?topic=configuration-configuring-kubernetes-ingress). > **Note** > If you choose to use the NGINX Ingress Controller, you must use the [licensing-instance-nginx.yaml](./licensing-instance-nginx.yaml) file. Refer to [Track ODM usage with the IBM License Service with NGINX Ingress Controller](README-NGINX.md#track-odm-usage-with-the-ibm-license-service-with-nginx-ingress-controller). #### c. Retrieving license usage -After a couple of minutes, the ALB reflects the Ingress configuration. You will be able to access the IBM License Service by retrieving the URL with this command: +The ALB address should be reflected in the Ingress configuration. You will be able to access the IBM License Service by retrieving the URL with this command: ```bash -export LICENSING_URL=$(kubectl get ingress ibm-licensing-service-instance -n ibm-common-services -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') -export TOKEN=$(kubectl get secret ibm-licensing-token -n ibm-common-services -o jsonpath='{.data.token}' |base64 -d) +export LICENSING_URL=$(kubectl get ingress ibm-licensing-service-instance -n ibm-licensing -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') +export TOKEN=$(kubectl get secret ibm-licensing-token -n ibm-licensing -o jsonpath='{.data.token}' |base64 -d) ``` > **Note** diff --git a/platform/eks/licensing-instance-nginx.yaml b/platform/eks/licensing-instance-nginx.yaml index df6ac2f3..ac0e8102 100644 --- a/platform/eks/licensing-instance-nginx.yaml +++ b/platform/eks/licensing-instance-nginx.yaml @@ -8,8 +8,7 @@ spec: httpsEnable: false ingressEnabled: true ingressOptions: + ingressClassName: nginx annotations: - kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: '/$2' - path: /ibm-licensing-service-instance(/|$)(.*) - instanceNamespace: ibm-common-services + path: /ibm-licensing-service-instance(/|$)(.*) \ No newline at end of file diff --git a/platform/eks/licensing-instance.yaml b/platform/eks/licensing-instance.yaml index c3d94174..5d8f8b06 100644 --- a/platform/eks/licensing-instance.yaml +++ b/platform/eks/licensing-instance.yaml @@ -8,9 +8,8 @@ spec: httpsEnable: false ingressEnabled: true ingressOptions: + ingressClassName: alb annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip - kubernetes.io/ingress.class: alb - path: /* - instanceNamespace: ibm-common-services + path: /* \ No newline at end of file diff --git a/platform/gcloud/README.md b/platform/gcloud/README.md index bf7dc65e..e361c6df 100644 --- a/platform/gcloud/README.md +++ b/platform/gcloud/README.md @@ -1,12 +1,12 @@ # Deploying IBM Operational Decision Manager on Google GKE -This project demonstrates how to deploy an IBM® Operational Decision Manager (ODM) clustered topology using the [container-native load balancer of GKE](https://cloud.google.com/blog/products/containers-kubernetes/container-native-load-balancing-on-gke-now-generally-available). +This project demonstrates how to deploy an IBM® Operational Decision Manager (ODM) clustered topology using the [container-native load balancer of GKE](https://cloud.google.com/kubernetes-engine/docs/concepts/container-native-load-balancing). The ODM services will be exposed using the Ingress provided by the ODM on Kubernetes Helm chart. This deployment implements Kubernetes and Docker technologies. -Here is the Google Cloud home page: https://cloud.google.com +Here is the Google Cloud home page: - +![Architecture](images/architecture.png) The ODM on Kubernetes Docker images are available in the [IBM Entitled Registry](https://www.ibm.com/cloud/container-registry). The ODM Helm chart is available in the [IBM Helm charts repository](https://github.com/IBM/charts). @@ -26,6 +26,7 @@ The commands and tools have been tested on macOS and Linux. ## Prerequisites First, install the following software on your machine: + - [gcloud CLI](https://cloud.google.com/sdk/gcloud) - [kubectl](https://kubernetes.io/docs/tasks/tools/) - [Helm v3](https://helm.sh/docs/intro/install/) @@ -40,7 +41,8 @@ Then, perform the following tasks: Without the relevant billing level, some Google Cloud resources will not be created. -> NOTE: Prerequisites and software supported by ODM 9.0.0 are listed on [the Detailed System Requirements page](https://www.ibm.com/support/pages/ibm-operational-decision-manager-detailed-system-requirements). +> [!NOTE] +> Prerequisites and software supported by ODM 9.0.0 are listed on [the Detailed System Requirements page](https://www.ibm.com/support/pages/ibm-operational-decision-manager-detailed-system-requirements). ## Steps to deploy ODM on Kubernetes from Google GKE @@ -64,8 +66,8 @@ Refer to the [GKE quickstart](https://cloud.google.com/kubernetes-engine/docs/qu After installing the `gcloud` tool, use the following command line: -``` -gcloud auth login +```shell +gcloud auth login ``` #### b. Create a GKE cluster @@ -76,49 +78,55 @@ Regions and zones (used below) can be listed respectively with `gcloud compute r - Set the project (associated to a billing account): - ``` + ```shell gcloud config set project ``` - Set the region: - ``` - gcloud config set compute/region + ```shell + gcloud config set compute/region ``` - Set the zone: - ``` - gcloud config set compute/zone + ```shell + gcloud config set compute/zone ``` - Create a cluster and [enable autoscaling](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-autoscaler). Here, we start with 6 nodes (16 max): - ``` + ```shell gcloud container clusters create \ - --release-channel=regular --cluster-version=1.28 \ + --release-channel=regular --cluster-version=1.30 \ --enable-autoscaling --num-nodes=6 --total-min-nodes=1 --total-max-nodes=16 ``` - > If you get a red warning about a missing gke-gcloud-auth-plugin, install it with `gcloud components install gke-gcloud-auth-plugin` and enable it for each kubectl command with `export USE_GKE_GCLOUD_AUTH_PLUGIN=True` ([more information](https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke)). +> [!NOTE] +> If you get a red warning about a missing gke-gcloud-auth-plugin, install it with `gcloud components install gke-gcloud-auth-plugin`. +> For Kubernetes versions lower than 1.26 you have to enable it for each kubectl command with `export USE_GKE_GCLOUD_AUTH_PLUGIN=True` ([more information](https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke)). - > NOTE: You can also create your cluster from the Google Cloud Platform using the **Kubernetes Engine** > **Clusters** panel and clicking the **Create** button - > +> [!NOTE] +> You can also create your cluster from the Google Cloud Platform using the **Kubernetes Engine** > **Clusters** panel and clicking the **Create** button +> ![Create cluster](images/create_cluster.png) #### c. Set up your environment - Create a kubeconfig to connect to your cluster: - ``` + + ```shell gcloud container clusters get-credentials ``` - > NOTE: You can also retrieve the command line to configure `kubectl` from the Google Cloud Console using the **Kubernetes Engine** > **Clusters** panel and clicking **Connect** on the dedicated cluster. - > +> [!NOTE] +> You can also retrieve the command line to configure `kubectl` from the Google Cloud Console using the **Kubernetes Engine** > **Clusters** panel and clicking **Connect** on the dedicated cluster. +> ![Connection](images/connection.png) - Check your environment If your environment is set up correctly, you should be able to get the cluster information by running the following command: - ``` + + ```shell kubectl cluster-info ``` @@ -130,11 +138,11 @@ We will use the Google Cloud Platform console to create the database instance. - Go to the [SQL context](https://console.cloud.google.com/sql), and then click the **CREATE INSTANCE** button - Click **Choose PostgreSQL** + - Database version: `PostgreSQL 15` - Instance ID: ```` - Password: ```` - Take note of this password. - - Database version: `PostgreSQL 15` - Region: ```` (must be the same as the cluster for the communication to be optimal between the database and the ODM instance) - - Keep **Multiple zones** for Zonal availability to the highest availability + - Eventually select **Multiple zones** for Zonal availability for redundancy - Expand **Show customization option** and expand **Connections** - As *Public IP* is selected by default, in Authorized networks, click the **ADD NETWORK** button, put a name and add *0.0.0.0/0* for Network, then click **DONE**. > NOTE: It is not recommended to use a public IP. In a production environment, you should use a private IP. @@ -142,24 +150,20 @@ We will use the Google Cloud Platform console to create the database instance. After the database instance is created, you can drill on the SQL instance overview to retrieve needed information to connect to this instance, like the IP address and the connection name. Take note of the **Public IP address**. - - -> NOTE: A default *postgres* database is created with a default *postgres* user. You can change the password of the postgres user in the **Users** panel by selecting the *postgres* user, and then using the **Change password** menu: -> +![Database overview](images/database_overview.png) #### b. Create the database secret for Google Cloud SQL PostgreSQL To secure access to the database, you must create a secret that encrypts the database user and password before you install the Helm release. -``` -kubectl create secret generic \ - --from-literal=db-user= \ - --from-literal=db-password=  +```shell +kubectl create secret generic odmdbsecret \ + --from-literal=db-user=postgres \ + --from-literal=db-password= ``` Where: -- `` is the secret name -- `` is the database username (default is *postgres*) + - `` is the database password (PASSWORD set during the PostgreSQL instance creation above) ### 3. Prepare your environment for the ODM installation (10 min) @@ -172,39 +176,39 @@ To get access to the ODM material, you need an IBM entitlement key to pull the i - In the Container software library tile, verify your entitlement on the **View library** page, and then go to **Get entitlement key** to retrieve the key. -#### b. Create a pull secret by running a kubectl create secret command. +#### b. Create a pull secret by running a kubectl create secret command -``` -kubectl create secret docker-registry \ +```shell +kubectl create secret docker-registry registrysecret \ --docker-server=cp.icr.io \ --docker-username=cp \ - --docker-password="" \ + --docker-password='' \ --docker-email= ``` Where: -* `` is the secret name. -* `` is the entitlement key from the previous step. Make sure you enclose the key in double-quotes. -* `` is the email address associated with your IBMid. +- `` is the entitlement key from the previous step. Make sure you enclose the key in quotes. +- `` is the email address associated with your IBMid. -> NOTE: The `cp.icr.io` value for the docker-server parameter is the only registry domain name that contains the images. You must set the docker-username to `cp` to use an entitlement key as docker-password. +> [!NOTE] +> The `cp.icr.io` value for the docker-server parameter is the only registry domain name that contains the images. You must set the docker-username to `cp` to use an entitlement key as docker-password. -Take note of the secret name so that you can set it for the *image.pullSecrets* parameter when you run a helm install command of your containers. The *image.repository* parameter will later be set to `cp.icr.io/cp/cp4a/odm`. +The *image.repository* parameter will later be set to `cp.icr.io/cp/cp4a/odm`. #### c. Add the public IBM Helm charts repository -``` +```shell helm repo add ibm-helm https://raw.githubusercontent.com/IBM/charts/master/repo/ibm-helm helm repo update ``` #### d. Check you can access ODM charts -``` +```shell helm search repo ibm-odm-prod -NAME CHART VERSION APP VERSION DESCRIPTION -ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager +NAME CHART VERSION APP VERSION DESCRIPTION +ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### 4. Manage a digital certificate (2 min) @@ -215,15 +219,15 @@ In this step, you will generate a certificate to be used by the GKE load balance If you do not have a trusted certificate, you can use OpenSSL and other cryptography and certificate management libraries to generate a certificate file and a private key to define the domain name and to set the expiration date. The following command creates a self-signed certificate (`.crt` file) and a private key (`.key` file) that accept the domain name *mynicecompany.com*. The expiration is set to 1000 days: -``` +```shell openssl req -x509 -nodes -days 1000 -newkey rsa:2048 -keyout mynicecompany.key \ -out mynicecompany.crt -subj "/CN=mynicecompany.com/OU=it/O=mynicecompany/L=Paris/C=FR" ``` #### b. Create a TLS secret with these keys -``` -kubectl create secret tls mynicecompany-crt-secret --key mynicecompany.key --cert mynicecompany.crt +```shell +kubectl create secret tls mynicecompany-tls-secret --key mynicecompany.key --cert mynicecompany.crt ``` The certificate must be the same as the one you used to enable TLS connections in your ODM release. For more information, see [Server certificates](https://www.ibm.com/docs/en/odm/9.0.0?topic=servers-server-certificates) and [Working with certificates and SSL](https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html). @@ -237,26 +241,25 @@ It automatically creates an HTTPS GKE load balancer. We will disable the ODM int - Get the [gcp-values.yaml](./gcp-values.yaml) file and replace the following keys: - - ``: the name of the secret containing the IBM Entitled Registry key - - ``: the name of the secret containing the database user and password - ``: the database IP - - ``: the database name (default is postgres) - > NOTE: You can configure the driversUrl parameter to point to the appropriate version of the Google Cloud SQL PostgreSQL driver. For more information, refer to the [Cloud SQL Connector for Java](https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#cloud-sql-connector-for-java) documentation. +> [!NOTE] +> You can configure the driversUrl parameter to point to the appropriate version of the Google Cloud SQL PostgreSQL driver. For more information, refer to the [Cloud SQL Connector for Java](https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#cloud-sql-connector-for-java) documentation. - Install the chart from IBM's public Helm charts repository: - ``` - helm install ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 -f gcp-values.yaml - ``` + ```shell + helm install ibm-helm/ibm-odm-prod --version 24.1.0 -f gcp-values.yaml + ``` - > NOTE: You might prefer to access ODM components through the NGINX Ingress controller instead of using the IP addresses. If so, please follow [these instructions](README_NGINX.md). +> [!NOTE] +> You might prefer to access ODM components through the NGINX Ingress controller instead of using the IP addresses. If so, please follow [these instructions](README_NGINX.md). #### b. Check the topology Run the following command to check the status of the pods that have been created: -``` +```shell kubectl get pods NAME READY STATUS RESTARTS AGE -odm-decisioncenter-*** 1/1 Running 0 20m @@ -271,18 +274,17 @@ To get the status of the current deployment, go to the [Kubernetes Engine / Serv The Ingress remains in the state *Creating ingress* for several minutes until the pods are up and running, and the backend gets in a healthy state. - +![Ingress creating](images/ingress_creating.png) -You can also check the [load balancer status](https://console.cloud.google.com/net-services/loadbalancing/list/loadBalancers). -It provides information about the backend using the service health check. +You can also check the [load balancer status](https://console.cloud.google.com/net-services/loadbalancing/list/loadBalancers). It provides information about the backend using the service health check. - +![Load balancer](images/lb.png) In the Ingress details, you should get a *HEALTHY* state on all backends. This panel also provides some logs on the load balancer activity. When the Ingress shows an OK status, all ODM services can be accessed. - +![Ingress details](images/ingress_details.png) #### d. Create a Backend Configuration for the Decision Center Service @@ -294,20 +296,20 @@ A configuration that uses [BackendConfig](https://cloud.google.com/kubernetes-en - Create the [Decision Center Backend Config](decisioncenter-backendconfig.yaml): - ``` + ```shell kubectl create -f decisioncenter-backendconfig.yaml ``` - Annotate the Decision Center Service with this GKE Backend Config: - ``` + ```shell kubectl annotate service -odm-decisioncenter \ - cloud.google.com/backend-config='{"ports": {"9453":"dc-backendconfig"}}' + cloud.google.com/backend-config='{"ports": {"9453":"dc-backendconfig"}}' ``` As soon as GKE manages Decision Center session affinity at the load balancer level, you can check the ClientIP availability below the Decision Center Network Endpoint Group configuration from the Google Cloud Console in the Load Balancer details. - + ![DecisionCenter session affinity](images/dc_sessionaffinity.png) ### 6. Access ODM services @@ -318,13 +320,13 @@ We only have to manage a configuration to simulate the mynicecompany.com access. - Get the EXTERNAL-IP with the command line: - ``` + ```shell kubectl get ingress -odm-ingress -o jsonpath='{.status.loadBalancer.ingress[].ip}' ``` - Edit your /etc/hosts file and add the following entry: - ``` + ```shell mynicecompany.com ``` @@ -333,14 +335,16 @@ We only have to manage a configuration to simulate the mynicecompany.com access. | SERVICE NAME | URL | USERNAME/PASSWORD | --- | --- | --- - | Decision Server Console | https://mynicecompany.com/res | odmAdmin/odmAdmin - | Decision Center | https://mynicecompany.com/decisioncenter | odmAdmin/odmAdmin - | Decision Center REST-API | https://mynicecompany.com/decisioncenter-api | odmAdmin/odmAdmin - | Decision Server Runtime | https://mynicecompany.com/DecisionService | odmAdmin/odmAdmin - | Decision Runner | https://mynicecompany.com/DecisionRunner | odmAdmin/odmAdmin + | Decision Server Console | | odmAdmin/odmAdmin + | Decision Center | | odmAdmin/odmAdmin + | Decision Center REST-API | | odmAdmin/odmAdmin + | Decision Server Runtime | | odmAdmin/odmAdmin + | Decision Runner | | odmAdmin/odmAdmin - > NOTE:You can also click the Ingress routes accessible from the Google Cloud console under the [Kubernetes Engine/Services & Ingress Details Panel](https://console.cloud.google.com/kubernetes/ingresses). - > + +> [!NOTE] +> You can also click the Ingress frontends accessible from the Google Cloud console under the [Kubernetes Engine/Services & Ingress Details Panel](https://console.cloud.google.com/kubernetes/ingresses). +> ![Ingress routes](images/ingress_routes.png) ### 7. Track ODM usage with the IBM License Service @@ -348,51 +352,51 @@ This section explains how to track ODM usage with the IBM License Service. #### a. Install the IBM License Service -Follow the **Installation** section of the [Manual installation without the Operator Lifecycle Manager (OLM)](https://www.ibm.com/docs/en/cpfs?topic=software-manual-installation-without-operator-lifecycle-manager-olm) +Follow the **Installation** section of the [Manual installation without the Operator Lifecycle Manager (OLM)](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.10?topic=ils-installing-license-service-without-operator-lifecycle-manager-olm) and stop before it asks you to update the License Service instance. It will be done in the next paragraph. -> NOTE: Make sure you do not follow the instantiation part! +#### b. Create the IBM Licensing instance -#### b. Create an NGINX Ingress controller +Get the [licensing-instance.yaml](./licensing-instance.yaml) file and run the following command: -- Add the official stable repository: +```shell +kubectl apply -f licensing-instance.yaml -n ibm-licensing +``` - ``` - helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx - helm repo update - ``` +> [!NOTE] +> You can find more information and use cases on [this page](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.10?topic=service-configuration). -- Use Helm to deploy the NGINX Ingress controller: +#### c. Modify GKE Load Balancer settings - ``` - helm install nginx-ingress ingress-nginx/ingress-nginx -n ibm-common-services - ``` +As Google native Load Balancer does not support the same URL rewriting rules as other ones (such as NGINX), [some settings have to be modified](https://cloud.google.com/load-balancing/docs/https/setting-up-url-rewrite) directly on GCP Web UI. -#### c. Create the IBM Licensing instance +You have to look for the ibm-licensing-service-instance in the list of Ingresses, then select its Load Balancer in the list of resources at the bottom: -Get the [licensing-instance.yaml](./licensing-instance.yaml) file and run the following command: +![Load balancing resources](images/lb_resources.png) -``` -kubectl create -f licensing-instance.yaml -n ibm-common-services -``` +Edit the rule about /ibm-licensing-service-instance/* and add `/` as path prefix rewrite: + +![Load balancing Host and Path rules](images/lb_host_and_path_rules.png) +![Load balancing Rewrite](images/lb_rewrite.png) -> NOTE: You can find more information and use cases on [this page](https://www.ibm.com/docs/en/cpfs?topic=software-configuration). +> [!NOTE] +> GKE Load Balancer may take a few minutes after its new configuration to actually apply it. #### d. Retrieving license usage After a couple of minutes, the Ingress configuration is created and you will be able to access the IBM License Service by retrieving the URL with the following command: -``` -export LICENSING_URL=$(kubectl get ingress ibm-licensing-service-instance -n ibm-common-services -o jsonpath='{.status.loadBalancer.ingress[0].ip}')/ibm-licensing-service-instance -export TOKEN=$(kubectl get secret ibm-licensing-token -o jsonpath={.data.token} -n ibm-common-services |base64 -d) +```shell +export LICENSING_URL=$(kubectl get ingress ibm-licensing-service-instance -n ibm-licensing -o jsonpath='{.status.loadBalancer.ingress[0].ip}')/ibm-licensing-service-instance +export TOKEN=$(kubectl get secret ibm-licensing-token -o jsonpath={.data.token} -n ibm-licensing |base64 -d) ``` You can access the `http://${LICENSING_URL}/status?token=${TOKEN}` URL to view the licensing usage or retrieve the licensing report .zip file by running the following command: -``` +```shell curl -v "http://${LICENSING_URL}/snapshot?token=${TOKEN}" --output report.zip ``` -If your IBM License Service instance is not running properly, refer to this [troubleshooting page](https://www.ibm.com/docs/en/cpfs?topic=software-troubleshooting). +If your IBM License Service instance is not running properly, refer to this [troubleshooting page](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.10?topic=service-troubleshooting-license). ## Troubleshooting @@ -402,6 +406,6 @@ If your ODM instances are not running properly, refer to [our dedicated troubles Get hands-on experience with IBM Operational Decision Manager in a container environment by following this [Getting started tutorial](https://github.com/DecisionsDev/odm-for-container-getting-started/blob/master/README.md). -# License +## License [Apache 2.0](/LICENSE) diff --git a/platform/gcloud/README_NGINX.md b/platform/gcloud/README_NGINX.md index 2e4fc274..8c60c724 100644 --- a/platform/gcloud/README_NGINX.md +++ b/platform/gcloud/README_NGINX.md @@ -16,7 +16,11 @@ For reference, see the Google Cloud documentation https://cloud.google.com/commu ### 1. Create a NGINX Ingress controller -Refer to the [Create a NGINX Ingress controller](README.md#a-create-a-nginx-ingress-controller) section if you have not created it already. +- Use Helm to deploy the NGINX Ingress controller: + + ```shell + helm upgrade --install ingress-nginx ingress-nginx --repo https://kubernetes.github.io/ingress-nginx --namespace ingress-nginx --create-namespace + ``` ### 2. Install the ODM release @@ -27,10 +31,10 @@ The secured HTTPS communication is managed by the NGINX ingress controller. So, Replace the placeholders in the [gcp-values.yaml](./gcp-values.yaml) file and install the chart: -``` -helm install mycompany ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ +```shell +helm install mycompany ibm-helm/ibm-odm-prod --version 24.1.0 \ -f gcp-values.yaml \ - --set service.ingress.annotations={"kubernetes.io/ingress.class: nginx"} + --set service.ingress.class=nginx ``` > **Note** @@ -40,10 +44,18 @@ helm install mycompany ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 \ Refer to the [the main README](README.md#b-check-the-topology) to check the deployment and access the ODM services. +### 4. Deploy and check IBM Licensing Service + +Refer to [the main README](README.md#b-check-the-topology) to install IBM Licensing Service, except that you have to apply this updated IBMLicensing instance instead: + +```shell +kubectl apply -f licensing-instance-NGINX.yaml -n ibm-licensing +``` + ## Troubleshooting If your ODM instances are not running properly, please refer to [our dedicated troubleshooting page](https://www.ibm.com/docs/en/odm/9.0.0?topic=900-troubleshooting-support). -# License +## License [Apache 2.0](/LICENSE) diff --git a/platform/gcloud/gcp-values.yaml b/platform/gcloud/gcp-values.yaml index 28bfef21..cfde4bfc 100644 --- a/platform/gcloud/gcp-values.yaml +++ b/platform/gcloud/gcp-values.yaml @@ -4,24 +4,24 @@ usersPassword: "odmAdmin" image: repository: cp.icr.io/cp/cp4a/odm pullSecrets: - - + - registrysecret service: enableTLS: false ingress: enabled: true - tlsSecretRef: mynicecompany-crt-secret + tlsSecretRef: mynicecompany-tls-secret host: mynicecompany.com tlsHosts: - mynicecompany.com externalDatabase: type: postgres - secretCredentials: + secretCredentials: odmdbsecret port: 5432 serverName: - databaseName: + databaseName: postgres # You can get the last Google Cloud SQL PostgreSQL driver version # at https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory/releases driversUrl: - - https://storage.googleapis.com/cloud-sql-java-connector/v1.7.1/postgres-socket-factory-1.7.1-jar-with-driver-and-dependencies.jar + - https://storage.googleapis.com/cloud-sql-connectors-java/v1.13.1/postgres-socket-factory-1.13.1-jar-with-driver-and-dependencies.jar diff --git a/platform/gcloud/images/database_changepassword.png b/platform/gcloud/images/database_changepassword.png deleted file mode 100644 index 26fae3f8..00000000 Binary files a/platform/gcloud/images/database_changepassword.png and /dev/null differ diff --git a/platform/gcloud/images/dc_sessionaffinity.png b/platform/gcloud/images/dc_sessionaffinity.png index d8b977ab..ff654048 100644 Binary files a/platform/gcloud/images/dc_sessionaffinity.png and b/platform/gcloud/images/dc_sessionaffinity.png differ diff --git a/platform/gcloud/images/loadbalancer.png b/platform/gcloud/images/lb.png similarity index 100% rename from platform/gcloud/images/loadbalancer.png rename to platform/gcloud/images/lb.png diff --git a/platform/gcloud/images/lb_host_and_path_rules.png b/platform/gcloud/images/lb_host_and_path_rules.png new file mode 100644 index 00000000..21f597bd Binary files /dev/null and b/platform/gcloud/images/lb_host_and_path_rules.png differ diff --git a/platform/gcloud/images/lb_resources.png b/platform/gcloud/images/lb_resources.png new file mode 100644 index 00000000..8ad41e8c Binary files /dev/null and b/platform/gcloud/images/lb_resources.png differ diff --git a/platform/gcloud/images/lb_rewrite.png b/platform/gcloud/images/lb_rewrite.png new file mode 100644 index 00000000..c451d604 Binary files /dev/null and b/platform/gcloud/images/lb_rewrite.png differ diff --git a/platform/gcloud/licensing-instance-NGINX.yaml b/platform/gcloud/licensing-instance-NGINX.yaml new file mode 100644 index 00000000..0c64fbee --- /dev/null +++ b/platform/gcloud/licensing-instance-NGINX.yaml @@ -0,0 +1,17 @@ +apiVersion: operator.ibm.com/v1alpha1 +kind: IBMLicensing +metadata: + name: instance +spec: + apiSecretToken: ibm-licensing-token + datasource: datacollector + httpsEnable: false + ingressEnabled: true + ingressOptions: + annotations: + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/rewrite-target: /$2 + path: /ibm-licensing-service-instance(/|$)(.*) + instanceNamespace: ibm-licensing + license: + accept: true diff --git a/platform/gcloud/licensing-instance.yaml b/platform/gcloud/licensing-instance.yaml index b1183a85..e87bd849 100644 --- a/platform/gcloud/licensing-instance.yaml +++ b/platform/gcloud/licensing-instance.yaml @@ -3,12 +3,14 @@ kind: IBMLicensing metadata: name: instance spec: + apiSecretToken: ibm-licensing-token datasource: datacollector - instanceNamespace: ibm-common-services httpsEnable: false ingressEnabled: true ingressOptions: annotations: - kubernetes.io/ingress.class: nginx - nginx.ingress.kubernetes.io/rewrite-target: '/$2' - path: /ibm-licensing-service-instance(/|$)(.*) + ingress.kubernetes.io/rewrite-target: / + path: /ibm-licensing-service-instance/* + instanceNamespace: ibm-licensing + license: + accept: true diff --git a/platform/minikube/README.md b/platform/minikube/README.md index 72e9f979..630b31a1 100644 --- a/platform/minikube/README.md +++ b/platform/minikube/README.md @@ -21,6 +21,7 @@ This tutorial was tested on macOS and Linux. - [Minikube](https://minikube.sigs.k8s.io/docs/start/) - [Helm](https://helm.sh/docs/intro/install/) +- [Kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/) ## Steps @@ -93,7 +94,7 @@ helm repo update ```shell $ helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION -ibmcharts/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager +ibmcharts/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### 3. Install an IBM Operational Decision Manager release @@ -103,7 +104,7 @@ ibmcharts/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Deci Get the [minikube-values.yaml](./minikube-values.yaml) file and run the following command: ```shell -helm install my-odm-release ibmcharts/ibm-odm-prod --set image.tag=9.0.0.0 -f minikube-values.yaml +helm install my-odm-release ibmcharts/ibm-odm-prod --version 24.1.0 -f minikube-values.yaml ``` #### b. Check the topology @@ -127,18 +128,17 @@ With this ODM topology in place, you can access web applications to author, depl ```shell $ minikube service list -|----------------------|------------------------------------------------|----------------------------------|---------------------------| -| NAMESPACE | NAME | TARGET PORT | URL | -|----------------------|------------------------------------------------|----------------------------------|---------------------------| -| default | my-odm-release-dbserver | No node port | -| default | my-odm-release-odm-decisioncenter | decisioncenter/9453 | http://:30108 | -| default | my-odm-release-odm-decisionrunner | decisionrunner/9443 | http://:32215 | -| default | my-odm-release-odm-decisionserverconsole | decisionserverconsole/9443 | http://:32040 | -| default | my-odm-release-odm-decisionserverconsole-notif | No node port | -| default | my-odm-release-odm-decisionserverruntime | decisionserverruntime/9443 | http://:32346 | -|----------------------|------------------------------------------------|----------------------------------|---------------------------| ``` +| *NAMESPACE* | *NAME* | *TARGET PORT* | *URL* | +|---|---|---|---| +| default | my-odm-release-dbserver | No node port | | +| default | my-odm-release-odm-decisioncenter | decisioncenter/9453 | http://``:30108 | +| default | my-odm-release-odm-decisionrunner | decisionrunner/9443 | http://``:32215 | +| default | my-odm-release-odm-decisionserverconsole | decisionserverconsole/9443 | http://``:32040 | +| default | my-odm-release-odm-decisionserverconsole-notif | No node port | | +| default | my-odm-release-odm-decisionserverruntime | decisionserverruntime/9443 | http://``:32346 | + > [!WARNING] > The URLs are prefixed with **http**. You must replace the prefix with **https** to access the services. diff --git a/platform/roks/README.md b/platform/roks/README.md index 71c18425..1096365d 100644 --- a/platform/roks/README.md +++ b/platform/roks/README.md @@ -1,8 +1,8 @@ -# Deploying IBM Operational Decision Manager on Redhat Openshift Kubernetes Service on IBM Cloud aka ROKS +# Deploying IBM Operational Decision Manager on a managed OpenShift cluster on IBM Cloud -This project demonstrates how to deploy an IBM® Operational Decision Manager (ODM) clustered topology on Redhat OpenShift Kubernetes Service on IBM Cloud (ROKS), leveraging Kubernetes and Docker technologies. +This project demonstrates how to deploy an IBM® Operational Decision Manager (ODM) clustered topology on a managed OpenShift Service on IBM Cloud, also known as ROKS, leveraging Kubernetes and Docker technologies. -Redhat OpenShift is available on various cloud platforms. More details about all [these availabilities](https://www.redhat.com/en/technologies/cloud-computing/openshift#cloud-services-editions). +Red Hat OpenShift is available on various cloud platforms. More details about all [these availabilities](https://www.redhat.com/en/technologies/cloud-computing/openshift#cloud-services-editions). This tutorial focuses on deploying ODM on the [IBM Cloud platform](https://www.redhat.com/en/technologies/cloud-computing/openshift/ibm). @@ -15,7 +15,7 @@ The ODM on Kubernetes Docker images are available in the [IBM Cloud Container Re The project uses the following components: - [IBM Operational Decision Manager](https://ibmdocs-test.dcs.ibm.com/docs/en/odm/9.0.0?topic=operational-decision-manager-certified-kubernetes-900) -- [IBM Cloud](https://cloud.ibm.com) +- [IBM Cloud](https://cloud.ibm.com/login) ## Tested environment @@ -43,15 +43,22 @@ Then, create an [IBM Cloud Account](https://cloud.ibm.com/registration). ### 1. Prepare your environment (20 min) -Create your IBM Cloud account and set up your first ROKS cluster following this [IBM Cloud tutorial](https://cloud.ibm.com/docs/openshift?topic=openshift-openshift_tutorial&locale=en). Then, create a project for ODM deployment: +1. Create your IBM Cloud account -```bash -oc new-project odm-tutorial -``` +1. Follow the steps to provision the full infrastructure via Terraform in this [README](./terraform/README.md) + + > Should you want to provision the cluster via the Console, you could follow this [IBM Cloud tutorial](https://cloud.ibm.com/docs/openshift?topic=openshift-openshift_tutorial&locale=en). + +1. Then, create an OpenShift project for ODM deployment: + + ```bash + oc new-project odm-tutorial + ``` ### 2. Prepare your environment for the ODM installation (5 min) To get access to the ODM material, you must have an IBM entitlement key to pull the images from the IBM Cloud Container registry. + This is what will be used in the next step of this tutorial. #### a. Retrieve your entitled registry key @@ -89,7 +96,7 @@ helm repo update ```bash $ helm search repo ibm-odm-prod NAME CHART VERSION APP VERSION DESCRIPTION -ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manager +ibm-helm/ibm-odm-prod 24.1.0 9.0.0.1 IBM Operational Decision Manager ``` ### 3. Install an IBM Operational Decision Manager release (10 min) @@ -97,7 +104,7 @@ ibm-helm/ibm-odm-prod 24.0.0 9.0.0.0 IBM Operational Decision Manag Get the [roks-values.yaml](./roks-values.yaml) file and install your ODM instance: ```bash -helm install roks-tuto ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 -f roks-values.yaml +helm install roks-tuto ibm-helm/ibm-odm-prod --version 24.1.0 -f roks-values.yaml ``` > This configuration will deployed ODM with a sample database. You should used your own database such as [IBM Cloud Databases for PostgreSQL](https://www.ibm.com/products/databases-for-postgresql) for production. @@ -138,7 +145,7 @@ roks-tuto-odm-ds-runtime-route ### 5. Track ODM usage with the IBM License Service -Follow the **Installation** section of the [Manual installation without the Operator Lifecycle Manager (OLM)](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.7?topic=ils-installing-license-service-without-operator-lifecycle-manager-olm) documentation. +Follow the **Installation** section of the [Manual installation without the Operator Lifecycle Manager (OLM)](https://www.ibm.com/docs/en/cloud-paks/foundational-services/4.9?topic=ils-installing-license-service-without-operator-lifecycle-manager-olm) documentation. ### 6. Deploy ODM to support sticky session on ROKS @@ -166,7 +173,7 @@ oc create secret tls default-ingress-cert --cert=./tls.crt --key=./tls.key -n od - Get the [roks-sticky-values.yaml](./roks-sticky-values.yaml) file and launch your ODM instance : ```bash -helm install roks-sticky-tuto ibm-helm/ibm-odm-prod --set image.tag=9.0.0.0 -f roks-sticky-values.yaml +helm install roks-sticky-tuto ibm-helm/ibm-odm-prod --version 24.1.0 -f roks-sticky-values.yaml ``` The ODM containers will embed the ROKS domain certificates. Additionally, two Decision Center pods will be launched to verify the sticky session behavior. diff --git a/platform/roks/images/ibm-cloud-roks-odm.drawio b/platform/roks/images/ibm-cloud-roks-odm.drawio new file mode 100644 index 00000000..704314fd --- /dev/null +++ b/platform/roks/images/ibm-cloud-roks-odm.drawio @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/roks/images/odm.drawio b/platform/roks/images/odm.drawio index c7851779..704314fd 100644 --- a/platform/roks/images/odm.drawio +++ b/platform/roks/images/odm.drawio @@ -1 +1,348 @@ -7T1Zc6rK1r/lPqTqnq9KqmnmR8fEfQWTaJJtXnYhIKIoXsA4/PpvNZNMDtmJ5yR3Ywah517zWg3dN0xzsb111dVUdnTDvsFI394wrRuMaZoR4Iuk7MIUXuLCBNO19DAJHRIG1t6Iasapa0s3vCgtTPIdx/atVTZRc5ZLQ/MzaarrOptssYlj65mElWoamWGQhIGm2kah2Iul+9N4Xrx0yLgzLHMadS3iaMJjVZubrrNeRv3dYKYTfMLshRq3FfXrTVXd2aSSmPYN03Qdxw+vFtumYRPYZsHWOZKbjNs1lv4lFURaDKu8qfbaiMfM21C5oVtvBJy2ZS6DDP6/azKshgZtG+7hHq5M8t1vyVC+/ti86w7bzeHTYxtu+wr8e+z/ZxC3CmMJGg7rRFDwdzHkJ5ZtNx3bcYNbhm3V6Q4HBT3fdeZGnLN0lgZJjKFHw43pqroFQ8uVmThLPyIwmoX7eD7RLKCRlapZS7NnTAjEOBTVSQ1iEnwgfeov7Ki3IqAj2L8Zrm9sU0kR4G8NZ2H47g6KRLkYs2GViEnYiCY2KYpDQpQ4TVFbXFCNqNxMmj5gGi4iZJcjnms7q3umjfXJz71e+6VMLKZfoxHCR8lhHOPs0dCnqk9wuzKW3tSakOv/rMeGuzR84FqMBob7ZmlGCuXjSxHe4cnPWYSj9yPcDhAco5vklqBaoMkPpEtt8gMXBJ8WSIZ61IzvrA6tDMlNq8bG3UbTQgWyYtEVyEfKkA+NJApzJSQUC600CXESogTuamTE4gKeDR0kbHTruP7UMZ2larcPqY1AbBp6BL9DmZ4TQJmAbWb4/i5Crrr2nSxQja3l/0xdj0hTFBfdtbZRy8HNLropIuIMZ3jO2tWM00UjviZTPolJ17BV33rLKp0ydERV7x1r6R8ogGEZikcCzWKRI/+z9IBZTCFWOnxy6PZV1zT8qMkcxpMxfkiWsCWyJEcVWS4HBtSDD+GnrFxIZHBG5ofVYxVNZ4iI3Kljz7HXvlF3tVgkkNTkDufkBV2UCIkgKCiOk+x8Tr5ezOYMTYmAS4kWGCSJNOa4LJa5AyOnuR6SGQkJjMhLEkKCUBQBAk9JwvUUCVdAfmgFoLv6vetsdwVS0FVvmnB/ZNip40SepqCdIw2OFtkOc0JlrEgbi61JbFXK1FaYmhrbLnQB2Ss3vGhptrPWf9mOqv8aq7a6DJVEA3DqR93a6tiw7x3P8q2ghhvCMtEQvVz+wtL1QLDlNFBeoyTlcpZICS0GnxzN4nfRH3sx/UUERgRonrpYtkhOTCR9PijTstRdoyUqJ7acycQzriWx+ALRvhIqKkitueFr04gwV2QCweC4BvyCbdYM/zgo2iQpgVouJJalCcVEujwlbjObWJYmFBPpsm7ziWVpuCSxNKXQLSoZH8pNBH5/R4CnJEOpBDhiJ2ZsyYzwyXPXOY1whK8zlmJsb5YYjjkDuNMR21fWKViQQPbztITY4H+W6dhSjSKARhFZDjMiksj/EpuSPhigV9AoknTenDB0K9AZTc97XNtBBIH6v5QSsBaB439UZI8d33cWsaxvJM58mSFSjm7VW4UBiYm1JQTVCLqsx6koToFrXfXVG6Ye3uKO92be4MYWaBk37+8U/LprsOOX7VrbI0u9e0Ray3nrMTqj7zhG3nFv2kJ7k2f1jdyU9vpCs7p3U398y+37y5HUXUyRftfY9y3xTV88z/Tb9lp9Ed/Gi856vOuaOrbn+q0pdWdt1JuN6P5wzvWHJlL2D1t51t52rYbz+mIv1bsHKNPdwD1WX56Zh4XE3g/gvlU35eHDWpk9cUHd1gOjtNo7edg2YUzWvTWaGbdtoTnc7vU723sdNJDxs2HfD36g159T1MPKXtt1Yb4/LIUdDb0fvaWC5Dt/ob5svb4lI3lm0q+zB2EyiFoacHu91RFeF7Y3bjkzZTbiXm9HuM+gRZeZTvub+VpjHnYGfl2Nbzd8F3fsEf6xGA19Ke7jnkCKjGbIxnVEjXnkxrdPqZFAT+2oFV9bPkPplQ0wXI/x4zwZzXDzVqx5f9eYAlTN1xayhkNtLe9lgNITfD/j3lBey62OLDfrbG/2gPRZcM+Ph3VTabJY+Tny5R27kZ82AN32vjerc3EZgP5sfNvZE0ogc+y2H6zePjWH2w5Sm405QFcJsTIy+00WKTADZcfu5V0d2rNx0P7LhunN5D0ZT//nyofxBBQwbqIgvduC9OfRTr5Nl3Os7q3ijX4qe+gD8NA2H5vdtxSWN6Ofj073FqhlHrfTyPQXtUvGkZ/P5uR8mnXcm82341YATwIj7nnWIHAstPXYbJCxHW0rgsVWbrIMjAXGpTFDQsk7llUYMrb6zrC65ghvpxojw1wezADelngUywH/4GB2Ld3rxViHUYbY++GFvaLzo90Tmnpd3hNdEfxeUwVIbNZbZIgfQRekPoNLwk+Y4q/nOAhFGyyOI4HuXGbkfRKRDMVznZif5vjfNCcSAwOj9MVfATwR0eW1ibqw7F1Y4c6w3wwiyFP5XqD8SS6NV9t0Rtg1yVk67kK1U3lvqmup8A3qQPXXLlE+J8tp6upYkU0EbZLJojBMgWzDB7+zltgT+ZqOu5qqy6jJ0ClAQAx+LTJT6kEbEz+VY4GltYz6QfFEgxzfhaYm0HrcT2AyhbQRRNdTnWwcV88OK2kLZjKeW9AcaTM0zmoRdWXKHcLmtRwuA3+XoDB98VdqpLqhOa5K9HfNn1rafGl40fCsJaj1GDr5silMniyXGk6m3AQ8RT8PHN3yVra6i4vbFvEd0L+sxcpxfXUZBctzYfOmvfbCeHocLA3p/Ei8tPI9vqrvcbE/8Tl+wxWVAydmPQKOLQkB0CUeALreykQcwjpl/hMRsvo4XJJ1xSj8dJNemyuDF89nV3J4sTQmJyFKKvGbRJ7ixOvBrWyB7w+Pwia0dJ4j0vgjAXVR5ERMFjgkLDBHcIkOnxPxr4/itXKHr+AOy7v+gOXkwK3VdvK+zfSHMpt1h2UGnKsduLxQpr4Hl3en7E22zEXuE6dlNt8RF1mejRhlqLHysAtOYX0Dzgar7OccuNx7cKOhrwfUncWuwO+5zcr09UWxXhft33eb9w8ws+eF0krcZrHHKMh42dpFdy/tEtatyP1D4PzATNum3CaubJcGd5e4t7ve7Intg7upWADhxSYqB9CYgYs8bNPd1gM4SU9IHqCdMmC38qzzQvKUlrY3FgjqP+yh/lYegLs2VDxwKqFeHVzLNrjUAFlw+AF7MNqwbXk/BwzM18q+Dm3PTWVGrke755kM0B8hcE33ssVu+wO0BYxC+VdM3Gdw2dGw1QXH7mlDXGcY7zbobziHPIB/q70N8qw6qcf2W+C6D9trBer1hm1wV2VGthBxMzfy7JEvdx8TJ5NgcNCN3MnujjihyqCOoDbqD1+93qyNFdITQERpgQNMAgmzB6YbOMQKhhkwCriZ8I3lvWYCdGiYBdBYd63MHtjecLQm9DdsPcCo2xzUg5mZu35nRENZoGHlkhFa8QhHgE8ZKc1ghDtlviH43PYJfAEGwDXg+JJZmAjwEIQA+i0TYA9wnT17waiGMoyCjEpDQB8wyjrXC+BXp3WL4FnDysvGD8ruTRQ41cBl4JonIYf7kMth1FeS+3EuohgGiwzPsKzIM7RUNIQoiRUljhUxI9I8K5YFRilW4nlGojmB5zB9PV0voqO+c+qZm5ahWR4R8Bg140d5Sh/NKdRsglJWwalJaozdfOkzj/cQ9wrSN1PLNwZg0pLkjauurq/Io1yWp7K2Lc1SPF/AqijGxTKRD4Zi2I9jr2HOBJl7q2lDe9Axt61WD9/VJPECQ61S6JVCrxR6pdAJ/cGoSWQcy4Mgoo3l1o+XUAXP92lVWY7dboxdDJjZK60HU2nVYRyvsgKqWR6a0P4TQGXO9AHTMBZWaekAMei7NSfqGiD+xJB5QB5NMEOoAGjfDMbdmvvBuFtk5YOo8WCFgZRlgM/IqsRWHv7IQpLQJX7ds++Mff+GUucoLKQejIoduZRG4KR0ftGVL3meBn9C7OOIZrjA1fsqoQ9aEimhqE+vHPsoh5tUZg79KaGPM6T0HSIfR7BKn8dqZSdVdlJlJ1V20h8X+Piw1P/acY8jGgGXaIRTYQ/yfgoJYqCmswT9bFwezvhCIZHPQvWFERGJ+9sjIhJTafpK01eavtL0VUTkutr+mwVEpLJnBL9oQASsqK8TELngGZo/LCCSkNI3DohUC0eVmVSZSZWZVAVEriD1v2VApGzB6KKAyON66VuL/6WAyPtR/WUDImCmXrCiVan6StVXqr5S9VVE5CPq/ntFRI5s3PVFQyIsh/+B92OOAe6CRYY/KybyrjfGvmhQ5LLdpypTqTKVKlOpMpWqqMi75f43DIuUbkp3Oi7yuF6+K5Lx1aMhv4PirxwOuWAdsNLxlY6vdHyl46twyIf0/LeLh1y0KP4lt6QG7Lm7n+mbVC1ye6gW3MX18rEIjvwk4YdUDh98Tqq0Nk9+4i7uDdcCxJB4wtU2zY73KQm3pT5ZNA4Snd1fOyJeAB1msgTLRJT3wd1qa1jM8oGUbaG4WW2hCUESKemwrSadaY/s/ky2aks+fLb9EK6FPbwLnUiIKbYrSkfb/by9wY+x50W7l/xD7Cn80fx5+hn7P409acRymahmbvv1M4x0KYPSNIcyDbNYLBzQcHWupC9aXq648utwpfTncmV2aDxH0QKXrCvgb82GF73hWrHhV2HDQ2Dxj+dDVvqOfLiypTbdEUayLBl+Y9KnF/fSZdsufFYUUTcm6to+vhvoO2KIU9+PNhbuwO96RY40oTbWHJhAt1TKcU1IJvcrcg/XmrNYOEsPrvzpejGGb4b8kSxywteAnPBV64HwGO5WBhXEJDu2ujQnbo2WgJO2tfJi1Co4QeWmPNTwDhY8yhs5p6bsoQKmZBGa4Sj8CUHpI2Nmyl6ySJ+oV9y/Or/pdLwvcn6r4NRRbCWtFMuX7PSFHp21f+RktrNrGp8w9KN7eBerZAkZUtUFYYWgmcf+07CdJEU9dM52MnZc3XDTmzq/qe6/a7V0+l+lg9EjUCaHH5Zv1nwy+d1rP1WAqlxaRjtuF551+ZBqP3Ni0gWqXXi3asd8rGQ+W7Xnl+zOqfbPO0RJKHMic0dInnwXPyuiSplm/CVkROGwgOwe+ql992drz7cmu1LJQk4KuHDv90oenJQHfxf7n95t6nLuR2IcVYu5n/4U7md5hqIlFsE34jnExkGp5HwnkWLFVFD592x0nhYpcgYljxhRYPmywNiJyPUR470oyeisk5Jr5qqCrMwNv0CQJe/QXFeQxV0nh+1WwuIbCQvhvcKCZvksG9diXqikRcruyYYNamdDGp8oLvC7xEX8aNnfIyTi3v4BGfFF+P2rHQ59VkYcXk24XEgwKLfQW4sP8PqgkAABQbECeDhYhBmwNMqtU4tSITz3OZKBlYhk4I69MHC5YMgfLJuLTF5TMpRu0JAOq8SObOpEszjMkI/oqL46Vr10AOdUACEOT2o7m5z15ZJTks88SToOGb43ThISjuqv/eBIq+itluhtFO53GOXyJ49EKeshY5qh4uPlM8fclzxYTIs5+X9BmO/JM9z+eEbiqhgFIiXB2Dlpi8iBaSqpF8joKHM59lYhBlP1vdBo+7VUg5etU83UsgVXrhOOJV2GypbRwhPEzjfmqkvdWfyaqt40V46wVq5V1zADTZXpWIufZ/YodbWCxuCGCo7OjkjABrqaOjbQmpcRNcHYgoRncv4deXMsSD8dgpfS8d+I2YrPRp87ADitSo6Fjo4eyl3GLg6UntjB+11TKGeQg8TTL2gddMdVwt41OivkOYEpC33zZae+/8Yjd3CbYop3ST6e+193S4o4pYumgCQKRaV/xj44q/Qv1uiXrmcko/zir0LaubW1Ag/nF98SXj7L9ckyXXTcXi84oS85xC/9wmXoCxUP9yuTF1Frjaj1/MmBR2noHc/n5kQCA04dKxZEQhybTUsE4f0SoYR0LnjcNnMmYvYVYpQFSI6UBI78HJPusY2z2JoA7SllaitM2eoqXDgFqPpHwXyg+IsBjaiioOVKoBqvO352ID85l+Yjhivcuo7jp4sT0MmOTqyd9v8D \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/roks/images/roks-schema.jpg b/platform/roks/images/roks-schema.jpg index 4ddf4ea0..dd7647e4 100644 Binary files a/platform/roks/images/roks-schema.jpg and b/platform/roks/images/roks-schema.jpg differ diff --git a/platform/roks/terraform/README.md b/platform/roks/terraform/README.md new file mode 100644 index 00000000..62ce970d --- /dev/null +++ b/platform/roks/terraform/README.md @@ -0,0 +1,80 @@ +# Provision an ODM landing zone on IBM CLoud + +> Estimated duration: 60 mins + +These Terraform scripts will provision the following Cloud Services in IBM Cloud: + +* a Resource Group to host resources +* a VPC with 3 subnets across a MZR (Multi Zone Region) +* a managed OpenShift cluster (ROKS) +* a managed Postgres Database + +You can then ssh into the newly created VSI. + +| Terraform | Estimation Duration | +| --------- | --------- | +| Apply | ~60 mins | +| Destroy | ~5-10 mins | + +## Before you begin + +This lab requires the following command lines: + +* [IBM Cloud CLI](https://github.com/IBM-Cloud/ibm-cloud-cli-release/releases) +* [Terraform CLI](https://developer.hashicorp.com/terraform/downloads) +* [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [jq CLI JSON processor](https://jqlang.github.io/jq/download/) + +> Unless you are Administrator of the Cloud Account, you need permissions to be able to provision VPC Resources. Ask the Administrator run the Terraform in `iam` folder. + +## Provisioning Steps + +1. Clone this repository + + ```sh + git clone https://github.com/lionelmace/learn-ibm-terraform + ``` + +1. Login to IBM Cloud + + ```sh + ibmcloud login + ``` + +1. Create and store the value of an API KEY as environment variable + + ```sh + export IBMCLOUD_API_KEY=$(ibmcloud iam api-key-create my-api-key --output json | jq -r .apikey) + ``` + + > If the variable "ibmcloud_api_key" is set in your provider, + > you can initialize it using the following command + > export TF_VAR_ibmcloud_api_key="Your IBM Cloud API Key" + +1. Terraform must initialize the provider before it can be used. + + ```sh + terraform init + ``` + +1. Review the plan + + ```sh + terraform plan + ``` + +1. Start provisioning. + + > Estimated duration: 45-60 mins + + ```sh + terraform apply --var-file="odm.auto.tfvars" + ``` + +## Destroy Resources + +1. Clean up the resources to avoid cost + + ```sh + terraform destroy + ``` diff --git a/platform/roks/terraform/account-rg.tf b/platform/roks/terraform/account-rg.tf new file mode 100644 index 00000000..69df0593 --- /dev/null +++ b/platform/roks/terraform/account-rg.tf @@ -0,0 +1,27 @@ +############################################################################## +# Create a resource group or reuse an existing one +############################################################################## + +variable "existing_resource_group_name" { + default = "" + description = "(Optional) Name of an existing resource group where to create resources" +} + +resource "ibm_resource_group" "group" { + count = var.existing_resource_group_name != "" ? 0 : 1 + name = "${local.basename}-group" + tags = var.tags +} + +data "ibm_resource_group" "group" { + count = var.existing_resource_group_name != "" ? 1 : 0 + name = var.existing_resource_group_name +} + +locals { + resource_group_id = var.existing_resource_group_name != "" ? data.ibm_resource_group.group.0.id : ibm_resource_group.group.0.id +} + +# output "resource_group_name" { +# value = ibm_resource_group.group.name +# } \ No newline at end of file diff --git a/platform/roks/terraform/container-openshift.tf b/platform/roks/terraform/container-openshift.tf new file mode 100644 index 00000000..368a36d2 --- /dev/null +++ b/platform/roks/terraform/container-openshift.tf @@ -0,0 +1,171 @@ + +# OpenShift Variables +############################################################################## + +variable "openshift_cluster_name" { + description = "Name of the cluster" + type = string + default = "roks" +} + +variable "openshift_version" { + description = "The OpenShift version that you want to set up in your cluster." + type = string + default = "" +} + +variable "openshift_os" { + description = "The Operating System (REDHAT_8_64 or RHCOS) for the Worker Nodes." + type = string + default = "RHCOS" +} + +variable "openshift_machine_flavor" { + description = " The default flavor of the OpenShift worker node." + type = string + default = "bx2.4x16" +} + +variable "openshift_worker_nodes_per_zone" { + description = "The number of worker nodes per zone in the default worker pool." + type = number + default = 1 +} + +variable "worker_labels" { + description = "Labels on all the workers in the default worker pool." + type = map(any) + default = null +} + +variable "openshift_wait_till" { + description = "specify the stage when Terraform to mark the cluster creation as completed." + type = string + default = "OneWorkerNodeReady" + + validation { + error_message = "`openshift_wait_till` value must be one of `MasterNodeReady`, `OneWorkerNodeReady`, or `IngressReady`." + condition = contains([ + "MasterNodeReady", + "OneWorkerNodeReady", + "IngressReady" + ], var.openshift_wait_till) + } +} + +variable "openshift_disable_outbound_traffic_protection" { + description = "Include this option to allow public outbound access from the cluster workers." + type = bool + default = true +} + +variable "openshift_disable_public_service_endpoint" { + description = "Boolean value true if Public service endpoint to be disabled." + type = bool + default = false +} + +variable "openshift_force_delete_storage" { + description = "force the removal of persistent storage associated with the cluster during cluster deletion." + type = bool + default = true +} + +variable "kms_config" { + type = list(map(string)) + default = [] +} + +variable "entitlement" { + description = "Enable openshift entitlement during cluster creation ." + type = string + default = "cloud_pak" +} + +variable "openshift_update_all_workers" { + description = "OpenShift version of the worker nodes is updated." + type = bool + default = true +} + +variable "is_openshift_cluster" { + type = bool + default = true +} + +variable "roks_worker_pools" { + description = "List of maps describing worker pools" + + type = list(object({ + pool_name = string + machine_type = string + workers_per_zone = number + })) + + default = [ + { + pool_name = "dev" + machine_type = "bx2.4x16" + workers_per_zone = 1 + } + ] + + validation { + error_message = "Worker pool names must match the regex `^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$`." + condition = length([ + for pool in var.roks_worker_pools : + false if !can(regex("^([a-z]|[a-z][-a-z0-9]*[a-z0-9])$", pool.pool_name)) + ]) == 0 + } + + validation { + error_message = "Worker pools cannot have duplicate names." + condition = length(distinct([ + for pool in var.roks_worker_pools : + pool.pool_name + ])) == length(var.roks_worker_pools) + } +} + +## Resources +############################################################################## +resource "ibm_container_vpc_cluster" "roks_cluster" { + name = format("%s-%s", local.basename, var.openshift_cluster_name) + vpc_id = ibm_is_vpc.vpc.id + resource_group_id = local.resource_group_id + # Optional: Specify OpenShift version. If not included, 4.16 is used + kube_version = var.openshift_version == "" ? "4.16_openshift" : var.openshift_version + operating_system = var.openshift_os + cos_instance_crn = var.is_openshift_cluster ? ibm_resource_instance.cos_openshift_registry[0].id : null + entitlement = var.entitlement + force_delete_storage = var.openshift_force_delete_storage + tags = var.tags + update_all_workers = var.openshift_update_all_workers + + flavor = var.openshift_machine_flavor + worker_count = var.openshift_worker_nodes_per_zone + wait_till = var.openshift_wait_till + disable_public_service_endpoint = var.openshift_disable_public_service_endpoint + # By default, public outbound access is blocked in OpenShift versions 4.15 + disable_outbound_traffic_protection = var.openshift_disable_outbound_traffic_protection + + dynamic "zones" { + for_each = { for subnet in ibm_is_subnet.subnet : subnet.id => subnet } + content { + name = zones.value.zone + subnet_id = zones.value.id + } + } +} + +# Object Storage to backup the OpenShift Internal Registry +############################################################################## +resource "ibm_resource_instance" "cos_openshift_registry" { + count = var.is_openshift_cluster ? 1 : 0 + name = join("-", [local.basename, "cos-registry"]) + resource_group_id = local.resource_group_id + service = "cloud-object-storage" + plan = "standard" + location = "global" + tags = var.tags +} diff --git a/platform/roks/terraform/database-postgres.tf b/platform/roks/terraform/database-postgres.tf new file mode 100644 index 00000000..67a42a8c --- /dev/null +++ b/platform/roks/terraform/database-postgres.tf @@ -0,0 +1,100 @@ + +# Variables +############################################################################## +variable "icd_postgres_plan" { + type = string + description = "The plan type of the Database instance" + default = "standard" +} + +variable "icd_postgres_adminpassword" { + type = string + description = "The admin user password for the instance" + default = "AdminPassw0rd01" +} + +variable "icd_postgres_ram_allocation" { + type = number + description = "RAM (GB/data member)" + default = 4096 +} + +variable "icd_postgres_disk_allocation" { + type = number + description = "Disk Usage (GB/data member)" + default = 5120 +} + +variable "icd_postgres_core_allocation" { + type = number + description = "Dedicated Cores (cores/data member)" + default = 2 +} + +variable "icd_postgres_db_version" { + type = string + description = "The database version to provision if specified" + default = "16" +} + +variable "icd_postgres_users" { + default = null + type = set(map(string)) + description = "Database Users. It is set of username and passwords" +} + +variable "icd_postgres_service_endpoints" { + default = "public" + type = string + description = "Types of the service endpoints. Possible values are 'public', 'private', 'public-and-private'." +} + +############################################################################## +## ICD Postgres +############################################################################## +resource "ibm_database" "icd_postgres" { + name = format("%s-%s", local.basename, "postgres") + service = "databases-for-postgresql" + plan = var.icd_postgres_plan + version = var.icd_postgres_db_version + service_endpoints = var.icd_postgres_service_endpoints + location = var.region + resource_group_id = local.resource_group_id + tags = var.tags + + # DB Settings + adminpassword = var.icd_postgres_adminpassword + group { + group_id = "member" + host_flavor { id = "multitenant" } + memory { allocation_mb = var.icd_postgres_ram_allocation } + disk { allocation_mb = var.icd_postgres_disk_allocation } + cpu { allocation_count = var.icd_postgres_core_allocation } + } +} + +## Service Credentials +############################################################################## +resource "ibm_resource_key" "db-svc-credentials" { + name = format("%s-%s", local.basename, "postgres-key") + resource_instance_id = ibm_database.icd_postgres.id + role = "Viewer" +} + +locals { + endpoints = [ + { + name = "postgres", + # crn = ibm_database.icd_postgres.id + db-name = nonsensitive(ibm_resource_key.db-svc-credentials.credentials["connection.postgres.database"]) + db-host = nonsensitive(ibm_resource_key.db-svc-credentials.credentials["connection.postgres.hosts.0.hostname"]) + db-port = nonsensitive(ibm_resource_key.db-svc-credentials.credentials["connection.postgres.hosts.0.port"]) + db-user = nonsensitive(ibm_resource_key.db-svc-credentials.credentials["connection.postgres.authentication.username"]) + db-password = nonsensitive(ibm_resource_key.db-svc-credentials.credentials["connection.postgres.authentication.password"]) + } + ] +} + +output "icd-postgres-credentials" { + value = local.endpoints +} \ No newline at end of file diff --git a/platform/roks/terraform/iam-ag.tf b/platform/roks/terraform/iam-ag.tf new file mode 100644 index 00000000..14babc7b --- /dev/null +++ b/platform/roks/terraform/iam-ag.tf @@ -0,0 +1,51 @@ +## IAM +############################################################################## + +# Create Access Group +resource "ibm_iam_access_group" "accgrp" { + name = format("%s-%s", local.basename, "ag") + tags = var.tags +} + +# Visibility on the Resource Group +resource "ibm_iam_access_group_policy" "iam-rg-viewer" { + access_group_id = ibm_iam_access_group.accgrp.id + roles = ["Viewer"] + resources { + resource_type = "resource-group" + resource = local.resource_group_id + } +} + +# Create a policy to all Kubernetes/OpenShift clusters within the Resource Group +resource "ibm_iam_access_group_policy" "policy-k8s" { + access_group_id = ibm_iam_access_group.accgrp.id + roles = ["Manager", "Writer", "Editor", "Operator", "Viewer", "Administrator"] + + resources { + service = "containers-kubernetes" + resource_group_id = local.resource_group_id + } +} + +# Assign Administrator platform access role to enable the creation of API Key +# Pre-Req to provision IKS/ROKS clusters within a Resource Group +resource "ibm_iam_access_group_policy" "policy-k8s-identity-administrator" { + access_group_id = ibm_iam_access_group.accgrp.id + roles = ["Administrator", "User API key creator", "Service ID creator"] + + resources { + service = "iam-identity" + } +} + +# Doc at https://cloud.ibm.com/docs/cloud-databases?topic=cloud-databases-iam +resource "ibm_iam_access_group_policy" "iam-postgres" { + access_group_id = ibm_iam_access_group.accgrp.id + roles = ["Editor"] + + resources { + service = "databases-for-postgresql" + resource_group_id = local.resource_group_id + } +} \ No newline at end of file diff --git a/platform/roks/terraform/iam-users.tf b/platform/roks/terraform/iam-users.tf new file mode 100644 index 00000000..370e6480 --- /dev/null +++ b/platform/roks/terraform/iam-users.tf @@ -0,0 +1,6 @@ + +# invite the users in the account and attach them to their access group +# resource "ibm_iam_user_invite" "invite_user" { +# users = ["firstname.lasname@fr.ibm.com"] +# access_groups = [ibm_iam_access_group.accgrp.id] +# } diff --git a/platform/roks/terraform/networking-vpc.tf b/platform/roks/terraform/networking-vpc.tf new file mode 100644 index 00000000..c373cf50 --- /dev/null +++ b/platform/roks/terraform/networking-vpc.tf @@ -0,0 +1,168 @@ +############################################################################## +# VPC Variables +############################################################################## + +variable "create_vpc" { + description = "True to create new VPC. False if VPC is already existing and subnets or address prefixies are to be added" + type = bool + default = true +} + +variable "vpc_address_prefix_management" { + description = "Default address prefix creation method" + type = string + default = "manual" +} + +variable "vpc_acl_rules" { + default = [ + { + name = "egress" + action = "allow" + source = "0.0.0.0/0" + destination = "0.0.0.0/0" + direction = "inbound" + }, + { + name = "ingress" + action = "allow" + source = "0.0.0.0/0" + destination = "0.0.0.0/0" + direction = "outbound" + } + ] +} + +variable "vpc_cidr_blocks" { + description = "List of CIDR blocks for Address Prefix" + default = [ + "10.243.0.0/18", + "10.243.64.0/18", + "10.243.128.0/18"] +} + +variable "subnet_cidr_blocks" { + description = "List of CIDR blocks for subnets" + default = [ + "10.243.0.0/24", + "10.243.64.0/24", + "10.243.128.0/24"] +} + +variable "vpc_enable_public_gateway" { + description = "Enable public gateways, true or false" + default = true +} + +variable "floating_ip" { + description = "Floating IP `id`'s or `address`'es that you want to assign to the public gateway" + type = map(any) + default = {} +} + +############################################################################## +# Create a VPC +############################################################################## + +resource "ibm_is_vpc" "vpc" { + name = format("%s-%s", local.basename, "vpc") + resource_group = local.resource_group_id + address_prefix_management = var.vpc_address_prefix_management + default_security_group_name = "${local.basename}-vpc-sg" + default_network_acl_name = "${local.basename}-vpc-acl" + # Delete all rules attached to default security group and default network ACL + # for a new VPC. This attribute has no impact on update. Default = false + # no_sg_acl_rules = true + tags = var.tags +} + + +############################################################################## +# Prefixes and subnets for zone +############################################################################## + +resource "ibm_is_vpc_address_prefix" "address_prefix" { + + count = length(var.vpc_cidr_blocks) + name = "${local.basename}-prefix-zone-${count.index + 1}" + zone = "${var.region}-${(count.index % 3) + 1}" + vpc = ibm_is_vpc.vpc.id + cidr = element(var.vpc_cidr_blocks, count.index) +} + + +############################################################################## +# Public Gateways +############################################################################## + +resource "ibm_is_public_gateway" "pgw" { + + count = var.vpc_enable_public_gateway ? length(var.subnet_cidr_blocks) : 0 + name = "${local.basename}-pgw-${count.index + 1}" + vpc = ibm_is_vpc.vpc.id + zone = "${var.region}-${count.index + 1}" + resource_group = local.resource_group_id + tags = var.tags +} + + +# Network ACLs +############################################################################## +resource "ibm_is_network_acl" "multizone_acl" { + + name = "${local.basename}-multizone-acl" + vpc = ibm_is_vpc.vpc.id + resource_group = local.resource_group_id + + dynamic "rules" { + + for_each = var.vpc_acl_rules + + content { + name = rules.value.name + action = rules.value.action + source = rules.value.source + destination = rules.value.destination + direction = rules.value.direction + } + } +} + + +############################################################################## +# Create Subnets +############################################################################## + +resource "ibm_is_subnet" "subnet" { + + count = length(var.subnet_cidr_blocks) + name = "${local.basename}-subnet-${count.index + 1}" + vpc = ibm_is_vpc.vpc.id + zone = "${var.region}-${count.index + 1}" + ipv4_cidr_block = element(var.subnet_cidr_blocks, count.index) + network_acl = ibm_is_network_acl.multizone_acl.id + public_gateway = var.vpc_enable_public_gateway ? element(ibm_is_public_gateway.pgw.*.id, count.index) : null + tags = var.tags + resource_group = local.resource_group_id + + depends_on = [ibm_is_vpc_address_prefix.address_prefix] +} + +############################################################################## +# Security Groups +############################################################################## + +# Rules required to allow necessary inbound traffic to your cluster (IKS/OCP) +############################################################################## +# To expose apps by using load balancers or Ingress, allow traffic through VPC +# load balancers. For example, for Ingress listening on TCP/443 +resource "ibm_is_security_group_rule" "sg-rule-inbound-https" { + group = ibm_is_vpc.vpc.default_security_group + direction = "inbound" + remote = "0.0.0.0/0" + + tcp { + port_min = 443 + port_max = 443 + } +} diff --git a/platform/roks/terraform/odm.auto.tfvars b/platform/roks/terraform/odm.auto.tfvars new file mode 100644 index 00000000..d8642529 --- /dev/null +++ b/platform/roks/terraform/odm.auto.tfvars @@ -0,0 +1,51 @@ +############################################################################## +## Global Variables +############################################################################## + +region = "eu-de" # eu-de for Frankfurt MZR +# existing_resource_group_name = "" + +############################################################################## +## VPC +############################################################################## +vpc_address_prefix_management = "manual" +vpc_enable_public_gateway = true + + +############################################################################## +## Cluster ROKS +############################################################################## +# Optional: Specify OpenShift version. If not included, 4.15 is used +openshift_version = "4.16_openshift" + +openshift_os = "RHCOS" +openshift_machine_flavor = "bx2.4x16" + +openshift_disable_public_service_endpoint = false +# By default, public outbound access is blocked in OpenShift 4.15 +openshift_disable_outbound_traffic_protection = true + +# Available values: MasterNodeReady, OneWorkerNodeReady, or IngressReady +openshift_wait_till = "OneWorkerNodeReady" +openshift_update_all_workers = false + + +############################################################################## +## ICD Postgres +############################################################################## +# Available Plans: standard, enterprise +icd_postgres_plan = "standard" +# expected length in the range (10 - 32) - must not contain special characters +icd_postgres_adminpassword = "Passw0rd01forODM" +icd_postgres_db_version = "16" +icd_postgres_service_endpoints = "public" + +# Minimum parameter for Standard Edition +icd_postgres_ram_allocation = 4096 +icd_postgres_disk_allocation = 5120 +icd_postgres_core_allocation = 0 + +# icd_postgres_users = [{ +# name = "user123" +# password = "Password12forODM" +# }] diff --git a/platform/roks/terraform/provider.tf b/platform/roks/terraform/provider.tf new file mode 100644 index 00000000..4e1f62a6 --- /dev/null +++ b/platform/roks/terraform/provider.tf @@ -0,0 +1,18 @@ +############################################################################## +# IBM Cloud Provider +############################################################################## + +terraform { + required_version = ">=1.6" + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + version = "1.71.2" + } + } +} + +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region +} \ No newline at end of file diff --git a/platform/roks/terraform/variables.tf b/platform/roks/terraform/variables.tf new file mode 100644 index 00000000..029a6174 --- /dev/null +++ b/platform/roks/terraform/variables.tf @@ -0,0 +1,38 @@ +############################################################################## +# Account Variables +############################################################################## + +variable "ibmcloud_api_key" { + description = "APIkey that's associated with the account to provision resources to" + type = string + default = "" + sensitive = true +} + +variable "prefix" { + type = string + default = "" + description = "A prefix for all resources to be created. If none provided a random prefix will be created" +} + +resource "random_string" "random" { + count = var.prefix == "" ? 1 : 0 + + length = 6 + special = false +} + +locals { + basename = lower(var.prefix == "" ? "odm-${random_string.random.0.result}" : var.prefix) +} + +variable "region" { + description = "IBM Cloud region where all resources will be provisioned (e.g. eu-de)" + default = "eu-de" +} + +variable "tags" { + description = "List of Tags" + type = list(string) + default = ["tf", "odm"] +} \ No newline at end of file diff --git a/repo/stable/ibm-odm-dev-24.0.0.tgz b/repo/stable/ibm-odm-dev-24.0.0.tgz deleted file mode 100644 index 26f55675..00000000 Binary files a/repo/stable/ibm-odm-dev-24.0.0.tgz and /dev/null differ diff --git a/repo/stable/ibm-odm-dev-24.1.0.tgz b/repo/stable/ibm-odm-dev-24.1.0.tgz new file mode 100644 index 00000000..90ef2b9d Binary files /dev/null and b/repo/stable/ibm-odm-dev-24.1.0.tgz differ diff --git a/repo/stable/index.yaml b/repo/stable/index.yaml index 89c40585..0af3668d 100644 --- a/repo/stable/index.yaml +++ b/repo/stable/index.yaml @@ -2,11 +2,11 @@ apiVersion: v1 entries: ibm-odm-dev: - apiVersion: v2 - appVersion: 9.0.0.0 - created: "2024-06-25T15:28:15.68567+02:00" + appVersion: 9.0.0.1 + created: "2024-11-18T14:11:47.025231+01:00" description: 'IBM Operational Decision Manager for Developers License By installing this product you accept the following license terms: https://www14.software.ibm.com/cgi-bin/weblap/lap.pl?li_formnum=L-RBPW-WQTC4A' - digest: 2804fe727c8d46d625eb359c8da76192c90d9dfe358c00ca8cbc16ed3167b3e1 + digest: 8cf16813b48a51c168ad515f3272e8b3c4b116549c2f4b7d45efeec1d6b1defb home: https://www.ibm.com/docs/en/odm/9.0.0?topic=kubernetes-installing-odm-developers icon: https://raw.githubusercontent.com/ODMDev/ruledesigner/master/icons/automation-decision.png keywords: @@ -20,15 +20,15 @@ entries: - RHOCP - ROKS - Middleware - kubeVersion: '>=1.24.0-0' + kubeVersion: '>=1.25.0-0' maintainers: - name: IBM name: ibm-odm-dev sources: - https://github.com/IBM/charts/tree/master/stable urls: - - https://raw.githubusercontent.com/DecisionsDev/odm-docker-kubernetes/master/repo/stable/ibm-odm-dev-24.0.0.tgz - version: 24.0.0 + - https://raw.githubusercontent.com/DecisionsDev/odm-docker-kubernetes/master/repo/stable/ibm-odm-dev-24.1.0.tgz + version: 24.1.0 - apiVersion: v2 appVersion: 8.12.0.1 created: "2024-06-10T15:32:15.412464+02:00" @@ -166,11 +166,11 @@ entries: - https://raw.githubusercontent.com/IBM/charts/master/repo/ibm-helm/ibm-odm-prod-23.2.0.tgz version: 23.2.0 - apiVersion: v2 - appVersion: 9.0.0.0 - created: "2024-06-25T08:35:54.901932045Z" + appVersion: 9.0.0.1 + created: "2024-12-13T08:40:54.646560428Z" description: 'IBM Operational Decision Manager License By installing this product you accept the following license terms: https://www14.software.ibm.com/cgi-bin/weblap/lap.pl?li_formnum=L-SJDA-MUA6UZ' - digest: ba5228ac3ed21e70f3410a17a4120d4964aac197f746406ac70c2031b2ac27a0 + digest: 6ab8415971373da4a91df0f2cbf31b5cb5ffeff621ceb15b17f8ae8bd2682f84 home: https://www.ibm.com/docs/en/odm/9.0.0?topic=production-installing-helm-release-odm icon: https://raw.githubusercontent.com/ODMDev/ruledesigner/master/icons/automation-decision.png keywords: @@ -183,13 +183,13 @@ entries: - ICP - RHOCP - Middleware - kubeVersion: '>= 1.24.0-0' + kubeVersion: '>= 1.25.0-0' maintainers: - name: IBM name: ibm-odm-prod sources: - https://github.com/IBM/charts/tree/master/stable urls: - - https://raw.githubusercontent.com/IBM/charts/master/repo/ibm-helm/ibm-odm-prod-24.0.0.tgz - version: 24.0.0 + - https://raw.githubusercontent.com/IBM/charts/master/repo/ibm-helm/ibm-odm-prod-24.1.0.tgz + version: 24.1.0 generated: "2024-06-10T15:32:15.406464+02:00"