Skip to content

Commit

Permalink
Merge pull request #468 from felicijus/feature/oauth-client-credentials
Browse files Browse the repository at this point in the history
feat: oauth2 client credentials
  • Loading branch information
dimastbk authored Oct 5, 2024
2 parents 729449f + 696722a commit cfff667
Show file tree
Hide file tree
Showing 11 changed files with 918 additions and 22 deletions.
128 changes: 110 additions & 18 deletions docs/channels.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@ Channels
========

In order to instantiate a ZeebeWorker or ZeebeClient you will need to provide an instance of a `grpc.aio.Channel`.
This Channel can be configured with the parameters `channel_credentials` and `channel_options`.

.. seealso::

`Python Channel Options <https://grpc.github.io/grpc/python/glossary.html#term-channel_arguments>`_
Documentation of the available Python `grpc.aio.Channel` `options` (channel_arguments).


.. note::

By default, channel_options is defined so that the grpc.keepalive_time_ms option is always set to 45_000 (45 seconds).
Reference Camunda Docs `keep alive intervals <https://docs.camunda.io/docs/self-managed/zeebe-deployment/operations/setting-up-a-cluster/#keep-alive-intervals>`_.

You can override the default `channel_options` by passing
e.g. `channel_options = (("grpc.keepalive_time_ms", 60_000),)` - for a keepalive time of 60 seconds.


Pyzeebe provides a couple standard ways to achieve this:

Expand Down Expand Up @@ -60,34 +76,110 @@ Example with oauth2 (like Camunda Identity):
channel = create_secure_channel(grpc_address="host:port", channel_credentials=channel_credentials)
Camunda Cloud
-------------
Oauth2 Client Credentials Channel
---------------------------------

Create a grpc channel connected to a Zeebe Gateway running in camunda cloud
.. autofunction:: pyzeebe.channel.oauth_channel.create_oauth2_client_credentials_channel

.. autofunction:: pyzeebe.create_camunda_cloud_channel
.. warning::
Some arguments are Optional and are highly dependent on your Authentication Server configuration,
`scope` is usually required and is often optional `audience` .

Example:

.. code-block:: python
from pyzeebe import create_camunda_cloud_channel
import grpc
from pyzeebe.channel.oauth_channel import create_oauth2_client_credentials_channel
channel = create_camunda_cloud_channel("client_id", "client_secret", "cluster_id")
channel: grpc.aio.Channel = create_oauth2_client_credentials_channel(
grpc_address=ZEEBE_ADDRESS,
client_id=ZEEBE_CLIENT_ID,
client_secret=ZEEBE_CLIENT_SECRET,
authorization_server=ZEEBE_AUTHORIZATION_SERVER_URL,
scope="profile email",
audience="zeebe-api", # NOTE: Can be omitted in some cases.
)
Example with custom `channel_options`:

.. code-block:: python
import grpc
from pyzeebe.channel.oauth_channel import create_oauth2_client_credentials_channel
from pyzeebe.types import ChannelArgumentType
Credentials
-----------
channel_options: ChannelArgumentType = (("grpc.so_reuseport", 0),)
.. autoclass:: pyzeebe.AuthMetadataPlugin
:members:
:undoc-members:
channel: grpc.aio.Channel = create_oauth2_client_credentials_channel(
grpc_address=ZEEBE_ADDRESS,
client_id=ZEEBE_CLIENT_ID,
client_secret=ZEEBE_CLIENT_SECRET,
authorization_server=ZEEBE_AUTHORIZATION_SERVER_URL,
scope="profile email",
audience="zeebe-api",
channel_options=channel_options,
)
.. autoclass:: pyzeebe.CredentialsABC
:members:
:undoc-members:
Example with custom `channel_credentials`:

.. autoclass:: pyzeebe.CamundaIdentityCredentials
:members:
:undoc-members:
Useful for self-signed certificates with `grpc.ssl_channel_credentials`.

.. code-block:: python
import grpc
from pyzeebe.channel.oauth_channel import create_oauth2_client_credentials_channel
from pyzeebe.types import ChannelArgumentType
channel_credentials: grpc.ChannelCredentials = grpc.ssl_channel_credentials(
certificate_chain=None, private_key=None, root_certificates=None
)
channel_options: ChannelArgumentType = (("grpc.so_reuseport", 0),)
channel: grpc.aio.Channel = create_oauth2_client_credentials_channel(
grpc_address=ZEEBE_ADDRESS,
client_id=ZEEBE_CLIENT_ID,
client_secret=ZEEBE_CLIENT_SECRET,
authorization_server=ZEEBE_AUTHORIZATION_SERVER_URL,
scope="profile email",
audience="zeebe-api",
channel_credentials=channel_credentials,
channel_options=channel_options,
)
Camunda Cloud (Oauth2 Client Credentials Channel)
-------------------------------------------------

