strongdm.client
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# Code generated by protogen. DO NOT EDIT. 17 18import base64 19import copy 20import datetime 21import grpc 22import hashlib 23import hmac 24import random 25import time 26from . import errors 27from . import plumbing 28from . import svc 29 30# These defaults are taken from AWS. Customization of these values 31# is a future step in the API. 32DEFAULT_MAX_RETRIES = 3 33DEFAULT_BASE_RETRY_DELAY = 0.0030 # 30 ms 34DEFAULT_MAX_RETRY_DELAY = 300 # 300 seconds 35API_VERSION = '2025-04-14' 36USER_AGENT = 'strongdm-sdk-python/14.10.0' 37 38 39class Client: 40 '''Client interacts with the strongDM API.''' 41 def __init__(self, 42 api_access_key, 43 api_secret, 44 host='app.strongdm.com:443', 45 insecure=False, 46 retry_rate_limit_errors=True, 47 page_limit=50): 48 ''' 49 Create a new Client. 50 51 - api_access_key: the access key to authenticate with strongDM 52 - api_secret: the secret key to authenticate with strongDM 53 ''' 54 self.api_access_key = api_access_key.strip() 55 self.api_secret = base64.b64decode(api_secret.strip()) 56 self.max_retries = DEFAULT_MAX_RETRIES 57 self.base_retry_delay = DEFAULT_BASE_RETRY_DELAY 58 self.max_retry_delay = DEFAULT_MAX_RETRY_DELAY 59 self.expose_rate_limit_errors = (not retry_rate_limit_errors) 60 self.snapshot_datetime = None 61 self.page_limit = page_limit 62 63 try: 64 if insecure: 65 channel = grpc.insecure_channel(host) 66 else: 67 creds = grpc.ssl_channel_credentials() 68 channel = grpc.secure_channel(host, creds) 69 except Exception as e: 70 raise plumbing.convert_error_to_porcelain(e) from e 71 self.channel = channel 72 self.access_requests = svc.AccessRequests(channel, self) 73 ''' 74 AccessRequests are requests for access to a resource that may match a Workflow. 75 76 See `strongdm.svc.AccessRequests`. 77 ''' 78 self.access_request_events_history = svc.AccessRequestEventsHistory( 79 channel, self) 80 ''' 81 AccessRequestEventsHistory provides records of all changes to the state of an AccessRequest. 82 83 See `strongdm.svc.AccessRequestEventsHistory`. 84 ''' 85 self.access_requests_history = svc.AccessRequestsHistory(channel, self) 86 ''' 87 AccessRequestsHistory provides records of all changes to the state of an AccessRequest. 88 89 See `strongdm.svc.AccessRequestsHistory`. 90 ''' 91 self.account_attachments = svc.AccountAttachments(channel, self) 92 ''' 93 AccountAttachments assign an account to a role. 94 95 See `strongdm.svc.AccountAttachments`. 96 ''' 97 self.account_attachments_history = svc.AccountAttachmentsHistory( 98 channel, self) 99 ''' 100 AccountAttachmentsHistory records all changes to the state of an AccountAttachment. 101 102 See `strongdm.svc.AccountAttachmentsHistory`. 103 ''' 104 self.account_grants = svc.AccountGrants(channel, self) 105 ''' 106 AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource. 107 108 See `strongdm.svc.AccountGrants`. 109 ''' 110 self.account_grants_history = svc.AccountGrantsHistory(channel, self) 111 ''' 112 AccountGrantsHistory records all changes to the state of an AccountGrant. 113 114 See `strongdm.svc.AccountGrantsHistory`. 115 ''' 116 self.account_permissions = svc.AccountPermissions(channel, self) 117 ''' 118 AccountPermissions records the granular permissions accounts have, allowing them to execute 119 relevant commands via StrongDM's APIs. 120 121 See `strongdm.svc.AccountPermissions`. 122 ''' 123 self.account_resources = svc.AccountResources(channel, self) 124 ''' 125 AccountResources enumerates the resources to which accounts have access. 126 The AccountResources service is read-only. 127 128 See `strongdm.svc.AccountResources`. 129 ''' 130 self.account_resources_history = svc.AccountResourcesHistory( 131 channel, self) 132 ''' 133 AccountResourcesHistory records all changes to the state of a AccountResource. 134 135 See `strongdm.svc.AccountResourcesHistory`. 136 ''' 137 self.accounts = svc.Accounts(channel, self) 138 ''' 139 Accounts are users that have access to strongDM. There are two types of accounts: 140 1. **Users:** humans who are authenticated through username and password or SSO. 141 2. **Service Accounts:** machines that are authenticated using a service token. 142 3. **Tokens** are access keys with permissions that can be used for authentication. 143 144 See `strongdm.svc.Accounts`. 145 ''' 146 self.accounts_history = svc.AccountsHistory(channel, self) 147 ''' 148 AccountsHistory records all changes to the state of an Account. 149 150 See `strongdm.svc.AccountsHistory`. 151 ''' 152 self.activities = svc.Activities(channel, self) 153 ''' 154 An Activity is a record of an action taken against a strongDM deployment, e.g. 155 a user creation, resource deletion, sso configuration change, etc. The Activities 156 service is read-only. 157 158 See `strongdm.svc.Activities`. 159 ''' 160 self.approval_workflow_approvers = svc.ApprovalWorkflowApprovers( 161 channel, self) 162 ''' 163 ApprovalWorkflowApprovers link approval workflow approvers to an ApprovalWorkflowStep 164 165 See `strongdm.svc.ApprovalWorkflowApprovers`. 166 ''' 167 self.approval_workflow_approvers_history = svc.ApprovalWorkflowApproversHistory( 168 channel, self) 169 ''' 170 ApprovalWorkflowApproversHistory records all changes to the state of an ApprovalWorkflowApprover. 171 172 See `strongdm.svc.ApprovalWorkflowApproversHistory`. 173 ''' 174 self.approval_workflow_steps = svc.ApprovalWorkflowSteps(channel, self) 175 ''' 176 ApprovalWorkflowSteps link approval workflow steps to an ApprovalWorkflow 177 178 See `strongdm.svc.ApprovalWorkflowSteps`. 179 ''' 180 self.approval_workflow_steps_history = svc.ApprovalWorkflowStepsHistory( 181 channel, self) 182 ''' 183 ApprovalWorkflowStepsHistory records all changes to the state of an ApprovalWorkflowStep. 184 185 See `strongdm.svc.ApprovalWorkflowStepsHistory`. 186 ''' 187 self.approval_workflows = svc.ApprovalWorkflows(channel, self) 188 ''' 189 ApprovalWorkflows are the mechanism by which requests for access can be viewed by authorized 190 approvers and be approved or denied. 191 192 See `strongdm.svc.ApprovalWorkflows`. 193 ''' 194 self.approval_workflows_history = svc.ApprovalWorkflowsHistory( 195 channel, self) 196 ''' 197 ApprovalWorkflowsHistory records all changes to the state of an ApprovalWorkflow. 198 199 See `strongdm.svc.ApprovalWorkflowsHistory`. 200 ''' 201 self.control_panel = svc.ControlPanel(channel, self) 202 ''' 203 ControlPanel contains all administrative controls. 204 205 See `strongdm.svc.ControlPanel`. 206 ''' 207 self.health_checks = svc.HealthChecks(channel, self) 208 ''' 209 HealthChecks lists the last healthcheck between each node and resource. 210 Note the unconventional capitalization here is to prevent having a collision with GRPC 211 212 See `strongdm.svc.HealthChecks`. 213 ''' 214 self.identity_aliases = svc.IdentityAliases(channel, self) 215 ''' 216 IdentityAliases assign an alias to an account within an IdentitySet. 217 The alias is used as the username when connecting to a identity supported resource. 218 219 See `strongdm.svc.IdentityAliases`. 220 ''' 221 self.identity_aliases_history = svc.IdentityAliasesHistory( 222 channel, self) 223 ''' 224 IdentityAliasesHistory records all changes to the state of a IdentityAlias. 225 226 See `strongdm.svc.IdentityAliasesHistory`. 227 ''' 228 self.identity_sets = svc.IdentitySets(channel, self) 229 ''' 230 A IdentitySet is a named grouping of Identity Aliases for Accounts. 231 An Account's relationship to a IdentitySet is defined via IdentityAlias objects. 232 233 See `strongdm.svc.IdentitySets`. 234 ''' 235 self.identity_sets_history = svc.IdentitySetsHistory(channel, self) 236 ''' 237 IdentitySetsHistory records all changes to the state of a IdentitySet. 238 239 See `strongdm.svc.IdentitySetsHistory`. 240 ''' 241 self.managed_secrets = svc.ManagedSecrets(channel, self) 242 ''' 243 ManagedSecret is a private vertical for creating, reading, updating, 244 deleting, listing and rotating the managed secrets in the secrets engines as 245 an authenticated user. 246 247 See `strongdm.svc.ManagedSecrets`. 248 ''' 249 self.nodes = svc.Nodes(channel, self) 250 ''' 251 Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes: 252 - **Gateways** are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers. 253 - **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. 254 255 See `strongdm.svc.Nodes`. 256 ''' 257 self.nodes_history = svc.NodesHistory(channel, self) 258 ''' 259 NodesHistory records all changes to the state of a Node. 260 261 See `strongdm.svc.NodesHistory`. 262 ''' 263 self.organization_history = svc.OrganizationHistory(channel, self) 264 ''' 265 OrganizationHistory records all changes to the state of an Organization. 266 267 See `strongdm.svc.OrganizationHistory`. 268 ''' 269 self.peering_group_nodes = svc.PeeringGroupNodes(channel, self) 270 ''' 271 PeeringGroupNodes provides the building blocks necessary to obtain attach a node to a peering group. 272 273 See `strongdm.svc.PeeringGroupNodes`. 274 ''' 275 self.peering_group_peers = svc.PeeringGroupPeers(channel, self) 276 ''' 277 PeeringGroupPeers provides the building blocks necessary to link two peering groups. 278 279 See `strongdm.svc.PeeringGroupPeers`. 280 ''' 281 self.peering_group_resources = svc.PeeringGroupResources(channel, self) 282 ''' 283 PeeringGroupResources provides the building blocks necessary to obtain attach a resource to a peering group. 284 285 See `strongdm.svc.PeeringGroupResources`. 286 ''' 287 self.peering_groups = svc.PeeringGroups(channel, self) 288 ''' 289 PeeringGroups provides the building blocks necessary to obtain explicit network topology and routing. 290 291 See `strongdm.svc.PeeringGroups`. 292 ''' 293 self.policies = svc.Policies(channel, self) 294 ''' 295 Policies are the collection of one or more statements that enforce fine-grained access 296 control for the users of an organization. 297 298 See `strongdm.svc.Policies`. 299 ''' 300 self.policies_history = svc.PoliciesHistory(channel, self) 301 ''' 302 PoliciesHistory records all changes to the state of a Policy. 303 304 See `strongdm.svc.PoliciesHistory`. 305 ''' 306 self.proxy_cluster_keys = svc.ProxyClusterKeys(channel, self) 307 ''' 308 Proxy Cluster Keys are authentication keys for all proxies within a cluster. 309 The proxies within a cluster share the same key. One cluster can have 310 multiple keys in order to facilitate key rotation. 311 312 See `strongdm.svc.ProxyClusterKeys`. 313 ''' 314 self.queries = svc.Queries(channel, self) 315 ''' 316 A Query is a record of a single client request to a resource, such as a SQL query. 317 Long-running SSH, RDP, or Kubernetes interactive sessions also count as queries. 318 The Queries service is read-only. 319 320 See `strongdm.svc.Queries`. 321 ''' 322 self.remote_identities = svc.RemoteIdentities(channel, self) 323 ''' 324 RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource. 325 326 See `strongdm.svc.RemoteIdentities`. 327 ''' 328 self.remote_identities_history = svc.RemoteIdentitiesHistory( 329 channel, self) 330 ''' 331 RemoteIdentitiesHistory records all changes to the state of a RemoteIdentity. 332 333 See `strongdm.svc.RemoteIdentitiesHistory`. 334 ''' 335 self.remote_identity_groups = svc.RemoteIdentityGroups(channel, self) 336 ''' 337 A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. 338 An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects. 339 340 See `strongdm.svc.RemoteIdentityGroups`. 341 ''' 342 self.remote_identity_groups_history = svc.RemoteIdentityGroupsHistory( 343 channel, self) 344 ''' 345 RemoteIdentityGroupsHistory records all changes to the state of a RemoteIdentityGroup. 346 347 See `strongdm.svc.RemoteIdentityGroupsHistory`. 348 ''' 349 self.replays = svc.Replays(channel, self) 350 ''' 351 A Replay captures the data transferred over a long-running SSH, RDP, or Kubernetes interactive session 352 (otherwise referred to as a query). The Replays service is read-only. 353 354 See `strongdm.svc.Replays`. 355 ''' 356 self.resources = svc.Resources(channel, self) 357 ''' 358 Resources are databases, servers, clusters, websites, or clouds that strongDM 359 delegates access to. 360 361 See `strongdm.svc.Resources`. 362 ''' 363 self.resources_history = svc.ResourcesHistory(channel, self) 364 ''' 365 ResourcesHistory records all changes to the state of a Resource. 366 367 See `strongdm.svc.ResourcesHistory`. 368 ''' 369 self.role_resources = svc.RoleResources(channel, self) 370 ''' 371 RoleResources enumerates the resources to which roles have access. 372 The RoleResources service is read-only. 373 374 See `strongdm.svc.RoleResources`. 375 ''' 376 self.role_resources_history = svc.RoleResourcesHistory(channel, self) 377 ''' 378 RoleResourcesHistory records all changes to the state of a RoleResource. 379 380 See `strongdm.svc.RoleResourcesHistory`. 381 ''' 382 self.roles = svc.Roles(channel, self) 383 ''' 384 A Role has a list of access rules which determine which Resources the members 385 of the Role have access to. An Account can be a member of multiple Roles via 386 AccountAttachments. 387 388 See `strongdm.svc.Roles`. 389 ''' 390 self.roles_history = svc.RolesHistory(channel, self) 391 ''' 392 RolesHistory records all changes to the state of a Role. 393 394 See `strongdm.svc.RolesHistory`. 395 ''' 396 self.secret_stores = svc.SecretStores(channel, self) 397 ''' 398 SecretStores are servers where resource secrets (passwords, keys) are stored. 399 400 See `strongdm.svc.SecretStores`. 401 ''' 402 self.secret_engines = svc.SecretEngines(channel, self) 403 ''' 404 405 406 See `strongdm.svc.SecretEngines`. 407 ''' 408 self.secret_store_healths = svc.SecretStoreHealths(channel, self) 409 ''' 410 SecretStoreHealths exposes health states for secret stores. 411 412 See `strongdm.svc.SecretStoreHealths`. 413 ''' 414 self.secret_stores_history = svc.SecretStoresHistory(channel, self) 415 ''' 416 SecretStoresHistory records all changes to the state of a SecretStore. 417 418 See `strongdm.svc.SecretStoresHistory`. 419 ''' 420 self.workflow_approvers = svc.WorkflowApprovers(channel, self) 421 ''' 422 WorkflowApprovers is an account or a role with the ability to approve requests bound to a workflow. 423 424 See `strongdm.svc.WorkflowApprovers`. 425 ''' 426 self.workflow_approvers_history = svc.WorkflowApproversHistory( 427 channel, self) 428 ''' 429 WorkflowApproversHistory provides records of all changes to the state of a WorkflowApprover. 430 431 See `strongdm.svc.WorkflowApproversHistory`. 432 ''' 433 self.workflow_assignments = svc.WorkflowAssignments(channel, self) 434 ''' 435 WorkflowAssignments links a Resource to a Workflow. The assigned resources are those that a user can request 436 access to via the workflow. 437 438 See `strongdm.svc.WorkflowAssignments`. 439 ''' 440 self.workflow_assignments_history = svc.WorkflowAssignmentsHistory( 441 channel, self) 442 ''' 443 WorkflowAssignmentsHistory provides records of all changes to the state of a WorkflowAssignment. 444 445 See `strongdm.svc.WorkflowAssignmentsHistory`. 446 ''' 447 self.workflow_roles = svc.WorkflowRoles(channel, self) 448 ''' 449 WorkflowRole links a role to a workflow. The linked roles indicate which roles a user must be a part of 450 to request access to a resource via the workflow. 451 452 See `strongdm.svc.WorkflowRoles`. 453 ''' 454 self.workflow_roles_history = svc.WorkflowRolesHistory(channel, self) 455 ''' 456 WorkflowRolesHistory provides records of all changes to the state of a WorkflowRole 457 458 See `strongdm.svc.WorkflowRolesHistory`. 459 ''' 460 self.workflows = svc.Workflows(channel, self) 461 ''' 462 Workflows are the collection of rules that define the resources to which access can be requested, 463 the users that can request that access, and the mechanism for approving those requests which can either 464 be automatic approval or a set of users authorized to approve the requests. 465 466 See `strongdm.svc.Workflows`. 467 ''' 468 self.workflows_history = svc.WorkflowsHistory(channel, self) 469 ''' 470 WorkflowsHistory provides records of all changes to the state of a Workflow. 471 472 See `strongdm.svc.WorkflowsHistory`. 473 ''' 474 475 def close(self): 476 '''Closes this Client and releases all resources held by it. 477 478 Closing the Client will immediately terminate all RPCs active with the 479 Client and it is not valid to invoke new RPCs with the Client. 480 481 This method is idempotent. 482 ''' 483 self.channel.close() 484 485 def get_metadata(self, method_name, req): 486 return [ 487 ('x-sdm-authentication', self.api_access_key), 488 ('x-sdm-signature', self.sign(method_name, 489 req.SerializeToString())), 490 ('x-sdm-api-version', API_VERSION), 491 ('x-sdm-user-agent', USER_AGENT), 492 ] 493 494 def sign(self, method_name, request_bytes): 495 def hmac_digest(key, msg_byte_string): 496 return hmac.new(key, msg=msg_byte_string, 497 digestmod=hashlib.sha256).digest() 498 499 current_utc_date = datetime.datetime.now( 500 datetime.timezone.utc).strftime('%Y-%m-%d') 501 signing_key = hmac_digest(self.api_secret, current_utc_date.encode()) 502 signing_key = hmac_digest(signing_key, b'sdm_api_v1') 503 504 hash = hashlib.sha256() 505 506 hash.update(method_name.encode()) 507 hash.update(b'\n') 508 hash.update(request_bytes) 509 510 return base64.b64encode(hmac_digest(signing_key, hash.digest())) 511 512 def jitterSleep(self, iter): 513 dur_max = self.base_retry_delay * 2**iter 514 if (dur_max > self.max_retry_delay): 515 dur_max = self.max_retry_delay 516 # get a value between 0 and max 517 dur = random.random() * dur_max 518 time.sleep(dur) 519 520 def shouldRetry(self, iter, err): 521 if (iter >= self.max_retries - 1): 522 return False 523 if not isinstance(err, grpc.RpcError): 524 return True 525 porcelain_err = plumbing.convert_error_to_porcelain(err) 526 if (not self.expose_rate_limit_errors) and isinstance( 527 porcelain_err, errors.RateLimitError): 528 wait_until = porcelain_err.rate_limit.reset_at 529 now = datetime.datetime.now(datetime.timezone.utc) 530 sleep_for = (wait_until - now).total_seconds() 531 # If timezones or clock drift causes this calculation to fail, 532 # wait at most one minute. 533 if sleep_for < 0 or sleep_for > 60: 534 sleep_for = 60 535 time.sleep(sleep_for) 536 return True 537 return err.code() == grpc.StatusCode.INTERNAL or err.code( 538 ) == grpc.StatusCode.UNAVAILABLE 539 540 def snapshot_at(self, snapshot_datetime): 541 ''' 542 Constructs a read-only client that will provide historical data from the provided timestamp. 543 544 See `SnapshotClient`. 545 ''' 546 client = copy.copy(self) 547 client.snapshot_datetime = snapshot_datetime 548 client.access_requests = svc.AccessRequests(client.channel, client) 549 client.account_attachments = svc.AccountAttachments( 550 client.channel, client) 551 client.account_grants = svc.AccountGrants(client.channel, client) 552 client.account_permissions = svc.AccountPermissions( 553 client.channel, client) 554 client.account_resources = svc.AccountResources(client.channel, client) 555 client.accounts = svc.Accounts(client.channel, client) 556 client.approval_workflow_approvers = svc.ApprovalWorkflowApprovers( 557 client.channel, client) 558 client.approval_workflow_steps = svc.ApprovalWorkflowSteps( 559 client.channel, client) 560 client.approval_workflows = svc.ApprovalWorkflows( 561 client.channel, client) 562 client.identity_aliases = svc.IdentityAliases(client.channel, client) 563 client.identity_sets = svc.IdentitySets(client.channel, client) 564 client.nodes = svc.Nodes(client.channel, client) 565 client.policies = svc.Policies(client.channel, client) 566 client.proxy_cluster_keys = svc.ProxyClusterKeys( 567 client.channel, client) 568 client.remote_identities = svc.RemoteIdentities(client.channel, client) 569 client.remote_identity_groups = svc.RemoteIdentityGroups( 570 client.channel, client) 571 client.resources = svc.Resources(client.channel, client) 572 client.role_resources = svc.RoleResources(client.channel, client) 573 client.roles = svc.Roles(client.channel, client) 574 client.secret_stores = svc.SecretStores(client.channel, client) 575 client.workflow_approvers = svc.WorkflowApprovers( 576 client.channel, client) 577 client.workflow_assignments = svc.WorkflowAssignments( 578 client.channel, client) 579 client.workflow_roles = svc.WorkflowRoles(client.channel, client) 580 client.workflows = svc.Workflows(client.channel, client) 581 return SnapshotClient(client) 582 583 584class SnapshotClient: 585 '''SnapshotClient exposes methods to query historical records at a provided timestamp.''' 586 def __init__(self, client): 587 self.access_requests = svc.SnapshotAccessRequests( 588 client.access_requests) 589 ''' 590 AccessRequests are requests for access to a resource that may match a Workflow. 591 592 See `strongdm.svc.SnapshotAccessRequests`. 593 ''' 594 self.account_attachments = svc.SnapshotAccountAttachments( 595 client.account_attachments) 596 ''' 597 AccountAttachments assign an account to a role. 598 599 See `strongdm.svc.SnapshotAccountAttachments`. 600 ''' 601 self.account_grants = svc.SnapshotAccountGrants(client.account_grants) 602 ''' 603 AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource. 604 605 See `strongdm.svc.SnapshotAccountGrants`. 606 ''' 607 self.account_permissions = svc.SnapshotAccountPermissions( 608 client.account_permissions) 609 ''' 610 AccountPermissions records the granular permissions accounts have, allowing them to execute 611 relevant commands via StrongDM's APIs. 612 613 See `strongdm.svc.SnapshotAccountPermissions`. 614 ''' 615 self.account_resources = svc.SnapshotAccountResources( 616 client.account_resources) 617 ''' 618 AccountResources enumerates the resources to which accounts have access. 619 The AccountResources service is read-only. 620 621 See `strongdm.svc.SnapshotAccountResources`. 622 ''' 623 self.accounts = svc.SnapshotAccounts(client.accounts) 624 ''' 625 Accounts are users that have access to strongDM. There are two types of accounts: 626 1. **Users:** humans who are authenticated through username and password or SSO. 627 2. **Service Accounts:** machines that are authenticated using a service token. 628 3. **Tokens** are access keys with permissions that can be used for authentication. 629 630 See `strongdm.svc.SnapshotAccounts`. 631 ''' 632 self.approval_workflow_approvers = svc.SnapshotApprovalWorkflowApprovers( 633 client.approval_workflow_approvers) 634 ''' 635 ApprovalWorkflowApprovers link approval workflow approvers to an ApprovalWorkflowStep 636 637 See `strongdm.svc.SnapshotApprovalWorkflowApprovers`. 638 ''' 639 self.approval_workflow_steps = svc.SnapshotApprovalWorkflowSteps( 640 client.approval_workflow_steps) 641 ''' 642 ApprovalWorkflowSteps link approval workflow steps to an ApprovalWorkflow 643 644 See `strongdm.svc.SnapshotApprovalWorkflowSteps`. 645 ''' 646 self.approval_workflows = svc.SnapshotApprovalWorkflows( 647 client.approval_workflows) 648 ''' 649 ApprovalWorkflows are the mechanism by which requests for access can be viewed by authorized 650 approvers and be approved or denied. 651 652 See `strongdm.svc.SnapshotApprovalWorkflows`. 653 ''' 654 self.identity_aliases = svc.SnapshotIdentityAliases( 655 client.identity_aliases) 656 ''' 657 IdentityAliases assign an alias to an account within an IdentitySet. 658 The alias is used as the username when connecting to a identity supported resource. 659 660 See `strongdm.svc.SnapshotIdentityAliases`. 661 ''' 662 self.identity_sets = svc.SnapshotIdentitySets(client.identity_sets) 663 ''' 664 A IdentitySet is a named grouping of Identity Aliases for Accounts. 665 An Account's relationship to a IdentitySet is defined via IdentityAlias objects. 666 667 See `strongdm.svc.SnapshotIdentitySets`. 668 ''' 669 self.nodes = svc.SnapshotNodes(client.nodes) 670 ''' 671 Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes: 672 - **Gateways** are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers. 673 - **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. 674 675 See `strongdm.svc.SnapshotNodes`. 676 ''' 677 self.policies = svc.SnapshotPolicies(client.policies) 678 ''' 679 Policies are the collection of one or more statements that enforce fine-grained access 680 control for the users of an organization. 681 682 See `strongdm.svc.SnapshotPolicies`. 683 ''' 684 self.proxy_cluster_keys = svc.SnapshotProxyClusterKeys( 685 client.proxy_cluster_keys) 686 ''' 687 Proxy Cluster Keys are authentication keys for all proxies within a cluster. 688 The proxies within a cluster share the same key. One cluster can have 689 multiple keys in order to facilitate key rotation. 690 691 See `strongdm.svc.SnapshotProxyClusterKeys`. 692 ''' 693 self.remote_identities = svc.SnapshotRemoteIdentities( 694 client.remote_identities) 695 ''' 696 RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource. 697 698 See `strongdm.svc.SnapshotRemoteIdentities`. 699 ''' 700 self.remote_identity_groups = svc.SnapshotRemoteIdentityGroups( 701 client.remote_identity_groups) 702 ''' 703 A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. 704 An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects. 705 706 See `strongdm.svc.SnapshotRemoteIdentityGroups`. 707 ''' 708 self.resources = svc.SnapshotResources(client.resources) 709 ''' 710 Resources are databases, servers, clusters, websites, or clouds that strongDM 711 delegates access to. 712 713 See `strongdm.svc.SnapshotResources`. 714 ''' 715 self.role_resources = svc.SnapshotRoleResources(client.role_resources) 716 ''' 717 RoleResources enumerates the resources to which roles have access. 718 The RoleResources service is read-only. 719 720 See `strongdm.svc.SnapshotRoleResources`. 721 ''' 722 self.roles = svc.SnapshotRoles(client.roles) 723 ''' 724 A Role has a list of access rules which determine which Resources the members 725 of the Role have access to. An Account can be a member of multiple Roles via 726 AccountAttachments. 727 728 See `strongdm.svc.SnapshotRoles`. 729 ''' 730 self.secret_stores = svc.SnapshotSecretStores(client.secret_stores) 731 ''' 732 SecretStores are servers where resource secrets (passwords, keys) are stored. 733 734 See `strongdm.svc.SnapshotSecretStores`. 735 ''' 736 self.workflow_approvers = svc.SnapshotWorkflowApprovers( 737 client.workflow_approvers) 738 ''' 739 WorkflowApprovers is an account or a role with the ability to approve requests bound to a workflow. 740 741 See `strongdm.svc.SnapshotWorkflowApprovers`. 742 ''' 743 self.workflow_assignments = svc.SnapshotWorkflowAssignments( 744 client.workflow_assignments) 745 ''' 746 WorkflowAssignments links a Resource to a Workflow. The assigned resources are those that a user can request 747 access to via the workflow. 748 749 See `strongdm.svc.SnapshotWorkflowAssignments`. 750 ''' 751 self.workflow_roles = svc.SnapshotWorkflowRoles(client.workflow_roles) 752 ''' 753 WorkflowRole links a role to a workflow. The linked roles indicate which roles a user must be a part of 754 to request access to a resource via the workflow. 755 756 See `strongdm.svc.SnapshotWorkflowRoles`. 757 ''' 758 self.workflows = svc.SnapshotWorkflows(client.workflows) 759 ''' 760 Workflows are the collection of rules that define the resources to which access can be requested, 761 the users that can request that access, and the mechanism for approving those requests which can either 762 be automatic approval or a set of users authorized to approve the requests. 763 764 See `strongdm.svc.SnapshotWorkflows`. 765 '''
40class Client: 41 '''Client interacts with the strongDM API.''' 42 def __init__(self, 43 api_access_key, 44 api_secret, 45 host='app.strongdm.com:443', 46 insecure=False, 47 retry_rate_limit_errors=True, 48 page_limit=50): 49 ''' 50 Create a new Client. 51 52 - api_access_key: the access key to authenticate with strongDM 53 - api_secret: the secret key to authenticate with strongDM 54 ''' 55 self.api_access_key = api_access_key.strip() 56 self.api_secret = base64.b64decode(api_secret.strip()) 57 self.max_retries = DEFAULT_MAX_RETRIES 58 self.base_retry_delay = DEFAULT_BASE_RETRY_DELAY 59 self.max_retry_delay = DEFAULT_MAX_RETRY_DELAY 60 self.expose_rate_limit_errors = (not retry_rate_limit_errors) 61 self.snapshot_datetime = None 62 self.page_limit = page_limit 63 64 try: 65 if insecure: 66 channel = grpc.insecure_channel(host) 67 else: 68 creds = grpc.ssl_channel_credentials() 69 channel = grpc.secure_channel(host, creds) 70 except Exception as e: 71 raise plumbing.convert_error_to_porcelain(e) from e 72 self.channel = channel 73 self.access_requests = svc.AccessRequests(channel, self) 74 ''' 75 AccessRequests are requests for access to a resource that may match a Workflow. 76 77 See `strongdm.svc.AccessRequests`. 78 ''' 79 self.access_request_events_history = svc.AccessRequestEventsHistory( 80 channel, self) 81 ''' 82 AccessRequestEventsHistory provides records of all changes to the state of an AccessRequest. 83 84 See `strongdm.svc.AccessRequestEventsHistory`. 85 ''' 86 self.access_requests_history = svc.AccessRequestsHistory(channel, self) 87 ''' 88 AccessRequestsHistory provides records of all changes to the state of an AccessRequest. 89 90 See `strongdm.svc.AccessRequestsHistory`. 91 ''' 92 self.account_attachments = svc.AccountAttachments(channel, self) 93 ''' 94 AccountAttachments assign an account to a role. 95 96 See `strongdm.svc.AccountAttachments`. 97 ''' 98 self.account_attachments_history = svc.AccountAttachmentsHistory( 99 channel, self) 100 ''' 101 AccountAttachmentsHistory records all changes to the state of an AccountAttachment. 102 103 See `strongdm.svc.AccountAttachmentsHistory`. 104 ''' 105 self.account_grants = svc.AccountGrants(channel, self) 106 ''' 107 AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource. 108 109 See `strongdm.svc.AccountGrants`. 110 ''' 111 self.account_grants_history = svc.AccountGrantsHistory(channel, self) 112 ''' 113 AccountGrantsHistory records all changes to the state of an AccountGrant. 114 115 See `strongdm.svc.AccountGrantsHistory`. 116 ''' 117 self.account_permissions = svc.AccountPermissions(channel, self) 118 ''' 119 AccountPermissions records the granular permissions accounts have, allowing them to execute 120 relevant commands via StrongDM's APIs. 121 122 See `strongdm.svc.AccountPermissions`. 123 ''' 124 self.account_resources = svc.AccountResources(channel, self) 125 ''' 126 AccountResources enumerates the resources to which accounts have access. 127 The AccountResources service is read-only. 128 129 See `strongdm.svc.AccountResources`. 130 ''' 131 self.account_resources_history = svc.AccountResourcesHistory( 132 channel, self) 133 ''' 134 AccountResourcesHistory records all changes to the state of a AccountResource. 135 136 See `strongdm.svc.AccountResourcesHistory`. 137 ''' 138 self.accounts = svc.Accounts(channel, self) 139 ''' 140 Accounts are users that have access to strongDM. There are two types of accounts: 141 1. **Users:** humans who are authenticated through username and password or SSO. 142 2. **Service Accounts:** machines that are authenticated using a service token. 143 3. **Tokens** are access keys with permissions that can be used for authentication. 144 145 See `strongdm.svc.Accounts`. 146 ''' 147 self.accounts_history = svc.AccountsHistory(channel, self) 148 ''' 149 AccountsHistory records all changes to the state of an Account. 150 151 See `strongdm.svc.AccountsHistory`. 152 ''' 153 self.activities = svc.Activities(channel, self) 154 ''' 155 An Activity is a record of an action taken against a strongDM deployment, e.g. 156 a user creation, resource deletion, sso configuration change, etc. The Activities 157 service is read-only. 158 159 See `strongdm.svc.Activities`. 160 ''' 161 self.approval_workflow_approvers = svc.ApprovalWorkflowApprovers( 162 channel, self) 163 ''' 164 ApprovalWorkflowApprovers link approval workflow approvers to an ApprovalWorkflowStep 165 166 See `strongdm.svc.ApprovalWorkflowApprovers`. 167 ''' 168 self.approval_workflow_approvers_history = svc.ApprovalWorkflowApproversHistory( 169 channel, self) 170 ''' 171 ApprovalWorkflowApproversHistory records all changes to the state of an ApprovalWorkflowApprover. 172 173 See `strongdm.svc.ApprovalWorkflowApproversHistory`. 174 ''' 175 self.approval_workflow_steps = svc.ApprovalWorkflowSteps(channel, self) 176 ''' 177 ApprovalWorkflowSteps link approval workflow steps to an ApprovalWorkflow 178 179 See `strongdm.svc.ApprovalWorkflowSteps`. 180 ''' 181 self.approval_workflow_steps_history = svc.ApprovalWorkflowStepsHistory( 182 channel, self) 183 ''' 184 ApprovalWorkflowStepsHistory records all changes to the state of an ApprovalWorkflowStep. 185 186 See `strongdm.svc.ApprovalWorkflowStepsHistory`. 187 ''' 188 self.approval_workflows = svc.ApprovalWorkflows(channel, self) 189 ''' 190 ApprovalWorkflows are the mechanism by which requests for access can be viewed by authorized 191 approvers and be approved or denied. 192 193 See `strongdm.svc.ApprovalWorkflows`. 194 ''' 195 self.approval_workflows_history = svc.ApprovalWorkflowsHistory( 196 channel, self) 197 ''' 198 ApprovalWorkflowsHistory records all changes to the state of an ApprovalWorkflow. 199 200 See `strongdm.svc.ApprovalWorkflowsHistory`. 201 ''' 202 self.control_panel = svc.ControlPanel(channel, self) 203 ''' 204 ControlPanel contains all administrative controls. 205 206 See `strongdm.svc.ControlPanel`. 207 ''' 208 self.health_checks = svc.HealthChecks(channel, self) 209 ''' 210 HealthChecks lists the last healthcheck between each node and resource. 211 Note the unconventional capitalization here is to prevent having a collision with GRPC 212 213 See `strongdm.svc.HealthChecks`. 214 ''' 215 self.identity_aliases = svc.IdentityAliases(channel, self) 216 ''' 217 IdentityAliases assign an alias to an account within an IdentitySet. 218 The alias is used as the username when connecting to a identity supported resource. 219 220 See `strongdm.svc.IdentityAliases`. 221 ''' 222 self.identity_aliases_history = svc.IdentityAliasesHistory( 223 channel, self) 224 ''' 225 IdentityAliasesHistory records all changes to the state of a IdentityAlias. 226 227 See `strongdm.svc.IdentityAliasesHistory`. 228 ''' 229 self.identity_sets = svc.IdentitySets(channel, self) 230 ''' 231 A IdentitySet is a named grouping of Identity Aliases for Accounts. 232 An Account's relationship to a IdentitySet is defined via IdentityAlias objects. 233 234 See `strongdm.svc.IdentitySets`. 235 ''' 236 self.identity_sets_history = svc.IdentitySetsHistory(channel, self) 237 ''' 238 IdentitySetsHistory records all changes to the state of a IdentitySet. 239 240 See `strongdm.svc.IdentitySetsHistory`. 241 ''' 242 self.managed_secrets = svc.ManagedSecrets(channel, self) 243 ''' 244 ManagedSecret is a private vertical for creating, reading, updating, 245 deleting, listing and rotating the managed secrets in the secrets engines as 246 an authenticated user. 247 248 See `strongdm.svc.ManagedSecrets`. 249 ''' 250 self.nodes = svc.Nodes(channel, self) 251 ''' 252 Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes: 253 - **Gateways** are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers. 254 - **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. 255 256 See `strongdm.svc.Nodes`. 257 ''' 258 self.nodes_history = svc.NodesHistory(channel, self) 259 ''' 260 NodesHistory records all changes to the state of a Node. 261 262 See `strongdm.svc.NodesHistory`. 263 ''' 264 self.organization_history = svc.OrganizationHistory(channel, self) 265 ''' 266 OrganizationHistory records all changes to the state of an Organization. 267 268 See `strongdm.svc.OrganizationHistory`. 269 ''' 270 self.peering_group_nodes = svc.PeeringGroupNodes(channel, self) 271 ''' 272 PeeringGroupNodes provides the building blocks necessary to obtain attach a node to a peering group. 273 274 See `strongdm.svc.PeeringGroupNodes`. 275 ''' 276 self.peering_group_peers = svc.PeeringGroupPeers(channel, self) 277 ''' 278 PeeringGroupPeers provides the building blocks necessary to link two peering groups. 279 280 See `strongdm.svc.PeeringGroupPeers`. 281 ''' 282 self.peering_group_resources = svc.PeeringGroupResources(channel, self) 283 ''' 284 PeeringGroupResources provides the building blocks necessary to obtain attach a resource to a peering group. 285 286 See `strongdm.svc.PeeringGroupResources`. 287 ''' 288 self.peering_groups = svc.PeeringGroups(channel, self) 289 ''' 290 PeeringGroups provides the building blocks necessary to obtain explicit network topology and routing. 291 292 See `strongdm.svc.PeeringGroups`. 293 ''' 294 self.policies = svc.Policies(channel, self) 295 ''' 296 Policies are the collection of one or more statements that enforce fine-grained access 297 control for the users of an organization. 298 299 See `strongdm.svc.Policies`. 300 ''' 301 self.policies_history = svc.PoliciesHistory(channel, self) 302 ''' 303 PoliciesHistory records all changes to the state of a Policy. 304 305 See `strongdm.svc.PoliciesHistory`. 306 ''' 307 self.proxy_cluster_keys = svc.ProxyClusterKeys(channel, self) 308 ''' 309 Proxy Cluster Keys are authentication keys for all proxies within a cluster. 310 The proxies within a cluster share the same key. One cluster can have 311 multiple keys in order to facilitate key rotation. 312 313 See `strongdm.svc.ProxyClusterKeys`. 314 ''' 315 self.queries = svc.Queries(channel, self) 316 ''' 317 A Query is a record of a single client request to a resource, such as a SQL query. 318 Long-running SSH, RDP, or Kubernetes interactive sessions also count as queries. 319 The Queries service is read-only. 320 321 See `strongdm.svc.Queries`. 322 ''' 323 self.remote_identities = svc.RemoteIdentities(channel, self) 324 ''' 325 RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource. 326 327 See `strongdm.svc.RemoteIdentities`. 328 ''' 329 self.remote_identities_history = svc.RemoteIdentitiesHistory( 330 channel, self) 331 ''' 332 RemoteIdentitiesHistory records all changes to the state of a RemoteIdentity. 333 334 See `strongdm.svc.RemoteIdentitiesHistory`. 335 ''' 336 self.remote_identity_groups = svc.RemoteIdentityGroups(channel, self) 337 ''' 338 A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. 339 An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects. 340 341 See `strongdm.svc.RemoteIdentityGroups`. 342 ''' 343 self.remote_identity_groups_history = svc.RemoteIdentityGroupsHistory( 344 channel, self) 345 ''' 346 RemoteIdentityGroupsHistory records all changes to the state of a RemoteIdentityGroup. 347 348 See `strongdm.svc.RemoteIdentityGroupsHistory`. 349 ''' 350 self.replays = svc.Replays(channel, self) 351 ''' 352 A Replay captures the data transferred over a long-running SSH, RDP, or Kubernetes interactive session 353 (otherwise referred to as a query). The Replays service is read-only. 354 355 See `strongdm.svc.Replays`. 356 ''' 357 self.resources = svc.Resources(channel, self) 358 ''' 359 Resources are databases, servers, clusters, websites, or clouds that strongDM 360 delegates access to. 361 362 See `strongdm.svc.Resources`. 363 ''' 364 self.resources_history = svc.ResourcesHistory(channel, self) 365 ''' 366 ResourcesHistory records all changes to the state of a Resource. 367 368 See `strongdm.svc.ResourcesHistory`. 369 ''' 370 self.role_resources = svc.RoleResources(channel, self) 371 ''' 372 RoleResources enumerates the resources to which roles have access. 373 The RoleResources service is read-only. 374 375 See `strongdm.svc.RoleResources`. 376 ''' 377 self.role_resources_history = svc.RoleResourcesHistory(channel, self) 378 ''' 379 RoleResourcesHistory records all changes to the state of a RoleResource. 380 381 See `strongdm.svc.RoleResourcesHistory`. 382 ''' 383 self.roles = svc.Roles(channel, self) 384 ''' 385 A Role has a list of access rules which determine which Resources the members 386 of the Role have access to. An Account can be a member of multiple Roles via 387 AccountAttachments. 388 389 See `strongdm.svc.Roles`. 390 ''' 391 self.roles_history = svc.RolesHistory(channel, self) 392 ''' 393 RolesHistory records all changes to the state of a Role. 394 395 See `strongdm.svc.RolesHistory`. 396 ''' 397 self.secret_stores = svc.SecretStores(channel, self) 398 ''' 399 SecretStores are servers where resource secrets (passwords, keys) are stored. 400 401 See `strongdm.svc.SecretStores`. 402 ''' 403 self.secret_engines = svc.SecretEngines(channel, self) 404 ''' 405 406 407 See `strongdm.svc.SecretEngines`. 408 ''' 409 self.secret_store_healths = svc.SecretStoreHealths(channel, self) 410 ''' 411 SecretStoreHealths exposes health states for secret stores. 412 413 See `strongdm.svc.SecretStoreHealths`. 414 ''' 415 self.secret_stores_history = svc.SecretStoresHistory(channel, self) 416 ''' 417 SecretStoresHistory records all changes to the state of a SecretStore. 418 419 See `strongdm.svc.SecretStoresHistory`. 420 ''' 421 self.workflow_approvers = svc.WorkflowApprovers(channel, self) 422 ''' 423 WorkflowApprovers is an account or a role with the ability to approve requests bound to a workflow. 424 425 See `strongdm.svc.WorkflowApprovers`. 426 ''' 427 self.workflow_approvers_history = svc.WorkflowApproversHistory( 428 channel, self) 429 ''' 430 WorkflowApproversHistory provides records of all changes to the state of a WorkflowApprover. 431 432 See `strongdm.svc.WorkflowApproversHistory`. 433 ''' 434 self.workflow_assignments = svc.WorkflowAssignments(channel, self) 435 ''' 436 WorkflowAssignments links a Resource to a Workflow. The assigned resources are those that a user can request 437 access to via the workflow. 438 439 See `strongdm.svc.WorkflowAssignments`. 440 ''' 441 self.workflow_assignments_history = svc.WorkflowAssignmentsHistory( 442 channel, self) 443 ''' 444 WorkflowAssignmentsHistory provides records of all changes to the state of a WorkflowAssignment. 445 446 See `strongdm.svc.WorkflowAssignmentsHistory`. 447 ''' 448 self.workflow_roles = svc.WorkflowRoles(channel, self) 449 ''' 450 WorkflowRole links a role to a workflow. The linked roles indicate which roles a user must be a part of 451 to request access to a resource via the workflow. 452 453 See `strongdm.svc.WorkflowRoles`. 454 ''' 455 self.workflow_roles_history = svc.WorkflowRolesHistory(channel, self) 456 ''' 457 WorkflowRolesHistory provides records of all changes to the state of a WorkflowRole 458 459 See `strongdm.svc.WorkflowRolesHistory`. 460 ''' 461 self.workflows = svc.Workflows(channel, self) 462 ''' 463 Workflows are the collection of rules that define the resources to which access can be requested, 464 the users that can request that access, and the mechanism for approving those requests which can either 465 be automatic approval or a set of users authorized to approve the requests. 466 467 See `strongdm.svc.Workflows`. 468 ''' 469 self.workflows_history = svc.WorkflowsHistory(channel, self) 470 ''' 471 WorkflowsHistory provides records of all changes to the state of a Workflow. 472 473 See `strongdm.svc.WorkflowsHistory`. 474 ''' 475 476 def close(self): 477 '''Closes this Client and releases all resources held by it. 478 479 Closing the Client will immediately terminate all RPCs active with the 480 Client and it is not valid to invoke new RPCs with the Client. 481 482 This method is idempotent. 483 ''' 484 self.channel.close() 485 486 def get_metadata(self, method_name, req): 487 return [ 488 ('x-sdm-authentication', self.api_access_key), 489 ('x-sdm-signature', self.sign(method_name, 490 req.SerializeToString())), 491 ('x-sdm-api-version', API_VERSION), 492 ('x-sdm-user-agent', USER_AGENT), 493 ] 494 495 def sign(self, method_name, request_bytes): 496 def hmac_digest(key, msg_byte_string): 497 return hmac.new(key, msg=msg_byte_string, 498 digestmod=hashlib.sha256).digest() 499 500 current_utc_date = datetime.datetime.now( 501 datetime.timezone.utc).strftime('%Y-%m-%d') 502 signing_key = hmac_digest(self.api_secret, current_utc_date.encode()) 503 signing_key = hmac_digest(signing_key, b'sdm_api_v1') 504 505 hash = hashlib.sha256() 506 507 hash.update(method_name.encode()) 508 hash.update(b'\n') 509 hash.update(request_bytes) 510 511 return base64.b64encode(hmac_digest(signing_key, hash.digest())) 512 513 def jitterSleep(self, iter): 514 dur_max = self.base_retry_delay * 2**iter 515 if (dur_max > self.max_retry_delay): 516 dur_max = self.max_retry_delay 517 # get a value between 0 and max 518 dur = random.random() * dur_max 519 time.sleep(dur) 520 521 def shouldRetry(self, iter, err): 522 if (iter >= self.max_retries - 1): 523 return False 524 if not isinstance(err, grpc.RpcError): 525 return True 526 porcelain_err = plumbing.convert_error_to_porcelain(err) 527 if (not self.expose_rate_limit_errors) and isinstance( 528 porcelain_err, errors.RateLimitError): 529 wait_until = porcelain_err.rate_limit.reset_at 530 now = datetime.datetime.now(datetime.timezone.utc) 531 sleep_for = (wait_until - now).total_seconds() 532 # If timezones or clock drift causes this calculation to fail, 533 # wait at most one minute. 534 if sleep_for < 0 or sleep_for > 60: 535 sleep_for = 60 536 time.sleep(sleep_for) 537 return True 538 return err.code() == grpc.StatusCode.INTERNAL or err.code( 539 ) == grpc.StatusCode.UNAVAILABLE 540 541 def snapshot_at(self, snapshot_datetime): 542 ''' 543 Constructs a read-only client that will provide historical data from the provided timestamp. 544 545 See `SnapshotClient`. 546 ''' 547 client = copy.copy(self) 548 client.snapshot_datetime = snapshot_datetime 549 client.access_requests = svc.AccessRequests(client.channel, client) 550 client.account_attachments = svc.AccountAttachments( 551 client.channel, client) 552 client.account_grants = svc.AccountGrants(client.channel, client) 553 client.account_permissions = svc.AccountPermissions( 554 client.channel, client) 555 client.account_resources = svc.AccountResources(client.channel, client) 556 client.accounts = svc.Accounts(client.channel, client) 557 client.approval_workflow_approvers = svc.ApprovalWorkflowApprovers( 558 client.channel, client) 559 client.approval_workflow_steps = svc.ApprovalWorkflowSteps( 560 client.channel, client) 561 client.approval_workflows = svc.ApprovalWorkflows( 562 client.channel, client) 563 client.identity_aliases = svc.IdentityAliases(client.channel, client) 564 client.identity_sets = svc.IdentitySets(client.channel, client) 565 client.nodes = svc.Nodes(client.channel, client) 566 client.policies = svc.Policies(client.channel, client) 567 client.proxy_cluster_keys = svc.ProxyClusterKeys( 568 client.channel, client) 569 client.remote_identities = svc.RemoteIdentities(client.channel, client) 570 client.remote_identity_groups = svc.RemoteIdentityGroups( 571 client.channel, client) 572 client.resources = svc.Resources(client.channel, client) 573 client.role_resources = svc.RoleResources(client.channel, client) 574 client.roles = svc.Roles(client.channel, client) 575 client.secret_stores = svc.SecretStores(client.channel, client) 576 client.workflow_approvers = svc.WorkflowApprovers( 577 client.channel, client) 578 client.workflow_assignments = svc.WorkflowAssignments( 579 client.channel, client) 580 client.workflow_roles = svc.WorkflowRoles(client.channel, client) 581 client.workflows = svc.Workflows(client.channel, client) 582 return SnapshotClient(client)
Client interacts with the strongDM API.
42 def __init__(self, 43 api_access_key, 44 api_secret, 45 host='app.strongdm.com:443', 46 insecure=False, 47 retry_rate_limit_errors=True, 48 page_limit=50): 49 ''' 50 Create a new Client. 51 52 - api_access_key: the access key to authenticate with strongDM 53 - api_secret: the secret key to authenticate with strongDM 54 ''' 55 self.api_access_key = api_access_key.strip() 56 self.api_secret = base64.b64decode(api_secret.strip()) 57 self.max_retries = DEFAULT_MAX_RETRIES 58 self.base_retry_delay = DEFAULT_BASE_RETRY_DELAY 59 self.max_retry_delay = DEFAULT_MAX_RETRY_DELAY 60 self.expose_rate_limit_errors = (not retry_rate_limit_errors) 61 self.snapshot_datetime = None 62 self.page_limit = page_limit 63 64 try: 65 if insecure: 66 channel = grpc.insecure_channel(host) 67 else: 68 creds = grpc.ssl_channel_credentials() 69 channel = grpc.secure_channel(host, creds) 70 except Exception as e: 71 raise plumbing.convert_error_to_porcelain(e) from e 72 self.channel = channel 73 self.access_requests = svc.AccessRequests(channel, self) 74 ''' 75 AccessRequests are requests for access to a resource that may match a Workflow. 76 77 See `strongdm.svc.AccessRequests`. 78 ''' 79 self.access_request_events_history = svc.AccessRequestEventsHistory( 80 channel, self) 81 ''' 82 AccessRequestEventsHistory provides records of all changes to the state of an AccessRequest. 83 84 See `strongdm.svc.AccessRequestEventsHistory`. 85 ''' 86 self.access_requests_history = svc.AccessRequestsHistory(channel, self) 87 ''' 88 AccessRequestsHistory provides records of all changes to the state of an AccessRequest. 89 90 See `strongdm.svc.AccessRequestsHistory`. 91 ''' 92 self.account_attachments = svc.AccountAttachments(channel, self) 93 ''' 94 AccountAttachments assign an account to a role. 95 96 See `strongdm.svc.AccountAttachments`. 97 ''' 98 self.account_attachments_history = svc.AccountAttachmentsHistory( 99 channel, self) 100 ''' 101 AccountAttachmentsHistory records all changes to the state of an AccountAttachment. 102 103 See `strongdm.svc.AccountAttachmentsHistory`. 104 ''' 105 self.account_grants = svc.AccountGrants(channel, self) 106 ''' 107 AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource. 108 109 See `strongdm.svc.AccountGrants`. 110 ''' 111 self.account_grants_history = svc.AccountGrantsHistory(channel, self) 112 ''' 113 AccountGrantsHistory records all changes to the state of an AccountGrant. 114 115 See `strongdm.svc.AccountGrantsHistory`. 116 ''' 117 self.account_permissions = svc.AccountPermissions(channel, self) 118 ''' 119 AccountPermissions records the granular permissions accounts have, allowing them to execute 120 relevant commands via StrongDM's APIs. 121 122 See `strongdm.svc.AccountPermissions`. 123 ''' 124 self.account_resources = svc.AccountResources(channel, self) 125 ''' 126 AccountResources enumerates the resources to which accounts have access. 127 The AccountResources service is read-only. 128 129 See `strongdm.svc.AccountResources`. 130 ''' 131 self.account_resources_history = svc.AccountResourcesHistory( 132 channel, self) 133 ''' 134 AccountResourcesHistory records all changes to the state of a AccountResource. 135 136 See `strongdm.svc.AccountResourcesHistory`. 137 ''' 138 self.accounts = svc.Accounts(channel, self) 139 ''' 140 Accounts are users that have access to strongDM. There are two types of accounts: 141 1. **Users:** humans who are authenticated through username and password or SSO. 142 2. **Service Accounts:** machines that are authenticated using a service token. 143 3. **Tokens** are access keys with permissions that can be used for authentication. 144 145 See `strongdm.svc.Accounts`. 146 ''' 147 self.accounts_history = svc.AccountsHistory(channel, self) 148 ''' 149 AccountsHistory records all changes to the state of an Account. 150 151 See `strongdm.svc.AccountsHistory`. 152 ''' 153 self.activities = svc.Activities(channel, self) 154 ''' 155 An Activity is a record of an action taken against a strongDM deployment, e.g. 156 a user creation, resource deletion, sso configuration change, etc. The Activities 157 service is read-only. 158 159 See `strongdm.svc.Activities`. 160 ''' 161 self.approval_workflow_approvers = svc.ApprovalWorkflowApprovers( 162 channel, self) 163 ''' 164 ApprovalWorkflowApprovers link approval workflow approvers to an ApprovalWorkflowStep 165 166 See `strongdm.svc.ApprovalWorkflowApprovers`. 167 ''' 168 self.approval_workflow_approvers_history = svc.ApprovalWorkflowApproversHistory( 169 channel, self) 170 ''' 171 ApprovalWorkflowApproversHistory records all changes to the state of an ApprovalWorkflowApprover. 172 173 See `strongdm.svc.ApprovalWorkflowApproversHistory`. 174 ''' 175 self.approval_workflow_steps = svc.ApprovalWorkflowSteps(channel, self) 176 ''' 177 ApprovalWorkflowSteps link approval workflow steps to an ApprovalWorkflow 178 179 See `strongdm.svc.ApprovalWorkflowSteps`. 180 ''' 181 self.approval_workflow_steps_history = svc.ApprovalWorkflowStepsHistory( 182 channel, self) 183 ''' 184 ApprovalWorkflowStepsHistory records all changes to the state of an ApprovalWorkflowStep. 185 186 See `strongdm.svc.ApprovalWorkflowStepsHistory`. 187 ''' 188 self.approval_workflows = svc.ApprovalWorkflows(channel, self) 189 ''' 190 ApprovalWorkflows are the mechanism by which requests for access can be viewed by authorized 191 approvers and be approved or denied. 192 193 See `strongdm.svc.ApprovalWorkflows`. 194 ''' 195 self.approval_workflows_history = svc.ApprovalWorkflowsHistory( 196 channel, self) 197 ''' 198 ApprovalWorkflowsHistory records all changes to the state of an ApprovalWorkflow. 199 200 See `strongdm.svc.ApprovalWorkflowsHistory`. 201 ''' 202 self.control_panel = svc.ControlPanel(channel, self) 203 ''' 204 ControlPanel contains all administrative controls. 205 206 See `strongdm.svc.ControlPanel`. 207 ''' 208 self.health_checks = svc.HealthChecks(channel, self) 209 ''' 210 HealthChecks lists the last healthcheck between each node and resource. 211 Note the unconventional capitalization here is to prevent having a collision with GRPC 212 213 See `strongdm.svc.HealthChecks`. 214 ''' 215 self.identity_aliases = svc.IdentityAliases(channel, self) 216 ''' 217 IdentityAliases assign an alias to an account within an IdentitySet. 218 The alias is used as the username when connecting to a identity supported resource. 219 220 See `strongdm.svc.IdentityAliases`. 221 ''' 222 self.identity_aliases_history = svc.IdentityAliasesHistory( 223 channel, self) 224 ''' 225 IdentityAliasesHistory records all changes to the state of a IdentityAlias. 226 227 See `strongdm.svc.IdentityAliasesHistory`. 228 ''' 229 self.identity_sets = svc.IdentitySets(channel, self) 230 ''' 231 A IdentitySet is a named grouping of Identity Aliases for Accounts. 232 An Account's relationship to a IdentitySet is defined via IdentityAlias objects. 233 234 See `strongdm.svc.IdentitySets`. 235 ''' 236 self.identity_sets_history = svc.IdentitySetsHistory(channel, self) 237 ''' 238 IdentitySetsHistory records all changes to the state of a IdentitySet. 239 240 See `strongdm.svc.IdentitySetsHistory`. 241 ''' 242 self.managed_secrets = svc.ManagedSecrets(channel, self) 243 ''' 244 ManagedSecret is a private vertical for creating, reading, updating, 245 deleting, listing and rotating the managed secrets in the secrets engines as 246 an authenticated user. 247 248 See `strongdm.svc.ManagedSecrets`. 249 ''' 250 self.nodes = svc.Nodes(channel, self) 251 ''' 252 Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes: 253 - **Gateways** are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers. 254 - **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. 255 256 See `strongdm.svc.Nodes`. 257 ''' 258 self.nodes_history = svc.NodesHistory(channel, self) 259 ''' 260 NodesHistory records all changes to the state of a Node. 261 262 See `strongdm.svc.NodesHistory`. 263 ''' 264 self.organization_history = svc.OrganizationHistory(channel, self) 265 ''' 266 OrganizationHistory records all changes to the state of an Organization. 267 268 See `strongdm.svc.OrganizationHistory`. 269 ''' 270 self.peering_group_nodes = svc.PeeringGroupNodes(channel, self) 271 ''' 272 PeeringGroupNodes provides the building blocks necessary to obtain attach a node to a peering group. 273 274 See `strongdm.svc.PeeringGroupNodes`. 275 ''' 276 self.peering_group_peers = svc.PeeringGroupPeers(channel, self) 277 ''' 278 PeeringGroupPeers provides the building blocks necessary to link two peering groups. 279 280 See `strongdm.svc.PeeringGroupPeers`. 281 ''' 282 self.peering_group_resources = svc.PeeringGroupResources(channel, self) 283 ''' 284 PeeringGroupResources provides the building blocks necessary to obtain attach a resource to a peering group. 285 286 See `strongdm.svc.PeeringGroupResources`. 287 ''' 288 self.peering_groups = svc.PeeringGroups(channel, self) 289 ''' 290 PeeringGroups provides the building blocks necessary to obtain explicit network topology and routing. 291 292 See `strongdm.svc.PeeringGroups`. 293 ''' 294 self.policies = svc.Policies(channel, self) 295 ''' 296 Policies are the collection of one or more statements that enforce fine-grained access 297 control for the users of an organization. 298 299 See `strongdm.svc.Policies`. 300 ''' 301 self.policies_history = svc.PoliciesHistory(channel, self) 302 ''' 303 PoliciesHistory records all changes to the state of a Policy. 304 305 See `strongdm.svc.PoliciesHistory`. 306 ''' 307 self.proxy_cluster_keys = svc.ProxyClusterKeys(channel, self) 308 ''' 309 Proxy Cluster Keys are authentication keys for all proxies within a cluster. 310 The proxies within a cluster share the same key. One cluster can have 311 multiple keys in order to facilitate key rotation. 312 313 See `strongdm.svc.ProxyClusterKeys`. 314 ''' 315 self.queries = svc.Queries(channel, self) 316 ''' 317 A Query is a record of a single client request to a resource, such as a SQL query. 318 Long-running SSH, RDP, or Kubernetes interactive sessions also count as queries. 319 The Queries service is read-only. 320 321 See `strongdm.svc.Queries`. 322 ''' 323 self.remote_identities = svc.RemoteIdentities(channel, self) 324 ''' 325 RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource. 326 327 See `strongdm.svc.RemoteIdentities`. 328 ''' 329 self.remote_identities_history = svc.RemoteIdentitiesHistory( 330 channel, self) 331 ''' 332 RemoteIdentitiesHistory records all changes to the state of a RemoteIdentity. 333 334 See `strongdm.svc.RemoteIdentitiesHistory`. 335 ''' 336 self.remote_identity_groups = svc.RemoteIdentityGroups(channel, self) 337 ''' 338 A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. 339 An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects. 340 341 See `strongdm.svc.RemoteIdentityGroups`. 342 ''' 343 self.remote_identity_groups_history = svc.RemoteIdentityGroupsHistory( 344 channel, self) 345 ''' 346 RemoteIdentityGroupsHistory records all changes to the state of a RemoteIdentityGroup. 347 348 See `strongdm.svc.RemoteIdentityGroupsHistory`. 349 ''' 350 self.replays = svc.Replays(channel, self) 351 ''' 352 A Replay captures the data transferred over a long-running SSH, RDP, or Kubernetes interactive session 353 (otherwise referred to as a query). The Replays service is read-only. 354 355 See `strongdm.svc.Replays`. 356 ''' 357 self.resources = svc.Resources(channel, self) 358 ''' 359 Resources are databases, servers, clusters, websites, or clouds that strongDM 360 delegates access to. 361 362 See `strongdm.svc.Resources`. 363 ''' 364 self.resources_history = svc.ResourcesHistory(channel, self) 365 ''' 366 ResourcesHistory records all changes to the state of a Resource. 367 368 See `strongdm.svc.ResourcesHistory`. 369 ''' 370 self.role_resources = svc.RoleResources(channel, self) 371 ''' 372 RoleResources enumerates the resources to which roles have access. 373 The RoleResources service is read-only. 374 375 See `strongdm.svc.RoleResources`. 376 ''' 377 self.role_resources_history = svc.RoleResourcesHistory(channel, self) 378 ''' 379 RoleResourcesHistory records all changes to the state of a RoleResource. 380 381 See `strongdm.svc.RoleResourcesHistory`. 382 ''' 383 self.roles = svc.Roles(channel, self) 384 ''' 385 A Role has a list of access rules which determine which Resources the members 386 of the Role have access to. An Account can be a member of multiple Roles via 387 AccountAttachments. 388 389 See `strongdm.svc.Roles`. 390 ''' 391 self.roles_history = svc.RolesHistory(channel, self) 392 ''' 393 RolesHistory records all changes to the state of a Role. 394 395 See `strongdm.svc.RolesHistory`. 396 ''' 397 self.secret_stores = svc.SecretStores(channel, self) 398 ''' 399 SecretStores are servers where resource secrets (passwords, keys) are stored. 400 401 See `strongdm.svc.SecretStores`. 402 ''' 403 self.secret_engines = svc.SecretEngines(channel, self) 404 ''' 405 406 407 See `strongdm.svc.SecretEngines`. 408 ''' 409 self.secret_store_healths = svc.SecretStoreHealths(channel, self) 410 ''' 411 SecretStoreHealths exposes health states for secret stores. 412 413 See `strongdm.svc.SecretStoreHealths`. 414 ''' 415 self.secret_stores_history = svc.SecretStoresHistory(channel, self) 416 ''' 417 SecretStoresHistory records all changes to the state of a SecretStore. 418 419 See `strongdm.svc.SecretStoresHistory`. 420 ''' 421 self.workflow_approvers = svc.WorkflowApprovers(channel, self) 422 ''' 423 WorkflowApprovers is an account or a role with the ability to approve requests bound to a workflow. 424 425 See `strongdm.svc.WorkflowApprovers`. 426 ''' 427 self.workflow_approvers_history = svc.WorkflowApproversHistory( 428 channel, self) 429 ''' 430 WorkflowApproversHistory provides records of all changes to the state of a WorkflowApprover. 431 432 See `strongdm.svc.WorkflowApproversHistory`. 433 ''' 434 self.workflow_assignments = svc.WorkflowAssignments(channel, self) 435 ''' 436 WorkflowAssignments links a Resource to a Workflow. The assigned resources are those that a user can request 437 access to via the workflow. 438 439 See `strongdm.svc.WorkflowAssignments`. 440 ''' 441 self.workflow_assignments_history = svc.WorkflowAssignmentsHistory( 442 channel, self) 443 ''' 444 WorkflowAssignmentsHistory provides records of all changes to the state of a WorkflowAssignment. 445 446 See `strongdm.svc.WorkflowAssignmentsHistory`. 447 ''' 448 self.workflow_roles = svc.WorkflowRoles(channel, self) 449 ''' 450 WorkflowRole links a role to a workflow. The linked roles indicate which roles a user must be a part of 451 to request access to a resource via the workflow. 452 453 See `strongdm.svc.WorkflowRoles`. 454 ''' 455 self.workflow_roles_history = svc.WorkflowRolesHistory(channel, self) 456 ''' 457 WorkflowRolesHistory provides records of all changes to the state of a WorkflowRole 458 459 See `strongdm.svc.WorkflowRolesHistory`. 460 ''' 461 self.workflows = svc.Workflows(channel, self) 462 ''' 463 Workflows are the collection of rules that define the resources to which access can be requested, 464 the users that can request that access, and the mechanism for approving those requests which can either 465 be automatic approval or a set of users authorized to approve the requests. 466 467 See `strongdm.svc.Workflows`. 468 ''' 469 self.workflows_history = svc.WorkflowsHistory(channel, self) 470 ''' 471 WorkflowsHistory provides records of all changes to the state of a Workflow. 472 473 See `strongdm.svc.WorkflowsHistory`. 474 '''
Create a new Client.
- api_access_key: the access key to authenticate with strongDM
- api_secret: the secret key to authenticate with strongDM
AccessRequestEventsHistory provides records of all changes to the state of an AccessRequest.
AccessRequestsHistory provides records of all changes to the state of an AccessRequest.
AccountAttachmentsHistory records all changes to the state of an AccountAttachment.
AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource.
AccountPermissions records the granular permissions accounts have, allowing them to execute relevant commands via StrongDM's APIs.
AccountResources enumerates the resources to which accounts have access. The AccountResources service is read-only.
AccountResourcesHistory records all changes to the state of a AccountResource.
Accounts are users that have access to strongDM. There are two types of accounts:
- Users: humans who are authenticated through username and password or SSO.
- Service Accounts: machines that are authenticated using a service token.
- Tokens are access keys with permissions that can be used for authentication.
An Activity is a record of an action taken against a strongDM deployment, e.g. a user creation, resource deletion, sso configuration change, etc. The Activities service is read-only.
ApprovalWorkflowApprovers link approval workflow approvers to an ApprovalWorkflowStep
ApprovalWorkflowApproversHistory records all changes to the state of an ApprovalWorkflowApprover.
ApprovalWorkflowStepsHistory records all changes to the state of an ApprovalWorkflowStep.
ApprovalWorkflows are the mechanism by which requests for access can be viewed by authorized approvers and be approved or denied.
ApprovalWorkflowsHistory records all changes to the state of an ApprovalWorkflow.
HealthChecks lists the last healthcheck between each node and resource. Note the unconventional capitalization here is to prevent having a collision with GRPC
IdentityAliases assign an alias to an account within an IdentitySet. The alias is used as the username when connecting to a identity supported resource.
IdentityAliasesHistory records all changes to the state of a IdentityAlias.
A IdentitySet is a named grouping of Identity Aliases for Accounts. An Account's relationship to a IdentitySet is defined via IdentityAlias objects.
ManagedSecret is a private vertical for creating, reading, updating, deleting, listing and rotating the managed secrets in the secrets engines as an authenticated user.
Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes:
- Gateways are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers.
- 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.
See strongdm.svc.Nodes
.
PeeringGroupNodes provides the building blocks necessary to obtain attach a node to a peering group.
PeeringGroupPeers provides the building blocks necessary to link two peering groups.
PeeringGroupResources provides the building blocks necessary to obtain attach a resource to a peering group.
PeeringGroups provides the building blocks necessary to obtain explicit network topology and routing.
Policies are the collection of one or more statements that enforce fine-grained access control for the users of an organization.
Proxy Cluster Keys are authentication keys for all proxies within a cluster. The proxies within a cluster share the same key. One cluster can have multiple keys in order to facilitate key rotation.
A Query is a record of a single client request to a resource, such as a SQL query. Long-running SSH, RDP, or Kubernetes interactive sessions also count as queries. The Queries service is read-only.
See strongdm.svc.Queries
.
RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource.
RemoteIdentitiesHistory records all changes to the state of a RemoteIdentity.
A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects.
RemoteIdentityGroupsHistory records all changes to the state of a RemoteIdentityGroup.
A Replay captures the data transferred over a long-running SSH, RDP, or Kubernetes interactive session (otherwise referred to as a query). The Replays service is read-only.
See strongdm.svc.Replays
.
Resources are databases, servers, clusters, websites, or clouds that strongDM delegates access to.
RoleResources enumerates the resources to which roles have access. The RoleResources service is read-only.
A Role has a list of access rules which determine which Resources the members of the Role have access to. An Account can be a member of multiple Roles via AccountAttachments.
See strongdm.svc.Roles
.
WorkflowApprovers is an account or a role with the ability to approve requests bound to a workflow.
WorkflowApproversHistory provides records of all changes to the state of a WorkflowApprover.
WorkflowAssignments links a Resource to a Workflow. The assigned resources are those that a user can request access to via the workflow.
WorkflowAssignmentsHistory provides records of all changes to the state of a WorkflowAssignment.
WorkflowRole links a role to a workflow. The linked roles indicate which roles a user must be a part of to request access to a resource via the workflow.
WorkflowRolesHistory provides records of all changes to the state of a WorkflowRole
Workflows are the collection of rules that define the resources to which access can be requested, the users that can request that access, and the mechanism for approving those requests which can either be automatic approval or a set of users authorized to approve the requests.
476 def close(self): 477 '''Closes this Client and releases all resources held by it. 478 479 Closing the Client will immediately terminate all RPCs active with the 480 Client and it is not valid to invoke new RPCs with the Client. 481 482 This method is idempotent. 483 ''' 484 self.channel.close()
Closes this Client and releases all resources held by it.
Closing the Client will immediately terminate all RPCs active with the Client and it is not valid to invoke new RPCs with the Client.
This method is idempotent.
495 def sign(self, method_name, request_bytes): 496 def hmac_digest(key, msg_byte_string): 497 return hmac.new(key, msg=msg_byte_string, 498 digestmod=hashlib.sha256).digest() 499 500 current_utc_date = datetime.datetime.now( 501 datetime.timezone.utc).strftime('%Y-%m-%d') 502 signing_key = hmac_digest(self.api_secret, current_utc_date.encode()) 503 signing_key = hmac_digest(signing_key, b'sdm_api_v1') 504 505 hash = hashlib.sha256() 506 507 hash.update(method_name.encode()) 508 hash.update(b'\n') 509 hash.update(request_bytes) 510 511 return base64.b64encode(hmac_digest(signing_key, hash.digest()))
521 def shouldRetry(self, iter, err): 522 if (iter >= self.max_retries - 1): 523 return False 524 if not isinstance(err, grpc.RpcError): 525 return True 526 porcelain_err = plumbing.convert_error_to_porcelain(err) 527 if (not self.expose_rate_limit_errors) and isinstance( 528 porcelain_err, errors.RateLimitError): 529 wait_until = porcelain_err.rate_limit.reset_at 530 now = datetime.datetime.now(datetime.timezone.utc) 531 sleep_for = (wait_until - now).total_seconds() 532 # If timezones or clock drift causes this calculation to fail, 533 # wait at most one minute. 534 if sleep_for < 0 or sleep_for > 60: 535 sleep_for = 60 536 time.sleep(sleep_for) 537 return True 538 return err.code() == grpc.StatusCode.INTERNAL or err.code( 539 ) == grpc.StatusCode.UNAVAILABLE
541 def snapshot_at(self, snapshot_datetime): 542 ''' 543 Constructs a read-only client that will provide historical data from the provided timestamp. 544 545 See `SnapshotClient`. 546 ''' 547 client = copy.copy(self) 548 client.snapshot_datetime = snapshot_datetime 549 client.access_requests = svc.AccessRequests(client.channel, client) 550 client.account_attachments = svc.AccountAttachments( 551 client.channel, client) 552 client.account_grants = svc.AccountGrants(client.channel, client) 553 client.account_permissions = svc.AccountPermissions( 554 client.channel, client) 555 client.account_resources = svc.AccountResources(client.channel, client) 556 client.accounts = svc.Accounts(client.channel, client) 557 client.approval_workflow_approvers = svc.ApprovalWorkflowApprovers( 558 client.channel, client) 559 client.approval_workflow_steps = svc.ApprovalWorkflowSteps( 560 client.channel, client) 561 client.approval_workflows = svc.ApprovalWorkflows( 562 client.channel, client) 563 client.identity_aliases = svc.IdentityAliases(client.channel, client) 564 client.identity_sets = svc.IdentitySets(client.channel, client) 565 client.nodes = svc.Nodes(client.channel, client) 566 client.policies = svc.Policies(client.channel, client) 567 client.proxy_cluster_keys = svc.ProxyClusterKeys( 568 client.channel, client) 569 client.remote_identities = svc.RemoteIdentities(client.channel, client) 570 client.remote_identity_groups = svc.RemoteIdentityGroups( 571 client.channel, client) 572 client.resources = svc.Resources(client.channel, client) 573 client.role_resources = svc.RoleResources(client.channel, client) 574 client.roles = svc.Roles(client.channel, client) 575 client.secret_stores = svc.SecretStores(client.channel, client) 576 client.workflow_approvers = svc.WorkflowApprovers( 577 client.channel, client) 578 client.workflow_assignments = svc.WorkflowAssignments( 579 client.channel, client) 580 client.workflow_roles = svc.WorkflowRoles(client.channel, client) 581 client.workflows = svc.Workflows(client.channel, client) 582 return SnapshotClient(client)
Constructs a read-only client that will provide historical data from the provided timestamp.
See SnapshotClient
.
585class SnapshotClient: 586 '''SnapshotClient exposes methods to query historical records at a provided timestamp.''' 587 def __init__(self, client): 588 self.access_requests = svc.SnapshotAccessRequests( 589 client.access_requests) 590 ''' 591 AccessRequests are requests for access to a resource that may match a Workflow. 592 593 See `strongdm.svc.SnapshotAccessRequests`. 594 ''' 595 self.account_attachments = svc.SnapshotAccountAttachments( 596 client.account_attachments) 597 ''' 598 AccountAttachments assign an account to a role. 599 600 See `strongdm.svc.SnapshotAccountAttachments`. 601 ''' 602 self.account_grants = svc.SnapshotAccountGrants(client.account_grants) 603 ''' 604 AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource. 605 606 See `strongdm.svc.SnapshotAccountGrants`. 607 ''' 608 self.account_permissions = svc.SnapshotAccountPermissions( 609 client.account_permissions) 610 ''' 611 AccountPermissions records the granular permissions accounts have, allowing them to execute 612 relevant commands via StrongDM's APIs. 613 614 See `strongdm.svc.SnapshotAccountPermissions`. 615 ''' 616 self.account_resources = svc.SnapshotAccountResources( 617 client.account_resources) 618 ''' 619 AccountResources enumerates the resources to which accounts have access. 620 The AccountResources service is read-only. 621 622 See `strongdm.svc.SnapshotAccountResources`. 623 ''' 624 self.accounts = svc.SnapshotAccounts(client.accounts) 625 ''' 626 Accounts are users that have access to strongDM. There are two types of accounts: 627 1. **Users:** humans who are authenticated through username and password or SSO. 628 2. **Service Accounts:** machines that are authenticated using a service token. 629 3. **Tokens** are access keys with permissions that can be used for authentication. 630 631 See `strongdm.svc.SnapshotAccounts`. 632 ''' 633 self.approval_workflow_approvers = svc.SnapshotApprovalWorkflowApprovers( 634 client.approval_workflow_approvers) 635 ''' 636 ApprovalWorkflowApprovers link approval workflow approvers to an ApprovalWorkflowStep 637 638 See `strongdm.svc.SnapshotApprovalWorkflowApprovers`. 639 ''' 640 self.approval_workflow_steps = svc.SnapshotApprovalWorkflowSteps( 641 client.approval_workflow_steps) 642 ''' 643 ApprovalWorkflowSteps link approval workflow steps to an ApprovalWorkflow 644 645 See `strongdm.svc.SnapshotApprovalWorkflowSteps`. 646 ''' 647 self.approval_workflows = svc.SnapshotApprovalWorkflows( 648 client.approval_workflows) 649 ''' 650 ApprovalWorkflows are the mechanism by which requests for access can be viewed by authorized 651 approvers and be approved or denied. 652 653 See `strongdm.svc.SnapshotApprovalWorkflows`. 654 ''' 655 self.identity_aliases = svc.SnapshotIdentityAliases( 656 client.identity_aliases) 657 ''' 658 IdentityAliases assign an alias to an account within an IdentitySet. 659 The alias is used as the username when connecting to a identity supported resource. 660 661 See `strongdm.svc.SnapshotIdentityAliases`. 662 ''' 663 self.identity_sets = svc.SnapshotIdentitySets(client.identity_sets) 664 ''' 665 A IdentitySet is a named grouping of Identity Aliases for Accounts. 666 An Account's relationship to a IdentitySet is defined via IdentityAlias objects. 667 668 See `strongdm.svc.SnapshotIdentitySets`. 669 ''' 670 self.nodes = svc.SnapshotNodes(client.nodes) 671 ''' 672 Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes: 673 - **Gateways** are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers. 674 - **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. 675 676 See `strongdm.svc.SnapshotNodes`. 677 ''' 678 self.policies = svc.SnapshotPolicies(client.policies) 679 ''' 680 Policies are the collection of one or more statements that enforce fine-grained access 681 control for the users of an organization. 682 683 See `strongdm.svc.SnapshotPolicies`. 684 ''' 685 self.proxy_cluster_keys = svc.SnapshotProxyClusterKeys( 686 client.proxy_cluster_keys) 687 ''' 688 Proxy Cluster Keys are authentication keys for all proxies within a cluster. 689 The proxies within a cluster share the same key. One cluster can have 690 multiple keys in order to facilitate key rotation. 691 692 See `strongdm.svc.SnapshotProxyClusterKeys`. 693 ''' 694 self.remote_identities = svc.SnapshotRemoteIdentities( 695 client.remote_identities) 696 ''' 697 RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource. 698 699 See `strongdm.svc.SnapshotRemoteIdentities`. 700 ''' 701 self.remote_identity_groups = svc.SnapshotRemoteIdentityGroups( 702 client.remote_identity_groups) 703 ''' 704 A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. 705 An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects. 706 707 See `strongdm.svc.SnapshotRemoteIdentityGroups`. 708 ''' 709 self.resources = svc.SnapshotResources(client.resources) 710 ''' 711 Resources are databases, servers, clusters, websites, or clouds that strongDM 712 delegates access to. 713 714 See `strongdm.svc.SnapshotResources`. 715 ''' 716 self.role_resources = svc.SnapshotRoleResources(client.role_resources) 717 ''' 718 RoleResources enumerates the resources to which roles have access. 719 The RoleResources service is read-only. 720 721 See `strongdm.svc.SnapshotRoleResources`. 722 ''' 723 self.roles = svc.SnapshotRoles(client.roles) 724 ''' 725 A Role has a list of access rules which determine which Resources the members 726 of the Role have access to. An Account can be a member of multiple Roles via 727 AccountAttachments. 728 729 See `strongdm.svc.SnapshotRoles`. 730 ''' 731 self.secret_stores = svc.SnapshotSecretStores(client.secret_stores) 732 ''' 733 SecretStores are servers where resource secrets (passwords, keys) are stored. 734 735 See `strongdm.svc.SnapshotSecretStores`. 736 ''' 737 self.workflow_approvers = svc.SnapshotWorkflowApprovers( 738 client.workflow_approvers) 739 ''' 740 WorkflowApprovers is an account or a role with the ability to approve requests bound to a workflow. 741 742 See `strongdm.svc.SnapshotWorkflowApprovers`. 743 ''' 744 self.workflow_assignments = svc.SnapshotWorkflowAssignments( 745 client.workflow_assignments) 746 ''' 747 WorkflowAssignments links a Resource to a Workflow. The assigned resources are those that a user can request 748 access to via the workflow. 749 750 See `strongdm.svc.SnapshotWorkflowAssignments`. 751 ''' 752 self.workflow_roles = svc.SnapshotWorkflowRoles(client.workflow_roles) 753 ''' 754 WorkflowRole links a role to a workflow. The linked roles indicate which roles a user must be a part of 755 to request access to a resource via the workflow. 756 757 See `strongdm.svc.SnapshotWorkflowRoles`. 758 ''' 759 self.workflows = svc.SnapshotWorkflows(client.workflows) 760 ''' 761 Workflows are the collection of rules that define the resources to which access can be requested, 762 the users that can request that access, and the mechanism for approving those requests which can either 763 be automatic approval or a set of users authorized to approve the requests. 764 765 See `strongdm.svc.SnapshotWorkflows`. 766 '''
SnapshotClient exposes methods to query historical records at a provided timestamp.
587 def __init__(self, client): 588 self.access_requests = svc.SnapshotAccessRequests( 589 client.access_requests) 590 ''' 591 AccessRequests are requests for access to a resource that may match a Workflow. 592 593 See `strongdm.svc.SnapshotAccessRequests`. 594 ''' 595 self.account_attachments = svc.SnapshotAccountAttachments( 596 client.account_attachments) 597 ''' 598 AccountAttachments assign an account to a role. 599 600 See `strongdm.svc.SnapshotAccountAttachments`. 601 ''' 602 self.account_grants = svc.SnapshotAccountGrants(client.account_grants) 603 ''' 604 AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource. 605 606 See `strongdm.svc.SnapshotAccountGrants`. 607 ''' 608 self.account_permissions = svc.SnapshotAccountPermissions( 609 client.account_permissions) 610 ''' 611 AccountPermissions records the granular permissions accounts have, allowing them to execute 612 relevant commands via StrongDM's APIs. 613 614 See `strongdm.svc.SnapshotAccountPermissions`. 615 ''' 616 self.account_resources = svc.SnapshotAccountResources( 617 client.account_resources) 618 ''' 619 AccountResources enumerates the resources to which accounts have access. 620 The AccountResources service is read-only. 621 622 See `strongdm.svc.SnapshotAccountResources`. 623 ''' 624 self.accounts = svc.SnapshotAccounts(client.accounts) 625 ''' 626 Accounts are users that have access to strongDM. There are two types of accounts: 627 1. **Users:** humans who are authenticated through username and password or SSO. 628 2. **Service Accounts:** machines that are authenticated using a service token. 629 3. **Tokens** are access keys with permissions that can be used for authentication. 630 631 See `strongdm.svc.SnapshotAccounts`. 632 ''' 633 self.approval_workflow_approvers = svc.SnapshotApprovalWorkflowApprovers( 634 client.approval_workflow_approvers) 635 ''' 636 ApprovalWorkflowApprovers link approval workflow approvers to an ApprovalWorkflowStep 637 638 See `strongdm.svc.SnapshotApprovalWorkflowApprovers`. 639 ''' 640 self.approval_workflow_steps = svc.SnapshotApprovalWorkflowSteps( 641 client.approval_workflow_steps) 642 ''' 643 ApprovalWorkflowSteps link approval workflow steps to an ApprovalWorkflow 644 645 See `strongdm.svc.SnapshotApprovalWorkflowSteps`. 646 ''' 647 self.approval_workflows = svc.SnapshotApprovalWorkflows( 648 client.approval_workflows) 649 ''' 650 ApprovalWorkflows are the mechanism by which requests for access can be viewed by authorized 651 approvers and be approved or denied. 652 653 See `strongdm.svc.SnapshotApprovalWorkflows`. 654 ''' 655 self.identity_aliases = svc.SnapshotIdentityAliases( 656 client.identity_aliases) 657 ''' 658 IdentityAliases assign an alias to an account within an IdentitySet. 659 The alias is used as the username when connecting to a identity supported resource. 660 661 See `strongdm.svc.SnapshotIdentityAliases`. 662 ''' 663 self.identity_sets = svc.SnapshotIdentitySets(client.identity_sets) 664 ''' 665 A IdentitySet is a named grouping of Identity Aliases for Accounts. 666 An Account's relationship to a IdentitySet is defined via IdentityAlias objects. 667 668 See `strongdm.svc.SnapshotIdentitySets`. 669 ''' 670 self.nodes = svc.SnapshotNodes(client.nodes) 671 ''' 672 Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes: 673 - **Gateways** are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers. 674 - **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. 675 676 See `strongdm.svc.SnapshotNodes`. 677 ''' 678 self.policies = svc.SnapshotPolicies(client.policies) 679 ''' 680 Policies are the collection of one or more statements that enforce fine-grained access 681 control for the users of an organization. 682 683 See `strongdm.svc.SnapshotPolicies`. 684 ''' 685 self.proxy_cluster_keys = svc.SnapshotProxyClusterKeys( 686 client.proxy_cluster_keys) 687 ''' 688 Proxy Cluster Keys are authentication keys for all proxies within a cluster. 689 The proxies within a cluster share the same key. One cluster can have 690 multiple keys in order to facilitate key rotation. 691 692 See `strongdm.svc.SnapshotProxyClusterKeys`. 693 ''' 694 self.remote_identities = svc.SnapshotRemoteIdentities( 695 client.remote_identities) 696 ''' 697 RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource. 698 699 See `strongdm.svc.SnapshotRemoteIdentities`. 700 ''' 701 self.remote_identity_groups = svc.SnapshotRemoteIdentityGroups( 702 client.remote_identity_groups) 703 ''' 704 A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. 705 An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects. 706 707 See `strongdm.svc.SnapshotRemoteIdentityGroups`. 708 ''' 709 self.resources = svc.SnapshotResources(client.resources) 710 ''' 711 Resources are databases, servers, clusters, websites, or clouds that strongDM 712 delegates access to. 713 714 See `strongdm.svc.SnapshotResources`. 715 ''' 716 self.role_resources = svc.SnapshotRoleResources(client.role_resources) 717 ''' 718 RoleResources enumerates the resources to which roles have access. 719 The RoleResources service is read-only. 720 721 See `strongdm.svc.SnapshotRoleResources`. 722 ''' 723 self.roles = svc.SnapshotRoles(client.roles) 724 ''' 725 A Role has a list of access rules which determine which Resources the members 726 of the Role have access to. An Account can be a member of multiple Roles via 727 AccountAttachments. 728 729 See `strongdm.svc.SnapshotRoles`. 730 ''' 731 self.secret_stores = svc.SnapshotSecretStores(client.secret_stores) 732 ''' 733 SecretStores are servers where resource secrets (passwords, keys) are stored. 734 735 See `strongdm.svc.SnapshotSecretStores`. 736 ''' 737 self.workflow_approvers = svc.SnapshotWorkflowApprovers( 738 client.workflow_approvers) 739 ''' 740 WorkflowApprovers is an account or a role with the ability to approve requests bound to a workflow. 741 742 See `strongdm.svc.SnapshotWorkflowApprovers`. 743 ''' 744 self.workflow_assignments = svc.SnapshotWorkflowAssignments( 745 client.workflow_assignments) 746 ''' 747 WorkflowAssignments links a Resource to a Workflow. The assigned resources are those that a user can request 748 access to via the workflow. 749 750 See `strongdm.svc.SnapshotWorkflowAssignments`. 751 ''' 752 self.workflow_roles = svc.SnapshotWorkflowRoles(client.workflow_roles) 753 ''' 754 WorkflowRole links a role to a workflow. The linked roles indicate which roles a user must be a part of 755 to request access to a resource via the workflow. 756 757 See `strongdm.svc.SnapshotWorkflowRoles`. 758 ''' 759 self.workflows = svc.SnapshotWorkflows(client.workflows) 760 ''' 761 Workflows are the collection of rules that define the resources to which access can be requested, 762 the users that can request that access, and the mechanism for approving those requests which can either 763 be automatic approval or a set of users authorized to approve the requests. 764 765 See `strongdm.svc.SnapshotWorkflows`. 766 '''
AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource.
AccountPermissions records the granular permissions accounts have, allowing them to execute relevant commands via StrongDM's APIs.
AccountResources enumerates the resources to which accounts have access. The AccountResources service is read-only.
Accounts are users that have access to strongDM. There are two types of accounts:
- Users: humans who are authenticated through username and password or SSO.
- Service Accounts: machines that are authenticated using a service token.
- Tokens are access keys with permissions that can be used for authentication.
ApprovalWorkflowApprovers link approval workflow approvers to an ApprovalWorkflowStep
ApprovalWorkflows are the mechanism by which requests for access can be viewed by authorized approvers and be approved or denied.
IdentityAliases assign an alias to an account within an IdentitySet. The alias is used as the username when connecting to a identity supported resource.
A IdentitySet is a named grouping of Identity Aliases for Accounts. An Account's relationship to a IdentitySet is defined via IdentityAlias objects.
Nodes make up the strongDM network, and allow your users to connect securely to your resources. There are two types of nodes:
- Gateways are the entry points into network. They listen for connection from the strongDM client, and provide access to databases and servers.
- 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.
Policies are the collection of one or more statements that enforce fine-grained access control for the users of an organization.
Proxy Cluster Keys are authentication keys for all proxies within a cluster. The proxies within a cluster share the same key. One cluster can have multiple keys in order to facilitate key rotation.
RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource.
A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects.
Resources are databases, servers, clusters, websites, or clouds that strongDM delegates access to.
RoleResources enumerates the resources to which roles have access. The RoleResources service is read-only.
A Role has a list of access rules which determine which Resources the members of the Role have access to. An Account can be a member of multiple Roles via AccountAttachments.
WorkflowApprovers is an account or a role with the ability to approve requests bound to a workflow.
WorkflowAssignments links a Resource to a Workflow. The assigned resources are those that a user can request access to via the workflow.
WorkflowRole links a role to a workflow. The linked roles indicate which roles a user must be a part of to request access to a resource via the workflow.