Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pki --api option #4867

Merged
merged 2 commits into from
Oct 2, 2024
Merged

Add pki --api option #4867

merged 2 commits into from
Oct 2, 2024

Conversation

edewata
Copy link
Contributor

@edewata edewata commented Sep 30, 2024

The pki CLI has been updated to provide an option to specify the REST API version to use when communicating with the server. By default the CLI will use API v1, but it might change in the future.

The PKIClient class has been modified to store the API version which will automatically be used by other client classes (e.g. InfoClient).

The basic CA test has been updated to run pki info with the default API and API v2 and verify the access logs generated by these commands.

The CertServlet has been modified to use the same path (i.e. /ca/v2/certs) for list and search operations, but list will will use a GET method and search will use a POST method.

The CACertClient has been updated to use the proper path based on the API version.

The search operation has also been modified to no longer return the total certs found to allow future performance optimization. Calculating the total certs found with Simple Paged Results requires retrieving the full search results from the database so it should be avoided.

The basic CA test has been updated to test pki ca-cert-find with the default API and API v2 then verify the access logs generated by these commands. The test-ca-certs.sh script is no longer used so it has been removed.

Copy link
Member

@fmarco76 fmarco76 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have several concerns on this change. We are not going to have a CLI working with v1 and a CLI working with v2. It is possible for the moment to share the code because there are very few differences but these could diverge.
Additionally, I do not see a use case where you have to call a mix of v1 and v2 endpoints to complete a task since v1 and v2 implement the same functionalities (almost 1:1).
We have a switch at server level which change the default APIs provided by the server, and the client should work with them, v1 and v2 are needed to external tools unless we want to develop two CLI interface. The switch is not to support multiple API versions but to have a soft switch before removing the old version.

The only reason I see for the switch in the client is if we have the v2 without resteasy client and we need to test and compare with current implementation. Is this the goal?

@edewata
Copy link
Contributor Author

edewata commented Oct 1, 2024

Generally to ensure a smooth transition, protocol changes (including API version, data format, encryption algorithm, etc.) should be done incrementally:

  • initially the server should enable the new protocol while continuing to support the old protocol so existing clients will still work
  • when a client is ready to migrate it will use the new protocol to talk to the server, but other clients not ready to migrate will still work too. this transition period could take a long time.
  • when there is no more clients using the old protocol, the server can disable the old protocol

If the protocol is changed immediately (only one protocol is supported) on the server without a transition period, that means all clients need to be switched simultaneously too, otherwise they will stop working. If there are many clients or the clients are managed by different people, this could be difficult to accomplish. This challenge applies to both live production environment as well as code still in development.

In our case we'll just have a single PKI CLI, but to allow a smooth transition during development the CLI will need to be able to select whether to use API v1 or v2, and it will need a separate code for parts of the API that have diverged, but still one CLI. This way we can individually migrate each PKI CLI command (there are a lot of them), add a new test for it using v2 API, and we can still change the v2 API for that command if needed (e.g. fixing the path, params). Once all PKI CLI commands support v2, we can change the default in PKI CLI to v2, but we still have other clients: Console, Web UI, IPA, third-party clients, so we cannot disable v1 yet.

We can migrate IPA the same way too. IPA is making many different calls to PKI and we need to migrate each call to v2 as well. Without a transition period, it will be difficult to implement.

@fmarco76
Copy link
Member

fmarco76 commented Oct 1, 2024

Once all PKI CLI commands support v2

PKI CLI already support v2. The PR #4837 runs all 145 tests we have upstream using v2 and all pass. The only failing tests are from IPA which uses its client.

Not sure if it is reasonable double the tests to try with v1 and v2.

For the other clients it is reasonable to test incrementally.

I was not saying that we have to drop v1 too early but that the CLI was used and tested during the development to make v2 identical to v1 and we can go wild to find some corner cases.

Different the situation for the other clients. IMHO these should move to v1 endpoints to avoid problems and when the path has changed for all known clients then we can move to v2 default. v1 will be dropped when it is not used by clients.

The pki CLI has been updated to provide an option to specify
the REST API version to use when communicating with the server.
By default the CLI will use API v1, but it might change in the
future.

