Skip to content

Commit ac31e72

Browse files
Added support for IAM endpoints (#552)
1 parent 3a1ec42 commit ac31e72

8 files changed

Lines changed: 560 additions & 0 deletions

File tree

linode_api4/groups/iam.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
from typing import Any, Dict, List, Optional, Union
2+
3+
from linode_api4.errors import UnexpectedResponseError
4+
from linode_api4.groups import Group
5+
from linode_api4.objects import EntityAccess, LinodeEntity
6+
7+
8+
class IAMGroup(Group):
9+
def role_permissions(self):
10+
"""
11+
Returns the permissions available on the account assigned to any user of the account.
12+
13+
This is intended to be called off of the :any:`LinodeClient`
14+
class, like this::
15+
16+
permissions = client.role_permissions()
17+
18+
API Documentation: TODO
19+
20+
:returns: The JSON role permissions for the account.
21+
"""
22+
return self.client.get("/iam/role-permissions", model=self)
23+
24+
def role_permissions_user_get(self, username):
25+
"""
26+
Returns the permissions available on the account assigned to the specified user.
27+
28+
This is intended to be called off of the :any:`LinodeClient`
29+
class, like this::
30+
31+
permissions = client.role_permissions_user_get("myusername")
32+
33+
API Documentation: TODO
34+
35+
:returns: The JSON role permissions for the user.
36+
"""
37+
return self.client.get(
38+
f"/iam/users/{username}/role-permissions", model=self
39+
)
40+
41+
def role_permissions_user_set(
42+
self,
43+
username,
44+
account_access: Optional[List[str]] = None,
45+
entity_access: Optional[
46+
Union[List[EntityAccess], Dict[str, Any]]
47+
] = None,
48+
):
49+
"""
50+
Assigns the specified permissions to the specified user, and returns them.
51+
52+
This is intended to be called off of the :any:`LinodeClient`
53+
class, like this::
54+
55+
permissions = client.role_permissions_user_set("muusername")
56+
57+
API Documentation: TODO
58+
59+
:returns: The JSON role permissions for the user.
60+
"""
61+
params = {
62+
"account_access": account_access,
63+
"entity_access": entity_access,
64+
}
65+
66+
result = self.client.put(
67+
f"/iam/users/{username}/role-permissions",
68+
data=params,
69+
)
70+
71+
if "account_access" not in result:
72+
raise UnexpectedResponseError(
73+
"Unexpected response updating role permissions!", json=result
74+
)
75+
76+
return result
77+
78+
def entities(self, *filters):
79+
"""
80+
Returns the current entities of the account.
81+
82+
This is intended to be called off of the :any:`LinodeClient`
83+
class, like this::
84+
85+
permissions = client.entities()
86+
87+
API Documentation: TODO
88+
89+
:param filters: Any number of filters to apply to this query.
90+
See :doc:`Filtering Collections</linode_api4/objects/filtering>`
91+
for more details on filtering.
92+
93+
:returns: A list of entities that match the query.
94+
:rtype: PaginatedList of Entity
95+
"""
96+
return self.client._get_and_filter(
97+
LinodeEntity, *filters, endpoint="/entities"
98+
)

linode_api4/linode_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
)
3333
from linode_api4.objects import Image, and_
3434

35+
from .groups.iam import IAMGroup
3536
from .groups.placement import PlacementAPIGroup
3637
from .paginated_list import PaginatedList
3738

