Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env_integration_tests.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,11 @@ CLOUD_SDK_CFG_DESTINATION_DEFAULT_URL=https://your-destination-auth-url-here
CLOUD_SDK_CFG_DESTINATION_DEFAULT_URI=https://your-destination-configuration-uri-here
CLOUD_SDK_CFG_DESTINATION_DEFAULT_IDENTITYZONE=your-identity-zone-here

CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_URL=https://your-data-anonymization-api-url-here
CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_CERT=your-base64-encoded-client-certificate-pem
CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_KEY=your-base64-encoded-client-private-key-pem
# Alternative to inline base64 cert/key values:
# CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_DESTINATION_NAME=your-client-certificate-destination-name

CLOUD_SDK_CFG_SDM_DEFAULT_URI=https://your-sdm-api-uri-here
CLOUD_SDK_CFG_SDM_DEFAULT_UAA='{"url":"https://your-auth-url","clientid":"your-client-id","clientsecret":"your-client-secret","identityzone":"your-identity-zone"}'
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## About this project

This SDK provides consistent interfaces for interacting with foundational services such as object storage, destination management, audit logging, telemetry, and secure credential handling.
This SDK provides consistent interfaces for interacting with foundational services such as object storage, destination management, audit logging, data anonymization, telemetry, and secure credential handling.

The Python SDK offers a clean, type-safe API following Python best practices while maintaining compatibility with the SAP Application Foundation ecosystem.

Expand All @@ -17,6 +17,7 @@ The Python SDK offers a clean, type-safe API following Python best practices whi
- **ObjectStore Service**
- **Secret Resolver**
- **Telemetry & Observability**
- **Data Anonymization Service**

## Requirements and Setup

Expand Down Expand Up @@ -62,6 +63,7 @@ Each module has comprehensive usage guides:
- [ObjectStore](src/sap_cloud_sdk/objectstore/user-guide.md)
- [Secret Resolver](src/sap_cloud_sdk/core/secret_resolver/user-guide.md)
- [Telemetry](src/sap_cloud_sdk/core/telemetry/user-guide.md)
- [Data Anonymization](src/sap_cloud_sdk/core/data_anonymization/user-guide.md)

## Support, Feedback, Contributing

Expand Down
23 changes: 23 additions & 0 deletions docs/INTEGRATION_TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,28 @@ CLOUD_SDK_CFG_DESTINATION_DEFAULT_URI=https://your-destination-configuration-uri
CLOUD_SDK_CFG_DESTINATION_DEFAULT_IDENTITYZONE=your-identity-zone-here
```

### Data Anonymization Integration Tests

For Data Anonymization integration tests, configure the following variables in `.env_integration_tests`:

```bash
# Data Anonymization Configuration
CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_URL=https://your-data-anonymization-api-url-here
CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_CERT=your-base64-encoded-client-certificate-pem
CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_KEY=your-base64-encoded-client-private-key-pem
```

`CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_CERT` and `CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_KEY` must contain the base64-encoded PEM content, not filesystem paths.

If the certificate is managed through BTP Destination service, you can use a destination instead of inline certificate values:

```bash
CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_URL=https://your-data-anonymization-api-url-here
CLOUD_SDK_CFG_DATA_ANONYMIZATION_DEFAULT_DESTINATION_NAME=your-client-certificate-destination-name
```

The destination must be configured with `ClientCertificateAuthentication` and reference a certificate bundle containing the client certificate and private key.

## Running Integration Tests

```bash
Expand All @@ -70,6 +92,7 @@ uv run pytest tests/ -m integration -v

