threatstack 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 187538b81d44fb05e61ceed262abe656e82a2a4d
4
- data.tar.gz: 4bf4c21c0ea8af3cc10f96044427763f5800b3c3
3
+ metadata.gz: 74577f2d9484d086e874ca7e040cd1091e4a50a8
4
+ data.tar.gz: 159fa0747f42351a160133662896e4de9466febb
5
5
  SHA512:
6
- metadata.gz: 628ec3682dac755b55796c97fca8611786ea5a90fdf1412bf18f7081a1f30b47ae4e37ae836ce017ee5e23834086b5d1e3a5a446409d2e1a26d1341f8fa64c4e
7
- data.tar.gz: 5746ae5b1648fd66e077b81a15f9341d8a5c18e38560fe455e900e820012f14d4b4bcf39a46316c2acd9f9612b8535c80aa5f77b489d06e84b1ea877d01fe447
6
+ metadata.gz: a54cf4e5e7b6b5fffb2d624391129b1b836692f98cab6d0a6bf2ae74a8c2ec3d009d999ad8d3d01478ee322619ebf4494b636122dd5c7ac4278a1770ef2c48e6
7
+ data.tar.gz: faf63d2859b2e75f18916c2005cba0d488c8a35f9720b4355d2bdfd0704f5270010144be3090188f4136e8bf91208833478a05139bafae70c5e5d4cb3abafe14
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ *.gem
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Threatstack
2
2
 
3
- Threatstack is a tool for monitoring your infrastructure and hosts for malicious or suspicious activity. They have this handy little API that I decided to write a Ruby wrapper for. This is a very thin wrapper that only transforms keys for the purpose of changing them to snake_case like the rest of the ruby world. Otherwise, this maps very closely to the API docs found here: https://app.threatstack.com/api/docs
3
+ Threatstack is a tool for monitoring your infrastructure and hosts for malicious or suspicious activity. They have this handy little API that I decided to write a Ruby wrapper for. This is a very thin wrapper that only transforms keys for the purpose of changing them to snake_case like the rest of the ruby world. Otherwise, this maps very closely to the API docs found here: https://apidocs.threatstack.com/v2
4
+
5
+ ### NOTE: From version 1.0.0 onward, only Threatstack API v2 is supported
4
6
 
5
7
  ## Installation
6
8
 
@@ -23,30 +25,33 @@ Or install it yourself as:
23
25
  You can access all attributes on responses thanks to the method_missing function in Ruby. We only munged the attributes that don't correspond to snake_case. If you want to see a list of all available attributes for a serializable response object, simply do something like this:
24
26
 
25
27
  ```
26
- client = Threatstack::Client.new(API_TOKEN)
27
- client.policies.first.attrs
28
- => [:rules,
29
- :id,
30
- :name,
28
+ client = Threatstack::Client.new(API_TOKEN, organization_id: ORG_ID)
29
+ [threatstack] main> ts.alerts.first.attrs
30
+ => [:id,
31
+ :title,
32
+ :type,
31
33
  :created_at,
32
- :updated_at,
33
- :enabled,
34
- :agent_count,
35
- :alert_rule_count,
36
- :description,
37
- :organization_id,
38
- :alert_policy_id,
39
- :alert_policy,
40
- :file_integrity_rules]
34
+ :event_count,
35
+ :is_dismissed,
36
+ :dismissed_at,
37
+ :dismissed_reason,
38
+ :dismissed_reason_text,
39
+ :dismissed_by,
40
+ :severity,
41
+ :agent_id,
42
+ :rule_id,
43
+ :ruleset_id,
44
+ :event_ids]
45
+
41
46
  ```
42
47
 
43
48
  ### Alerts
44
49
 
