Skip to content
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

FalconPy v1.3.2 - Address authenticated method handler breaking change #1046

Merged
merged 13 commits into from
Sep 13, 2023
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
# Version 1.3.2
> This release resolves a breaking change introduced in Version 1.3.0. This issue presents itself when developers attempt to call the `authenticated` method directly from the `OAuth2` Service Class. Review issue #1043 for more detail.

## Added features and functionality
+ Added: Expanded the Uber Class into a submodule, and restored the 1.2.16 version of this class as `APIHarness`. This class is now __DEPRECATED__. The 1.3.0 version of this class is now named `APIHarnessV2` (The advanced Uber Class) .
- `_auth_object/_base_falcon_auth.py`
- `_auth_object/_falcon_interface.py`
- `_auth_object/_uber_interface.py`
- `api_complete/__init__.py`
- `api_complete/_advanced.py`
- `api_complete/_legacy.py`
- `__init__.py`
> Expanded unit testing to complete code coverage.
- `tests/test_authorizations.py`
- `tests/test_falcon_container.py`
- `tests/test_uber_api_complete.py`
- `tests/test_uber.py`

## Issues resolved
+ Fixed: Error generated when trying leverage the legacy `authenticated` lambda method handler within the `OAuth2` Service Class. Closes #1043.
- `_auth_object/_base_falcon_auth.py`
- `_auth_object/_falcon_interface.py`
- `_service_class/_service_class.py`
- `oauth2.py`
> Expanded unit testing to complete code coverage.
- `tests/test_service_class.py`
- Thanks go out to @morcef for identifying and reporting this issue. 🙇
+ Fixed: Type check failure when creating a mock of the `OAuth2` Service Class. Relates to #1043.
- `_service_class/_base_service_class.py`
- Thanks go out to @davidt99 for identifying / reporting this issue and providing the fix. 🙇

---

# Version 1.3.1
## Added features and functionality
+ Added: 1 new operation added (`highVolumeQueryChanges`) from the _FileVantage_ service collection.
Expand Down
4 changes: 2 additions & 2 deletions src/falconpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
RequestValidator
)
from .alerts import Alerts
from .api_complete import APIHarness
from .api_complete import APIHarness, APIHarnessV2
from .cloud_snapshots import CloudSnapshots
from .cloud_connect_aws import CloudConnectAWS
from .cspm_registration import CSPMRegistration
Expand Down Expand Up @@ -173,7 +173,7 @@
"RequestPayloads", "RequestValidator", "PayloadValidationError", "MIN_TOKEN_RENEW_WINDOW",
"MAX_TOKEN_RENEW_WINDOW", "GLOBAL_API_MAX_RETURN", "MOCK_OPERATIONS", "CloudSnapshots",
"NoAuthenticationMechanism", "InvalidIndex", "version", "InvalidCredentialFormat",
"UnnecessaryEncodingUsed"
"UnnecessaryEncodingUsed", "APIHarnessV2"
]
"""
This is free and unencumbered software released into the public domain.
Expand Down
10 changes: 0 additions & 10 deletions src/falconpy/_auth_object/_base_falcon_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,6 @@ def logout(self) -> Union[dict, bool]:
def auth_headers(self) -> Dict[str, str]:
"""Get a dictionary of headers that can authenticate a HTTP request."""

@property
@abstractmethod
def authenticated(self) -> bool:
"""Read-only property to return whether authentication is successful."""

@property
@abstractmethod
def token_expired(self) -> bool:
"""Read-only property that returns the current token expiration status."""

@property
@abstractmethod
def cred_format_valid(self) -> bool:
Expand Down
8 changes: 4 additions & 4 deletions src/falconpy/_auth_object/_falcon_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,14 +456,14 @@ def refreshable(self) -> bool:
return self.cred_format_valid

@property
def token_expired(self) -> bool:
def token_stale(self) -> bool:
"""Return whether the token is ready to be renewed."""
return (time.time() - self.token_time) >= (self.token_expiration - self.renew_window)

@property
def authenticated(self) -> bool:
def token_valid(self) -> bool:
"""Return if we are authenticated by retrieving the inverse of token_expired."""
return not self.token_expired
return not self.token_stale

@property
def cred_format_valid(self) -> bool:
Expand All @@ -489,7 +489,7 @@ def log_facility(self) -> LogFacility:
@property
def auth_headers(self) -> Dict[str, str]:
"""Return a Bearer token baked into an Authorization header ready for an HTTP request."""
if self.token_expired and self.refreshable:
if self.token_stale and self.refreshable:
self.login()

return {"Authorization": f"Bearer {self.token_value}"}
Expand Down
11 changes: 10 additions & 1 deletion src/falconpy/_auth_object/_uber_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,23 @@ def login(self) -> bool:
"""Generate an authorization token."""
super().login()

return self.authenticated
return self.token_valid

def logout(self) -> bool:
"""Revoke the current authorization token."""
result = super().logout()

return bool(result["status_code"] == 200)

# Legacy property getters maintained for backwards functionality.
def authenticated(self) -> bool:
"""Return the current authentication status."""
return self.token_valid

def token_expired(self) -> bool:
"""Return the current token expiration status."""
return self.token_stale

# _ ____ ____ ____ ____ _ _ _ _ ____ _ _ ___ _ ____ ____ ____
# | |___ | __ |__| | \_/ |__| |__| |\ | | \ | |___ |__/ [__
# |___ |___ |__] | | |___ | | | | | | \| |__/ |___ |___ | \ ___]
Expand Down
4 changes: 2 additions & 2 deletions src/falconpy/_service_class/_base_service_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ def __init__(self: "BaseServiceClass",
# do not maintain authentication detail outside of the auth_object.
# An auth_object is treated as an atomic collection.
if auth_object:
if issubclass(type(auth_object), FalconInterface):
if isinstance(auth_object, FalconInterface): # Issue 1043
self.auth_object: Union[FalconInterface, UberInterface] = auth_object
else:
# Easy Object Authentication
# Look for an auth_object as an attribute to the object they
# provided. This attribute must be a FalconInterface derivative.
if hasattr(auth_object, "auth_object"):
if issubclass(type(auth_object.auth_object), FalconInterface):
if isinstance(auth_object.auth_object, FalconInterface):
self.auth_object: Union[FalconInterface, UberInterface] = auth_object.auth_object
else:
# Get all constructor arguments for the default authentication class.
Expand Down
14 changes: 12 additions & 2 deletions src/falconpy/_service_class/_service_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,11 @@ def logout(self) -> dict:
# Legacy property getters maintained for backwards functionality.
def authenticated(self) -> bool:
"""Return the current authentication status."""
return self.auth_object.authenticated
return self.auth_object.token_valid

def token_expired(self) -> bool:
"""Return a boolean reflecting token expiration status."""
return self.auth_object.token_expired
return self.auth_object.token_stale

# Manual operation override
def override(self,
Expand Down Expand Up @@ -320,3 +320,13 @@ def token(self) -> str:
This recreates pre-1.3.0 functionality.
"""
return self.auth_object.token_value