# Run specific module integration tests
uv run pytest tests/core/integration/auditlog -v
uv run pytest tests/core/integration/data_anonymization -v
uv run pytest tests/objectstore/integration/ -v
uv run pytest tests/destination/integration/ -v
```
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "sap-cloud-sdk"
version = "0.14.2"
version = "0.15.0"
description = "SAP Cloud SDK for Python"
readme = "README.md"
license = "Apache-2.0"
Expand Down
138 changes: 138 additions & 0 deletions src/sap_cloud_sdk/core/data_anonymization/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
"""SAP Cloud SDK extension – Data Anonymization module.

Telemetry for this module is limited to operation-level metrics. Sensitive
payloads such as source text, pseudonymization metadata, file contents, or
certificate material are never emitted as telemetry attributes.

Usage::

from sap_cloud_sdk.core.data_anonymization import (
create_client,
AnonymizeRequest,
PseudonymizeRequest,
)

# Auto-detect config from environment / mount
client = create_client()

# Anonymize (irreversible)
result = client.anonymize(AnonymizeRequest(text="John Doe, john@example.com"))
assert result.result is not None

# Pseudonymize (reversible)
pseudo = client.pseudonymize(PseudonymizeRequest(text="John Doe"))
assert pseudo.result is not None
assert len(pseudo.metadata) >= 0

# Explicit config with inline base64 Key Store
from sap_cloud_sdk.core.data_anonymization import DataAnonymizationConfig
cfg = DataAnonymizationConfig(
service_url="https://anonymization.example.com",
cert="<base64-encoded-client-certificate>",
key="<base64-encoded-client-private-key>",
)
client = create_client(config=cfg)

# BTP Destination Key Store (cloud)
client = create_client(config=DataAnonymizationConfig(
service_url="https://anonymization.example.com",
destination_name="my-anonymization-dest",
))
"""

from typing import Optional

from sap_cloud_sdk.core.data_anonymization.client import DataAnonymizationClient
from sap_cloud_sdk.core.data_anonymization.config import (
DataAnonymizationConfig,
_load_config_from_env,
)
from sap_cloud_sdk.core.data_anonymization._http_transport import HttpTransport
from sap_cloud_sdk.core.data_anonymization.models import (
AnonymizeTextRequest,
AnonymizeFileRequest,
AnonymizeRequest,
AnonymizeFileResult,
AnonymizeResult,
FileOperationResult,
PseudonymizeTextRequest,
PseudonymizeFileRequest,
PseudonymizeRequest,
PseudonymizeFileResult,
PseudonymizeResult,
EntityMapping,
)
from sap_cloud_sdk.core.data_anonymization.exceptions import (
DataAnonymizationError,
ClientCreationError,
TransportError,
AuthenticationError,
)
from sap_cloud_sdk.core.telemetry import Module, Operation, record_metrics


@record_metrics(
Module.DATA_ANONYMIZATION,
Operation.DATA_ANONYMIZATION_CREATE_CLIENT,
)
def create_client(
*,
config: Optional[DataAnonymizationConfig] = None,
instance: str = "default",
_telemetry_source: Optional[Module] = None,
) -> DataAnonymizationClient:
"""Create a DataAnonymizationClient with automatic configuration detection.

Args:
config: Optional explicit DataAnonymizationConfig. When omitted the
config is loaded from environment variables / secret mounts.
instance: Service instance name used for secret resolution when
*config* is not provided. Defaults to ``"default"``.
_telemetry_source: Internal parameter; not for end-user use.

Returns:
DataAnonymizationClient ready for anonymize / pseudonymize calls.

Raises:
ClientCreationError: If client creation fails.

Note:
Telemetry for client creation records only module/operation metadata and
never includes configuration values or processed user content.
"""
try:
resolved = config if config is not None else _load_config_from_env(instance)
transport = HttpTransport(resolved)
return DataAnonymizationClient(transport, _telemetry_source=_telemetry_source)
except Exception as e:
raise ClientCreationError(
f"Failed to create DataAnonymizationClient: {e}"
) from e


__all__ = [
# Factory
"create_client",
# Client
"DataAnonymizationClient",
# Config
"DataAnonymizationConfig",
# Request / response models
"AnonymizeTextRequest",
"AnonymizeRequest",
"AnonymizeFileRequest",
"AnonymizeFileResult",
"AnonymizeResult",
"FileOperationResult",
"PseudonymizeTextRequest",
"PseudonymizeRequest",
"PseudonymizeFileRequest",
"PseudonymizeFileResult",
"PseudonymizeResult",
"EntityMapping",
# Exceptions
"DataAnonymizationError",
"ClientCreationError",
"TransportError",
"AuthenticationError",
]
Loading
Loading