threatstack 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bb2d3822b5477af93812d538e414b247230d3539
4
+ data.tar.gz: 46428650cbe22613630d2f91daa71e8bb79bafee
5
+ SHA512:
6
+ metadata.gz: eccd2edb7ed85e4cb2e9818413e8ecc54361407c03920b912d12a5209302cd0a9b6d88deba537ec54ef07b354d42604ae691f78dbefb26deea069e88e3efe835
7
+ data.tar.gz: fcfca22363bef5e091c8aae805c9589af22d3b61ff1007f3286ef753c37389d728cee48af7e0379c5b79e99a8194f2ea52fcb08ce8c497a9cd117c61a69d0716
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.3
5
+ before_install: gem install bundler -v 1.14.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in threatstack.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Ryan Canty
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # Threatstack
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
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'threatstack'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install threatstack
20
+
21
+ ## Usage
22
+
23
+ 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
+
25
+ ```
26
+ client = Threatstack::Client.new(API_TOKEN)
27
+ client.policies.first.attrs
28
+ => [:rules,
29
+ :id,
30
+ :name,
31
+ :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]
41
+ ```
42
+
43
+ ### Alerts
44
+
45
+ ```
46
+ client = Threatstack::Client.new(API_TOKEN)
47
+ ## All these are optional url params. See the Threatstack API Docs
48
+ alert = client.alerts(start: 3.days.ago, end: Time.now, count: 5).last
49
+ => #<Threatstack::Alert::Alert:0x007fde0b01cbd8
50
+ @raw=
51
+ {"created_at"=>1496850520000,
52
+ "expires_at"=>1496936920000,
53
+ "last_updated_at"=>"2017-06-07T16:03:56.270Z",
54
+ "count"=>4,
55
+ "title"=>"CloudTrail Activity : EC2 Service Policy Changes : CreateVolume by ryan_canty",
56
+ ...
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
+
66
+ ```
67
+
68
+ You can also limit the response if that's important to you:
69
+
70
+ ```
71
+ client.alerts(fields: ['title', 'alerts'])
72
+ => [#<Threatstack::Alert::Alert:0x007fd61348c768
73
+ @raw={"title"=>"CloudTrail Activity (IAM Policy Changes) : CreateAccessKey by ryan_canty", "severity"=>2}>]
74
+ ```
75
+
76
+ You can also get a single alert by id using:
77
+
78
+ ```
79
+ client.alert('1234567890')
80
+ ```
81
+
82
+ ### Agents
83
+
84
+ ```
85
+ client.agents
86
+ => [#<Threatstack::Agent::Agent:0x007fa262b0b2e0 @raw={...}> ]
87
+ client.agent
88
+ => #<Threatstack::Agent::Agent:0x007fa262b0b2e0 @raw={...}>
89
+ ```
90
+
91
+
92
+ ### Policies
93
+
94
+ ```
95
+ client.policies
96
+ => [#<Threatstack::Policy::Policy:0x007fa262b0b2e0 @raw={...}> ]
97
+ client.policy
98
+ => #<Threatstack::Policy::Policy:0x007fa262b0b2e0 @raw={...}>
99
+ ```
100
+
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
+
117
+ ## Development
118
+
119
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
120
+
121
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
122
+
123
+ ## Contributing
124
+
125
+ Bug reports and pull requests are welcome on GitHub at https://github.com/onetwopunch/threatstack.
126
+
127
+
128
+ ## License
129
+
130
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
3
+ require "bundler/setup"
4
+ require "threatstack"
5
+ require "pry"
6
+
7
+ Pry.config.prompt = lambda do |context, nesting, pry|
8
+ "[threatstack] #{context}> "
9
+ end
10
+
11
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ require "threatstack/version"
2
+ require "threatstack/client"
3
+
4
+ module Threatstack
5
+ end
@@ -0,0 +1,9 @@
1
+ require 'threatstack/agent/agent'
2
+
3
+ module Threatstack
4
+ module Agent
5
+ class Agent
6
+ include Serializable
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ require 'threatstack/agent/agent'
2
+
3
+ module Threatstack
4
+ module Agent
5
+ class Response
6
+ attr_reader :raw
7
+ def initialize(raw)
8
+ @raw = raw
9
+ end
10
+
11
+ def agents
12
+ raw.map{ |a| Agent.new(a) }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ require 'threatstack/alert/event'
2
+ require 'threatstack/alert/rule'
3
+ require 'threatstack/serializable'
4
+
5
+ module Threatstack
6
+ module Alert
7
+ class Alert
8
+ include Serializable
9
+ attributes :latest_events, :rule
10
+
11
+ def latest_events
12
+ raw['latest_events'].map do |event|
13
+ Event.new(event)
14
+ end
15
+ end
16
+
17
+ def rule
18
+ Rule.new(raw['rule'])
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ require 'threatstack/alert/user_identity'
2
+ require 'threatstack/serializable'
3
+
4
+ module Threatstack
5
+ module Alert
6
+ class Event
7
+ include Serializable
8
+ attributes :user_identity
9
+
10
+ def user_identity
11
+ UserIdentity.new(raw['userIdentity'])
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'threatstack/alert/alert'
2
+ require 'threatstack/serializable'
3
+
4
+ module Threatstack
5
+ module Alert
6
+ class Response
7
+ include Serializable
8
+ attributes :alerts
9
+
10
+ def alerts
11
+ raw.map{ |a| Alert.new(a) }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ require 'threatstack/serializable'
2
+ module Threatstack
3
+ module Alert
4
+ class Rule
5
+ include Serializable
6
+ attributes :original_rule
7
+
8
+ def original_rule
9
+ Rule.new(raw['original_rule'])
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,34 @@
1
+ require 'threatstack/serializable'
2
+
3
+ module Threatstack
4
+ module Alert
5
+ class UserIdentity
6
+ include Serializable
7
+ attributes :user_name, :session_context, :invoked_by, :account_id, :access_key_id, :principal_id
8
+
9
+ def user_name
10
+ raw['userName']
11
+ end
12
+
13
+ def session_context
14
+ raw['sessionContext']
15
+ end
16
+
17
+ def invoked_by
18
+ raw['invokedBy']
19
+ end
20
+
21
+ def account_id
22
+ raw['accountId']
23
+ end
24
+
25
+ def access_key_id
26
+ raw['accessKeyId']
27
+ end
28
+
29
+ def principal_id
30
+ raw['principalId']
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,93 @@
1
+ require 'open-uri'
2
+ require 'httparty'
3
+ require 'threatstack/alert/response'
4
+ require 'threatstack/alert/alert'
5
+ require 'threatstack/agent/response'
6
+ require 'threatstack/agent/agent'
7
+ require 'threatstack/policy/response'
8
+ require 'threatstack/policy/policy'
9
+ require 'threatstack/organization/response'
10
+ require 'threatstack/log/response'
11
+
12
+ module Threatstack
13
+ class ThreatstackError < StandardError; end
14
+
15
+ class Client
16
+ THREATSTACK_API = 'https://app.threatstack.com/api/v1'
17
+
18
+ attr_reader :token, :org_id
19
+
20
+ def initialize(token)
21
+ @token = token
22
+ end
23
+
24
+ def alerts(params = {})
25
+ response = do_request(:get, 'alerts', params)
26
+ Alert::Response.new(response).alerts
27
+ end
28
+
29
+ def alert(alert_id, params = {})
30
+ raise ThreatstackError, "Must specify alert id" unless alert_id
31
+ response = do_request(:get, "alerts/#{alert_id}", params)
32
+ Alert::Alert.new(response)
33
+ end
34
+
35
+ def agents(params = {})
36
+ response = do_request(:get, 'agents', params)
37
+ Agent::Response.new(response).agents
38
+ end
39
+
40
+ def agent(agent_id, params = {})
41
+ raise ThreatstackError, "Must specify agent id" unless agent_id
42
+ response = do_request(:get, "agents/#{agent_id}", params)
43
+ Agent::Agent.new(response)
44
+ end
45
+
46
+ def policies(params = {})
47
+ response = do_request(:get, 'policies', params)
48
+ Policy::Response.new(response).policies
49
+ end
50
+
51
+ def policy(policy_id, params = {})
52
+ raise ThreatstackError, "Must specify policy id" unless policy_id
53
+ response = do_request(:get, "policies/#{policy_id}", params)
54
+ Policy::Policy.new(response)
55
+ end
56
+
57
+ def organizations(params = {})
58
+ response = do_request(:get, 'organizations', params)
59
+ Organization::Response.new(response).organizations
60
+ end
61
+
62
+ def logs(params = {})
63
+ response = do_request(:get, 'logs', params)
64
+ Log::Response.new(response).logs
65
+ end
66
+
67
+ def search(query, params = {})
68
+ logs(params.merge(q: query))
69
+ end
70
+
71
+ private
72
+
73
+ def do_request(method, path, params = {})
74
+ response = HTTParty.public_send(method, build_uri(path, params), headers: { "Authorization" => token })
75
+ if response.instance_of?(Hash) && response['status'] == 'error'
76
+ raise ThreatstackError, response['message']
77
+ end
78
+ response
79
+ end
80
+
81
+ def build_uri(path, params = {})
82
+ params[:start] = params[:start].utc if params[:start]
83
+ params[:end] = params[:end].utc if params[:end]
84
+ params[:fields] = params[:fields].join(',') if params[:fields]&.is_a?(Array)
85
+
86
+ query = params.each_pair.map { |k, v| "#{k}=#{v}" }.join('&')
87
+ uri = "#{THREATSTACK_API}/#{path}"
88
+ uri += "?#{URI::encode(query)}" if params.any?
89
+ uri
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,9 @@
1
+ require 'threatstack/serializable'
2
+
3
+ module Threatstack
4
+ module Log
5
+ class Log
6
+ include Serializable
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ require 'threatstack/log/log'
2
+
3
+ module Threatstack
4
+ module Log
5
+ class Response
6
+ include Serializable
7
+ attributes :logs
8
+
9
+ def logs
10
+ raw.map{ |a| Log.new(a) }
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ require 'threatstack/organization/organization'
2
+ require 'threatstack/serializable'
3
+
4
+ module Threatstack
5
+ module Organization
6
+ class Organization
7
+ include Serializable
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ require 'threatstack/organization/organization'
2
+ require 'threatstack/serializable'
3
+
4
+ module Threatstack
5
+ module Organization
6
+ class Response
7
+ include Serializable
8
+ attributes :organizations
9
+
10
+ def organizations
11
+ raw.map{ |a| Organization.new(a) }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'threatstack/policy/policy'
2
+ require 'threatstack/alert/rule'
3
+
4
+ module Threatstack
5
+ module Policy
6
+ class Policy
7
+ include Serializable
8
+ attributes :rules
9
+
10
+ def rules
11
+ raw['alert_policy'].map{ |r| Threatstack::Alert::Rule.new(r) }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'threatstack/policy/policy'
2
+ require 'threatstack/serializable'
3
+
4
+ module Threatstack
5
+ module Policy
6
+ class Response
7
+ include Serializable
8
+ attributes :policies
9
+
10
+ def policies
11
+ raw.map{ |a| Policy.new(a) }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ module Threatstack
2
+ module Serializable
3
+ attr_reader :raw
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ def initialize(raw)
10
+ @raw = raw
11
+ end
12
+
13
+ def method_missing(m, *args)
14
+ raw[m.to_s]
15
+ end
16
+
17
+ def attrs
18
+ @attrs ||= self.class.default_attrs + raw.keys.map(&:to_sym)
19
+ end
20
+
21
+ module ClassMethods
22
+ def attributes(*args)
23
+ @default_attrs = args
24
+ end
25
+
26
+ def default_attrs
27
+ @default_attrs ||= []
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Threatstack
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'threatstack/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "threatstack"
8
+ spec.version = Threatstack::VERSION
9
+ spec.authors = ["Ryan Canty"]
10
+ spec.email = ["jrcanty@gmail.com"]
11
+
12
+ spec.summary = %q{Threatstack API integration for Ruby}
13
+ spec.description = %q{Threatstack API integration for Ruby}
14
+ spec.homepage = "https://github.com/onetwopunch/threatstack"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.14"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "minitest", "~> 5.0"
27
+ spec.add_development_dependency "pry"
28
+ spec.add_runtime_dependency "httparty"
29
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: threatstack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Canty
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-06-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Threatstack API integration for Ruby
84
+ email:
85
+ - jrcanty@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".travis.yml"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - bin/console
97
+ - bin/setup
98
+ - lib/threatstack.rb
99
+ - lib/threatstack/agent/agent.rb
100
+ - lib/threatstack/agent/response.rb
101
+ - lib/threatstack/alert/alert.rb
102
+ - lib/threatstack/alert/event.rb
103
+ - lib/threatstack/alert/response.rb
104
+ - lib/threatstack/alert/rule.rb
105
+ - lib/threatstack/alert/user_identity.rb
106
+ - lib/threatstack/client.rb
107
+ - lib/threatstack/log/log.rb
108
+ - lib/threatstack/log/response.rb
109
+ - lib/threatstack/organization/organization.rb
110
+ - lib/threatstack/organization/response.rb
111
+ - lib/threatstack/policy/policy.rb
112
+ - lib/threatstack/policy/response.rb
113
+ - lib/threatstack/serializable.rb
114
+ - lib/threatstack/version.rb
115
+ - threatstack.gemspec
116
+ homepage: https://github.com/onetwopunch/threatstack
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.6.10
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Threatstack API integration for Ruby
140
+ test_files: []