# Copyright 2020 StrongDM Inc # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # @internal Code generated by protogen. DO NOT EDIT. require_relative "./svc" require "base64" require "grpc" require "openssl" require "time" module SDM #:nodoc: # Client bundles all the services together and initializes them. class Client DEFAULT_MAX_RETRIES = 3 DEFAULT_BASE_RETRY_DELAY = 0.0030 # 30 ms DEFAULT_MAX_RETRY_DELAY = 300 # 300 seconds API_VERSION = "2021-08-23" USER_AGENT = "strongdm-sdk-ruby/3.9.0" private_constant :DEFAULT_MAX_RETRIES, :DEFAULT_BASE_RETRY_DELAY, :DEFAULT_MAX_RETRY_DELAY, :API_VERSION, :USER_AGENT # Creates a new strongDM API client. def initialize(api_access_key, api_secret_key, host: "api.strongdm.com:443", insecure: false, retry_rate_limit_errors: true) raise TypeError, "client access key must be a string" unless api_access_key.kind_of?(String) raise TypeError, "client secret key must be a string" unless api_secret_key.kind_of?(String) raise TypeError, "client host must be a string" unless host.kind_of?(String) @api_access_key = api_access_key.strip @api_secret_key = Base64.strict_decode64(api_secret_key.strip) @max_retries = DEFAULT_MAX_RETRIES @base_retry_delay = DEFAULT_BASE_RETRY_DELAY @max_retry_delay = DEFAULT_MAX_RETRY_DELAY @expose_rate_limit_errors = (not retry_rate_limit_errors) @snapshot_time = nil begin if insecure @channel = GRPC::Core::Channel.new(host, {}, :this_channel_is_insecure) else cred = GRPC::Core::ChannelCredentials.new() @channel = GRPC::Core::Channel.new(host, {}, cred) end rescue => exception raise Plumbing::convert_error_to_porcelain(exception) end @account_attachments = AccountAttachments.new(@channel, self) @account_attachments_history = AccountAttachmentsHistory.new(@channel, self) @account_grants = AccountGrants.new(@channel, self) @account_grants_history = AccountGrantsHistory.new(@channel, self) @account_permissions = AccountPermissions.new(@channel, self) @account_resources = AccountResources.new(@channel, self) @accounts = Accounts.new(@channel, self) @accounts_history = AccountsHistory.new(@channel, self) @activities = Activities.new(@channel, self) @control_panel = ControlPanel.new(@channel, self) @nodes = Nodes.new(@channel, self) @nodes_history = NodesHistory.new(@channel, self) @organization_history = OrganizationHistory.new(@channel, self) @queries = Queries.new(@channel, self) @remote_identities = RemoteIdentities.new(@channel, self) @remote_identities_history = RemoteIdentitiesHistory.new(@channel, self) @remote_identity_groups = RemoteIdentityGroups.new(@channel, self) @remote_identity_groups_history = RemoteIdentityGroupsHistory.new(@channel, self) @replays = Replays.new(@channel, self) @resources = Resources.new(@channel, self) @resources_history = ResourcesHistory.new(@channel, self) @role_resources = RoleResources.new(@channel, self) @role_resources_history = RoleResourcesHistory.new(@channel, self) @roles = Roles.new(@channel, self) @roles_history = RolesHistory.new(@channel, self) @secret_stores = SecretStores.new(@channel, self) @secret_stores_history = SecretStoresHistory.new(@channel, self) @_test_options = Hash.new end # Closes this client and releases all resources held by it. def close begin @channel.close() rescue => exception raise Plumbing::convert_error_to_porcelain(exception) end end # @private def get_metadata(method_name, req) return { 'x-sdm-authentication': @api_access_key, 'x-sdm-signature': self.sign(method_name, req.to_proto), 'x-sdm-api-version': API_VERSION, 'x-sdm-user-agent': USER_AGENT, } end def sign(method_name, msg_bytes) current_utc_date = Time.now.utc date = sprintf("%04d-%02d-%02d", current_utc_date.year, current_utc_date.month, current_utc_date.day) signing_key = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, @api_secret_key, date) signing_key = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, signing_key, "sdm_api_v1") sha_req = Digest::SHA256.new sha_req << method_name sha_req << "\n" sha_req << msg_bytes request_hash = sha_req.digest return Base64.strict_encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, signing_key, request_hash)) end # @private def jitterSleep(iter) dur_max = @base_retry_delay * 2 ** iter if (dur_max > @max_retry_delay) dur_max = @max_retry_delay end dur = rand() * dur_max sleep(dur) end # @private def shouldRetry(iter, err) if (iter >= @max_retries - 1) return false end # The grpc library unfortunately does not raise a more specific error class. if err.is_a? RuntimeError and err.message == "closed!" return false end if not err.is_a? GRPC::BadStatus return true end porcelainErr = Plumbing::convert_error_to_porcelain(err) if (not @expose_rate_limit_errors) and (porcelainErr.is_a? RateLimitError) sleep_for = porcelainErr.rate_limit.reset_at - Time.now # If timezones or clock drift causes this calculation to fail, # wait at most one minute. if sleep_for < 0 or sleep_for > 60 sleep_for = 60 end sleep(sleep_for) return true end return (err.code() == 13 or err.code() == 14) end # Constructs a read-only client that will provide historical data from the provided timestamp. # See {SnapshotClient}. def snapshot_at(snapshot_time) client = self.clone client.snapshot_time = snapshot_time return SnapshotClient.new(client) end attr_reader :max_retries attr_reader :base_retry_delay attr_reader :max_retry_delay # API authentication token (read-only). attr_reader :api_access_key # Optional timestamp at which to provide historical data attr_reader :snapshot_time # AccountAttachments assign an account to a role. # # See {AccountAttachments}. attr_reader :account_attachments # AccountAttachmentsHistory records all changes to the state of an AccountAttachment. # # See {AccountAttachmentsHistory}. attr_reader :account_attachments_history # AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource. # # See {AccountGrants}. attr_reader :account_grants # AccountGrantsHistory records all changes to the state of an AccountGrant. # # See {AccountGrantsHistory}. attr_reader :account_grants_history # AccountPermissions records the granular permissions accounts have, allowing them to execute # relevant commands via StrongDM's APIs. # # See {AccountPermissions}. attr_reader :account_permissions # AccountResources enumerates the resources to which accounts have access. # The AccountResources service is read-only. # # See {AccountResources}. attr_reader :account_resources # Accounts are users that have access to strongDM. There are two types of accounts: # 1. **Users:** humans who are authenticated through username and password or SSO. # 2. **Service Accounts:** machines that are authenticated using a service token. # # See {Accounts}. attr_reader :accounts # AccountsHistory records all changes to the state of an Account. # # See {AccountsHistory}. attr_reader :accounts_history # 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. # # See {Activities}. attr_reader :activities # ControlPanel contains all administrative controls. # # See {ControlPanel}. attr_reader :control_panel # 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 {Nodes}. attr_reader :nodes # NodesHistory records all changes to the state of a Node. # # See {NodesHistory}. attr_reader :nodes_history # OrganizationHistory records all changes to the state of an Organization. # # See {OrganizationHistory}. attr_reader :organization_history # A Query is a record of a single client request to a resource, such as an SQL query. # Long-running SSH, RDP, or Kubernetes interactive sessions also count as queries. # The Queries service is read-only. # # See {Queries}. attr_reader :queries # RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource. # # See {RemoteIdentities}. attr_reader :remote_identities # RemoteIdentitiesHistory records all changes to the state of a RemoteIdentity. # # See {RemoteIdentitiesHistory}. attr_reader :remote_identities_history # A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. # An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects. # # See {RemoteIdentityGroups}. attr_reader :remote_identity_groups # RemoteIdentityGroupsHistory records all changes to the state of a RemoteIdentityGroup. # # See {RemoteIdentityGroupsHistory}. attr_reader :remote_identity_groups_history # 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 {Replays}. attr_reader :replays # Resources are databases, servers, clusters, websites, or clouds that strongDM # delegates access to. # # See {Resources}. attr_reader :resources # ResourcesHistory records all changes to the state of a Resource. # # See {ResourcesHistory}. attr_reader :resources_history # RoleResources enumerates the resources to which roles have access. # The RoleResources service is read-only. # # See {RoleResources}. attr_reader :role_resources # RoleResourcesHistory records all changes to the state of a RoleResource. # # See {RoleResourcesHistory}. attr_reader :role_resources_history # 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 {Roles}. attr_reader :roles # RolesHistory records all changes to the state of a Role. # # See {RolesHistory}. attr_reader :roles_history # SecretStores are servers where resource secrets (passwords, keys) are stored. # # See {SecretStores}. attr_reader :secret_stores # SecretStoresHistory records all changes to the state of a SecretStore. # # See {SecretStoresHistory}. attr_reader :secret_stores_history # @private attr_reader :_test_options protected attr_writer :snapshot_time private def initialize_copy(other) @account_attachments = AccountAttachments.new(@channel, self) @account_attachments_history = AccountAttachmentsHistory.new(@channel, self) @account_grants = AccountGrants.new(@channel, self) @account_grants_history = AccountGrantsHistory.new(@channel, self) @account_permissions = AccountPermissions.new(@channel, self) @account_resources = AccountResources.new(@channel, self) @accounts = Accounts.new(@channel, self) @accounts_history = AccountsHistory.new(@channel, self) @activities = Activities.new(@channel, self) @control_panel = ControlPanel.new(@channel, self) @nodes = Nodes.new(@channel, self) @nodes_history = NodesHistory.new(@channel, self) @organization_history = OrganizationHistory.new(@channel, self) @queries = Queries.new(@channel, self) @remote_identities = RemoteIdentities.new(@channel, self) @remote_identities_history = RemoteIdentitiesHistory.new(@channel, self) @remote_identity_groups = RemoteIdentityGroups.new(@channel, self) @remote_identity_groups_history = RemoteIdentityGroupsHistory.new(@channel, self) @replays = Replays.new(@channel, self) @resources = Resources.new(@channel, self) @resources_history = ResourcesHistory.new(@channel, self) @role_resources = RoleResources.new(@channel, self) @role_resources_history = RoleResourcesHistory.new(@channel, self) @roles = Roles.new(@channel, self) @roles_history = RolesHistory.new(@channel, self) @secret_stores = SecretStores.new(@channel, self) @secret_stores_history = SecretStoresHistory.new(@channel, self) end end # SnapshotClient exposes methods to query historical records at a provided timestamp. class SnapshotClient def initialize(client) @account_attachments = SnapshotAccountAttachments.new(client.account_attachments) @account_grants = SnapshotAccountGrants.new(client.account_grants) @account_permissions = SnapshotAccountPermissions.new(client.account_permissions) @account_resources = SnapshotAccountResources.new(client.account_resources) @accounts = SnapshotAccounts.new(client.accounts) @nodes = SnapshotNodes.new(client.nodes) @remote_identities = SnapshotRemoteIdentities.new(client.remote_identities) @remote_identity_groups = SnapshotRemoteIdentityGroups.new(client.remote_identity_groups) @resources = SnapshotResources.new(client.resources) @role_resources = SnapshotRoleResources.new(client.role_resources) @roles = SnapshotRoles.new(client.roles) @secret_stores = SnapshotSecretStores.new(client.secret_stores) end # AccountAttachments assign an account to a role. # # See {SnapshotAccountAttachments}. attr_reader :account_attachments # AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource. # # See {SnapshotAccountGrants}. attr_reader :account_grants # AccountPermissions records the granular permissions accounts have, allowing them to execute # relevant commands via StrongDM's APIs. # # See {SnapshotAccountPermissions}. attr_reader :account_permissions # AccountResources enumerates the resources to which accounts have access. # The AccountResources service is read-only. # # See {SnapshotAccountResources}. attr_reader :account_resources # Accounts are users that have access to strongDM. There are two types of accounts: # 1. **Users:** humans who are authenticated through username and password or SSO. # 2. **Service Accounts:** machines that are authenticated using a service token. # # See {SnapshotAccounts}. attr_reader :accounts # 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 {SnapshotNodes}. attr_reader :nodes # RemoteIdentities assign a resource directly to an account, giving the account the permission to connect to that resource. # # See {SnapshotRemoteIdentities}. attr_reader :remote_identities # A RemoteIdentityGroup is a named grouping of Remote Identities for Accounts. # An Account's relationship to a RemoteIdentityGroup is defined via RemoteIdentity objects. # # See {SnapshotRemoteIdentityGroups}. attr_reader :remote_identity_groups # Resources are databases, servers, clusters, websites, or clouds that strongDM # delegates access to. # # See {SnapshotResources}. attr_reader :resources # RoleResources enumerates the resources to which roles have access. # The RoleResources service is read-only. # # See {SnapshotRoleResources}. attr_reader :role_resources # 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 {SnapshotRoles}. attr_reader :roles # SecretStores are servers where resource secrets (passwords, keys) are stored. # # See {SnapshotSecretStores}. attr_reader :secret_stores end end