salesforce-data-customcode 6.1.0.dev6__tar.gz → 6.1.0.dev7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/PKG-INFO +1 -1
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/pyproject.toml +1 -1
- salesforce_data_customcode-6.1.0.dev7/src/datacustomcode/named_credential/direct/auth.py +191 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/direct/credentials.py +1 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/external_callout/README.md +5 -1
- salesforce_data_customcode-6.1.0.dev6/src/datacustomcode/named_credential/direct/auth.py +0 -63
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/LICENSE.txt +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/README.md +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/auth.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/cli.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/client.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/cmd.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/common_config.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/config.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/config.yaml +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/constants.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/credentials.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/deploy.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_platform_client.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_platform_config.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/errors.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/impl/default.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/spark_base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/spark_default.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions/types.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/einstein_predictions_config.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/file/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/file/base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/file/path/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/file/path/default.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/feature_types/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/feature_types/chunking.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function/runtime.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/function_utils.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/query_api.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/sf_cli.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/reader/utils.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/writer/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/writer/base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/writer/csv.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/io/writer/print.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/default.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/errors.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/spark_base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/spark_default.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/generate_text_request.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/generate_text_request_builder.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/generate_text_response.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway/types/generate_text_response_builder.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/llm_gateway_config.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/mixin.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/default.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/direct/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/direct/transport.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/direct/url_resolver.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/errors.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/spark_base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/spark_default.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_method.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_request.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_request_builder.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_response.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential/types/http_response_builder.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/named_credential_config.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/py.typed +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/run.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/scan.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/spark/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/spark/base.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/spark/default.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/template.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/__init__.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/.devcontainer/devcontainer.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/Dockerfile.dependencies +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/README.md +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/build_native_dependencies.sh +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/chunking/payload/config.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/chunking/payload/entrypoint.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/chunking/requirements.txt +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/README.md +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/config.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/entrypoint.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/external_callout_config.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_external_callout/tests/test.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_llm/config.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_llm/entrypoint.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_llm/files/chunking_prompt.txt +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_llm/tests/test.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_prediction/config.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_prediction/entrypoint.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/example/chunking_with_prediction/tests/test.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/payload/config.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/payload/entrypoint.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/payload/utility.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/requirements-dev.txt +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/function/requirements.txt +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/.devcontainer/devcontainer.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/Dockerfile +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/Dockerfile.dependencies +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/README.md +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/account.ipynb +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/build_native_dependencies.sh +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/employee_hierarchy/employee_data.csv +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/employee_hierarchy/entrypoint.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/external_callout/entrypoint.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/external_callout/external_callout_config.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/examples/streaming_deltas/entrypoint.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/jupyterlab.sh +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/payload/config.json +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/payload/entrypoint.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/requirements-dev.txt +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/templates/script/requirements.txt +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/token_provider.py +0 -0
- {salesforce_data_customcode-6.1.0.dev6 → salesforce_data_customcode-6.1.0.dev7}/src/datacustomcode/version.py +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Copyright (c) 2025, Salesforce, Inc.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""
|
|
16
|
+
Inject external credential auth into an outgoing request.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import base64
|
|
22
|
+
import datetime
|
|
23
|
+
import hashlib
|
|
24
|
+
import hmac
|
|
25
|
+
from typing import (
|
|
26
|
+
TYPE_CHECKING,
|
|
27
|
+
Any,
|
|
28
|
+
Dict,
|
|
29
|
+
)
|
|
30
|
+
import urllib.parse
|
|
31
|
+
|
|
32
|
+
from requests.auth import AuthBase
|
|
33
|
+
|
|
34
|
+
from datacustomcode.named_credential.direct.credentials import AuthType
|
|
35
|
+
|
|
36
|
+
if TYPE_CHECKING:
|
|
37
|
+
from requests.models import PreparedRequest
|
|
38
|
+
|
|
39
|
+
_SIGV4_ALGORITHM = "AWS4-HMAC-SHA256"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class DynamicAuthHandler(AuthBase):
|
|
43
|
+
def __init__(self, cred_config: Dict[str, Any]) -> None:
|
|
44
|
+
self.config = cred_config
|
|
45
|
+
self.auth_type = cred_config.get("auth_type")
|
|
46
|
+
|
|
47
|
+
def __call__(self, request: PreparedRequest) -> PreparedRequest:
|
|
48
|
+
if self.auth_type == AuthType.BASIC.value:
|
|
49
|
+
user = self.config.get("username", "")
|
|
50
|
+
pwd = self.config.get("password", "")
|
|
51
|
+
token = base64.b64encode(f"{user}:{pwd}".encode()).decode()
|
|
52
|
+
request.headers["Authorization"] = f"Basic {token}"
|
|
53
|
+
|
|
54
|
+
elif self.auth_type == AuthType.CUSTOM.value:
|
|
55
|
+
for name, value in self.config.get("custom_headers", {}).items():
|
|
56
|
+
request.headers[name] = value
|
|
57
|
+
|
|
58
|
+
elif self.auth_type in (AuthType.OAUTH.value, AuthType.JWT.value):
|
|
59
|
+
bearer = self.config.get("access_token") or self.config.get("token")
|
|
60
|
+
if not bearer:
|
|
61
|
+
raise ValueError(
|
|
62
|
+
f"'{self.auth_type}' auth requires an 'access_token' or 'token'."
|
|
63
|
+
)
|
|
64
|
+
request.headers["Authorization"] = f"Bearer {bearer}"
|
|
65
|
+
|
|
66
|
+
elif self.auth_type == AuthType.AWS_SIG_V4.value:
|
|
67
|
+
self._sign_aws_sigv4(request)
|
|
68
|
+
|
|
69
|
+
else:
|
|
70
|
+
raise ValueError(f"Unsupported auth_type '{self.auth_type}'.")
|
|
71
|
+
|
|
72
|
+
return request
|
|
73
|
+
|
|
74
|
+
def _sign_aws_sigv4(self, request: PreparedRequest) -> None:
|
|
75
|
+
"""Sign ``request`` with AWS Signature Version 4.
|
|
76
|
+
|
|
77
|
+
Requires ``aws_access_key_id``, ``aws_secret_access_key``, ``aws_region``,
|
|
78
|
+
and ``aws_service`` in the credential config; ``aws_session_token`` is
|
|
79
|
+
optional (for temporary credentials). The signed date, payload hash, and
|
|
80
|
+
(when present) session token are added as ``x-amz-*`` headers so the sent
|
|
81
|
+
request matches what was signed.
|
|
82
|
+
"""
|
|
83
|
+
access_key = self.config.get("aws_access_key_id")
|
|
84
|
+
secret_key = self.config.get("aws_secret_access_key")
|
|
85
|
+
region = self.config.get("aws_region")
|
|
86
|
+
service = self.config.get("aws_service")
|
|
87
|
+
session_token = self.config.get("aws_session_token")
|
|
88
|
+
missing = [
|
|
89
|
+
name
|
|
90
|
+
for name, value in (
|
|
91
|
+
("aws_access_key_id", access_key),
|
|
92
|
+
("aws_secret_access_key", secret_key),
|
|
93
|
+
("aws_region", region),
|
|
94
|
+
("aws_service", service),
|
|
95
|
+
)
|
|
96
|
+
if not value
|
|
97
|
+
]
|
|
98
|
+
if missing:
|
|
99
|
+
raise ValueError(f"'{self.auth_type}' auth requires {', '.join(missing)}.")
|
|
100
|
+
access_key = str(access_key)
|
|
101
|
+
secret_key = str(secret_key)
|
|
102
|
+
region = str(region)
|
|
103
|
+
service = str(service)
|
|
104
|
+
|
|
105
|
+
parsed = urllib.parse.urlsplit(str(request.url or ""))
|
|
106
|
+
host = parsed.netloc
|
|
107
|
+
canonical_uri = urllib.parse.quote(parsed.path or "/", safe="/-_.~")
|
|
108
|
+
canonical_query = _canonical_query_string(parsed.query)
|
|
109
|
+
|
|
110
|
+
body = request.body or b""
|
|
111
|
+
if isinstance(body, str):
|
|
112
|
+
body = body.encode("utf-8")
|
|
113
|
+
payload_hash = hashlib.sha256(body).hexdigest()
|
|
114
|
+
|
|
115
|
+
now = datetime.datetime.now(datetime.timezone.utc)
|
|
116
|
+
amz_date = now.strftime("%Y%m%dT%H%M%SZ")
|
|
117
|
+
datestamp = now.strftime("%Y%m%d")
|
|
118
|
+
|
|
119
|
+
request.headers["x-amz-date"] = amz_date
|
|
120
|
+
request.headers["x-amz-content-sha256"] = payload_hash
|
|
121
|
+
if session_token:
|
|
122
|
+
request.headers["x-amz-security-token"] = session_token
|
|
123
|
+
|
|
124
|
+
signed = {
|
|
125
|
+
"host": host,
|
|
126
|
+
"x-amz-content-sha256": payload_hash,
|
|
127
|
+
"x-amz-date": amz_date,
|
|
128
|
+
}
|
|
129
|
+
if session_token:
|
|
130
|
+
signed["x-amz-security-token"] = session_token
|
|
131
|
+
signed_headers = ";".join(sorted(signed))
|
|
132
|
+
canonical_headers = "".join(
|
|
133
|
+
f"{name}:{signed[name]}\n" for name in sorted(signed)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
canonical_request = "\n".join(
|
|
137
|
+
[
|
|
138
|
+
request.method or "GET",
|
|
139
|
+
canonical_uri,
|
|
140
|
+
canonical_query,
|
|
141
|
+
canonical_headers,
|
|
142
|
+
signed_headers,
|
|
143
|
+
payload_hash,
|
|
144
|
+
]
|
|
145
|
+
)
|
|
146
|
+
credential_scope = f"{datestamp}/{region}/{service}/aws4_request"
|
|
147
|
+
string_to_sign = "\n".join(
|
|
148
|
+
[
|
|
149
|
+
_SIGV4_ALGORITHM,
|
|
150
|
+
amz_date,
|
|
151
|
+
credential_scope,
|
|
152
|
+
hashlib.sha256(canonical_request.encode("utf-8")).hexdigest(),
|
|
153
|
+
]
|
|
154
|
+
)
|
|
155
|
+
signing_key = _derive_signing_key(secret_key, datestamp, region, service)
|
|
156
|
+
signature = hmac.new(
|
|
157
|
+
signing_key, string_to_sign.encode("utf-8"), hashlib.sha256
|
|
158
|
+
).hexdigest()
|
|
159
|
+
|
|
160
|
+
request.headers["Authorization"] = (
|
|
161
|
+
f"{_SIGV4_ALGORITHM} Credential={access_key}/{credential_scope}, "
|
|
162
|
+
f"SignedHeaders={signed_headers}, Signature={signature}"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _canonical_query_string(query: str) -> str:
|
|
167
|
+
"""Build the AWS Sig V4 canonical query string from a raw query string."""
|
|
168
|
+
pairs = urllib.parse.parse_qsl(query, keep_blank_values=True)
|
|
169
|
+
encoded = [
|
|
170
|
+
(
|
|
171
|
+
urllib.parse.quote(key, safe="-_.~"),
|
|
172
|
+
urllib.parse.quote(value, safe="-_.~"),
|
|
173
|
+
)
|
|
174
|
+
for key, value in pairs
|
|
175
|
+
]
|
|
176
|
+
encoded.sort()
|
|
177
|
+
return "&".join(f"{key}={value}" for key, value in encoded)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _derive_signing_key(
|
|
181
|
+
secret_key: str, datestamp: str, region: str, service: str
|
|
182
|
+
) -> bytes:
|
|
183
|
+
"""Derive the AWS Sig V4 signing key via the chained HMAC-SHA256 sequence."""
|
|
184
|
+
|
|
185
|
+
def _hmac(key: bytes, msg: str) -> bytes:
|
|
186
|
+
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
|
|
187
|
+
|
|
188
|
+
k_date = _hmac(f"AWS4{secret_key}".encode(), datestamp)
|
|
189
|
+
k_region = _hmac(k_date, region)
|
|
190
|
+
k_service = _hmac(k_region, service)
|
|
191
|
+
return _hmac(k_service, "aws4_request")
|
|
@@ -122,7 +122,7 @@ matching entries in `config.json`) to point at your own DLOs.
|
|
|
122
122
|
`auth_type` selects how auth is injected for local testing. It should mirror the
|
|
123
123
|
External Credential your Named Credential uses in the org, so local and deployed
|
|
124
124
|
runs behave the same. This example uses `Custom` (Gemini's `X-goog-api-key`);
|
|
125
|
-
all
|
|
125
|
+
all supported types:
|
|
126
126
|
|
|
127
127
|
| `auth_type` | Fields read | Header sent |
|
|
128
128
|
| ----------- | ------------------------------- | --------------------------------------- |
|
|
@@ -130,7 +130,11 @@ all four supported types:
|
|
|
130
130
|
| `Custom` | `custom_headers` (sent verbatim)| the headers you list |
|
|
131
131
|
| `OAuth` | `access_token` or `token` | `Authorization: Bearer <token>` |
|
|
132
132
|
| `Jwt` | `access_token` or `token` | `Authorization: Bearer <token>` |
|
|
133
|
+
| `AwsSv4` | `aws_access_key_id`, `aws_secret_access_key`, `aws_region`, `aws_service`, optional `aws_session_token` | `Authorization: AWS4-HMAC-SHA256 ...` plus `x-amz-date` / `x-amz-content-sha256` (and `x-amz-security-token` when a session token is set) |
|
|
133
134
|
|
|
134
135
|
`OAuth`/`Jwt` take a token you supply for the local run — the SDK does not fetch
|
|
135
136
|
or refresh it. In the Data Cloud runtime the Named Credential handles token
|
|
136
137
|
acquisition; this local config only stands in for that during testing.
|
|
138
|
+
|
|
139
|
+
`AwsSv4` signs the request with AWS Signature Version 4 using the keys you
|
|
140
|
+
supply, mirroring an AWS Signature Version 4 External Credential in the org.
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2025, Salesforce, Inc.
|
|
2
|
-
# SPDX-License-Identifier: Apache-2
|
|
3
|
-
#
|
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
# you may not use this file except in compliance with the License.
|
|
6
|
-
# You may obtain a copy of the License at
|
|
7
|
-
#
|
|
8
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
#
|
|
10
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
# See the License for the specific language governing permissions and
|
|
14
|
-
# limitations under the License.
|
|
15
|
-
"""
|
|
16
|
-
Inject external credential auth into an outgoing request.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
from __future__ import annotations
|
|
20
|
-
|
|
21
|
-
import base64
|
|
22
|
-
from typing import (
|
|
23
|
-
TYPE_CHECKING,
|
|
24
|
-
Any,
|
|
25
|
-
Dict,
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
from requests.auth import AuthBase
|
|
29
|
-
|
|
30
|
-
from datacustomcode.named_credential.direct.credentials import AuthType
|
|
31
|
-
|
|
32
|
-
if TYPE_CHECKING:
|
|
33
|
-
from requests.models import PreparedRequest
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class DynamicAuthHandler(AuthBase):
|
|
37
|
-
def __init__(self, cred_config: Dict[str, Any]) -> None:
|
|
38
|
-
self.config = cred_config
|
|
39
|
-
self.auth_type = cred_config.get("auth_type")
|
|
40
|
-
|
|
41
|
-
def __call__(self, request: PreparedRequest) -> PreparedRequest:
|
|
42
|
-
if self.auth_type == AuthType.BASIC.value:
|
|
43
|
-
user = self.config.get("username", "")
|
|
44
|
-
pwd = self.config.get("password", "")
|
|
45
|
-
token = base64.b64encode(f"{user}:{pwd}".encode()).decode()
|
|
46
|
-
request.headers["Authorization"] = f"Basic {token}"
|
|
47
|
-
|
|
48
|
-
elif self.auth_type == AuthType.CUSTOM.value:
|
|
49
|
-
for name, value in self.config.get("custom_headers", {}).items():
|
|
50
|
-
request.headers[name] = value
|
|
51
|
-
|
|
52
|
-
elif self.auth_type in (AuthType.OAUTH.value, AuthType.JWT.value):
|
|
53
|
-
bearer = self.config.get("access_token") or self.config.get("token")
|
|
54
|
-
if not bearer:
|
|
55
|
-
raise ValueError(
|
|
56
|
-
f"'{self.auth_type}' auth requires an 'access_token' or 'token'."
|
|
57
|
-
)
|
|
58
|
-
request.headers["Authorization"] = f"Bearer {bearer}"
|
|
59
|
-
|
|
60
|
-
else:
|
|
61
|
-
raise ValueError(f"Unsupported auth_type '{self.auth_type}'.")
|
|
62
|
-
|
|
63
|
-
return request
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|