-
Notifications
You must be signed in to change notification settings - Fork 139
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
Update Python API to support REST API v2 #4900
Conversation
It is unexpected that one has to always pass in port when instantiating PKIClient when using a URL. If no port is provided for an http/https connection the port should default to 80/443. |
list_certs is not working:
Fails with a huge traceback but the bottom-line error is: *** requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://ipa.example.test:443/ca/v2/certs/search?size=1 |
I've updated the PR to fix this. |
I think this is because IPA currently doesn't provide a proxy for REST API v2: |
I was using the python classes directly and not going through IPA. |
Yes, but port 443 is owned by IPA and with the current proxy configuration it's not forwarding the request to PKI. |
There was a problem hiding this 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 but the overall looks good.Feel free to update/merge this so it is possible to continue integrating the other APIs and improve the design.
base/common/python/pki/user.py
Outdated
logger = logging.getLogger(__name__) | ||
|
||
|
||
class UserClient(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
object
should not be needed in python3
base/common/python/pki/ca.py
Outdated
logger = logging.getLogger(__name__) | ||
|
||
|
||
class CAClient(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
object
should not be needed in python3
(see https://www.python.org/doc/newstyle/ or https://www.geeksforgeeks.org/comparing-old-style-and-new-style-classes-in-python/)
else: | ||
self.api_version = 'v1' | ||
self.api_path = 'rest' | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some parameters could have different meaning between v1 and v2. As an example: #4672.
Also the output could be different when accessing with v1 or v2 and these difference could increase with the API evolution.
I think the user should be aware of the used API so I would prefer to not automatically revert to v1, or at least a warning should be present.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm.. do you have some examples? Ideally the Python API is supposed to take params that can be used for both REST API v1 and v2, then call either REST API v1 or v2 depending on the availability and client's requirements, then parse the server's response and put it into objects that can be used by the Python client regardless of which REST API version was actually used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the linked PR the GET parameter start
for AgentCertRequestService
is an index for v2 and a serial number for v1 so the user could have different results.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. In that particular case the REST API v1 and v2 aren't compatible, so we probably need to provide separate Python methods/parameters for them, and if the required API version is not available the call should fail instead of automatically switching to the other version. We'll deal with this when we get there.
|
||
class CAClient(object): | ||
|
||
def __init__(self, parent): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is almost empty providing only the subsytem name. To access the API, looking in the pki-ca-cert-find.py
as example, it is needed to create a PKIClient
, then a CAClient
and finally a UserClient
.
Using inheritance the CAClient
could extend the PKIClient so there is no need to create both.
Additionally, with multi inheritance the operation could be invoked on this subsystem object making evident the supported operation. Alternatively, the other clients could create here so instead of
users = user_client.find_users()
it would be
users = ca_client.users.find()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same would be for the other subsystems
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The updated Python API is more consistent with the Java API, so the PKIClient
serves as the main entry point for the client to set up the connection and the authentication, then the operations are grouped by subsystems (e.g. CA, KRA). Ideally the subsystem classes should inherit from a SubsystemClient
class just like in Java API, but that can be added later. Having said that, I'm open to client API redesign as long as it's consistently done in Python and Java API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I did not check the Java version before and they seems consistent. I think there is room for improvement in the design to avoid this multiple clients for the moment I agree it is better to be consistent. We can work on this later.
The PKIClient class has been added to replace PKIConnection as the main access point to PKI services. By default it will use REST API v2, then fall back to v1 if it's not available. Optionally, PKIClient can be configured to use a specific REST API version. The InfoClient, CertClient, AccountClient, and UserClient classes have been added/updated to construct the proper REST URL according to the REST API version in PKIClient. The pki-healthcheck has been updated to use PKIClient. Some simple Python scripts have also been added to demonstrate how to use PKIClient. New tests have been added to run these scripts against the current CA and KRA which support both REST API v1 and v2 and also against an older CA that only supports REST API v1.
@fmarco76 Thanks! I've clean up the PR as you suggested and will merge after the CI is done. Feel free to continue the client API design discussion. |
Quality Gate passedIssues Measures |
Python CI is failing for a deprecated library. We should schedule the work to fix this since we are working on the python code |
Looks like the container tests are failing too, but it doesn't seem to be related to this PR. I'll take a look after this. |
The
PKIClient
class has been added to replacePKIConnection
as the main access point to PKI services. By default it will use REST API v2, then fall back to v1 if it's not available. Optionally,PKIClient
can be configured to use a specific REST API version.The
InfoClient
,CertClient
,AccountClient
, andUserClient
classes have been added/updated to construct the proper REST URL according to the REST API version inPKIClient
.The
pki-healthcheck
has been updated to usePKIClient
. Some simple Python scripts have also been added to demonstrate how to usePKIClient
.New tests have been added to run these scripts against the current CA and KRA which support both REST API v1 and v2 and also against an older CA that only supports REST API v1.