Class: SDM::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/strongdm.rb

Overview

Client bundles all the services together and initializes them.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_access_key, api_secret_key, host: "api.strongdm.com:443", insecure: false, retry_rate_limit_errors: true) ⇒ Client

Creates a new strongDM API client.

Raises:

  • (TypeError)

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/strongdm.rb', line 35

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)
  @account_attachments = AccountAttachments.new(host, insecure, self)
  @account_grants = AccountGrants.new(host, insecure, self)
  @accounts = Accounts.new(host, insecure, self)
  @control_panel = ControlPanel.new(host, insecure, self)
  @nodes = Nodes.new(host, insecure, self)
  @resources = Resources.new(host, insecure, self)
  @role_attachments = RoleAttachments.new(host, insecure, self)
  @role_grants = RoleGrants.new(host, insecure, self)
  @roles = Roles.new(host, insecure, self)
  @secret_stores = SecretStores.new(host, insecure, self)
  @_test_options = Hash.new
end

Instance Attribute Details

#_test_optionsObject (readonly)

Returns the value of attribute _test_options.


176
177
178
# File 'lib/strongdm.rb', line 176

def _test_options
  @_test_options
end

#account_attachmentsObject (readonly)

AccountAttachments assign an account to a role.

See AccountAttachments.


122
123
124
# File 'lib/strongdm.rb', line 122

def 
  @account_attachments
end

#account_grantsObject (readonly)

AccountGrants assign a resource directly to an account, giving the account the permission to connect to that resource.

See AccountGrants.


126
127
128
# File 'lib/strongdm.rb', line 126

def 
  @account_grants
end

#accountsObject (readonly)

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.


132
133
134
# File 'lib/strongdm.rb', line 132

def accounts
  @accounts
end

#api_access_keyObject (readonly)

API authentication token (read-only).


118
119
120
# File 'lib/strongdm.rb', line 118

def api_access_key
  @api_access_key
end

#base_retry_delayObject (readonly)

Returns the value of attribute base_retry_delay.


114
115
116
# File 'lib/strongdm.rb', line 114

def base_retry_delay
  @base_retry_delay
end

#control_panelObject (readonly)

ControlPanel contains all administrative controls.

See SDM::ControlPanel.


136
137
138
# File 'lib/strongdm.rb', line 136

def control_panel
  @control_panel
end

#max_retriesObject (readonly)

Returns the value of attribute max_retries.


113
114
115
# File 'lib/strongdm.rb', line 113

def max_retries
  @max_retries
end

#max_retry_delayObject (readonly)

Returns the value of attribute max_retry_delay.


115
116
117
# File 'lib/strongdm.rb', line 115

def max_retry_delay
  @max_retry_delay
end

#nodesObject (readonly)

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.


142
143
144
# File 'lib/strongdm.rb', line 142

def nodes
  @nodes
end

#resourcesObject (readonly)

Resources are databases, servers, clusters, websites, or clouds that strongDM delegates access to.

See Resources.


147
148
149
# File 'lib/strongdm.rb', line 147

def resources
  @resources
end

#role_attachmentsObject (readonly)

RoleAttachments represent relationships between composite roles and the roles that make up those composite roles. When a composite role is attached to another role, the permissions granted to members of the composite role are augmented to include the permissions granted to members of the attached role.

Deprecated: use multi-role via AccountAttachments instead.

See RoleAttachments.


156
157
158
# File 'lib/strongdm.rb', line 156

def role_attachments
  @role_attachments
end

#role_grantsObject (readonly)

RoleGrants represent relationships between composite roles and the roles that make up those composite roles. When a composite role is attached to another role, the permissions granted to members of the composite role are augmented to include the permissions granted to members of the attached role.

Deprecated: use Role access rules instead.

See RoleGrants.


165
166
167
# File 'lib/strongdm.rb', line 165

def role_grants
  @role_grants
end

#rolesObject (readonly)

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.


171
172
173
# File 'lib/strongdm.rb', line 171

def roles
  @roles
end

#secret_storesObject (readonly)

SecretStores are servers where resource secrets (passwords, keys) are stored.

See SecretStores.


175
176
177
# File 'lib/strongdm.rb', line 175

def secret_stores
  @secret_stores
end

Instance Method Details

#get_metadata(method_name, req) ⇒ Object


58
59
60
61
62
63
64
65
# File 'lib/strongdm.rb', line 58

def (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

#jitterSleep(iter) ⇒ Object


83
84
85
86
87
88
89
90
# File 'lib/strongdm.rb', line 83

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

#shouldRetry(iter, err) ⇒ Object


92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/strongdm.rb', line 92

def shouldRetry(iter, err)
  if (iter >= @max_retries - 1)
    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
end

#sign(method_name, msg_bytes) ⇒ Object


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/strongdm.rb', line 67

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