Skip to content

Commit e5c4e6f

Browse files
authored
Ianhelle/bokeh3.7 fixes 2025 03 31 (#843)
* Compat fixes for Bokeh 3.7 Also suppressing classes of mypy errors in bokeh modules since it is broadly incompatible with Bokeh. Fixing flake8 error in common/utilty/types * Fix for vt-py changing structure VTObject dictionary - causing conversion to dataframe to contain hundreds of columns. Limiting json_normalize to max_levels=0 * Fix for using AzCli credential with Managed Identity * Mypy fix for azure_auth_core.py * Fixing logic in build_cli_client * Dependency vulns Updating cryptography to >=43.0.1 Add explicit dependencies for jinja2>=3.1.5 and tornado>=6.4.2 to avoid vulnerable versions * Update azure-piplelines to skip pip-authenticate
1 parent 060cf38 commit e5c4e6f

File tree

6 files changed

+106
-29
lines changed

6 files changed

+106
-29
lines changed

.azurepipelines/azure-pipelines-publish-pypi.yml

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,10 @@ extends:
5757
versionSpec: '>=3.10'
5858
architecture: 'x64'
5959
displayName: 'Use latest Python'
60-
- powershell: |
61-
# Define the content for pip.conf
62-
# Define the content for pip.conf
63-
$pipConfContent = "[global]`nindex-url=https://pkgs.dev.azure.com/mstic-detections/mstic-jupyter/_packaging/PyPIInternalFeed/pypi/simple/`nextra-index-url=https://pypi.org/simple"
64-
# Create the .pip directory if it doesn't exist
65-
New-Item -ItemType Directory -Force -Path "$HOME\.pip"
66-
# Write the content to pip.conf
67-
$pipConfContent | Out-File -FilePath "$HOME\.pip\pip.conf" -Encoding UTF8
68-
# Verify the creation
69-
Get-Content "$HOME\.pip\pip.conf"
70-
displayName: Create pip.conf
71-
- task: PipAuthenticate@1
72-
inputs:
73-
artifactFeeds: PyPIInternalFeed
74-
displayName: 'Authenticate pip for internal feed'
60+
#- task: PipAuthenticate@1
61+
# inputs:
62+
# artifactFeeds: PyPIInternalFeed
63+
# displayName: 'Authenticate pip for internal feed'
7564

7665
- powershell: python -m pip install --upgrade pip
7766
displayName: 'Upgrade pip'

conda/conda-reqs.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ azure-storage-blob>=12.5.0
1414
azure-mgmt-subscription
1515
beautifulsoup4>=4.0.0
1616
bokeh>=3.0.0
17-
cryptography>=3.1
17+
cryptography>=43.0.1
1818
deprecated>=1.2.4
1919
dnspython>=2.0.0, <3.0.0
2020
folium>=0.9.0
@@ -23,6 +23,7 @@ html5lib
2323
httpx>=0.23.0, <1.0.0
2424
ipython>=7.23.1
2525
ipywidgets>=7.4.2, <9.0.0
26+
jinja2>=3.1.5 # (sec vuln) transitive dependency via multiple packages
2627
keyring>=13.2.1
2728
lxml>=4.6.5
2829
matplotlib>=3.0.0
@@ -45,6 +46,7 @@ scipy
4546
setuptools>=40.6.3
4647
statsmodels
4748
tldextract>=2.2.2
49+
tornado>=6.4.2 # (sec vuln) transitive dependency via bokeh
4850
tqdm>=4.36.1
4951
typing-extensions>=4.2.0
5052
urllib3>=1.23

msticpy/auth/azure_auth_core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ def _build_cli_client(
162162
except ClientAuthenticationError as ex:
163163
logger.info("Azure CLI credential failed to authenticate: %s", str(ex))
164164
# Check if the error is related to tenant ID
165-
if "Tenant" not in str(ex).lower():
165+
if "tenant" not in str(ex).casefold():
166166
raise # re-raise if it's a different error
167167
logger.info("Creating Azure CLI credential without tenant_id")
168168
cred = AzureCliCredential()

requirements-all.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ azure-monitor-query>=1.0.0, <=2.0.0
1616
azure-storage-blob>=12.5.0
1717
beautifulsoup4>=4.0.0
1818
bokeh>=3.0.0
19-
cryptography>=3.1
19+
cryptography>=43.0.1
2020
deprecated>=1.2.4
2121
dnspython>=2.0.0, <3.0.0
2222
folium>=0.9.0
@@ -27,6 +27,7 @@ importlib-resources >= 6.4.0; python_version <= "3.8"
2727
ipython >= 7.1.1; python_version < "3.8"
2828
ipython >= 7.23.1; python_version >= "3.8"
2929
ipywidgets>=7.4.2, <9.0.0
30+
jinja2>=3.1.5 # (sec vuln) transitive dependency via multiple packages
3031
keyring>=13.2.1
3132
KqlmagicCustom[jupyter-extended]>=0.1.114.post22
3233
lxml>=4.6.5
@@ -58,6 +59,7 @@ splunk-sdk>=1.6.0,!=2.0.0
5859
statsmodels>=0.11.1
5960
sumologic-sdk>=0.1.11
6061
tldextract>=2.2.2
62+
tornado>=6.4.2 # (sec vuln) transitive dependency via bokeh
6163
tqdm>=4.36.1
6264
typing-extensions>=4.2.0
6365
urllib3>=1.23

requirements.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ azure-mgmt-subscription>=3.0.0
99
azure-monitor-query>=1.0.0, <=2.0.0
1010
beautifulsoup4>=4.0.0
1111
bokeh>=3.0.0
12-
cryptography>=3.1
12+
cryptography>=43.0.1
1313
deprecated>=1.2.4
1414
dnspython>=2.0.0, <3.0.0
1515
folium>=0.9.0
@@ -20,6 +20,7 @@ importlib-resources >= 6.4.0; python_version <= "3.8"
2020
ipython >= 7.1.1; python_version < "3.8"
2121
ipython >= 7.23.1; python_version >= "3.8"
2222
ipywidgets>=7.4.2, <9.0.0
23+
jinja2>=3.1.5 # (sec vuln) transitive dependency via multiple packages
2324
keyring>=13.2.1
2425
lxml>=4.6.5
2526
msal>=1.12.0
@@ -40,6 +41,7 @@ pytz>=2019.2 # pandas
4041
pyyaml>=3.13
4142
setuptools>=40.6.3
4243
tldextract>=2.2.2
44+
tornado>=6.4.2 # (sec vuln) transitive dependency via bokeh
4345
tqdm>=4.36.1
4446
typing-extensions>=4.2.0
4547
urllib3>=1.23

tests/auth/test_azure_auth_core.py

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414

1515
import pytest
1616
import pytest_check as check
17-
from azure.identity import ChainedTokenCredential, DeviceCodeCredential
17+
from azure.identity import (
18+
AzureCliCredential,
19+
ChainedTokenCredential,
20+
DeviceCodeCredential,
21+
)
1822

1923
from msticpy.auth.azure_auth_core import (
2024
AzCredentials,
@@ -305,14 +309,6 @@ def test_build_env_client_alt(
305309
assert result is None
306310

307311

308-
@patch("msticpy.auth.azure_auth_core.AzureCliCredential", autospec=True)
309-
def test_build_cli_client(mock_cli_credential):
310-
"""Test _build_cli_client function."""
311-
_build_cli_client()
312-
# assert isinstance(result, mock_cli_credential)
313-
mock_cli_credential.assert_called_once()
314-
315-
316312
@pytest.mark.parametrize(
317313
"env_vars, tenant_id, aad_uri, client_id",
318314
[
@@ -812,8 +808,94 @@ def side_effect_func(
812808
1 for instance in mock_instances if instance.get_token.called
813809
)
814810
assert token_calls_made > 0
815-
# This assertion was already done above when checking mock_instances, so no need to do it twice
811+
# This assertion was already done above when checking mock_instances,
812+
# so no need to do it twice
816813
# with different instances that may not have been called properly
817814
elif side_effect is None:
818815
# Simple case: verify the token was requested at least once
819816
assert mock_msi_credential.return_value.get_token.called
817+
818+
819+
@pytest.mark.parametrize(
820+
"tenant_id, token_side_effects, expected_exception, expected_logs",
821+
[
822+
# Case 1: tenant_id provided, get_token succeeds
823+
(
824+
"some-tenant-id",
825+
[None], # No exception from get_token
826+
None,
827+
["Creating Azure CLI credential with tenant_id"],
828+
),
829+
# Case 2: tenant_id provided, get_token fails with a non-tenant error
830+
(
831+
"some-tenant-id",
832+
[ClientAuthenticationError("Some other error")],
833+
ClientAuthenticationError,
834+
[
835+
"Creating Azure CLI credential with tenant_id",
836+
"Azure CLI credential failed to authenticate: Some other error",
837+
],
838+
),
839+
# Case 3: tenant_id provided, get_token fails due to tenant error
840+
(
841+
"some-tenant-id",
842+
[ClientAuthenticationError("tenant error")],
843+
None,
844+
[
845+
"Creating Azure CLI credential with tenant_id",
846+
"Azure CLI credential failed to authenticate: tenant error",
847+
"Creating Azure CLI credential without tenant_id",
848+
],
849+
),
850+
# Case 4: no tenant_id, get_token succeeds
851+
(
852+
None,
853+
[None],
854+
None,
855+
["Creating Azure CLI credential without tenant_id"],
856+
),
857+
# Case 5: no tenant_id, get_token fails
858+
(
859+
None,
860+
[ClientAuthenticationError("No tenant set error")],
861+
ClientAuthenticationError,
862+
["Creating Azure CLI credential without tenant_id"],
863+
),
864+
],
865+
)
866+
def test_build_cli_client(
867+
tenant_id,
868+
token_side_effects,
869+
expected_exception,
870+
expected_logs,
871+
caplog,
872+
monkeypatch,
873+
):
874+
"""Test _build_cli_client with various tenant_id cases and token side effects."""
875+
# Set caplog level to capture INFO messages
876+
caplog.set_level(logging.INFO)
877+
878+
mock_cred = MagicMock(spec=AzureCliCredential)
879+
# Configure the mock to apply side effect only on first call
880+
if token_side_effects:
881+
mock_cred.get_token.side_effect = token_side_effects + [
882+
None
883+
] # First call uses side effect, then return None
884+
885+
# Patch the AzureCliCredential constructor to return the mock
886+
with patch(
887+
"msticpy.auth.azure_auth_core.AzureCliCredential", return_value=mock_cred
888+
):
889+
if expected_exception:
890+
with pytest.raises(expected_exception):
891+
_build_cli_client(tenant_id=tenant_id)
892+
else:
893+
returned_cred = _build_cli_client(tenant_id=tenant_id)
894+
# We should get our mock credential or a new one if it tries fallback
895+
assert isinstance(returned_cred, AzureCliCredential)
896+
897+
found_logs = [rec.message for rec in caplog.records if rec.levelname == "INFO"]
898+
for log_msg in expected_logs:
899+
assert any(
900+
log_msg in msg for msg in found_logs
901+
), f"Expected log message not found: {log_msg}"

0 commit comments

Comments
 (0)