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