@@ -171,6 +172,9 @@ def __init__(
171172
#: Access methods related to Managed Databases - see :any:`DatabaseGroup` for more information.
172173
self.database = DatabaseGroup(self)
173174

175+
#: Access methods related to IAM - see :any:`IAMGroup` for more information.
176+
self.iam = IAMGroup(self)
177+
174178
#: Access methods related to NodeBalancers - see :any:`NodeBalancerGroup` for more information.
175179
self.nodebalancers = NodeBalancerGroup(self)
176180

linode_api4/objects/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .serializable import JSONObject
55
from .filtering import and_, or_
66
from .region import Region
7+
from .iam import *
78
from .image import Image
89
from .linode import *
910
from .volume import *

linode_api4/objects/iam.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from __future__ import annotations
2+
3+
from dataclasses import dataclass
4+
from typing import List
5+
6+
from linode_api4.objects.base import Base, JSONObject, Property
7+
8+
9+
class LinodeEntity(Base):
10+
"""
11+
An Entity represents an entity of the account.
12+
13+
Currently the Entity can only be retrieved by listing, i.e.:
14+
entities = client.iam.entities()
15+
16+
API documentation: TODO
17+
"""
18+
19+
properties = {
20+
"id": Property(identifier=True),
21+
"label": Property(),
22+
"type": Property(),
23+
}
24+
25+
26+
@dataclass
27+
class EntityAccess(JSONObject):
28+
"""
29+
EntityAccess represents a user's access to an entity.
30+
"""
31+
32+
id: int
33+
type: str
34+
roles: List[str]

test/fixtures/entities.json

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
{
2+
"data": [
3+
{
4+
"id": 7,
5+
"label": "linode7",
6+
"type": "linode"
7+
},
8+
{
9+
"id": 10,
10+
"label": "linode10",
11+
"type": "linode"
12+
},
13+
{
14+
"id": 1,
15+
"label": "no_devices",
16+
"type": "firewall"
17+
},
18+
{
19+
"id": 2,
20+
"label": "active_with_nodebalancer",
21+
"type": "firewall"
22+
},
23+
{
24+
"id": 1,
25+
"label": "nodebalancer-active",
26+
"type": "nodebalancer"
27+
},
28+
{
29+
"id": 1,
30+
"label": "active",
31+
"type": "longview"
32+
},
33+
{
34+
"id": 3,
35+
"label": "LongviewClientTest",
36+
"type": "longview"
37+
},
38+
{
39+
"id": 1,
40+
"label": "linDomTest1.com",
41+
"type": "domain"
42+
},
43+
{
44+
"id": 1,
45+
"label": "API Test",
46+
"type": "stackscript"
47+
},
48+
{
49+
"id": 1,
50+
"label": "Test image - mine",
51+
"type": "image"
52+
},
53+
{
54+
"id": 3,
55+
"label": "Test image - mine - creating",
56+
"type": "image"
57+
},
58+
{
59+
"id": 1,
60+
"label": "volume1",
61+
"type": "volume"
62+
},
63+
{
64+
"id": 1,
65+
"label": "mongo_cluster",
66+
"type": "database"
67+
},
68+
{
69+
"id": 3,
70+
"label": "empty-vpc",
71+
"type": "vpc"
72+
}
73+
],
74+
"page": 1,
75+
"pages": 1,
76+
"results": 14
77+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"account_access": [
3+
{
4+
"type": "account",
5+
"roles": [
6+
{
7+
"name": "account_admin",
8+
"description": "Access to perform any supported action on all entities of the account",
9+
"permissions": [
10+
"create_linode",
11+
"update_linode",
12+
"update_firewall"
13+
]
14+
}
15+
]
16+
},
17+
{
18+
"type": "linode",
19+
"roles": [
20+
{
21+
"name": "account_linode_admin",
22+
"description": "Access to perform any supported action on all linode instances of the account",
23+
"permissions": [
24+
"create_linode",
25+
"update_linode",
26+
"delete_linode"
27+
]
28+
}
29+
]
30+
},
31+
{
32+
"type": "firewall",
33+
"roles": [
34+
{
35+
"name": "firewall_creator",
36+
"description": "Access to create a firewall instance",
37+
"permissions": [
38+
"update_linode",
39+
"view_linode"
40+
]
41+
}
42+
]
43+
}
44+
],
45+
"entity_access": [
46+
{
47+
"type": "linode",
48+
"roles": [
49+
{
50+
"name": "linode_contributor",
51+
"description": "Access to update a linode instance",
52+
"permissions": [
53+
"update_linode",
54+
"view_linode"
55+
]
56+
}
57+
]
58+
},
59+
{
60+
"type": "firewall",
61+
"roles": [
62+
{
63+
"name": "firewall_viewer",
64+
"description": "Access to view a firewall instance",
65+
"permissions": [
66+
"update_linode",
67+
"view_linode"
68+
]
69+
},
70+
{
71+
"name": "firewall_admin",
72+
"description": "Access to perform any supported action on a firewall instance",
73+
"permissions": [
74+
"update_linode",
75+
"view_linode"
76+
]
77+
}
78+
]
79+
}
80+
]
81+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"account_access": [
3+
"account_linode_admin",
4+
"linode_creator",
5+
"firewall_creator"
6+
],
7+
"entity_access": [
8+
{
9+
"id": 1,
10+
"type": "linode",
11+
"roles": [
12+
"linode_contributor"
13+
]
14+
},
15+
{
16+
"id": 1,
17+
"type": "firewall",
18+
"roles": [
19+
"firewall_admin"
20+
]
21+
}
22+
]
23+
}

0 commit comments

Comments
 (0)