45
50
  ```
46
- client = Threatstack::Client.new(API_TOKEN)
51
+ client = Threatstack::Client.new(API_TOKEN, organization_id: ORG_ID)
47
52
  ## All these are optional url params. See the Threatstack API Docs
48
53
  alert = client.alerts(start: 3.days.ago, end: Time.now, count: 5).last
49
- => #<Threatstack::Alert::Alert:0x007fde0b01cbd8
54
+ => #<Threatstack::Alert:0x007fde0b01cbd8
50
55
  @raw=
51
56
  {"created_at"=>1496850520000,
52
57
  "expires_at"=>1496936920000,
@@ -54,22 +59,15 @@ alert = client.alerts(start: 3.days.ago, end: Time.now, count: 5).last
54
59
  "count"=>4,
55
60
  "title"=>"CloudTrail Activity : EC2 Service Policy Changes : CreateVolume by ryan_canty",
56
61
  ...
57
- event = alert.latest_events.last
58
- => <Threatstack::Alert::Event:0x007fde0ca08420
59
- @raw=
60
- {"user"=>"ryan_canty",
61
- "userType"=>"IAMUser",
62
- ...
63
- user_that_caused_the_event = event.user_identity.arn
64
- => "arn:aws:iam::1234567890:user/ryan_canty"
65
-
62
+ count = alert.count
63
+ => 4
66
64
  ```
67
65
 
68
66
  You can also limit the response if that's important to you:
69
67
 
70
68
  ```
71
69
  client.alerts(fields: ['title', 'alerts'])
72
- => [#<Threatstack::Alert::Alert:0x007fd61348c768
70
+ => [#<Threatstack::Alert:0x007fd61348c768
73
71
  @raw={"title"=>"CloudTrail Activity (IAM Policy Changes) : CreateAccessKey by ryan_canty", "severity"=>2}>]
74
72
  ```
75
73
 
@@ -83,36 +81,19 @@ client.alert('1234567890')
83
81
 
84
82
  ```
85
83
  client.agents
86
- => [#<Threatstack::Agent::Agent:0x007fa262b0b2e0 @raw={...}> ]
87
- client.agent
88
- => #<Threatstack::Agent::Agent:0x007fa262b0b2e0 @raw={...}>
84
+ => [#<Threatstack::Response:0x007fa262b0b2e0 @raw={...}> ]
85
+ client.agent('123123123')
86
+ => #<Threatstack::Agent:0x007fa262b0b2e0 @raw={...}>
89
87
  ```
90
88
 
91
-
92
- ### Policies
89
+ ### Vulnerabilities
93
90
 
94
91
  ```
95
- client.policies
96
- => [#<Threatstack::Policy::Policy:0x007fa262b0b2e0 @raw={...}> ]
97
- client.policy
98
- => #<Threatstack::Policy::Policy:0x007fa262b0b2e0 @raw={...}>
92
+ client.vulnerabilities
93
+ client.vulnerability('CVE-123')
99
94
  ```
95
+ ## TODO: Write docs for all the things (contributions welcome)
100
96
 
101
- ### Organizations
102
-
103
- ```
104
- client.organizations
105
- => [#<Threatstack::Organization::Organization:0x007fa262b0b2e0 @raw={...}> ]
106
- ```
107
-
108
- ### Audit Logs
109
-
110
- ```
111
- client.logs
112
- => [#<Threatstack::Log::Log:0x007fa262b0b2e0 @raw={...}>]
113
- client.search('query')
114
- => [#<Threatstack::Log::Log:0x007fa262b0b2e0 @raw={...}>]
115
- ```
116
97
 
117
98
  ## Development
118
99
 
@@ -3,77 +3,154 @@ require 'httparty'
3
3
  require 'threatstack/response'
4
4
  require 'threatstack/entities/agent'
5
5
  require 'threatstack/entities/alert'
6
- require 'threatstack/entities/log'
7
- require 'threatstack/entities/organization'
8
- require 'threatstack/entities/policy'
6
+ require 'threatstack/entities/ruleset'
7
+ require 'threatstack/entities/rule'
8
+
9
9
 
10
10
  module Threatstack
11
11
  class ThreatstackError < StandardError; end
12
12
 
13
13
  class Client
14
- THREATSTACK_API = 'https://app.threatstack.com/api'.freeze
15
-
16
- attr_reader :token, :org_id, :api_version
14
+ THREATSTACK_API = 'https://api.threatstack.com'.freeze
15
+ attr_reader :token, :org_id, :api_version, :last_pagination_token
17
16
 
18
- def initialize(token, api_version = 'v1')
17
+ def initialize(token, organization_id: nil, api_version: 'v2')
19
18
  @api_version = api_version