@property
def token_valid(self) -> bool:
"""Return the current status of the token."""
return self.auth_object.token_valid

@property
def token_stale(self) -> bool:
"""Return the current expiration status of the token."""
return self.auth_object.token_stale
2 changes: 1 addition & 1 deletion src/falconpy/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

For more information, please refer to <https://unlicense.org>
"""
_VERSION = '1.3.1'
_VERSION = '1.3.2'
_MAINTAINER = 'Joshua Hiller'
_AUTHOR = 'CrowdStrike'
_AUTHOR_EMAIL = '[email protected]'
Expand Down
50 changes: 50 additions & 0 deletions src/falconpy/api_complete/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
r"""FalconPy Uber Class module.

_______ __ _______ __ __ __
| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----.
|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__|
|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____|
|: 1 | |: 1 |
|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy
`-------' `-------'

The
__ __ ____ ___ ____ __ _ ____ _____ _____
| T T| \ / _]| \ / ]| T / T/ ___// ___/
| | || o ) / [_ | D ) / / | | Y o ( \_( \_
| | || TY _]| / / / | l___ | |\__ T\__ T
| : || O || [_ | \ / \_ | T| _ |/ \ |/ \ |
l || || T| . Y \ || || | |\ |\ |
\__,_jl_____jl_____jl__j\_j \____jl_____jl__j__j \___j \___j

for the CrowdStrike OAuth2 API Customer SDK

This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <https://unlicense.org>
"""
from ._legacy import APIHarness
from ._advanced import APIHarnessV2

__all__ = ["APIHarness", "APIHarnessV2"]
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,18 @@
"""
import functools
from typing import Dict, Union, Callable
from ._constant import ALLOWED_METHODS
from ._util import (
from .._constant import ALLOWED_METHODS
from .._util import (
perform_request
)
from ._auth_object import UberInterface
from ._util import (
from .._auth_object import UberInterface
from .._util import (
handle_body_payload_ids,
scrub_target,
handle_container_operations,
uber_request_keywords
)
from ._error import (
from .._error import (
InvalidOperation,
InvalidMethod,
TokenNotSpecified,
Expand Down Expand Up @@ -89,8 +89,8 @@ def log_failure(msg, code: int, res: dict = None):
return wrapper


class APIHarness(UberInterface):
"""The FalconPy Uber Class.
class APIHarnessV2(UberInterface):
"""The FalconPy Uber Class, enhanced version.

The Uber Class inherits from the UberInterface class, which is a stand alone
class that encapsulates the FalconAuth class. This allows the Uber Class to
Expand Down
Loading
Loading