Skip to content

[Feedback] Overhaul to credentials providers #47

Open
@brysontyrrell

Description

@brysontyrrell

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.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestfeedbackPotential improvements or changes

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions