Skip to content

Commit

Permalink
🥷 Private Endpoint Client (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
dgonzo27 committed Sep 22, 2022
1 parent 6bb8a10 commit e70bcfa
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 15 deletions.
4 changes: 4 additions & 0 deletions docs/public/static/changelog/iotStorageClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ title: iot-storage-client Changelog

# Release History for iot-storage-client

### 1.2.0 (09/22/2022)

- Instantiate clients that interact via Azure Private Links/Endpoints

### 1.1.8 (09/13/2022)

- Update documentation
Expand Down
6 changes: 5 additions & 1 deletion docs/public/static/packages/iotStorageClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ A wrapper client to interact with the Azure Blob Service at the account level.
This client provides operations to list, create and delete storage containers and blobs within the account.

```python
IoTStorageClient(credential_type, location_type, account_name, credential, module=None, host=None, port=None)
IoTStorageClient(credential_type, location_type, account_name, credential, module=None, host=None, port=None, private=False)
```

**Parameters**
Expand Down Expand Up @@ -126,6 +126,10 @@ IoTStorageClient(credential_type, location_type, account_name, credential, modul

The open port of the Azure storage account when it lives on an IoT Edge device.

- `private` Optional[bool]

Does this client connect to an Azure storage account over a private endpoint?

### Container Exists Method

Check if a container exists.
Expand Down
6 changes: 5 additions & 1 deletion docs/public/static/packages/iotStorageClientAsync.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ A wrapper client to interact with the Azure Blob Service asynchronously at the a
This client provides operations to list, create and delete storage containers and blobs within the account.

```python
IoTStorageClientAsync(credential_type, location_type, account_name, credential, module=None, host=None, port=None)
IoTStorageClientAsync(credential_type, location_type, account_name, credential, module=None, host=None, port=None, private=False)
```

**Parameters**
Expand Down Expand Up @@ -126,6 +126,10 @@ IoTStorageClientAsync(credential_type, location_type, account_name, credential,

The open port of the Azure storage account when it lives on an IoT Edge device.

- `private` Optional[bool]

Does this client connect to an Azure storage account over a private endpoint?

### Container Exists Method

Check if a container exists.
Expand Down
4 changes: 4 additions & 0 deletions iot-storage-client/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release History

## 1.2.0 (09/22/2022)

- Instantiate clients that interact via Azure Private Links/Endpoints

## 1.1.8 (09/13/2022)

- Update documentation
Expand Down
10 changes: 10 additions & 0 deletions iot-storage-client/iot/storage/client/_aioclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class IoTStorageClientAsync:
module: Optional[str] = None
host: Optional[str] = None
port: Optional[str] = None
private: Optional[bool] = False

service_client: BlobServiceClient
container_client: ContainerClient
Expand All @@ -51,6 +52,7 @@ def __init__(
module: Optional[str] = None,
host: Optional[str] = None,
port: Optional[str] = None,
private: Optional[bool] = False,
) -> None:
self.credential_type = credential_type
self.location_type = location_type
Expand All @@ -59,6 +61,7 @@ def __init__(
self.module = module
self.host = host
self.port = port
self.private = private
self.instantiate_service_client()

def __repr__(self) -> str:
Expand All @@ -82,6 +85,7 @@ def instantiate_service_client(self) -> None:
if self.location_type == LocationType.CLOUD_BASED:
connection_string = generate_cloud_conn_str(
account=self.account_name,
private=self.private,
account_key=self.credential
if self.credential_type == CredentialType.ACCOUNT_KEY
else None,
Expand Down Expand Up @@ -520,6 +524,7 @@ async def generate_file_sas_url(
return generate_cloud_sas_url(
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=f"{container_name}/{source}",
)
if self.location_type == LocationType.EDGE_BASED:
Expand All @@ -528,6 +533,7 @@ async def generate_file_sas_url(
port=self.port,
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=f"{container_name}/{source}",
)
if self.location_type == LocationType.LOCAL_BASED:
Expand All @@ -536,6 +542,7 @@ async def generate_file_sas_url(
port=self.port,
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=f"{container_name}/{source}",
)
return None
Expand Down Expand Up @@ -583,6 +590,7 @@ async def generate_container_sas_url(
return generate_cloud_sas_url(
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=container_name,
)
if self.location_type == LocationType.EDGE_BASED:
Expand All @@ -591,6 +599,7 @@ async def generate_container_sas_url(
port=self.port,
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=container_name,
)
if self.location_type == LocationType.LOCAL_BASED:
Expand All @@ -599,6 +608,7 @@ async def generate_container_sas_url(
port=self.port,
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=container_name,
)
return None
Expand Down
10 changes: 10 additions & 0 deletions iot-storage-client/iot/storage/client/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class IoTStorageClient:
module: Optional[str] = None
host: Optional[str] = None
port: Optional[str] = None
private: Optional[bool] = False

service_client: BlobServiceClient
container_client: ContainerClient
Expand All @@ -53,6 +54,7 @@ def __init__(
module: Optional[str] = None,
host: Optional[str] = None,
port: Optional[str] = None,
private: Optional[bool] = False,
) -> None:
self.credential_type = credential_type
self.location_type = location_type
Expand All @@ -61,6 +63,7 @@ def __init__(
self.module = module
self.host = host
self.port = port
self.private = private
self.instantiate_service_client()

def __repr__(self) -> str:
Expand All @@ -84,6 +87,7 @@ def instantiate_service_client(self) -> None:
if self.location_type == LocationType.CLOUD_BASED:
connection_string = generate_cloud_conn_str(
account=self.account_name,
private=self.private,
account_key=self.credential
if self.credential_type == CredentialType.ACCOUNT_KEY
else None,
Expand Down Expand Up @@ -505,6 +509,7 @@ def generate_file_sas_url(
return generate_cloud_sas_url(
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=f"{container_name}/{source}",
)
if self.location_type == LocationType.EDGE_BASED:
Expand All @@ -513,6 +518,7 @@ def generate_file_sas_url(
port=self.port,
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=f"{container_name}/{source}",
)
if self.location_type == LocationType.LOCAL_BASED:
Expand All @@ -521,6 +527,7 @@ def generate_file_sas_url(
port=self.port,
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=f"{container_name}/{source}",
)
return None
Expand Down Expand Up @@ -568,6 +575,7 @@ def generate_container_sas_url(
return generate_cloud_sas_url(
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=container_name,
)
if self.location_type == LocationType.EDGE_BASED:
Expand All @@ -576,6 +584,7 @@ def generate_container_sas_url(
port=self.port,
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=container_name,
)
if self.location_type == LocationType.LOCAL_BASED:
Expand All @@ -584,6 +593,7 @@ def generate_container_sas_url(
port=self.port,
account=self.account_name,
account_sas=sas_token,
private=self.private,
blob_path=container_name,
)
return None
Expand Down
42 changes: 30 additions & 12 deletions iot-storage-client/iot/storage/client/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,27 @@ def generate_edge_sas_url(
port: str,
account: str,
account_sas: str,
private: bool,
blob_path: Optional[str] = None,
) -> str:
"""
generate a SAS url for a child gateway device
interacting with a parent gateway storage account
"""
link = "privatelink.blob" if private else "blob"
if not blob_path:
return "http://{host}:{port}/{account}.blob.core.windows.net?{sas}".format(
return "http://{host}:{port}/{account}.{link}.core.windows.net?{sas}".format(
host=host,
port=port,
account=account,
link=link,
sas=account_sas,
)
return "http://{host}:{port}/{account}.blob.core.windows.net/{path}?{sas}".format(
return "http://{host}:{port}/{account}.{link}.core.windows.net/{path}?{sas}".format(
host=host,
port=port,
account=account,
link=link,
path=blob_path,
sas=account_sas,
)
Expand Down Expand Up @@ -84,31 +88,38 @@ def generate_local_sas_url(
port: str,
account: str,
account_sas: str,
private: bool,
blob_path: Optional[str] = None,
) -> str:
"""
generate a SAS url for an edge gateway device
interacting with a locally available storage account
(AzureBlobStorageonIoTEdge)
"""
link = "privatelink.blob" if private else "blob"
if not blob_path:
return "http://{module}:{port}/{account}.blob.core.windows.net?{sas}".format(
return "http://{module}:{port}/{account}.{link}.core.windows.net?{sas}".format(
module=module,
port=port,
account=account,
link=link,
sas=account_sas,
)
return (
"http://{module}:{port}/{account}.{link}.core.windows.net/{path}?{sas}".format(
module=module,
port=port,
account=account,
link=link,
path=blob_path,
sas=account_sas,
)
return "http://{module}:{port}/{account}.blob.core.windows.net/{path}?{sas}".format(
module=module,
port=port,
account=account,
path=blob_path,
sas=account_sas,
)


def generate_cloud_conn_str(
account: str,
private: bool,
account_key: Optional[str] = None,
account_sas: Optional[str] = None,
) -> str:
Expand All @@ -120,7 +131,10 @@ def generate_cloud_conn_str(
return "Please provide your storage account key or SAS token"

protocol = "DefaultEndpointsProtocol=https;"
endpoint = f"BlobEndpoint=https://{account}.blob.core.windows.net;"
if private:
endpoint = f"BlobEndpoint=https://{account}.privatelink.blob.core.windows.net;"
else:
endpoint = f"BlobEndpoint=https://{account}.blob.core.windows.net;"

if account_key:
credential = f"AccountName={account};AccountKey={account_key};"
Expand All @@ -132,19 +146,23 @@ def generate_cloud_conn_str(
def generate_cloud_sas_url(
account: str,
account_sas: str,
private: bool,
blob_path: Optional[str] = None,
) -> str:
"""
generate a SAS url for an edge gateway device
interacting with a cloud storage account
"""
link = "privatelink.blob" if private else "blob"
if not blob_path:
return "https://{account}.blob.core.windows.net?{sas}".format(
return "https://{account}.{link}.core.windows.net?{sas}".format(
account=account,
link=link,
sas=account_sas,
)
return "https://{account}.blob.core.windows.net/{path}?{sas}".format(
return "https://{account}.{link}.core.windows.net/{path}?{sas}".format(
account=account,
link=link,
path=blob_path,
sas=account_sas,
)
2 changes: 1 addition & 1 deletion iot-storage-client/iot/storage/client/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
VERSION = "1.1.8"
VERSION = "1.2.0"

__version__ = VERSION

0 comments on commit e70bcfa

Please sign in to comment.