Solution Overview
The solution described here requires cleaning the API Manager configuration for all the management components available, meaning all the Management servers belonging to the Management service in the API Connect cloud. Afterward, the API Manager is reconfigured from scratch. This solution can be applied both on single-server and in cluster topology. However, if a rollback should be needed to return to the original configuration, it would be necessary to restart from the backed up API Manager configuration, for each Management server.
Let us pick as a starting point the typical operational schema for the API publication both in single-server and cluster topology:
During the API Manager reconfiguration, the existing APIs will continue to be available without interruption (see API Old Config below). When configuring the new Gateway service, we will choose a publication port different from the default one for HTTPS communications (443), say port 444. This way, when the same APIs will be published in the new domain (or Gateway service), they will be available directly at the FQDN (or IP) of the individual Gateway server but on a different port (see API New Config, port 444 below). After restoring the developer organization, apps and subscriptions, these APIs will be protected by new credentials (Client Id and Client Secret). Subsequently, using the Developer Portal REST services, the original credentials to secure the APIs will be restored:
After successfully testing the invocation of the new published APIs, the switch-off between the new and the old Gateway service will take place:
The old Gateway service will be moved on a different port (see API Old Config, port 445). This operation will be executed using the DataPower web console, since that domain is no longer available on the API Manager CMC console. The new Gateway server will instead be moved on port 443 via the API Manager CMC console. Once verified that the solution is working properly, the old Gateway service can be deleted via the DataPower web console. We have now reproduced the original API Manager configuration, except for the user registry which has been updated according to our requirements.
Recovering the original credentials (Client ID and Client Secret) for the Applications
API Connect makes available a set of Developer Portal REST services suited to operate on Users, Products, APIs, Applications, etc. This is the related link to the Knowledge Center: https://www.ibm.com/support/knowledgecenter/en/SSMNED_5.0.0/com.ibm.apic.apirest.doc/dev_portal_apis.html
We are interested in the Application management REST service credentials:
https://www.ibm.com/support/knowledgecenter/en/SSMNED_5.0.0/com.ibm.apic.apirest.doc/apirest_reference_topics/rest_op_portal_orgs__orgID__apps__appID__credentialsPUT.html
When invoked with PUT method, this service allows updating the credentials (Client ID and Client Secret) of a given Application. This REST service uses ids as input parameters, so it will be necessary to invoke the following sequence of REST services to reach the objective:
- v1/portal/orgs, to get the desired Developer Organization identifier <developer-organization-id>
- v1/portal/orgs/<developer-organization-id>/apps, to get the Application identifier <app-id> related to the desired Application, available from the Application list related to the Developer Organization specified by the identifier <developer-organization-id>
- v1/portal/orgs/<developer-organization-id>/apps/<app-id>/credentials, to update the credentials (Client ID and Client Secret) for the Application specified by <app-id> and the Developer Organization specified by <developer-organization-id>.
These REST services require also the following information sent as http request headers:
- Context, in terms of Provider Organization and Catalog, using the header X-IBM-APIManagement-Context, in the form: X-IBM-APIManagement-Context:<provider-organization-name>.<catalog-name>
- Response format, using the header Content-Type, in the form: Content-Type:application/json
- Developer Organization Owner’s credentials, using the header Authorization with the credentials set to base64 as with Basic authentication, in the canonical form: Authorization:Basic aVHtNMZ6cm4yC3NjaGU=.
As an example, let us assume to work with the Provider Organization myOrg, Catalog myCatalog, Developer Organization myDevOrg, and Application myApp.
After connecting via SSH to the Developer Portal, let’s invoke the first mentioned REST service v1/portal/orgs. A possible output follows:
admin@s-developerportal:~$ curl -k -H “X-IBM-APIManagement-Context:myOrg.myCatalog” -H “Content-Type:application/json” -H “Authorization:Basic aWJtN5U6gm8dM3NjaGU=” https://apimanager.mycompany.com/v1/portal/orgs
[{“roles”:[“5cb59c810cf2ee801253c6ea”],”id”:”5cb59c800cf2ee801253c6e9″,”name”:”myDevOrg”, “url”:”https://apimanager.mycompany.com/v1/portal/orgs/5cb59c800cf2ee801253c6e9”,”owner”:true}]
Subsequently we invoke the second REST service, v1/portal/orgs/<developer-organization-id>/apps, using the result of the preceding service invocation. A possible output follows:
admin@s-developerportal:~$ curl -k -H “X-IBM-APIManagement-Context:myOrg.myCatalog” -H “Content-Type:application/json” -H “Authorization:Basic aWJtN5U6gm8dM3NjaGU=” https://apimanager.mycompany.com/v1/portal/orgs/5cb59c800cf2ee801253c6e9/apps
[{“type”:”PRODUCTION”,”promoteTo”:null,”id”:”5cb59e420cf2ee801253c6f3″,”name”:”myApp”, “orgID”:”5cb59c800cf2ee801253c6e9″,”public”:false,”description”:””, “credentials”:{“clientID”:”af4095a2-a069-438f-bb62-3b4715de6cb9″,”clientSecret”:”********************************************”,”description”:”Default”, “url”:”https://apimanager.mycompany.com/v1/portal/orgs/5cb59c800cf2ee801253c6e9/apps/ 5cb59e420cf2ee801253c6f3/credentials”},”appCredentials”:[{“id”:”5cb59e420cf2ee801253c6f4″,”description”:”Default”, “url”:”https://apimanager.mycompany.com/v1/portal/orgs/5cb59c800cf2ee801253c6e9/apps/ 5cb59e420cf2ee801253c6f3/credentials/5cb59e420cf2ee801253c6f4″,”clientID”:”af4095a2-a069-438f-bb62-3b4715de6cb9″,”clientSecret”:”********************************************”}], “enabled”:true,”state”:”ACTIVE”,”imageURL”:null, “appImageURL”:”https://developerportal.mycompany.com/myOrg/myCatalog/sites/all/modules/ibm_apim/images/icons/ app/app_14.png”,”oauthRedirectURI”:””,”certificate”:null,”createdAt”:”2019-04-16T09:20:02.237+0000″,”updatedAt”:”2019-04-16T09:20:02.237+0000″, “url”:”https://apimanager.mycompany.com/v1/portal/orgs/5cb59c800cf2ee801253c6e9/apps/ 5cb59e420cf2ee801253c6f3”}]
We can now invoke the third REST service, v1/portal/orgs/<developer-organization-id>/apps/<app-id>/credentials, using the results obtained from the preceding services. However, in addition, it is required to input the Client Secret with SHA256 base64 hash format.
Assuming the textual form of the Client Secret to be: jM2kG1eI5aF4aQ4qW1hH7wT4hK5sG3oB6sL2pV0rW8aR4rG8bT, executing the SHA256 base64 hash conversion can be accomplished via the following Linux command:
admin@s-developerportal:~$ printf “jM2kG1eI5aF4aQ4qW1hH7wT4hK5sG3oB6sL2pV0rW8aR4rG8bT” | shasum -a 256 | cut -d ” ” -f 1 | xxd -r -p | base64
ZFGcgrXetduo6x41snstOV4HBITAej8gXODfGkJPaoE=
Now we can invoke the third REST service:
admin@s-developerportal:~$ curl -k -i -H “X-IBM-APIManagement-Context:myOrg.myCatalog” -H “Content-Type:application/json” -H “Authorization:Basic aWJtN5U6gm8dM3NjaGU=” -d ‘{“clientID”: “0ec9010b-11d5-4459-8e9f-2695459c9ed5”, “clientSecret”: “ZFGcgrXetduo6x41snstOV4HBITAej8gXODfGkJPaoE=”, “description”: “The original ClientSecret”}’ -X PUT https://apimanager.mycompany.com/v1/portal/orgs/5cb59c800cf2ee801253c6e9/apps/5cb59e420cf2ee801253c6f3/credentials
HTTP/1.1 200 Connection established
HTTP/1.1 200 OK
Date: Tue, 16 Apr 2019 15:31:33 GMT
Server: Apache
Strict-Transport-Security: max-age=31536000; includeSubdomains;
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Pragma: No-cache
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 UTC
Content-Location: https://s-apimanager.mycompany.com/v1/portal/orgs/5cb59c800cf2ee801253c6e9/apps/5cb59e420cf2ee801253c6f3/credentials
Content-Type: application/json
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Processed-By: 99cf3d9a68baac5182f507e677f9f800a87c9470
Vary: Accept-Encoding
Transfer-Encoding: chunked
{“clientID”:”0ec9010b-11d5-4459-8e9f-2695459c9ed5″,”clientSecret”:”********************************************”,”description”:”The original ClientSecret”,”url”:”https://s-apimanager.mycompany.com/v1/portal/orgs/5cb59c800cf2ee801253c6e9/apps/5cb59e420cf2ee801253c6f3/credentials”}
The application myApp has now the desired credentials.
We are hence able to assign to an Application, which was redefined after an API Manager reconfiguration, the same credentials it had in the initial API Manager configuration. As the outcome, clients can continue to invoke the APIs included in the plans subscribed by that Application using the original credentials.