.. autofunction:: pyzeebe.channel.oauth_channel.create_camunda_cloud_channel

.. note::
This is a convenience function for creating a channel with the correct parameters for Camunda Cloud.
It is equivalent to calling `create_oauth2_client_credentials_channel` with the correct parameters.

Example:

.. code-block:: python
from pyzeebe.channel.oauth_channel import create_camunda_cloud_channel
channel: grpc.aio.Channel = create_camunda_cloud_channel(
client_id=ZEEBE_CLIENT_ID,
client_secret=ZEEBE_CLIENT_SECRET,
cluster_id=CAMUNDA_CLUSTER_ID,
)
Camunda Cloud (Deprecated)
--------------------------

Create a grpc channel connected to a Zeebe Gateway running in camunda cloud

.. autofunction:: pyzeebe.channel.camunda_cloud_channel.create_camunda_cloud_channel

Example:

.. code-block:: python
from pyzeebe.channel.camunda_cloud_channel import create_camunda_cloud_channel
channel = create_camunda_cloud_channel("client_id", "client_secret", "cluster_id")
57 changes: 57 additions & 0 deletions docs/credentials.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
===========
Credentials
===========

Oauth2 Client Credentials Plugin
--------------------------------

.. autoclass:: pyzeebe.credentials.Oauth2ClientCredentialsMetadataPlugin
:members:
:special-members:
:private-members:

Example:

.. code-block:: python
oauth2_client_credentials = Oauth2ClientCredentialsMetadataPlugin(
client_id=ZEEBE_CLIENT_ID,
client_secret=ZEEBE_CLIENT_SECRET,
authorization_server=ZEEBE_AUTHORIZATION_SERVER_URL,
scope="profile email",
audience="zeebe-api",
)
call_credentials: grpc.CallCredentials = grpc.metadata_call_credentials(oauth2_client_credentials)
channel_credentials: grpc.ChannelCredentials = grpc.ssl_channel_credentials(
certificate_chain=None, private_key=None, root_certificates=None
)
composite_credentials: grpc.ChannelCredentials = grpc.composite_channel_credentials(
channel_credentials, call_credentials
)
options: ChannelArgumentType = (("grpc.so_reuseport", 0),)
channel: grpc.aio.Channel = grpc.aio.secure_channel(
target=ZEEBE_ADDRESS, credentials=composite_credentials, options=options
)
client = ZeebeClient(channel)
Oauth2 Plugin
-------------
.. autoclass:: pyzeebe.credentials.OAuth2MetadataPlugin
:members:
:special-members:
:private-members:

Internal (Deprecated)
---------------------

.. autoclass:: pyzeebe.AuthMetadataPlugin
:members:
:undoc-members:

.. autoclass:: pyzeebe.CredentialsABC
:members:
:undoc-members:

.. autoclass:: pyzeebe.CamundaIdentityCredentials
:members:
:undoc-members:
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Table Of Contents
Client <client>
Worker <worker>
Channels <channels>
Credentials <credentials>
Decorators <decorators>
Exceptions <errors>
Zeebe Adapter <zeebe_adapter>
5 changes: 4 additions & 1 deletion pyzeebe/channel/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from pyzeebe.channel.camunda_cloud_channel import create_camunda_cloud_channel
from pyzeebe.channel.insecure_channel import create_insecure_channel
from pyzeebe.channel.oauth_channel import (
create_camunda_cloud_channel,
create_oauth2_client_credentials_channel,
)
from pyzeebe.channel.secure_channel import create_secure_channel
9 changes: 7 additions & 2 deletions pyzeebe/channel/camunda_cloud_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from oauthlib import oauth2
from requests import HTTPError
from requests_oauthlib import OAuth2Session
from typing_extensions import deprecated

from pyzeebe.channel.channel_options import get_channel_options
from pyzeebe.errors import (
Expand All @@ -13,6 +14,11 @@
from pyzeebe.types import ChannelArgumentType


@deprecated(
"Use pyzeebe.channel.oauth_channel.create_camunda_cloud_channel function instead",
category=DeprecationWarning,
stacklevel=1,
)
def create_camunda_cloud_channel(
client_id: str,
client_secret: str,
Expand All @@ -28,8 +34,7 @@ def create_camunda_cloud_channel(
client_secret (str): The client secret provided by Camunda Cloud
cluster_id (str): The zeebe cluster id to connect to
region (str): The cluster's region. Defaults to bru-2
channel_options (Optional[Dict], optional): GRPC channel options.
See https://grpc.github.io/grpc/python/glossary.html
channel_options (Optional[ChannelArgumentType]): GRPC channel options. See https://grpc.github.io/grpc/python/glossary.html
Returns:
grpc.aio.Channel: A GRPC Channel connected to the Zeebe gateway.
Expand Down
Loading

0 comments on commit cfff667

Please sign in to comment.