20
19
  @token = token
20
+ @org_id = organization_id
21
+ if api_version == 'v1'
22
+ raise ThreatstackError, "This version of threatstack-ruby does not support Threatstack API v1"
23
+ end
21
24
  end
22
25
 
26
+ ### ALERTS ###
27
+
23
28
  def agents(params = {})
24
29
  response = do_request(:get, 'agents', params)
25
- Response.new(:agent, response).agents
30
+ Response.new(response['agents'], self, entity: :agent).agents
26
31
  end
27
32
 
28
33
  def agent(agent_id, params = {})
29
34
  raise ThreatstackError, "Must specify agent id" unless agent_id
30
35
  response = do_request(:get, "agents/#{agent_id}", params)
31
- Agent.new(response)
36
+ Agent.new(response, self)
32
37
  end
33
38
 
39
+ ### ALERTS ###
34
40
  def alerts(params = {})
35
41
  response = do_request(:get, 'alerts', params)
36
- Response.new(:alert, response).alerts
42
+ Response.new(response['alerts'], self, entity: :alert).alerts
43
+ end
44
+
45
+ def dismissed_alerts(params = {})
46
+ response = do_request(:get, 'alerts/dismissed', params)
47
+ Response.new(response['alerts'], self, entity: :alert).alerts
37
48
  end
38
49
 
39
50
  def alert(alert_id, params = {})
40
51
  raise ThreatstackError, "Must specify alert id" unless alert_id
41
52
  response = do_request(:get, "alerts/#{alert_id}", params)
42
- Alert.new(response)
53
+ Alert.new(response, self)
54
+ end
55
+
56
+ def severity_counts(params = {})
57
+ response = do_request(:get, "alerts/severity-counts", params)
58
+ Response.new(response['severityCounts'], self, entity: :severity_count).list
59
+ end
60
+
61
+ def event(alert_id, event_id, params = {})
62
+ response = do_request(:get, "alerts/#{alert_id}/events/#{event_id}", params)
63
+ GenericObject.new(response['details'], self, entity: :event)
43
64
  end
44
65
 
45
- def policies(params = {})
46
- response = do_request(:get, 'policies', params)
47
- Response.new(:policy, response).policies
66
+ ### CVEs ###
67
+
68
+ def vulnerabilities(params = {})
69
+ uri = "vulnerabilities"
70
+ uri += "/suppressed" if params[:suppressed]
71
+ response = do_request(:get, uri, params)
72
+ Response.new(response['cves'], self, entity: :cve).cves
48
73
  end
49
74
 
50
- def policy(policy_id, params = {})
51
- raise ThreatstackError, "Must specify policy id" unless policy_id
52
- response = do_request(:get, "policies/#{policy_id}", params)
53
- Policy.new(response)
75
+ def vulnerability(vuln_id, params = {})
76
+ raise ThreatstackError, "Must specify vulnerability id" unless vuln_id
77
+ response = do_request(:get, "vulnerabilities/#{vuln_id}", params)
78
+ Cve.new(response, self)
54
79
  end
55
80
 
56
- def organizations(params = {})
57
- response = do_request(:get, 'organizations', params)
58
- Response.new(:organization, response).organizations
81
+ def package_vulnerabilities(package, params = {})
82
+ raise ThreatstackError, "Must specify package" unless package
83
+ uri = "vulnerabilities/package/#{package}"
84
+ uri += "/suppressed" if params[:suppressed]
85
+ response = do_request(:get, uri, params)
86
+ Response.new(response['packages'], self, entity: :package).list
59
87
  end
60
88
 
61
- def logs(params = {})
62
- response = do_request(:get, 'logs', params)
63
- Response.new(:log, response).logs
89
+ def server_vulnerabilities(server, params = {})
90
+ raise ThreatstackError, "Must specify server" unless server
91
+ uri = "vulnerabilities/server/#{server}"
92
+ uri += "/suppressed" if params[:suppressed]
93
+ response = do_request(:get, uri, params)
94
+ response['cves']
64
95
  end
65
96
 
