Skip to content

Commit 6930938

Browse files
authored
Add KeyVaultAccessControlClient for data plane RBAC (#13372)
1 parent 7007c69 commit 6930938

11 files changed

+1107
-1
lines changed

sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,15 @@
22
# Copyright (c) Microsoft Corporation.
33
# Licensed under the MIT License.
44
# ------------------------------------
5-
__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
5+
from ._access_control_client import KeyVaultAccessControlClient
6+
from ._internal.client_base import ApiVersion
7+
from ._models import KeyVaultPermission, KeyVaultRoleAssignment, KeyVaultRoleDefinition
8+
9+
10+
__all__ = [
11+
"ApiVersion",
12+
"KeyVaultAccessControlClient",
13+
"KeyVaultPermission",
14+
"KeyVaultRoleAssignment",
15+
"KeyVaultRoleDefinition",
16+
]
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# ------------------------------------
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
# ------------------------------------
5+
from typing import TYPE_CHECKING
6+
7+
from azure.core.tracing.decorator import distributed_trace
8+
9+
from ._models import KeyVaultRoleAssignment, KeyVaultRoleDefinition
10+
from ._internal import KeyVaultClientBase
11+
12+
if TYPE_CHECKING:
13+
from typing import Any, Union
14+
from uuid import UUID
15+
from azure.core.paging import ItemPaged
16+
17+
18+
class KeyVaultAccessControlClient(KeyVaultClientBase):
19+
"""Manages role-based access to Azure Key Vault.
20+
21+
:param str vault_url: URL of the vault the client will manage. This is also called the vault's "DNS Name".
22+
:param credential: an object which can provide an access token for the vault, such as a credential from
23+
:mod:`azure.identity`
24+
"""
25+
26+
# pylint:disable=protected-access
27+
28+
@distributed_trace
29+
def create_role_assignment(self, role_scope, role_assignment_name, role_definition_id, principal_id, **kwargs):
30+
# type: (str, Union[str, UUID], str, str, **Any) -> KeyVaultRoleAssignment
31+
"""Create a role assignment.
32+
33+
:param str role_scope: scope the role assignment will apply over
34+
:param role_assignment_name: a name for the role assignment. Must be a UUID.
35+
:type role_assignment_name: str or uuid.UUID
36+
:param str role_definition_id: ID of the role's definition
37+
:param str principal_id: Azure Active Directory object ID of the principal which will be assigned the role. The
38+
principal can be a user, service principal, or security group.
39+
:rtype: KeyVaultRoleAssignment
40+
"""
41+
create_parameters = self._client.role_assignments.models.RoleAssignmentCreateParameters(
42+
properties=self._client.role_assignments.models.RoleAssignmentProperties(
43+
principal_id=principal_id, role_definition_id=str(role_definition_id)
44+
)
45+
)
46+
assignment = self._client.role_assignments.create(
47+
vault_base_url=self._vault_url,
48+
scope=role_scope,
49+
role_assignment_name=role_assignment_name,
50+
parameters=create_parameters,
51+
**kwargs
52+
)
53+
return KeyVaultRoleAssignment._from_generated(assignment)
54+
55+
@distributed_trace
56+
def delete_role_assignment(self, role_scope, role_assignment_name, **kwargs):
57+
# type: (str, Union[str, UUID], **Any) -> KeyVaultRoleAssignment
58+
"""Delete a role assignment.
59+
60+
:param str role_scope: the assignment's scope, for example "/", "/keys", or "/keys/<specific key identifier>"
61+
:param role_assignment_name: the assignment's name. Must be a UUID.
62+
:type role_assignment_name: str or uuid.UUID
63+
:returns: the deleted assignment
64+
:rtype: KeyVaultRoleAssignment
65+
"""
66+
assignment = self._client.role_assignments.delete(
67+
vault_base_url=self._vault_url, scope=role_scope, role_assignment_name=str(role_assignment_name), **kwargs
68+
)
69+
return KeyVaultRoleAssignment._from_generated(assignment)
70+
71+
@distributed_trace
72+
def get_role_assignment(self, role_scope, role_assignment_name, **kwargs):
73+
# type: (str, Union[str, UUID], **Any) -> KeyVaultRoleAssignment
74+
"""Get a role assignment.
75+
76+
:param str role_scope: the assignment's scope, for example "/", "/keys", or "/keys/<specific key identifier>"
77+
:param role_assignment_name: the assignment's name. Must be a UUID.
78+
:type role_assignment_name: str or uuid.UUID
79+
:rtype: KeyVaultRoleAssignment
80+
"""
81+
assignment = self._client.role_assignments.get(
82+
vault_base_url=self._vault_url, scope=role_scope, role_assignment_name=str(role_assignment_name), **kwargs
83+
)
84+
return KeyVaultRoleAssignment._from_generated(assignment)
85+
86+
@distributed_trace
87+
def list_role_assignments(self, role_scope, **kwargs):
88+
# type: (str, **Any) -> ItemPaged[KeyVaultRoleAssignment]
89+
"""List all role assignments for a scope.
90+
91+
:param str role_scope: scope of the role assignments
92+
:rtype: ~azure.core.paging.ItemPaged[KeyVaultRoleAssignment]
93+
"""
94+
return self._client.role_assignments.list_for_scope(
95+
self._vault_url,
96+
role_scope,
97+
cls=lambda result: [KeyVaultRoleAssignment._from_generated(a) for a in result],
98+
**kwargs
99+
)
100+
101+
@distributed_trace
102+
def list_role_definitions(self, role_scope, **kwargs):
103+
# type: (str, **Any) -> ItemPaged[KeyVaultRoleDefinition]
104+
"""List all role definitions applicable at and above a scope.
105+
106+
:param str role_scope: scope of the role definitions
107+
:rtype: ~azure.core.paging.ItemPaged[KeyVaultRoleDefinition]
108+
"""
109+
return self._client.role_definitions.list(
110+
self._vault_url,
111+
role_scope,
112+
cls=lambda result: [KeyVaultRoleDefinition._from_generated(d) for d in result],
113+
**kwargs
114+
)
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# ------------------------------------
2+
# Copyright (c) Microsoft Corporation.
3+
# Licensed under the MIT License.
4+
# ------------------------------------
5+
from typing import TYPE_CHECKING
6+
7+
if TYPE_CHECKING:
8+
from typing import Any
9+
10+
11+
# pylint:disable=protected-access
12+
13+
14+
class KeyVaultPermission(object):
15+
"""Role definition permissions.
16+
17+
:ivar list[str] actions: allowed actions
18+
:ivar list[str] not_actions: denied actions
19+
:ivar list[str] data_actions: allowed data actions
20+
:ivar list[str] not_data_actions: denied data actions
21+
"""
22+
23+
def __init__(self, **kwargs):
24+
# type: (**Any) -> None
25+
self.actions = kwargs.get("actions")
26+
self.not_actions = kwargs.get("not_actions")
27+
self.data_actions = kwargs.get("data_actions")
28+
self.not_data_actions = kwargs.get("not_data_actions")
29+
30+
@classmethod
31+
def _from_generated(cls, permissions):
32+
return cls(
33+
actions=permissions.actions,
34+
not_actions=permissions.not_actions,
35+
data_actions=permissions.data_actions,
36+
not_data_actions=permissions.not_data_actions,
37+
)
38+
39+
40+
class KeyVaultRoleAssignment(object):
41+
"""Represents the assignment to a principal of a role over a scope"""
42+
43+
def __init__(self, **kwargs):
44+
# type: (**Any) -> None
45+
self._assignment_id = kwargs.get("assignment_id")
46+
self._name = kwargs.get("name")
47+
self._properties = kwargs.get("properties")
48+
self._type = kwargs.get("assignment_type")
49+
50+
def __repr__(self):
51+
# type: () -> str
52+
return "KeyVaultRoleAssignment<{}>".format(self._assignment_id)
53+
54+
@property
55+
def assignment_id(self):
56+
# type: () -> str
57+
"""unique identifier for this assignment"""
58+
return self._assignment_id
59+
60+
@property
61+
def name(self):
62+
# type: () -> str
63+
"""name of the assignment"""
64+
return self._name
65+
66+
@property
67+
def principal_id(self):
68+
# type: () -> str
69+
"""ID of the principal this assignment applies to.
70+
71+
This maps to the ID inside the Active Directory. It can point to a user, service principal, or security group.
72+
"""
73+
return self._properties.principal_id
74+
75+
@property
76+
def role_definition_id(self):
77+
# type: () -> str
78+
"""ID of the role's definition"""
79+
return self._properties.role_definition_id
80+
81+
@property
82+
def scope(self):
83+
# type: () -> str
84+
"""scope of the assignment"""
85+
return self._properties.scope
86+
87+
@property
88+
def type(self):
89+
# type: () -> str
90+
"""the type of this assignment"""
91+
return self._type
92+
93+
@classmethod
94+
def _from_generated(cls, role_assignment):
95+
return cls(
96+
assignment_id=role_assignment.id,
97+
name=role_assignment.name,
98+
assignment_type=role_assignment.type,
99+
properties=KeyVaultRoleAssignmentProperties._from_generated(role_assignment.properties),
100+
)
101+
102+
103+
class KeyVaultRoleAssignmentProperties(object):
104+
def __init__(self, **kwargs):
105+
# type: (**Any) -> None
106+
self.principal_id = kwargs.get("principal_id")
107+
self.role_definition_id = kwargs.get("role_definition_id")
108+
self.scope = kwargs.get("scope")
109+
110+
def __repr__(self):
111+
# type: () -> str
112+
return "KeyVaultRoleAssignmentProperties(principal_id={}, role_definition_id={}, scope={})".format(
113+
self.principal_id, self.role_definition_id, self.scope
114+
)[:1024]
115+
116+
@classmethod
117+
def _from_generated(cls, role_assignment_properties):
118+
# the generated RoleAssignmentProperties and RoleAssignmentPropertiesWithScope
119+
# models differ only in that the latter has a "scope" attribute
120+
return cls(
121+
principal_id=role_assignment_properties.principal_id,
122+
role_definition_id=role_assignment_properties.role_definition_id,
123+
scope=getattr(role_assignment_properties, "scope", None),
124+
)
125+
126+
127+
class KeyVaultRoleDefinition(object):
128+
"""Role definition.
129+
130+
:ivar str id: The role definition ID.
131+
:ivar str name: The role definition name.
132+
:ivar str type: The role definition type.
133+
:ivar str role_name: The role name.
134+
:ivar str description: The role definition description.
135+
:ivar str role_type: The role type.
136+
:ivar permissions: Role definition permissions.
137+
:vartype permissions: list[KeyVaultPermission]
138+
:ivar list[str] assignable_scopes: Role definition assignable scopes.
139+
"""
140+
141+
def __init__(self, **kwargs):
142+
# type: (**Any) -> None
143+
self.id = kwargs.get("id")
144+
self.name = kwargs.get("name")
145+
self.role_name = kwargs.get("role_name")
146+
self.description = kwargs.get("description")
147+
self.role_type = kwargs.get("role_type")
148+
self.type = kwargs.get("type")
149+
self.permissions = kwargs.get("permissions")
150+
self.assignable_scopes = kwargs.get("assignable_scopes")
151+
152+
def __repr__(self):
153+
# type: () -> str
154+
return "<KeyVaultRoleDefinition {}>".format(self.role_name)[:1024]
155+
156+
@classmethod
157+
def _from_generated(cls, definition):
158+
return cls(
159+
assignable_scopes=definition.assignable_scopes,
160+
description=definition.description,
161+
id=definition.id,
162+
name=definition.name,
163+
permissions=[KeyVaultPermission._from_generated(p) for p in definition.permissions],
164+
role_name=definition.role_name,
165+
role_type=definition.role_type,
166+
type=definition.type,
167+
)

sdk/keyvault/azure-keyvault-administration/azure/keyvault/administration/aio/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
# Copyright (c) Microsoft Corporation.
33
# Licensed under the MIT License.
44
# ------------------------------------
5+
from ._access_control_client import KeyVaultAccessControlClient
6+
7+
__all__ = ["KeyVaultAccessControlClient"]

0 commit comments

Comments
 (0)