strongdm 3.6.1__zip → 3.7.0__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {strongdm-3.6.1 → strongdm-3.7.0}/PKG-INFO +2 -2
- {strongdm-3.6.1 → strongdm-3.7.0}/setup.py +2 -2
- strongdm-3.7.0/strongdm/account_attachments_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/account_attachments_history_pb2_grpc.py +84 -0
- strongdm-3.7.0/strongdm/account_grants_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/account_grants_history_pb2_grpc.py +84 -0
- strongdm-3.7.0/strongdm/account_permissions_pb2.py +97 -0
- strongdm-3.7.0/strongdm/account_permissions_pb2_grpc.py +87 -0
- strongdm-3.7.0/strongdm/account_resources_pb2.py +99 -0
- strongdm-3.7.0/strongdm/account_resources_pb2_grpc.py +87 -0
- strongdm-3.7.0/strongdm/accounts_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/accounts_history_pb2_grpc.py +84 -0
- strongdm-3.7.0/strongdm/activities_pb2.py +177 -0
- strongdm-3.7.0/strongdm/activities_pb2_grpc.py +124 -0
- strongdm-3.7.0/strongdm/client.py +432 -0
- strongdm-3.7.0/strongdm/constants.py +377 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/drivers_pb2.py +6 -6
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/models.py +1872 -132
- strongdm-3.7.0/strongdm/nodes_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/nodes_history_pb2_grpc.py +84 -0
- strongdm-3.7.0/strongdm/organization_history_pb2.py +154 -0
- strongdm-3.7.0/strongdm/organization_history_pb2_grpc.py +84 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/plumbing.py +935 -0
- strongdm-3.7.0/strongdm/queries_pb2.py +133 -0
- strongdm-3.7.0/strongdm/queries_pb2_grpc.py +90 -0
- strongdm-3.7.0/strongdm/remote_identities_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/remote_identities_history_pb2_grpc.py +84 -0
- strongdm-3.7.0/strongdm/remote_identity_groups_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/remote_identity_groups_history_pb2_grpc.py +84 -0
- strongdm-3.7.0/strongdm/replays_pb2.py +107 -0
- strongdm-3.7.0/strongdm/replays_pb2_grpc.py +87 -0
- strongdm-3.7.0/strongdm/resources_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/resources_history_pb2_grpc.py +84 -0
- strongdm-3.7.0/strongdm/role_resources_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/role_resources_history_pb2_grpc.py +84 -0
- strongdm-3.7.0/strongdm/role_resources_pb2.py +93 -0
- strongdm-3.7.0/strongdm/role_resources_pb2_grpc.py +87 -0
- strongdm-3.7.0/strongdm/roles_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/roles_history_pb2_grpc.py +84 -0
- strongdm-3.7.0/strongdm/secret_stores_history_pb2.py +96 -0
- strongdm-3.7.0/strongdm/secret_stores_history_pb2_grpc.py +84 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/svc.py +1199 -12
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm.egg-info/PKG-INFO +2 -2
- strongdm-3.7.0/strongdm.egg-info/SOURCES.txt +78 -0
- strongdm-3.6.1/strongdm/client.py +0 -199
- strongdm-3.6.1/strongdm/constants.py +0 -66
- strongdm-3.6.1/strongdm.egg-info/SOURCES.txt +0 -44
- {strongdm-3.6.1 → strongdm-3.7.0}/README.md +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/setup.cfg +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/__init__.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/account_attachments_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/account_attachments_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/account_grants_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/account_grants_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/accounts_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/accounts_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/control_panel_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/control_panel_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/drivers_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/errors.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/nodes_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/nodes_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/options_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/options_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/remote_identities_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/remote_identities_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/remote_identity_groups_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/remote_identity_groups_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/resources_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/resources_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/roles_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/roles_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/secret_store_types_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/secret_store_types_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/secret_stores_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/secret_stores_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/spec_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/spec_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/tags_pb2.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm/tags_pb2_grpc.py +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm.egg-info/dependency_links.txt +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm.egg-info/requires.txt +0 -0
- {strongdm-3.6.1 → strongdm-3.7.0}/strongdm.egg-info/top_level.txt +0 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
# Copyright 2020 StrongDM Inc
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
#
|
15
|
+
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
16
|
+
"""Client and server classes corresponding to protobuf-defined services."""
|
17
|
+
import grpc
|
18
|
+
|
19
|
+
from . import activities_pb2 as activities__pb2
|
20
|
+
|
21
|
+
|
22
|
+
class ActivitiesStub(object):
|
23
|
+
"""An Activity is a record of an action taken against a strongDM deployment, e.g.
|
24
|
+
a user creation, resource deletion, sso configuration change, etc. The Activities
|
25
|
+
service is read-only.
|
26
|
+
"""
|
27
|
+
|
28
|
+
def __init__(self, channel):
|
29
|
+
"""Constructor.
|
30
|
+
|
31
|
+
Args:
|
32
|
+
channel: A grpc.Channel.
|
33
|
+
"""
|
34
|
+
self.Get = channel.unary_unary(
|
35
|
+
'/v1.Activities/Get',
|
36
|
+
request_serializer=activities__pb2.ActivityGetRequest.SerializeToString,
|
37
|
+
response_deserializer=activities__pb2.ActivityGetResponse.FromString,
|
38
|
+
)
|
39
|
+
self.List = channel.unary_unary(
|
40
|
+
'/v1.Activities/List',
|
41
|
+
request_serializer=activities__pb2.ActivityListRequest.SerializeToString,
|
42
|
+
response_deserializer=activities__pb2.ActivityListResponse.FromString,
|
43
|
+
)
|
44
|
+
|
45
|
+
|
46
|
+
class ActivitiesServicer(object):
|
47
|
+
"""An Activity is a record of an action taken against a strongDM deployment, e.g.
|
48
|
+
a user creation, resource deletion, sso configuration change, etc. The Activities
|
49
|
+
service is read-only.
|
50
|
+
"""
|
51
|
+
|
52
|
+
def Get(self, request, context):
|
53
|
+
"""Get reads one Activity by ID.
|
54
|
+
"""
|
55
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
56
|
+
context.set_details('Method not implemented!')
|
57
|
+
raise NotImplementedError('Method not implemented!')
|
58
|
+
|
59
|
+
def List(self, request, context):
|
60
|
+
"""List gets a list of Activities matching a given set of criteria.
|
61
|
+
"""
|
62
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
63
|
+
context.set_details('Method not implemented!')
|
64
|
+
raise NotImplementedError('Method not implemented!')
|
65
|
+
|
66
|
+
|
67
|
+
def add_ActivitiesServicer_to_server(servicer, server):
|
68
|
+
rpc_method_handlers = {
|
69
|
+
'Get': grpc.unary_unary_rpc_method_handler(
|
70
|
+
servicer.Get,
|
71
|
+
request_deserializer=activities__pb2.ActivityGetRequest.FromString,
|
72
|
+
response_serializer=activities__pb2.ActivityGetResponse.SerializeToString,
|
73
|
+
),
|
74
|
+
'List': grpc.unary_unary_rpc_method_handler(
|
75
|
+
servicer.List,
|
76
|
+
request_deserializer=activities__pb2.ActivityListRequest.FromString,
|
77
|
+
response_serializer=activities__pb2.ActivityListResponse.SerializeToString,
|
78
|
+
),
|
79
|
+
}
|
80
|
+
generic_handler = grpc.method_handlers_generic_handler(
|
81
|
+
'v1.Activities', rpc_method_handlers)
|
82
|
+
server.add_generic_rpc_handlers((generic_handler,))
|
83
|
+
|
84
|
+
|
85
|
+
# This class is part of an EXPERIMENTAL API.
|
86
|
+
class Activities(object):
|
87
|
+
"""An Activity is a record of an action taken against a strongDM deployment, e.g.
|
88
|
+
a user creation, resource deletion, sso configuration change, etc. The Activities
|
89
|
+
service is read-only.
|
90
|
+
"""
|
91
|
+
|
92
|
+
@staticmethod
|
93
|
+
def Get(request,
|
94
|
+
target,
|
95
|
+
options=(),
|
96
|
+
channel_credentials=None,
|
97
|
+
call_credentials=None,
|
98
|
+
insecure=False,
|
99
|
+
compression=None,
|
100
|
+
wait_for_ready=None,
|
101
|
+
timeout=None,
|
102
|
+
metadata=None):
|
103
|
+
return grpc.experimental.unary_unary(request, target, '/v1.Activities/Get',
|
104
|
+
activities__pb2.ActivityGetRequest.SerializeToString,
|
105
|
+
activities__pb2.ActivityGetResponse.FromString,
|
106
|
+
options, channel_credentials,
|
107
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
108
|
+
|
109
|
+
@staticmethod
|
110
|
+
def List(request,
|
111
|
+
target,
|
112
|
+
options=(),
|
113
|
+
channel_credentials=None,
|
114
|
+
call_credentials=None,
|
115
|
+
insecure=False,
|
116
|
+
compression=None,
|
117
|
+
wait_for_ready=None,
|
118
|
+
timeout=None,
|
119
|
+
metadata=None):
|
120
|
+
return grpc.experimental.unary_unary(request, target, '/v1.Activities/List',
|
121
|
+
activities__pb2.ActivityListRequest.SerializeToString,
|
122
|
+
activities__pb2.ActivityListResponse.FromString,
|
123
|
+
options, channel_credentials,
|
124
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
@@ -0,0 +1,432 @@
|
|
1
|
+
# Copyright 2020 StrongDM Inc
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
#
|
15
|
+
|
16
|
+
# This file was generated by protogen. DO NOT EDIT.
|
17
|
+
|
18
|
+
import base64
|
19
|
+
import copy
|
20
|
+
import datetime
|
21
|
+
import grpc
|
22
|
+
import hashlib
|
23
|
+
import hmac
|
24
|
+
import random
|
25
|
+
import time
|
26
|
+
from . import svc
|
27
|
+
from . import plumbing
|
28
|
+
|
29
|
+
# These defaults are taken from AWS. Customization of these values
|
30
|
+
# is a future step in the API.
|
31
|
+
DEFAULT_MAX_RETRIES = 3
|
32
|
+
DEFAULT_BASE_RETRY_DELAY = 0.0030 # 30 ms
|
33
|
+
DEFAULT_MAX_RETRY_DELAY = 300 # 300 seconds
|
34
|
+
API_VERSION = '2021-08-23'
|
35
|
+
USER_AGENT = 'strongdm-sdk-python/3.7.0'
|
36
|
+
|
37
|
+
|
38
|
+
class Client:
|
39
|
+
'''Client interacts with the strongDM API.'''
|
40
|
+
def __init__(self,
|
41
|
+
api_access_key,
|
42
|
+
api_secret,
|
43
|
+
host='api.strongdm.com:443',
|
44
|
+
insecure=False,
|
45
|
+
retry_rate_limit_errors=True):
|
46
|
+
'''
|
47
|
+
Create a new Client.
|
48
|
+
|
49
|
+
- api_access_key: the access key to authenticate with strongDM
|
50
|
+
- api_secret: the secret key to authenticate with strongDM
|
51
|
+
'''
|
52
|
+
self.api_access_key = api_access_key.strip()
|
53
|
+
self.api_secret = base64.b64decode(api_secret.strip())
|
54
|
+
self.max_retries = DEFAULT_MAX_RETRIES
|
55
|
+
self.base_retry_delay = DEFAULT_BASE_RETRY_DELAY
|
56
|
+
self.max_retry_delay = DEFAULT_MAX_RETRY_DELAY
|
57
|
+
self.expose_rate_limit_errors = (not retry_rate_limit_errors)
|
58
|
+
self.snapshot_datetime = None
|
59
|
+
self._test_options = {}
|
60
|
+
|
61
|
+
try:
|
62
|
+
if insecure:
|
63
|
+
channel = grpc.insecure_channel(host)
|
64
|
+
else:
|
65
|
+
creds = grpc.ssl_channel_credentials()
|
66
|
+
channel = grpc.secure_channel(host, creds)
|
67
|
+
except Exception as e:
|
68
|
+
raise plumbing.convert_error_to_porcelain(e) from e
|
69
|
+
self.channel = channel
|
70
|
+
self.account_attachments = svc.AccountAttachments(channel, self)
|
71
|
+
'''
|
72
|
+
AccountAttachments assign an account to a role.
|
73
|
+
|
74
|
+
See `strongdm.svc.AccountAttachments`.
|
75
|
+
'''
|
76
|
+
self.account_attachments_history = svc.AccountAttachmentsHistory(
|
77
|
+
channel, self)
|
78
|
+
'''
|
79
|
+
AccountAttachmentsHistory records all changes to the state of an AccountAttachment.
|
80
|
+
|
81
|
+
See `strongdm.svc.AccountAttachmentsHistory`.
|
82
|
+
'''
|
83
|
+
self.account_grants = svc.AccountGrants(channel, self)
|
84
|
+
'''
|
85
|
+
AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource.
|
86
|
+
|
87
|
+
See `strongdm.svc.AccountGrants`.
|
88
|
+
'''
|
89
|
+
self.account_grants_history = svc.AccountGrantsHistory(channel, self)
|
90
|
+
'''
|
91
|
+
AccountGrantsHistory records all changes to the state of an AccountGrant.
|
92
|
+
|
93
|
+
See `strongdm.svc.AccountGrantsHistory`.
|
94
|
+
'''
|
95
|
+
self.account_permissions = svc.AccountPermissions(channel, self)
|
96
|
+
'''
|
97
|
+
AccountPermissions records the granular permissions accounts have, allowing them to execute
|
98
|
+
relevant commands via StrongDM's APIs.
|
99
|
+
|
100
|
+
See `strongdm.svc.AccountPermissions`.
|
101
|
+
'''
|
102
|
+
self.account_resources = svc.AccountResources(channel, self)
|
103
|
+
'''
|
104
|
+
AccountResources enumerates the resources to which accounts have access.
|
105
|
+
The AccountResources service is read-only.
|
106
|
+
|
107
|
+
See `strongdm.svc.AccountResources`.
|
108
|
+
'''
|
109
|
+
self.accounts = svc.Accounts(channel, self)
|
110
|
+
'''
|
111
|
+
Accounts are users that have access to strongDM. There are two types of accounts:
|
112
|
+
1. **Users:** humans who are authenticated through username and password or SSO.
|
113
|
+
2. **Service Accounts:** machines that are authenticated using a service token.
|
114
|
+
|
115
|
+
See `strongdm.svc.Accounts`.
|
116
|
+
'''
|
117
|
+
self.accounts_history = svc.AccountsHistory(channel, self)
|
118
|
+
'''
|
119
|
+
AccountsHistory records all changes to the state of an Account.
|
120
|
+
|
121
|
+
See `strongdm.svc.AccountsHistory`.
|
122
|
+
'''
|
123
|
+
self.activities = svc.Activities(channel, self)
|
124
|
+
'''
|
125
|
+
An Activity is a record of an action taken against a strongDM deployment, e.g.
|
126
|
+
a user creation, resource deletion, sso configuration change, etc. The Activities
|
127
|
+
service is read-only.
|
128
|
+
|
129
|
+
See `strongdm.svc.Activities`.
|
130
|
+
'''
|
131
|
+
self.control_panel = svc.ControlPanel(channel, self)
|
132
|
+
'''
|
133
|
+
ControlPanel contains all administrative controls.
|
134
|
+
|
135
|
+
See `strongdm.svc.ControlPanel`.
|
136
|
+
'''
|
137
|
+
self.nodes = svc.Nodes(channel, self)
|
138
|
+
'''
|
139
|
+
Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes:
|
140
|
+
- **Gateways** are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers.
|
141
|
+
- **Relays** are used to extend the strongDM network into segmented subnets. They provide access to databases and servers but do not listen for incoming connections.
|
142
|
+
|
143
|
+
See `strongdm.svc.Nodes`.
|
144
|
+
'''
|
145
|
+
self.nodes_history = svc.NodesHistory(channel, self)
|
146
|
+
'''
|
147
|
+
NodesHistory records all changes to the state of a Node.
|
148
|
+
|
149
|
+
See `strongdm.svc.NodesHistory`.
|
150
|
+
'''
|
151
|
+
self.organization_history = svc.OrganizationHistory(channel, self)
|
152
|
+
'''
|
153
|
+
OrganizationHistory records all changes to the state of an Organization.
|
154
|
+
|
155
|
+
See `strongdm.svc.OrganizationHistory`.
|
156
|
+
'''
|
157
|
+
self.queries = svc.Queries(channel, self)
|
158
|
+
'''
|
159
|
+
A Query is a record of a single client request to a resource, such as an SQL query.
|
160
|
+
Long-running SSH, RDP, or Kubernetes interactive sessions also count as queries.
|
161
|
+
The Queries service is read-only.
|
162
|
+
|
163
|
+
See `strongdm.svc.Queries`.
|
164
|
+
'''
|
165
|
+
self.remote_identities = svc.RemoteIdentities(channel, self)
|
166
|
+
'''
|
167
|
+
RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource.
|
168
|
+
|
169
|
+
See `strongdm.svc.RemoteIdentities`.
|
170
|
+
'''
|
171
|
+
self.remote_identities_history = svc.RemoteIdentitiesHistory(
|
172
|
+
channel, self)
|
173
|
+
'''
|
174
|
+
RemoteIdentitiesHistory records all changes to the state of a RemoteIdentity.
|
175
|
+
|
176
|
+
See `strongdm.svc.RemoteIdentitiesHistory`.
|
177
|
+
'''
|
178
|
+
self.remote_identity_groups = svc.RemoteIdentityGroups(channel, self)
|
179
|
+
'''
|
180
|
+
A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts.
|
181
|
+
An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects.
|
182
|
+
|
183
|
+
See `strongdm.svc.RemoteIdentityGroups`.
|
184
|
+
'''
|
185
|
+
self.remote_identity_groups_history = svc.RemoteIdentityGroupsHistory(
|
186
|
+
channel, self)
|
187
|
+
'''
|
188
|
+
RemoteIdentityGroupsHistory records all changes to the state of a RemoteIdentityGroup.
|
189
|
+
|
190
|
+
See `strongdm.svc.RemoteIdentityGroupsHistory`.
|
191
|
+
'''
|
192
|
+
self.replays = svc.Replays(channel, self)
|
193
|
+
'''
|
194
|
+
A Replay captures the data transferred over a long-running SSH, RDP, or Kubernetes interactive session
|
195
|
+
(otherwise referred to as a query). The Replays service is read-only.
|
196
|
+
|
197
|
+
See `strongdm.svc.Replays`.
|
198
|
+
'''
|
199
|
+
self.resources = svc.Resources(channel, self)
|
200
|
+
'''
|
201
|
+
Resources are databases, servers, clusters, websites, or clouds that strongDM
|
202
|
+
delegates access to.
|
203
|
+
|
204
|
+
See `strongdm.svc.Resources`.
|
205
|
+
'''
|
206
|
+
self.resources_history = svc.ResourcesHistory(channel, self)
|
207
|
+
'''
|
208
|
+
ResourcesHistory records all changes to the state of a Resource.
|
209
|
+
|
210
|
+
See `strongdm.svc.ResourcesHistory`.
|
211
|
+
'''
|
212
|
+
self.role_resources = svc.RoleResources(channel, self)
|
213
|
+
'''
|
214
|
+
RoleResources enumerates the resources to which roles have access.
|
215
|
+
The RoleResources service is read-only.
|
216
|
+
|
217
|
+
See `strongdm.svc.RoleResources`.
|
218
|
+
'''
|
219
|
+
self.role_resources_history = svc.RoleResourcesHistory(channel, self)
|
220
|
+
'''
|
221
|
+
RoleResourcesHistory records all changes to the state of a RoleResource.
|
222
|
+
|
223
|
+
See `strongdm.svc.RoleResourcesHistory`.
|
224
|
+
'''
|
225
|
+
self.roles = svc.Roles(channel, self)
|
226
|
+
'''
|
227
|
+
A Role has a list of access rules which determine which Resources the members
|
228
|
+
of the Role have access to. An Account can be a member of multiple Roles via
|
229
|
+
AccountAttachments.
|
230
|
+
|
231
|
+
See `strongdm.svc.Roles`.
|
232
|
+
'''
|
233
|
+
self.roles_history = svc.RolesHistory(channel, self)
|
234
|
+
'''
|
235
|
+
RolesHistory records all changes to the state of a Role.
|
236
|
+
|
237
|
+
See `strongdm.svc.RolesHistory`.
|
238
|
+
'''
|
239
|
+
self.secret_stores = svc.SecretStores(channel, self)
|
240
|
+
'''
|
241
|
+
SecretStores are servers where resource secrets (passwords, keys) are stored.
|
242
|
+
|
243
|
+
See `strongdm.svc.SecretStores`.
|
244
|
+
'''
|
245
|
+
self.secret_stores_history = svc.SecretStoresHistory(channel, self)
|
246
|
+
'''
|
247
|
+
SecretStoresHistory records all changes to the state of a SecretStore.
|
248
|
+
|
249
|
+
See `strongdm.svc.SecretStoresHistory`.
|
250
|
+
'''
|
251
|
+
|
252
|
+
def close(self):
|
253
|
+
'''Closes this Client and releases all resources held by it.
|
254
|
+
|
255
|
+
Closing the Client will immediately terminate all RPCs active with the
|
256
|
+
Client and it is not valid to invoke new RPCs with the Client.
|
257
|
+
|
258
|
+
This method is idempotent.
|
259
|
+
'''
|
260
|
+
self.channel.close()
|
261
|
+
|
262
|
+
def get_metadata(self, method_name, req):
|
263
|
+
return [
|
264
|
+
('x-sdm-authentication', self.api_access_key),
|
265
|
+
('x-sdm-signature', self.sign(method_name,
|
266
|
+
req.SerializeToString())),
|
267
|
+
('x-sdm-api-version', API_VERSION),
|
268
|
+
('x-sdm-user-agent', USER_AGENT),
|
269
|
+
]
|
270
|
+
|
271
|
+
def sign(self, method_name, request_bytes):
|
272
|
+
def hmac_digest(key, msg_byte_string):
|
273
|
+
return hmac.new(key, msg=msg_byte_string,
|
274
|
+
digestmod=hashlib.sha256).digest()
|
275
|
+
|
276
|
+
current_utc_date = datetime.datetime.utcnow().strftime('%Y-%m-%d')
|
277
|
+
signing_key = hmac_digest(self.api_secret, current_utc_date.encode())
|
278
|
+
signing_key = hmac_digest(signing_key, b'sdm_api_v1')
|
279
|
+
|
280
|
+
hash = hashlib.sha256()
|
281
|
+
|
282
|
+
hash.update(method_name.encode())
|
283
|
+
hash.update(b'\n')
|
284
|
+
hash.update(request_bytes)
|
285
|
+
|
286
|
+
return base64.b64encode(hmac_digest(signing_key, hash.digest()))
|
287
|
+
|
288
|
+
def jitterSleep(self, iter):
|
289
|
+
dur_max = self.base_retry_delay * 2**iter
|
290
|
+
if (dur_max > self.max_retry_delay):
|
291
|
+
dur_max = self.max_retry_delay
|
292
|
+
# get a value between 0 and max
|
293
|
+
dur = random.random() * dur_max
|
294
|
+
time.sleep(dur)
|
295
|
+
|
296
|
+
def shouldRetry(self, iter, err):
|
297
|
+
if (iter >= self.max_retries - 1):
|
298
|
+
return False
|
299
|
+
if not isinstance(err, grpc.RpcError):
|
300
|
+
return True
|
301
|
+
if (not self.expose_rate_limit_errors
|
302
|
+
) and err.code() == grpc.StatusCode.RESOURCE_EXHAUSTED:
|
303
|
+
porcelain_err = plumbing.convert_error_to_porcelain(err)
|
304
|
+
wait_until = porcelain_err.rate_limit.reset_at
|
305
|
+
now = datetime.datetime.now(datetime.timezone.utc)
|
306
|
+
sleep_for = (wait_until - now).total_seconds()
|
307
|
+
# If timezones or clock drift causes this calculation to fail,
|
308
|
+
# wait at most one minute.
|
309
|
+
if sleep_for < 0 or sleep_for > 60:
|
310
|
+
sleep_for = 60
|
311
|
+
time.sleep(sleep_for)
|
312
|
+
return True
|
313
|
+
return err.code() == grpc.StatusCode.INTERNAL or err.code(
|
314
|
+
) == grpc.StatusCode.UNAVAILABLE
|
315
|
+
|
316
|
+
def snapshot_at(self, snapshot_datetime):
|
317
|
+
'''
|
318
|
+
Constructs a read-only client that will provide historical data from the provided timestamp.
|
319
|
+
|
320
|
+
See `SnapshotClient`.
|
321
|
+
'''
|
322
|
+
client = copy.copy(self)
|
323
|
+
client.snapshot_datetime = snapshot_datetime
|
324
|
+
client.account_attachments = svc.AccountAttachments(
|
325
|
+
client.channel, client)
|
326
|
+
client.account_grants = svc.AccountGrants(client.channel, client)
|
327
|
+
client.account_permissions = svc.AccountPermissions(
|
328
|
+
client.channel, client)
|
329
|
+
client.account_resources = svc.AccountResources(client.channel, client)
|
330
|
+
client.accounts = svc.Accounts(client.channel, client)
|
331
|
+
client.nodes = svc.Nodes(client.channel, client)
|
332
|
+
client.remote_identities = svc.RemoteIdentities(client.channel, client)
|
333
|
+
client.remote_identity_groups = svc.RemoteIdentityGroups(
|
334
|
+
client.channel, client)
|
335
|
+
client.resources = svc.Resources(client.channel, client)
|
336
|
+
client.role_resources = svc.RoleResources(client.channel, client)
|
337
|
+
client.roles = svc.Roles(client.channel, client)
|
338
|
+
client.secret_stores = svc.SecretStores(client.channel, client)
|
339
|
+
return SnapshotClient(client)
|
340
|
+
|
341
|
+
|
342
|
+
class SnapshotClient:
|
343
|
+
'''SnapshotClient exposes methods to query historical records at a provided timestamp.'''
|
344
|
+
def __init__(self, client):
|
345
|
+
self.account_attachments = svc.SnapshotAccountAttachments(
|
346
|
+
client.account_attachments)
|
347
|
+
'''
|
348
|
+
AccountAttachments assign an account to a role.
|
349
|
+
|
350
|
+
See `strongdm.svc.SnapshotAccountAttachments`.
|
351
|
+
'''
|
352
|
+
self.account_grants = svc.SnapshotAccountGrants(client.account_grants)
|
353
|
+
'''
|
354
|
+
AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource.
|
355
|
+
|
356
|
+
See `strongdm.svc.SnapshotAccountGrants`.
|
357
|
+
'''
|
358
|
+
self.account_permissions = svc.SnapshotAccountPermissions(
|
359
|
+
client.account_permissions)
|
360
|
+
'''
|
361
|
+
AccountPermissions records the granular permissions accounts have, allowing them to execute
|
362
|
+
relevant commands via StrongDM's APIs.
|
363
|
+
|
364
|
+
See `strongdm.svc.SnapshotAccountPermissions`.
|
365
|
+
'''
|
366
|
+
self.account_resources = svc.SnapshotAccountResources(
|
367
|
+
client.account_resources)
|
368
|
+
'''
|
369
|
+
AccountResources enumerates the resources to which accounts have access.
|
370
|
+
The AccountResources service is read-only.
|
371
|
+
|
372
|
+
See `strongdm.svc.SnapshotAccountResources`.
|
373
|
+
'''
|
374
|
+
self.accounts = svc.SnapshotAccounts(client.accounts)
|
375
|
+
'''
|
376
|
+
Accounts are users that have access to strongDM. There are two types of accounts:
|
377
|
+
1. **Users:** humans who are authenticated through username and password or SSO.
|
378
|
+
2. **Service Accounts:** machines that are authenticated using a service token.
|
379
|
+
|
380
|
+
See `strongdm.svc.SnapshotAccounts`.
|
381
|
+
'''
|
382
|
+
self.nodes = svc.SnapshotNodes(client.nodes)
|
383
|
+
'''
|
384
|
+
Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes:
|
385
|
+
- **Gateways** are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers.
|
386
|
+
- **Relays** are used to extend the strongDM network into segmented subnets. They provide access to databases and servers but do not listen for incoming connections.
|
387
|
+
|
388
|
+
See `strongdm.svc.SnapshotNodes`.
|
389
|
+
'''
|
390
|
+
self.remote_identities = svc.SnapshotRemoteIdentities(
|
391
|
+
client.remote_identities)
|
392
|
+
'''
|
393
|
+
RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource.
|
394
|
+
|
395
|
+
See `strongdm.svc.SnapshotRemoteIdentities`.
|
396
|
+
'''
|
397
|
+
self.remote_identity_groups = svc.SnapshotRemoteIdentityGroups(
|
398
|
+
client.remote_identity_groups)
|
399
|
+
'''
|
400
|
+
A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts.
|
401
|
+
An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects.
|
402
|
+
|
403
|
+
See `strongdm.svc.SnapshotRemoteIdentityGroups`.
|
404
|
+
'''
|
405
|
+
self.resources = svc.SnapshotResources(client.resources)
|
406
|
+
'''
|
407
|
+
Resources are databases, servers, clusters, websites, or clouds that strongDM
|
408
|
+
delegates access to.
|
409
|
+
|
410
|
+
See `strongdm.svc.SnapshotResources`.
|
411
|
+
'''
|
412
|
+
self.role_resources = svc.SnapshotRoleResources(client.role_resources)
|
413
|
+
'''
|
414
|
+
RoleResources enumerates the resources to which roles have access.
|
415
|
+
The RoleResources service is read-only.
|
416
|
+
|
417
|
+
See `strongdm.svc.SnapshotRoleResources`.
|
418
|
+
'''
|
419
|
+
self.roles = svc.SnapshotRoles(client.roles)
|
420
|
+
'''
|
421
|
+
A Role has a list of access rules which determine which Resources the members
|
422
|
+
of the Role have access to. An Account can be a member of multiple Roles via
|
423
|
+
AccountAttachments.
|
424
|
+
|
425
|
+
See `strongdm.svc.SnapshotRoles`.
|
426
|
+
'''
|
427
|
+
self.secret_stores = svc.SnapshotSecretStores(client.secret_stores)
|
428
|
+
'''
|
429
|
+
SecretStores are servers where resource secrets (passwords, keys) are stored.
|
430
|
+
|
431
|
+
See `strongdm.svc.SnapshotSecretStores`.
|
432
|
+
'''
|