66
- def search(query, params = {})
67
- logs(params.merge(q: query))
97
+ def cves_by_agent(agent, params = {})
98
+ raise ThreatstackError, "Must specify agent" unless agent
99
+ uri = "vulnerabilities/agent/#{agent}"
100
+ uri += "/suppressed" if params[:suppressed]
101
+ response = do_request(:get, uri, params)
102
+ response['cves']
103
+ end
104
+
105
+ def vulnerability_suppressions(params = {})
106
+ response = do_request(:get, "vulnerabilities/suppressions", params)
107
+ Response.new(response['suppressions'], self, entity: :suppression).list
108
+ end
109
+
110
+ ### Rulesets ###
111
+
112
+ def rulesets(params = {})
113
+ response = do_request(:get, 'rulesets', params)
114
+ Response.new(response['rulesets'], self, entity: :ruleset).rulesets
115
+ end
116
+
117
+ def ruleset(ruleset_id, params = {})
118
+ raise ThreatstackError, "Must specify ruleset id" unless ruleset_id
119
+ response = do_request(:get, "rulesets/#{ruleset_id}", params)
120
+ Ruleset.new(response, self)
121
+ end
122
+
123
+ ### Rules ###
124
+
125
+ def rules(ruleset_id, params = {})
126
+ response = do_request(:get, "rulesets/#{ruleset_id}/rules", params)
127
+ Response.new(response['rules'], self, entity: :rule).rules
128
+ end
129
+
130
+ def rule(ruleset_id, rule_id, params = {})
131
+ raise ThreatstackError, "Must specify ruleset id and rule id" unless ruleset_id && rule_id
132
+ response = do_request(:get, "rulesets/#{ruleset_id}/rules/#{rule_id}", params)
133
+ Rule.new(response, self)
134
+ end
135
+
136
+ ### Servers ###
137
+
138
+ def servers(monitored = true, params = {})
139
+ uri = "servers"
140
+ uri += "/non-monitored" unless monitored
141
+ response = do_request(:get, uri, params)
142
+ Response.new(response['servers'], self, entity: :server).list
68
143
  end
69
144
 
70
145
  private
71
146
 
72
147
  def do_request(method, path, params = {})
73
- response = HTTParty.public_send(method, build_uri(path, params), headers: { "Authorization" => token })
148
+ headers = { "Authorization" => token, "Organization-Id" => org_id }
149
+ response = HTTParty.public_send(method, build_uri(path, params), headers: headers).parsed_response
74
150
  if response.instance_of?(Hash) && response['status'] == 'error'
75
151
  raise ThreatstackError, response['message']
76
152
  end
153
+ @last_pagination_token = response['token']
77
154
  response
78
155
  end
79
156
 
@@ -87,6 +164,5 @@ module Threatstack
87
164
  uri += "?#{URI::encode(query)}" if params.any?
88
165
  uri
89
166
  end
90
-
91
167
  end
92
168
  end
@@ -3,5 +3,19 @@ require 'threatstack/serializable'
3
3
  module Threatstack
4
4
  class Agent
5
5
  include Serializable
6
+ attributes :id, :instance_id, :status, :activated_at, :last_reported_at,
7
+ :version, :name, :description, :hostname, :tags, :agent_type
8
+
9
+ def tags
10
+ raw['tags'].map{ |t| Tag.new(t) }
11
+ end
12
+
13
+ def ruleset_ids
14
+ raw['rulesets']
15
+ end
16
+
17
+ def rulesets
18
+ ruleset_ids.each { |id| client.ruleset(id) }
19
+ end
6
20
  end
7
21
  end
@@ -1,20 +1,26 @@
1
- require 'threatstack/entities/event'
2
- require 'threatstack/entities/rule'
3
1
  require 'threatstack/serializable'
4
2
 
5
3
  module Threatstack
6
4
  class Alert
7
5
  include Serializable
8
- attributes :latest_events, :rule
6
+ attributes :id, :title, :type, :created_at, :event_count, :is_dismissed, :dismissed_at,
7
+ :dismissed_reason, :dismissed_reason_text, :dismissed_by, :severity, :agent_id,
8
+ :rule_id, :ruleset_id, :event_ids
9
9
 
10
- def latest_events
11
- raw['latest_events'].map do |event|
12
- Event.new(event)
13
- end
10
+ def rule
11
+ client.rule(rule_id)
14
12
  end
