Metadata-Version: 2.1
Name: confeasy-azure-appc
Version: 1.0.0
Summary: Azure AppConfiguration extension for confeasy.
Home-page: https://github.com/jdvor/confeasy-azure-appc
License: MIT
Keywords: configuration,azure,AppConfiguration
Author: jan Dvorak
Author-email: jandvorak.public@gmail.com
Requires-Python: >=3.12,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Dist: azure-appconfiguration (>=1.7.1,<2.0.0)
Requires-Dist: azure-identity (>=1.19.0,<2.0.0)
Requires-Dist: azure-keyvault-secrets (>=4.9.0,<5.0.0)
Project-URL: Bug Tracker, https://github.com/jdvor/confeasy-azure-appc/issues
Project-URL: Repository, https://github.com/jdvor/confeasy-azure-appc
Description-Content-Type: text/markdown

# confeasy.azure_appc

Application configuration inspired by Microsoft.Extensions.Configuration (.NET).<br/>
See details in GitHub [confeasy][confeasy_gh] ([PyPI][confeasy_pypi]).

This package is an extension to confeasy using [Azure AppConfiguration][azure] service.

## Getting started

Install required packages.

```shell
poetry add confeasy confeasy-azure-appc
# or similar command for your package manager of choice
```

In python, usually around application start:
```python

# DbOptions class is an illustrative example of strongly typed configuration.
class DbOptions:
    def __init__(self):
        self.connnection_string: str = ""
        self.max_connections: int = 100

from confeasy import Builder
from confeasy.envars import EnvironmentVariables
from confeasy.cmdline import CommandLine
from confeasy.azure_appc import AzureAppConfig

# Order of the configuration sources matters; later sources can overwrite values from earlier ones.
builder = (Builder()
           .add_source(AzureAppConfig.from_base_url_in_envars(prefix="db.*"))
           .add_source(EnvironmentVariables("MYAPP_"))
           .add_source(CommandLine()))

config = builder.build()

# Bind configuration to a class instance and pass the instance to other objects.
options = config.bind(DbOptions(), prefix="db")

# OR pick up individual values:
db_conn_str = config.get_value("db.connection_string")
```

## Authentication to Azure resources

#### Important Facts:

* The Python SDK for AppConfiguration allows authentication using both connection strings and credential providers from the azure-identity package.
* The Python SDK for KeyVault supports only credential providers from the azure-identity package, not connection strings.
* AppConfiguration can reference secrets from one or more key vaults.
* The most commonly used provider from azure-identity is [DefaultAzureCredential][dac], which combines several
  potential sources of authentication information, such as access tokens generated by az login or environment variables with conventional names.

> [!IMPORTANT]
> This creates a somewhat complex situation where a simple approach, such as using a single connection string,
> may not work (unless you are using only AppConfiguration).

#### Suggestion:

In the most common scenario, where authentication is required for both AppConfiguration and one or more KeyVault resources,
I recommend familiarizing yourself with managed identities and service principals in Azure and creating a specialized "account" for your application.

An example of how to do this is available in `tests/app_service_principal.sh` (a PowerShell variant is also available).

Once the service principal has been created, ensure the following environment variables are present in the environment:

* `AZURE_APPC_BASE_URL`: Set this to the URL of the Azure AppConfiguration resource, e.g., https://{name}.azconfig.io.
* `AZURE_CLIENT_ID`: Set this to the Application (client) ID of the service principal.
* `AZURE_CLIENT_SECRET`: Set this to the Client Secret of the service principal.
* `AZURE_TENANT_ID`: Set this to the Directory (tenant) ID.

This setup allows you to use the factory method `AzureAppConfig.from_base_url_in_envars`, enabling it to work both
in local environments (such as a developer's machine) and after deployment, such as in a GitHub Action or on the final host.

[azure]: https://learn.microsoft.com/en-us/azure/azure-app-configuration/overview
[confeasy_gh]: https://github.com/jdvor/confeasy
[confeasy_pypi]: https://pypi.org/project/confeasy
[dac]: https://learn.microsoft.com/en-us/python/api/azure-identity/azure.identity.defaultazurecredential?view=azure-python
