Skip to content

Commit

Permalink
update to latest refactoring of auth libs
Browse files Browse the repository at this point in the history
  • Loading branch information
carl-adams-planet committed Nov 30, 2024
1 parent 6b03579 commit 40755ff
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 25 deletions.
53 changes: 31 additions & 22 deletions planet/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@
import httpx

import planet_auth
import planet_auth_config
import planet_auth_utils

from .constants import SECRET_FILE_PATH

from .auth_builtins import _ProductionEnv

AuthType = httpx.Auth


# planet_auth and planet_auth_utils code more or less entirely
# entirely supersedes this class. But, keeping this here for
# supersedes this class. But, keeping this here for
# now for interface stability to bridge with the rest of the SDK.
class Auth(metaclass=abc.ABCMeta):
"""Handle authentication information for use with Planet APIs."""
Expand All @@ -47,10 +46,9 @@ def from_key(key: str) -> AuthType:
warnings.warn("Planet API keys will be deprecated at some point."
" Initialize an OAuth client, or create an OAuth service account."
" Proceeding for now.", PendingDeprecationWarning)
pl_authlib_context = planet_auth_utils.ProfileManager.initialize_auth_client_context(
auth_profile_opt=planet_auth_utils.Profiles.BUILTIN_PROFILE_NAME_LEGACY,
pl_authlib_context = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context(
auth_api_key_opt=key,
save_token_file=False
save_token_file=False,
)
return _PLAuthLibAuth(plauth=pl_authlib_context)

Expand All @@ -67,12 +65,14 @@ def from_file(
filename: Alternate path for the planet secret file.
"""
# There is no direct replacement for "from_file()", which held an API key.
# API keys will be deprecated, and user login will be different from service account
# login under OAuth.
# There is no direct replacement for "from_file()", which expected the
# file to only hold an API key (planet_auth_utils now can use it for
# other things, too). API keys will be deprecated for most use cases,
# and user login will be different from service account login under
# OAuth.
warnings.warn("Auth.from_file() will be deprecated.", PendingDeprecationWarning)
plauth_config = {
**planet_auth_config.Production.LEGACY_AUTH_AUTHORITY,
**_ProductionEnv.LEGACY_AUTH_AUTHORITY,
"client_type": planet_auth.PlanetLegacyAuthClientConfig.meta().get("client_type"),
}
pl_authlib_context = planet_auth.Auth.initialize_from_config_dict(client_config=plauth_config,
Expand All @@ -88,10 +88,8 @@ def from_env(variable_name: typing.Optional[str] = None) -> AuthType:
Parameters:
variable_name: Alternate environment variable.
"""
# There are just too many env vars and ways they interact and combine to continue to
# support this method with the planet auth lib in the future. Especially as we want
# to move away from API keys and towards OAuth methods.
warnings.warn("Auth.from_env() will be deprecated.", PendingDeprecationWarning)
# TODO: we should consider how we want to expose initialization
# from the ENV for OAuth M2M
variable_name = variable_name or planet_auth.EnvironmentVariables.AUTH_API_KEY
api_key = os.getenv(variable_name, None)
return Auth.from_key(api_key)
Expand All @@ -111,23 +109,34 @@ def from_login(email: str,
base_url: The base URL to use. Defaults to production
authentication API base url.
"""
warnings.warn("Auth.from_login() and password based user login will be deprecated.", PendingDeprecationWarning)
if base_url:
warnings.warn("base_url is not longer a supported parameter to Auth.from_login()", DeprecationWarning)
# TODO: Need to provide instructions on what an application should do.
# It would not be hard to add username/password support to the
# PlanetAuthFactory, but we should encourage an OAuth login.
# At a code level, we should provide "from_oauth_m2m" (Done) and something
# to use a user profile, that must be initialized interactively.
warnings.warn("Auth.from_login() has been deprecated.", DeprecationWarning)
raise DeprecationWarning("Auth.from_login() has been deprecated.")

@staticmethod
def from_oauth_m2m(client_id: str, client_secret: str) -> AuthType:
"""Create authentication from OAuth service account client ID and secret.
pl_authlib_context = planet_auth_utils.ProfileManager.initialize_auth_client_context(
auth_profile_opt=planet_auth_utils.Profiles.BUILTIN_PROFILE_NAME_LEGACY
Parameters:
client_id: Planet service account client ID.
client_secret: Planet service account client secret.
"""
pl_authlib_context = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context(
auth_client_id_opt=client_id,
auth_client_secret_opt=client_secret,
)
# Note: login() will save the resulting token
pl_authlib_context.login(username=email, password=password, allow_tty_prompt=False)
return _PLAuthLibAuth(plauth=pl_authlib_context)

@staticmethod
def from_plauth(pl_authlib_context: planet_auth.Auth):
"""
Create authentication from the provided Planet Auth Library Authentication Context.
Generally, applications will want to use one of the Auth Library helpers to
construct this context, such as the `initialize_auth_client_context()` method.
construct this context (See the factory class).
"""
return _PLAuthLibAuth(plauth=pl_authlib_context)

Expand Down
154 changes: 154 additions & 0 deletions planet/auth_builtins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Copyright 2024 Planet Labs PBC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
from typing import Dict, List, Optional
from planet_auth_utils.builtins_provider import BuiltinConfigurationProviderInterface

# Needs to be set at runtime (not necessarily at import time) for dependency injection to planet_auth_util
os.environ["PL_BUILTIN_AUTH_CONFIG_PROVIDER"] = "planet.auth_builtins._BuiltinConfigurationProvider"

class _ProductionEnv:
PRIMARY_PUBLIC_OAUTH_AUTHORITY_AUTH0 = {
"_comment": "OIDC/OAuth server used by Planet Public API endpoints",
"auth_server": "https://login.planet.com/",
"audiences": ["https://api.planet.com/"]
}
PRIMARY_PUBLIC_OAUTH_AUTHORITY_SENTINELHUB = {
"_comment": "OIDC/OAuth server used by Planet Public API endpoints",
"auth_server": "https://services.sentinel-hub.com/auth/realms/main",
"audiences": ["https://api.planet.com/"]
}
LEGACY_AUTH_AUTHORITY = {
"_comment": "Planet legacy JWT auth server used by Planet Public API endpoints",
"legacy_auth_endpoint": "https://api.planet.com/v0/auth/login"
}
PRIMARY_PUBLIC_OAUTH_AUTHORITIES = [
PRIMARY_PUBLIC_OAUTH_AUTHORITY_AUTH0,
PRIMARY_PUBLIC_OAUTH_AUTHORITY_SENTINELHUB,
]

_OIDC_AUTH_CLIENT_CONFIG__SDK_PROD = {
# The well known OIDC client that is the Planet Python CLI.
# Developers should register their own clients so that users may
# manage grants for different applications. Registering applications
# also allows for application specific URLs or auth flow selection.
**_ProductionEnv.PRIMARY_PUBLIC_OAUTH_AUTHORITY_AUTH0,
"client_type": "oidc_device_code",
"client_id": "49lHVBYlXCdfIYqE1B9zeXt0iFHSXees",
"scopes": ["planet", "offline_access", "openid", "profile", "email"],
}

_OIDC_AUTH_CLIENT_CONFIG__M2M_PROD = {
**_ProductionEnv.PRIMARY_PUBLIC_OAUTH_AUTHORITY_SENTINELHUB,
"client_type": "oidc_client_credentials_secret",
"scopes": [],
# "client_id": "__MUST_BE_USER_SUPPLIED__",
# "client_secret": "__MUST_BE_USER_SUPPLIED__",
# "scopes": ["planet"],
# "audiences": [""]
}

_LEGACY_AUTH_CLIENT_CONFIG__PROD = {
**_ProductionEnv.LEGACY_AUTH_AUTHORITY,
"client_type": "planet_legacy",
}

_NOOP_AUTH_CLIENT_CONFIG = {
"client_type": "none",
}


class _BuiltinConfigurationProvider(BuiltinConfigurationProviderInterface):
"""
Concrete implementation of built-in client profiles for the planet_auth
library that pertain to the Planet Lab's cloud service.
"""

# fmt: off
##
## OAuth production environment profiles
##
# Real
BUILTIN_PROFILE_NAME_PLANET_USER = "planet-user"
BUILTIN_PROFILE_NAME_PLANET_M2M = "planet-m2m"
# Aliases
# BUILTIN_PROFILE_NAME_PROD = "prod"
# BUILTIN_PROFILE_NAME_PROD_M2M = "prod-m2m"
# BUILTIN_PROFILE_NAME_PROD_AUTH0 = "prod-auth0"
# BUILTIN_PROFILE_NAME_PROD_SENTINEL_HUB = "prod-sentinel-hub"

##
## Profiles that use Planet's old (pre-OAuth) based auth protocol
##
BUILTIN_PROFILE_NAME_LEGACY = "legacy"

##
## Misc auth profiles
##
BUILTIN_PROFILE_NAME_NONE = "none"
BUILTIN_PROFILE_NAME_DEFAULT = "default"

##
## Default that should be used when no other selection has been made
##
DEFAULT_PROFILE = BUILTIN_PROFILE_NAME_PLANET_USER

_builtin_profile_auth_client_configs = {
## OAuth Client Configs
BUILTIN_PROFILE_NAME_PLANET_USER : _OIDC_AUTH_CLIENT_CONFIG__SDK_PROD,
BUILTIN_PROFILE_NAME_PLANET_M2M : _OIDC_AUTH_CLIENT_CONFIG__M2M_PROD,

# Planet Legacy Protocols
BUILTIN_PROFILE_NAME_LEGACY : _LEGACY_AUTH_CLIENT_CONFIG__PROD,

# Misc
BUILTIN_PROFILE_NAME_NONE : _NOOP_AUTH_CLIENT_CONFIG,
}

_builtin_profile_aliases = {
BUILTIN_PROFILE_NAME_DEFAULT : DEFAULT_PROFILE,
# BUILTIN_PROFILE_NAME_PROD : BUILTIN_PROFILE_NAME_PLANET_USER,
# BUILTIN_PROFILE_NAME_PROD_M2M : BUILTIN_PROFILE_NAME_PLANET_M2M,
# BUILTIN_PROFILE_NAME_PROD_AUTH0 : BUILTIN_PROFILE_NAME_PLANET_USER,
# BUILTIN_PROFILE_NAME_PROD_SENTINEL_HUB : BUILTIN_PROFILE_NAME_PLANET_M2M,
}
_builtin_profile_default_by_client_type = {
"oidc_device_code" : BUILTIN_PROFILE_NAME_PLANET_USER,
"oidc_auth_code" : BUILTIN_PROFILE_NAME_PLANET_USER,
"oidc_client_credentials_secret" : BUILTIN_PROFILE_NAME_PLANET_M2M,
"planet_legacy" : BUILTIN_PROFILE_NAME_LEGACY,
}
_builtin_trust_realms: Dict[str, Optional[List[dict]]] = {
"PRODUCTION": _ProductionEnv.PRIMARY_PUBLIC_OAUTH_AUTHORITIES,
"CUSTOM": None,
}
# fmt: on

def builtin_client_authclient_config_dicts(self) -> Dict[str, dict]:
return self._builtin_profile_auth_client_configs

def builtin_client_profile_aliases(self) -> Dict[str, str]:
return self._builtin_profile_aliases

def builtin_default_profile_by_client_type(self) -> Dict[str, str]:
pass

def builtin_default_profile(self) -> str:
return self.BUILTIN_PROFILE_NAME_DEFAULT

def builtin_trust_environment_names(self) -> List[str]:
return list(_BuiltinConfigurationProvider._builtin_trust_realms.keys())

def builtin_trust_environments(self) -> Dict[str, Optional[List[dict]]]:
return _BuiltinConfigurationProvider._builtin_trust_realms
6 changes: 3 additions & 3 deletions planet/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ def main(ctx, verbosity, quiet, auth_profile, auth_client_id, auth_client_secret


def _configure_cli_auth_ctx(ctx, auth_profile, auth_client_id, auth_client_secret, auth_api_key):
# planet-auth library Auth type
ctx.obj['AUTH'] = planet_auth_utils.ProfileManager.initialize_auth_client_context(
# planet-auth library Auth context type
ctx.obj['AUTH'] = planet_auth_utils.PlanetAuthFactory.initialize_auth_client_context(
auth_profile_opt=auth_profile,
auth_client_id_opt=auth_client_id,
auth_client_secret_opt=auth_client_secret,
auth_api_key_opt=auth_api_key,
)

# planet SDK Auth type
# planet SDK Auth context type
ctx.obj['PLSDK_AUTH'] = planet.Auth.from_plauth(pl_authlib_context=ctx.obj['AUTH'])


Expand Down

0 comments on commit 40755ff

Please sign in to comment.