15
13
 
16
- def rule
17
- Rule.new(raw['rule'])
14
+ def agent
15
+ client.agent(agent_id)
16
+ end
17
+
18
+ def ruleset
19
+ client.ruleset(ruleset_id)
20
+ end
21
+
22
+ def events
23
+ event_ids&.map{ |event_id| client.event(id, event_id)}
18
24
  end
19
25
  end
20
26
  end
@@ -0,0 +1,9 @@
1
+ require 'threatstack/serializable'
2
+
3
+ module Threatstack
4
+ class Cve
5
+ include Serializable
6
+ attributes :cve_number, :reported_package, :system_package, :vector_type,
7
+ :affected_servers, :is_suppressed, :severity
8
+ end
9
+ end
@@ -1,7 +1,5 @@
1
- require 'threatstack/serializable'
2
-
3
1
  module Threatstack
4
- class Log
2
+ class GenericObject
5
3
  include Serializable
6
4
  end
7
5
  end
@@ -3,10 +3,12 @@ require 'threatstack/serializable'
3
3
  module Threatstack
4
4
  class Rule
5
5
  include Serializable
6
- attributes :original_rule
6
+ attributes :id, :ruleset_id, :name, :type, :severity_of_alerts, :alert_description,
7
+ :aggregate_fields, :filter, :frequency, :threshold, :suppressions, :ignore_files,
8
+ :file_integrity_paths, :events_to_monitor
7
9
 
8
- def original_rule
9
- Rule.new(raw['original_rule'])
10
+ def ruleset
11
+ client.ruleset(ruleset_id)
10
12
  end
11
13
  end
12
14
  end
@@ -0,0 +1,12 @@
1
+ require 'threatstack/serializable'
2
+
3
+ module Threatstack
4
+ class Ruleset
5
+ include Serializable
6
+ attributes :id, :rule_ids, :name, :created_at, :updated_at, :description, :agents
7
+
8
+ def rules
9
+ client.rules(id)
10
+ end
11
+ end
12
+ end
@@ -1,41 +1,44 @@
1
+ require 'threatstack/serializable'
1
2
  require 'threatstack/entities/agent'
2
3
  require 'threatstack/entities/alert'
3
- require 'threatstack/entities/log'
4
- require 'threatstack/entities/organization'
5
- require 'threatstack/entities/policy'
4
+ require 'threatstack/entities/cve'
5
+ require 'threatstack/entities/generic_object'
6
+ require 'threatstack/entities/ruleset'
7
+ require 'threatstack/entities/rule'
6
8
 
7
9
  module Threatstack
8
10
  class InvalidEntity < StandardError; end
9
11
  class Response
10
- attr_reader :entity, :raw
11
- def initialize(entity, raw)
12
- @raw = raw
13
- @entity = entity
14
- end
12
+ attr_reader :entity, :raw, :client
13
+ include Serializable
15
14
 
16
15
  def agents
17
16
  raise InvalidEntity unless entity == :agent
18
- raw.map{ |a| Agent.new(a) }
17
+ raw.map{ |a| Agent.new(a, client) }
19
18
  end
20
19
 
21
20
  def alerts
22
21
  raise InvalidEntity unless entity == :alert
23
- raw.map{ |a| Alert.new(a) }
22
+ raw.map{ |a| Alert.new(a, client) }
23
+ end
24
+
25
+ def cves
26
+ raise InvalidEntity unless entity == :cve
27
+ raw.map{ |a| Cve.new(a, client) }
24
28
  end
25
29
 
26
- def logs
27
- raise InvalidEntity unless entity == :log
28
- raw.map{ |a| Log.new(a) }
30
+ def rulesets
31
+ raise InvalidEntity unless entity == :ruleset
32
+ raw.map{ |r| Ruleset.new(r, client) }
29
33
  end
30
34
 
31
- def organizations
32
- raise InvalidEntity unless entity == :organization
33
- raw.map{ |a| Organization.new(a) }
35
+ def rules
36
+ raise InvalidEntity unless entity == :rule
37
+ raw.map{ |r| Rule.new(r, client) }
34
38
  end
35
39
 
