Microsoft Azure Container Registry Client Library for managing container registries, replications, webhooks, and access control through Azure Resource Manager APIs.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Repository-level access control through scope maps and tokens, providing fine-grained permissions for registry access without using admin credentials. This system enables secure, principle-of-least-privilege access for applications, CI/CD systems, and users with customizable repository and action permissions.
Create and manage scope maps that define repository access permissions and allowed actions for token-based authentication.
def begin_create(resource_group_name: str, registry_name: str, scope_map_name: str, scope_map_create_parameters: ScopeMap, **kwargs) -> LROPoller[ScopeMap]:
"""
Create a scope map for a container registry.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
- scope_map_name: str - Name of the scope map
- scope_map_create_parameters: ScopeMap - Scope map configuration
Returns:
LROPoller[ScopeMap] - Long-running operation poller for the scope map
"""
def begin_delete(resource_group_name: str, registry_name: str, scope_map_name: str, **kwargs) -> LROPoller[None]:
"""
Delete a scope map from a container registry.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
- scope_map_name: str - Name of the scope map to delete
Returns:
LROPoller[None] - Long-running operation poller
"""
def begin_update(resource_group_name: str, registry_name: str, scope_map_name: str, scope_map_update_parameters: ScopeMapUpdateParameters, **kwargs) -> LROPoller[ScopeMap]:
"""
Update a scope map for a container registry.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
- scope_map_name: str - Name of the scope map to update
- scope_map_update_parameters: ScopeMapUpdateParameters - Update parameters
Returns:
LROPoller[ScopeMap] - Long-running operation poller for the updated scope map
"""
def get(resource_group_name: str, registry_name: str, scope_map_name: str, **kwargs) -> ScopeMap:
"""
Get properties of a scope map.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
- scope_map_name: str - Name of the scope map
Returns:
ScopeMap - Scope map resource with complete configuration
"""
def list(resource_group_name: str, registry_name: str, **kwargs) -> ItemPaged[ScopeMap]:
"""
List all scope maps for a container registry.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
Returns:
ItemPaged[ScopeMap] - Paginated list of all scope maps for the registry
"""Create and manage authentication tokens that use scope maps to define repository access permissions.
def begin_create(resource_group_name: str, registry_name: str, token_name: str, token_create_parameters: Token, **kwargs) -> LROPoller[Token]:
"""
Create a token for a container registry.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
- token_name: str - Name of the token
- token_create_parameters: Token - Token configuration
Returns:
LROPoller[Token] - Long-running operation poller for the token
"""
def begin_delete(resource_group_name: str, registry_name: str, token_name: str, **kwargs) -> LROPoller[None]:
"""
Delete a token from a container registry.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
- token_name: str - Name of the token to delete
Returns:
LROPoller[None] - Long-running operation poller
"""
def begin_update(resource_group_name: str, registry_name: str, token_name: str, token_update_parameters: TokenUpdateParameters, **kwargs) -> LROPoller[Token]:
"""
Update a token for a container registry.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
- token_name: str - Name of the token to update
- token_update_parameters: TokenUpdateParameters - Update parameters
Returns:
LROPoller[Token] - Long-running operation poller for the updated token
"""
def get(resource_group_name: str, registry_name: str, token_name: str, **kwargs) -> Token:
"""
Get properties of a token.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
- token_name: str - Name of the token
Returns:
Token - Token resource with complete configuration
"""
def list(resource_group_name: str, registry_name: str, **kwargs) -> ItemPaged[Token]:
"""
List all tokens for a container registry.
Parameters:
- resource_group_name: str - Name of the resource group
- registry_name: str - Name of the registry
Returns:
ItemPaged[Token] - Paginated list of all tokens for the registry
"""class ScopeMap:
"""
An object that represents a scope map for a container registry.
Attributes:
- id: str - Resource ID
- name: str - Resource name
- type: str - Resource type
- description: str - Description of the scope map
- type_properties_type: str - Type of the scope map
- creation_date: datetime - Creation timestamp
- provisioning_state: ProvisioningState - Current provisioning state
- actions: List[str] - List of actions allowed by this scope map
"""class ScopeMapUpdateParameters:
"""
Parameters for updating a scope map.
Attributes:
- description: str - Description of the scope map
- actions: List[str] - List of actions to update
"""class Token:
"""
An object that represents a token for a container registry.
Attributes:
- id: str - Resource ID
- name: str - Resource name
- type: str - Resource type
- creation_date: datetime - Creation timestamp
- provisioning_state: ProvisioningState - Current provisioning state
- scope_map_id: str - Resource ID of the scope map associated with the token
- credentials: TokenCredentialsProperties - Token credentials configuration
- status: TokenStatus - Token status (enabled/disabled)
"""class TokenUpdateParameters:
"""
Parameters for updating a token.
Attributes:
- scope_map_id: str - Resource ID of the scope map
- status: TokenStatus - Token status (enabled/disabled)
- credentials: TokenCredentialsProperties - Credentials configuration
"""class TokenCredentialsProperties:
"""
Properties for token credentials.
Attributes:
- certificates: List[TokenCertificate] - List of certificates
- passwords: List[TokenPassword] - List of passwords
"""class TokenPassword:
"""
Password for a token.
Attributes:
- creation_time: datetime - Password creation time
- expiry: datetime - Password expiry time
- name: TokenPasswordName - Password name (password1/password2)
- value: str - Password value (only returned on creation)
"""class TokenCertificate:
"""
Certificate for a token.
Attributes:
- name: TokenCertificateName - Certificate name (certificate1/certificate2)
- expiry: datetime - Certificate expiry time
- thumbprint: str - Certificate thumbprint
- encoded_pem_certificate: str - PEM-encoded certificate
"""class TokenStatus(str, Enum):
"""Token status options."""
ENABLED = "enabled"
DISABLED = "disabled"class TokenPasswordName(str, Enum):
"""Token password names."""
PASSWORD1 = "password1"
PASSWORD2 = "password2"class TokenCertificateName(str, Enum):
"""Token certificate names."""
CERTIFICATE1 = "certificate1"
CERTIFICATE2 = "certificate2"from azure.mgmt.containerregistry import ContainerRegistryManagementClient
from azure.mgmt.containerregistry.models import (
ScopeMap, Token, TokenStatus, TokenCredentialsProperties, TokenPassword
)
from azure.identity import DefaultAzureCredential
client = ContainerRegistryManagementClient(
DefaultAzureCredential(),
"subscription-id"
)
# Create scope map for frontend application access
frontend_scope_map = ScopeMap(
description="Access for frontend applications",
actions=[
"repositories/frontend/content/read",
"repositories/frontend/content/write",
"repositories/frontend/metadata/read"
]
)
frontend_scope = client.scope_maps.begin_create(
"my-resource-group",
"my-registry",
"frontend-access",
frontend_scope_map
).result()
# Create token for frontend applications
frontend_token = Token(
scope_map_id=frontend_scope.id,
status=TokenStatus.ENABLED,
credentials=TokenCredentialsProperties(
passwords=[
TokenPassword(name="password1"),
TokenPassword(name="password2")
]
)
)
frontend_auth_token = client.tokens.begin_create(
"my-resource-group",
"my-registry",
"frontend-token",
frontend_token
).result()
print(f"Created frontend token: {frontend_auth_token.name}")
print(f"Scope map: {frontend_auth_token.scope_map_id}")# Create scope map for CI/CD pipeline with broader permissions
cicd_scope_map = ScopeMap(
description="CI/CD pipeline access with push/pull permissions",
actions=[
"repositories/*/content/read", # Pull any repository
"repositories/*/content/write", # Push to any repository
"repositories/*/metadata/read", # Read metadata
"repositories/*/metadata/write" # Write metadata (for tags)
]
)
cicd_scope = client.scope_maps.begin_create(
"my-resource-group",
"my-registry",
"cicd-access",
cicd_scope_map
).result()
# Create token for CI/CD with long expiry
import datetime
from dateutil.relativedelta import relativedelta
expiry_date = datetime.datetime.utcnow() + relativedelta(years=1)
cicd_token = Token(
scope_map_id=cicd_scope.id,
status=TokenStatus.ENABLED,
credentials=TokenCredentialsProperties(
passwords=[
TokenPassword(
name="password1",
expiry=expiry_date
)
]
)
)
cicd_auth_token = client.tokens.begin_create(
"my-resource-group",
"my-registry",
"cicd-token",
cicd_token
).result()
print(f"Created CI/CD token: {cicd_auth_token.name}")# Create scope map for monitoring/scanning tools (read-only)
monitoring_scope_map = ScopeMap(
description="Read-only access for monitoring and security scanning",
actions=[
"repositories/*/content/read",
"repositories/*/metadata/read"
]
)
monitoring_scope = client.scope_maps.begin_create(
"my-resource-group",
"my-registry",
"monitoring-access",
monitoring_scope_map
).result()
# Create token for monitoring tools
monitoring_token = Token(
scope_map_id=monitoring_scope.id,
status=TokenStatus.ENABLED,
credentials=TokenCredentialsProperties(
passwords=[TokenPassword(name="password1")]
)
)
monitoring_auth_token = client.tokens.begin_create(
"my-resource-group",
"my-registry",
"monitoring-token",
monitoring_token
).result()
print(f"Created monitoring token: {monitoring_auth_token.name}")# Create different scope maps for different environments
environments = {
"dev": [
"repositories/dev/*/content/read",
"repositories/dev/*/content/write",
"repositories/dev/*/metadata/read",
"repositories/dev/*/metadata/write"
],
"staging": [
"repositories/staging/*/content/read",
"repositories/staging/*/content/write",
"repositories/staging/*/metadata/read"
],
"prod": [
"repositories/prod/*/content/read" # Read-only for production
]
}
created_tokens = {}
for env_name, actions in environments.items():
# Create scope map
scope_map = ScopeMap(
description=f"Access control for {env_name} environment",
actions=actions
)
scope = client.scope_maps.begin_create(
"my-resource-group",
"my-registry",
f"{env_name}-access",
scope_map
).result()
# Create token
token = Token(
scope_map_id=scope.id,
status=TokenStatus.ENABLED,
credentials=TokenCredentialsProperties(
passwords=[TokenPassword(name="password1")]
)
)
auth_token = client.tokens.begin_create(
"my-resource-group",
"my-registry",
f"{env_name}-token",
token
).result()
created_tokens[env_name] = auth_token
print(f"Created {env_name} environment token")
print(f"Total environment tokens created: {len(created_tokens)}")from azure.mgmt.containerregistry.models import TokenUpdateParameters
# List all tokens and check their status
tokens = client.tokens.list("my-resource-group", "my-registry")
print("Token Status Report:")
print("-" * 50)
for token in tokens:
print(f"Token: {token.name}")
print(f" Status: {token.status}")
print(f" Scope Map: {token.scope_map_id.split('/')[-1]}")
print(f" Created: {token.creation_date}")
print()
# Disable a token temporarily
update_params = TokenUpdateParameters(status=TokenStatus.DISABLED)
disabled_token = client.tokens.begin_update(
"my-resource-group",
"my-registry",
"frontend-token",
update_params
).result()
print(f"Disabled token: {disabled_token.name}")
# Re-enable the token later
enable_params = TokenUpdateParameters(status=TokenStatus.ENABLED)
enabled_token = client.tokens.begin_update(
"my-resource-group",
"my-registry",
"frontend-token",
enable_params
).result()
print(f"Re-enabled token: {enabled_token.name}")from azure.mgmt.containerregistry.models import ScopeMapUpdateParameters
# Update scope map to add new permissions
current_scope = client.scope_maps.get(
"my-resource-group",
"my-registry",
"frontend-access"
)
# Add delete permissions to existing scope map
updated_actions = current_scope.actions + [
"repositories/frontend/content/delete"
]
update_params = ScopeMapUpdateParameters(
description="Frontend access with delete permissions",
actions=updated_actions
)
updated_scope = client.scope_maps.begin_update(
"my-resource-group",
"my-registry",
"frontend-access",
update_params
).result()
print(f"Updated scope map with {len(updated_scope.actions)} actions")
print("New actions:", updated_scope.actions)# Clean up tokens and scope maps
tokens_to_delete = ["old-token", "temp-token"]
scope_maps_to_delete = ["old-scope", "temp-scope"]
# Delete tokens first (they depend on scope maps)
for token_name in tokens_to_delete:
try:
client.tokens.begin_delete(
"my-resource-group",
"my-registry",
token_name
).result()
print(f"Deleted token: {token_name}")
except Exception as e:
print(f"Failed to delete token {token_name}: {e}")
# Then delete scope maps
for scope_name in scope_maps_to_delete:
try:
client.scope_maps.begin_delete(
"my-resource-group",
"my-registry",
scope_name
).result()
print(f"Deleted scope map: {scope_name}")
except Exception as e:
print(f"Failed to delete scope map {scope_name}: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-azure-mgmt-containerregistry