The PKIClient class has been modified to store the API version
which will automatically be used by other client classes (e.g.
InfoClient).

The basic CA test has been updated to run pki info with the
default API and API v2 and verify the access logs generated by
these commands.
@edewata
Copy link
Contributor Author

edewata commented Oct 2, 2024

@fmarco76 Please see the updated patch and the PR description above.

I've changed the pki CLI to use /rest instead of /v1 in the path by default so the default API will be controlled by the server, not the client. Hopefully this will avoid conflicts with PR #4837.

My concern with PR #4837 is that we don't actually have a comprehensive test for API v1, and we haven't done much improvements in API v2 that we discussed previously (e.g. fixing the paths, params), so if we just change the default API to v2 on the server side now we won't see any problems except in IPA tests. Also, in order to merge that PR, all failures in IPA test have to be fixed, and the changes in PKI and IPA have to be merged at the same time, and the RPMs also have to be released at the same time, which could make things more complicated.

I added another patch in this PR to update pki ca-cert-find to demonstrate the kind of improvements we can make in API v2. Here the path is changed to be more consistent (or more RESTful). The total attribute has been removed since it requires a lot of resources to compute. So there's only one CLI but it can handle multiple API versions. Also, the API v1 is not affected, so all existing clients using the /rest path will continue to work, meaning this kind of change can be done incrementally until the API v2 improvements are complete.

Copy link
Member

@fmarco76 fmarco76 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look good. I have a small comment for the path change in cert-find.

I still have some doubt on the overall approach but you can merge this and then see for the other tests.

@@ -107,7 +107,7 @@ public void getCert(HttpServletRequest request, HttpServletResponse response) th
}
}

@WebAction(method = HttpMethod.POST, paths = {"search"})
@WebAction(method = HttpMethod.POST, paths = {""})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general REST semantic for POST is to create something or modify something in the server and it is generally used across the APIs so if we post to /ca/certs I am expecting to generate a cert entry so I would not modify this path

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reverted the path changes for now, we can revisit this issue another time.

My concern with this path is that the search keyword in POST /ca/v2/certs/search occupies the same position as the cert ID in GET /ca/v2/certs/{id}. Although they use different HTTP methods, it doesn't look RESTful since /ca/v2/certs/search does not point to an actual object.

For creating/adding an object I think usually it's advised to use PUT. POST is kind of a generic method that can be used for anything that doesn't fit other HTTP methods. Maybe it would be better to use something like POST /ca/v2/certs?action=search.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For creating/adding an object I think usually it's advised to use PUT. POST is kind of a generic method that can be used for anything that doesn't fit other HTTP methods. Maybe it would be better to use something like POST /ca/v2/certs?action=search.

Actually, POST is the method to create a new resource. PUT is used to create or modify a resource where you already know the ID (these some example from a very quick search: restfulapi web, mozilla or geeksforgeeks).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In our case the certs are always generated by the CA, so the client will never call this API to create a cert (enrollment/renewal is done using a different interface and it takes a CSR instead of a cert). Suppose we change the API to allow an authorized user to upload an existing cert to the CA, we might use PUT /ca/v2/certs/<cert ID>. If we don't want to require the client to include the cert ID in the request we probably can use POST, but I'd suggest we use POST /ca/v2/certs?action=upload. That way we can still use POST /ca/v2/certs?action=search for search.

Generally I'd say that all REST resources should support a GET operation. If GET doesn't make sense for that resource, like GET /ca/v2/certs/search, it's not really a RESTful design.

The CertServlet.listCerts() has modified to no longer
return the total certs found to allow future performance
optimization. Calculating the total certs found with Simple
Paged Results requires retrieving the full search results
from the database so it should be avoided.

The basic CA test has been updated to test pki ca-cert-find
with the default API and API v2 then verify the access logs
generated by these commands. The test-ca-certs.sh script is
no longer used so it has been removed.
@edewata
Copy link
Contributor Author

edewata commented Oct 2, 2024

@fmarco76 Thanks for the comments! I'll merge once the CI is done.

Copy link

sonarcloud bot commented Oct 2, 2024

@edewata edewata merged commit 269745d into dogtagpki:master Oct 2, 2024
158 of 165 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants