Metadata-Version: 2.4
Name: msgraph-py
Version: 1.5.0
Summary: This package contains API wrappers to simplify interaction with Microsoft Graph API through Python functions.
Author: fedamerd
License: MIT License
        
        Copyright (c) 2024 fedamerd
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        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 OR COPYRIGHT HOLDERS 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.
Project-URL: Changelog, https://github.com/fedamerd/msgraph-py/blob/main/CHANGELOG.md
Project-URL: Documentation, https://github.com/fedamerd/msgraph-py/blob/main/README.md
Project-URL: Issues, https://github.com/fedamerd/msgraph-py/issues
Project-URL: Source, https://github.com/fedamerd/msgraph-py
Classifier: Programming Language :: Python :: 3.9
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx[http2]
Requires-Dist: PyJWT[crypto]
Dynamic: license-file

# msgraph-py

## Description

This package contains API wrappers to simplify interaction with Microsoft Graph API through Python functions.

Some of the benefits of `msgraph-py` are:

- Automatic caching and renewal of access tokens, avoiding unnecessary API-calls.
- Sets the correct headers and parameters for you when required (advanced queries).
- Pages results automatically when retrieving large datasets.
- Useful logging and error messages with the Python logging module.
- Optional integration with Django settings.py for reading environment variables.

> [!NOTE]  
> The latest published version of this package can be found at [pypi.org/project/msgraph-py](https://pypi.org/project/msgraph-py/)

### List of available functions

#### [Identity](https://github.com/fedamerd/msgraph-py/blob/main/msgraph/identity.py)

- `get_user()`
- `get_user_risk()`
- `revoke_refresh_tokens()`
- `list_auth_methods()`
- `delete_auth_method()`
- `reset_strong_auth()`
- `get_signin()`

#### [Groups](https://github.com/fedamerd/msgraph-py/blob/main/msgraph/groups.py)

- `get_group()`
- `list_group_members()`
- `add_group_member()`
- `remove_group_member()`

#### [Devices](https://github.com/fedamerd/msgraph-py/blob/main/msgraph/devices.py)

- `get_device()`
- `delete_device()`
- `list_owned_devices()`
- `get_laps_password()`

#### [Mail](https://github.com/fedamerd/msgraph-py/blob/main/msgraph/mail.py)

- `send_mail()`

## Getting Started

1. Create an app registration in Entra ID with the necessary Graph application permissions for the functions you intend to use:  
[Authentication and authorization steps](https://learn.microsoft.com/en-us/graph/auth-v2-service?tabs=http#authentication-and-authorization-steps)

2. Install the latest version of the package:

    ```console
    python3 -m pip install msgraph-py
    ```

3. Configure environment variables:
    - If used within a Django project, `msgraph-py` will by default first attempt to load the following variables from the project's `settings.py`:

        ```python
        # project/settings.py

        AAD_TENANT_ID = "00000000-0000-0000-0000-000000000000"
        AAD_CLIENT_ID = "00000000-0000-0000-0000-000000000000"
        AAD_CLIENT_SECRET = "client-secret-value"
        ```

    - Alternatively you will need to set the following key-value pairs in `os.environ`:

        ```python
        import os

        os.environ["AAD_TENANT_ID"] = "00000000-0000-0000-0000-000000000000"
        os.environ["AAD_CLIENT_ID"] = "00000000-0000-0000-0000-000000000000"
        os.environ["AAD_CLIENT_SECRET"] = "client-secret-value"
        ```

> [!WARNING]  
> You should **never** store sensitive credentials or secrets in production code or commit them to your repository. Always load them at runtime from a secure location or from a local file excluded from the repository.

## Certificate-based authentication

For improved security, consider migrating to certificate-based authentication instead of a static client secret. The simplest way to do this is using the `openssl` command to create a self-signed certificate and private key:

```bash
hostname=$(hostname -s)
fqdn=$(hostname -f)

openssl req \
    -x509 \
    -newkey rsa:2048 \
    -sha256 \
    -days 3650 \
    -subj "/CN=${fqdn}" \
    -keyout "${hostname}_key.pem" \
    -out "${hostname}_cert.pem" \
    -noenc \
    &> /dev/null
```

> [!NOTE]  
> Remove the `-noenc` option if you want to encrypt the private key with a passphrase. Adjust options such as `-days` and `-subj` according to your requirements.

Upload the certificate PEM-file to the app registration in Microsoft Entra ID. Make a note of the certificate thumbprint, as we will be needing this in the next step. See [Microsofts documentation](https://learn.microsoft.com/en-us/graph/auth-register-app-v2#add-credentials) on adding credentials for more info.

Remove `AAD_CLIENT_SECRET` from your configuration and set the following environment variables (or `settings.py`) instead:

```python
os.environ["AAD_PRIVATE_KEY_PATH"] = "path/to/private_key.pem"

# Alternatively pass the key data directly (only PEM-format supported)
os.environ["AAD_PRIVATE_KEY"] = "-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----"

# Required if the private key is password-protected
os.environ["AAD_PRIVATE_KEY_PASSPHRASE"] = "key-passphrase-value"

# Required if the private key does not contain a X.509 certificate
os.environ["AAD_CERT_THUMBPRINT"] = "cert-thumbprint-value"
```

> [!NOTE]  
> You may omit setting `AAD_CERT_THUMBPRINT` if the certificate and private key are bundled together, as the required thumbprint will be retrieved from the certificate automatically at runtime.
>
> PKCS#12 format (`.pfx` or `.p12`) is also supported in addition to PEM when using `AAD_PRIVATE_KEY_PATH`.
> In order to convert a PEM-formatted private key and certificate to a single PKCS#12-formatted file, you can use the following command:
>
> ```bash
> openssl pkcs12 -inkey private-key.pem -in certificate.pem -export -out bundled-key-cert.pfx
> ```

## Usage examples

### Get a single user by objectId or userPrincipalName

```python
from msgraph import get_user

user = get_user("user@example.com")
```

List of returned properties for [user resource type](https://learn.microsoft.com/en-us/graph/api/resources/user#properties).

### Get a list of users using advanced query parameters

```python
from msgraph import get_user

filtered_users = get_user(
    filter="startsWith(department, 'sales')",
    select=[
        "displayName",
        "department",
        "createdDateTime",
    ],
    orderby="createdDateTime desc",
    all=True,
)
```

List of returned properties for [user resource type](https://learn.microsoft.com/en-us/graph/api/resources/user#properties).

### Get a users Entra ID joined devices

```python
from msgraph import list_owned_devices

user_devices = list_owned_devices(
    user_id="user@example.com",
    filter="isManaged eq true and trustType eq 'AzureAd'",
    select=[
        "deviceId",
        "displayName",
        "isCompliant",
        "approximateLastSignInDateTime",
    ],
    orderby="approximateLastSignInDateTime desc",
)
```

List of returned properties for [device resource type](https://learn.microsoft.com/en-us/graph/api/resources/device#properties).

### Send an e-mail with attachments

```python
from msgraph import send_mail

send_mail(
    sender_id="noreply@example.com",
    recipients=[
        "john.doe@example.com",
        "jane.doe@example.com",
    ],
    subject="Mail from Graph API",
    body="<h1>Content of the mail body</h1>",
    is_html=True,
    priority="high",
    attachments=[
        "/path/to/file1.txt",
        "/path/to/file2.txt",
    ],
)
```

## API documentation

- [Authentication and authorization basics](https://learn.microsoft.com/en-us/graph/auth/auth-concepts)
- [Use query parameters to customize responses](https://learn.microsoft.com/en-us/graph/query-parameters)
- [Microsoft Entra authentication methods API overview](https://learn.microsoft.com/en-us/graph/api/resources/authenticationmethods-overview)

### Resource types and properties

- [authenticationMethod resource type](https://learn.microsoft.com/en-us/graph/api/resources/authenticationmethod)
- [device resource type](https://learn.microsoft.com/en-us/graph/api/resources/device#properties)
- [directoryObject resource type](https://learn.microsoft.com/en-us/graph/api/resources/directoryobject)
- [group resource type](https://learn.microsoft.com/en-us/graph/api/resources/group#properties)
- [riskyUser resource type](https://learn.microsoft.com/en-us/graph/api/resources/riskyuser#properties)
- [signIn resource type](https://learn.microsoft.com/en-us/graph/api/resources/signin#properties)
- [user resource type](https://learn.microsoft.com/en-us/graph/api/resources/user#properties)