36
- def policies
37
- raise InvalidEntity unless entity == :policy
38
- raw.map{ |a| Policy.new(a) }
40
+ def list
41
+ raw.map { |g| GenericObject.new(g, client) }
39
42
  end
40
43
  end
41
44
  end
@@ -1,23 +1,29 @@
1
1
  module Threatstack
2
2
  module Serializable
3
- attr_reader :raw
3
+ attr_reader :client, :raw
4
4
 
5
5
  def self.included(base)
6
6
  base.extend ClassMethods
7
7
  end
8
8
 
9
- def initialize(raw)
9
+ def initialize(raw, client, entity: nil)
10
+ @client = client
10
11
  @raw = raw
12
+ @entity = entity
11
13
  end
12
14
 
13
15
  def method_missing(m, *args)
14
- raw[m.to_s]
16
+ raw[m.to_s] || raw[camelize(m.to_s)]
15
17
  end
16
18
 
17
19
  def attrs
18
- @attrs ||= self.class.default_attrs + raw.keys.map(&:to_sym)
20
+ @attrs ||= self.class.default_attrs
19
21
  end
20
22
 
23
+ def camelize(str)
24
+ string = str.sub(/^(?:(?=\b|[A-Z_])|\w)/) { $&.downcase }
25
+ string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub('/', '::')
26
+ end
21
27
  module ClassMethods
22
28
  def attributes(*args)
23
29
  @default_attrs = args
@@ -1,3 +1,3 @@
1
1
  module Threatstack
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: threatstack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Canty
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-20 00:00:00.000000000 Z
11
+ date: 2017-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -99,16 +99,13 @@ files:
99
99
  - lib/threatstack/client.rb
100
100
  - lib/threatstack/entities/agent.rb
101
101
  - lib/threatstack/entities/alert.rb
102
- - lib/threatstack/entities/event.rb
103
- - lib/threatstack/entities/log.rb
104
- - lib/threatstack/entities/organization.rb
105
- - lib/threatstack/entities/policy.rb
102
+ - lib/threatstack/entities/cve.rb
103
+ - lib/threatstack/entities/generic_object.rb
106
104
  - lib/threatstack/entities/rule.rb
107
- - lib/threatstack/entities/user_identity.rb
105
+ - lib/threatstack/entities/ruleset.rb
108
106
  - lib/threatstack/response.rb
109
107
  - lib/threatstack/serializable.rb
110
108
  - lib/threatstack/version.rb
111
- - threatstack-0.1.0.gem
112
109
  - threatstack.gemspec
113
110
  homepage: https://github.com/getoutreach/threatstack
114
111
  licenses:
@@ -1,13 +0,0 @@
1
- require 'threatstack/entities/user_identity'
2
- require 'threatstack/serializable'
3
-
4
- module Threatstack
5
- class Event
6
- include Serializable
7
- attributes :user_identity
8
-
9
- def user_identity
10
- UserIdentity.new(raw['userIdentity'])
11
- end
12
- end
13
- end
@@ -1,7 +0,0 @@
1
- require 'threatstack/serializable'
2
-
3
- module Threatstack
4
- class Organization
5
- include Serializable
6
- end
7
- end
@@ -1,12 +0,0 @@
1
- require 'threatstack/entities/rule'
2
-
3
- module Threatstack
4
- class Policy
5
- include Serializable
6
- attributes :rules
7
-
8
- def rules
9
- raw['alert_policy'].map{ |r| Rule.new(r) }
10
- end
11
- end
12
- end
@@ -1,32 +0,0 @@
1
- require 'threatstack/serializable'
2
-
3
- module Threatstack
4
- class UserIdentity
5
- include Serializable
6
- attributes :user_name, :session_context, :invoked_by, :account_id, :access_key_id, :principal_id
7
-
8
- def user_name
9
- raw['userName']
10
- end
11
-
12
- def session_context
13
- raw['sessionContext']
14
- end
15
-
16
- def invoked_by
17
- raw['invokedBy']
18
- end
19
-
20
- def account_id
21
- raw['accountId']
22
- end
23
-
24
- def access_key_id
25
- raw['accessKeyId']
26
- end
27
-
28
- def principal_id
29
- raw['principalId']
30
- end
31
- end
32
- end
Binary file