Description
Current
The original implementation of credentials providers was designed before API clients were introduced into the product.
The BasicAuthProvider
uses a username and password to perform basic auth in exchange for an access token. Other subclasses of this provider that shipped are all available as top level imports in the package.
from jamf_pro_sdk import JamfProClient, BasicAuthProvider
client = JamfProClient(
server="jamf.my.org",
credentials=BasicAuthProvider("oscar", "j@mf1234!")
)
Later, the ApiClientCredentialsProvider
was added to support API clients. It, along with all providers, is available at a lower level import.
from jamf_pro_sdk.clients.auth import ApiClientCredentialsProvider
The other builtin providers inherit from BasicAuthProvider
and creating API client versions means duplication of code and an unintuitive naming scheme. Plus, the top-level imports should be kept to a minimum.
Proposed
I am proposing a breaking change to the existing structure of the SDK's credentials providers and changing the subclasses to accept a credentials provider type to allow more flexibility and only one implementation of each type even if other authentication methods are introduced into the future.
Only the two base providers would be made available as top level imports.
from jamf_pro_sdk import ApiClientCredentialsProvider, UserCredentialsProvider
The BasicAuthProvider
would be renamed to UserCredentialsProvider
to avoid confusion with basic auth - which Jamf Pro no longer supports for direct API authentication - and make the use of a user account clear.
The PromptForCredentials
, LoadFromAwsSecretsManager
, and LoadFromKeychain
providers will be removed and replaced with helper utilities that return an instantiated credentials provider of the specified type.
import json
from typing import Type
import boto3
from jamf_pro_sdk.clients.auth import (
ApiClientCredentialsProvider,
CredentialsProvider,
UserCredentialsProvider,
)
def load_from_aws_secrets_manager(
credentials_provider_type: Type[ApiClientCredentialsProvider, UserCredentialsProvider],
secret_id: str,
version_id: str = None,
version_stage: str = None,
) -> CredentialsProvider:
secrets_client = boto3.client("secretsmanager")
kwargs = {"SecretId": secret_id}
if version_id:
kwargs["VersionId"] = version_id
if version_stage:
kwargs["VersionStage"] = version_stage
secret_value = secrets_client.get_secret_value(**kwargs)
credentials = json.loads(secret_value["SecretString"])
return credentials_provider_type(**credentials)
from jamf_pro_sdk import JamfProClient, ApiClientCredentialsProvider, load_from_aws_secrets_manager
client = JamfProClient(
server="jamf.my.org",
credentials=load_from_aws_secrets_manager(
credentials_provider_type=ApiClientCredentialsProvider,
secret_id="arn:aws:secretsmanager:us-west-2:111122223333:secret:aes128-1a2b3c"
)
)
The documentation will need an expanded section in the "Getting Started" guide and "SDK Reference" better explaining importing and using all of the available credentials providers and helper utils.