ats 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ade04cb82df5186dcc5e66d3d097f7586b7de46389aacfe5fe0244c21d7349a4
4
+ data.tar.gz: e6c84e03d1f6d7dc030b48536091b67d6ca5df024782ecdf02aa375f01b4ca7d
5
+ SHA512:
6
+ metadata.gz: dbdadbed11f23133cdaa012e039e840cd4856c4209d443fca3b8bd8f359ffb1cb83fd90000977bb8ae8da899cc5203b8436bbca0deb726dd7271fd9781c69d5a
7
+ data.tar.gz: 20f5685b7b7b2fb24a50107c7c80ba961cbe22d9e5a1af87a26a1a8cc42df58b810f27180a0326103146de651b60c136761b7c3fa9ddf395070c92dea6a7cafd
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in ats-cli.gemspec
6
+ gemspec
@@ -0,0 +1,37 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ats (0.1.0)
5
+ thor (~> 0.20)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.3)
11
+ rake (10.5.0)
12
+ rspec (3.7.0)
13
+ rspec-core (~> 3.7.0)
14
+ rspec-expectations (~> 3.7.0)
15
+ rspec-mocks (~> 3.7.0)
16
+ rspec-core (3.7.1)
17
+ rspec-support (~> 3.7.0)
18
+ rspec-expectations (3.7.0)
19
+ diff-lcs (>= 1.2.0, < 2.0)
20
+ rspec-support (~> 3.7.0)
21
+ rspec-mocks (3.7.0)
22
+ diff-lcs (>= 1.2.0, < 2.0)
23
+ rspec-support (~> 3.7.0)
24
+ rspec-support (3.7.1)
25
+ thor (0.20.0)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ ats!
32
+ bundler (~> 1.16)
33
+ rake (~> 10.0)
34
+ rspec (~> 3.0)
35
+
36
+ BUNDLED WITH
37
+ 1.16.1
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 mokha
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.
@@ -0,0 +1,39 @@
1
+ # Ats::Cli
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/ats/cli`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'ats-cli'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install ats-cli
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ 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).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/ats-cli.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,30 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "ats/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ats"
8
+ spec.version = ATS::VERSION
9
+ spec.authors = ["mokha"]
10
+ spec.email = ["mo@mokhan.ca"]
11
+
12
+ spec.summary = %q{A CLI for interacting with ATS.}
13
+ spec.description = %q{A CLI for interacting with ATS.}
14
+ spec.homepage = "https://www.mokhan.ca/"
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
+ f.match(/^\..*/) ||
20
+ f.match(%r{^bin/.*})
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency 'thor', '~> 0.20'
27
+ spec.add_development_dependency "bundler", "~> 1.16"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "rspec", "~> 3.0"
30
+ end
data/exe/ats ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ats/cli'
4
+
5
+ ATS::CLI::Application.start(ARGV)
@@ -0,0 +1,29 @@
1
+ require 'json'
2
+ require 'logger'
3
+ require 'net/http'
4
+ require 'yaml'
5
+
6
+ require 'ats/configuration'
7
+ require 'ats/http_api'
8
+ require 'ats/threat_grid/api'
9
+ require 'ats/threat_grid/organizations'
10
+ require 'ats/threat_grid/samples'
11
+ require 'ats/threat_grid/search'
12
+ require 'ats/threat_grid/users'
13
+ require 'ats/version'
14
+
15
+ module ATS
16
+ class << self
17
+ def logger
18
+ configuration.logger
19
+ end
20
+
21
+ def configure
22
+ yield configuration
23
+ end
24
+
25
+ def configuration
26
+ @configuration ||= Configuration.new
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ require 'thor'
2
+
3
+ require 'ats'
4
+ require 'ats/cli/threat_grid'
5
+
6
+ module ATS
7
+ module CLI
8
+ class Application < Thor
9
+ package_name "ATS"
10
+
11
+ desc 'threatgrid SUBCOMMAND ...ARGS', 'interact with the Threat Grid API'
12
+ subcommand 'threatgrid', ThreatGrid::Application
13
+
14
+ desc 'version', 'Display the current version'
15
+ def version
16
+ say ATS::VERSION
17
+ end
18
+
19
+ desc 'setup', 'Initialize the .atsrc file.'
20
+ def setup(configuration = ATS.configuration)
21
+ say "Current Configuration:", :green
22
+ say JSON.pretty_generate(configuration.configuration), :green
23
+
24
+ configuration.config_files.each do |file|
25
+ if File.exist?(file)
26
+ say "Found #{file}. Nothing to do. Good bye!", :green
27
+ exit 0
28
+ end
29
+ end
30
+
31
+ say "Configuration file not found."
32
+ new_file = configuration.config_files.first
33
+ say "New file created at #{new_file}."
34
+ yaml = YAML.dump({
35
+ default: {
36
+ threat_grid: {
37
+ api_host: 'https://example.com',
38
+ api_key: 'secret'
39
+ }
40
+ }
41
+ })
42
+ say yaml, :yellow
43
+ IO.write(new_file, yaml)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,14 @@
1
+ require 'ats/cli/threat_grid/command'
2
+ require 'ats/cli/threat_grid/organizations'
3
+ require 'ats/cli/threat_grid/samples'
4
+ require 'ats/cli/threat_grid/search'
5
+ require 'ats/cli/threat_grid/users'
6
+
7
+ require 'ats/cli/threat_grid/application'
8
+
9
+ module ATS
10
+ module CLI
11
+ module ThreatGrid
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ module ATS
2
+ module CLI
3
+ module ThreatGrid
4
+ class Application < Thor
5
+ class_option :profile, default: :default, required: false
6
+
7
+ desc 'users SUBCOMMAND ...ARGS', 'interact with the Threat Grid API'
8
+ subcommand :users, ATS::CLI::ThreatGrid::Users
9
+
10
+ desc 'organizations SUBCOMMAND ...ARGS', 'interact with the Threat Grid API'
11
+ subcommand :organizations, ATS::CLI::ThreatGrid::Organizations
12
+
13
+ desc 'samples SUBCOMMAND ...ARGS', 'interact with the Threat Grid API'
14
+ subcommand :samples, ATS::CLI::ThreatGrid::Samples
15
+
16
+ desc 'search SUBCOMMAND ...ARGS', 'interact with the Threat Grid API'
17
+ subcommand :search, ATS::CLI::ThreatGrid::Search
18
+
19
+ desc 'whoami', 'whoami'
20
+ def whoami
21
+ say JSON.pretty_generate(ATS::ThreatGrid::API.new(profile: options['profile']).whoami)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module ATS
2
+ module CLI
3
+ module ThreatGrid
4
+ class Command < Thor
5
+ class_option :profile, default: :default, required: false
6
+
7
+ def self.printable_commands(*args)
8
+ super.map do |x|
9
+ x[0] = x[0].gsub(/^ats/, 'ats threatgrid')
10
+ x
11
+ end
12
+ end
13
+
14
+ protected
15
+
16
+ def api
17
+ ATS::ThreatGrid::API.new(profile: options['profile'])
18
+ end
19
+
20
+ def print_json(json)
21
+ say JSON.pretty_generate(json), :green
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ module ATS
2
+ module CLI
3
+ module ThreatGrid
4
+ class Organizations < Command
5
+ desc 'search <TERM>', 'search'
6
+ def search(term)
7
+ print_json api.organizations.search(term)
8
+ end
9
+
10
+ desc 'list', 'list'
11
+ def list
12
+ print_json api.organizations.list
13
+ end
14
+
15
+ desc 'show <ORG_ID>', 'show'
16
+ def show(org_id)
17
+ print_json api.organizations.show(org_id)
18
+ end
19
+
20
+ desc 'users <ORG_ID>', 'users'
21
+ def users(org_id)
22
+ print_json api.organizations.users(org_id)
23
+ end
24
+
25
+ desc 'samples <ORG_ID>', 'samples'
26
+ def samples(org_id)
27
+ print_json api.organizations.samples(org_id)
28
+ end
29
+
30
+ desc 'user-activity <ORG_ID>', 'user-activity'
31
+ def user_activity(org_id)
32
+ print_json api.organizations.user_activity(org_id)
33
+ end
34
+
35
+ desc 'entitlements <ORG_ID>', 'entitlements'
36
+ def entitlements(org_id)
37
+ print_json api.organizations.entitlements(org_id)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,12 @@
1
+ module ATS
2
+ module CLI
3
+ module ThreatGrid
4
+ class Samples < Command
5
+ desc 'search <SHA256>', 'Search samples'
6
+ def search(term)
7
+ print_json api.samples.search(term)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module ATS
2
+ module CLI
3
+ module ThreatGrid
4
+ class Search < Command
5
+ desc 'urls <URL>', 'Search urls'
6
+ def urls(url)
7
+ print_json api.search.urls(url)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ module ATS
2
+ module CLI
3
+ module ThreatGrid
4
+ class Users < Command
5
+ desc 'show <login>', 'show'
6
+ def show(login)
7
+ print_json api.users.show(login)
8
+ end
9
+
10
+ desc 'organization <login>', 'organization'
11
+ def organization(login)
12
+ print_json api.users.organization(login)
13
+ end
14
+
15
+ desc 'activity <login>', 'activity'
16
+ def activity(login)
17
+ print_json api.users.activity(login)
18
+ end
19
+
20
+ desc 'samples <login>', 'samples'
21
+ def samples(login)
22
+ print_json api.users.samples(login)
23
+ end
24
+
25
+ desc 'rate-limit <login>', 'rate-limit'
26
+ def rate_limit(login)
27
+ print_json api.users.rate_limit(login)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ module ATS
2
+ class Configuration
3
+ attr_accessor :logger, :config_files, :configuration
4
+
5
+ def initialize
6
+ @logger = Logger.new(STDOUT)
7
+ @logger.level = Logger::DEBUG
8
+ @config_files = [
9
+ File.join(Dir.home, ".atsrc"),
10
+ File.expand_path('.atsrc'),
11
+ ENV['ATSRC']
12
+ ].compact
13
+
14
+ @configuration = load_configuration
15
+ end
16
+
17
+ def [](key)
18
+ @configuration[key]
19
+ end
20
+
21
+ def load_configuration(files = config_files)
22
+ files.inject({}) do |memo, file|
23
+ logger.debug("Loading... #{file}")
24
+ memo.merge!(YAML.load(IO.read(file))) if File.exist?(file)
25
+ memo
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ module ATS
2
+ class HttpAPI
3
+ def initialize(headers: {})
4
+ @default_headers = headers
5
+ end
6
+
7
+ def execute(uri, request)
8
+ http_for(uri).request(request)
9
+ end
10
+
11
+ def get(uri, headers: {}, body: {})
12
+ request = get_for(uri, headers: headers, body: body)
13
+ response = execute(uri, request)
14
+ if block_given?
15
+ yield request, response
16
+ else
17
+ response
18
+ end
19
+ end
20
+
21
+ def post(uri, headers: {}, body: {})
22
+ request = post_for(uri, headers: headers, body: body)
23
+ response = execute(uri, request)
24
+ if block_given?
25
+ yield request, response
26
+ else
27
+ response
28
+ end
29
+ end
30
+
31
+ def put(uri, headers: {}, body: {})
32
+ request = put_for(uri, headers: headers, body: body)
33
+ response = execute(uri, request)
34
+ if block_given?
35
+ yield request, response
36
+ else
37
+ response
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def http_for(uri)
44
+ http = Net::HTTP.new(uri.host, uri.port)
45
+ http.read_timeout = 30
46
+ http.use_ssl = uri.is_a?(URI::HTTPS)
47
+ http.set_debug_output(ATS.logger)
48
+ http
49
+ end
50
+
51
+ def post_for(uri, headers: {}, body: {})
52
+ Net::HTTP::Post.new(uri.path, @default_headers.merge(headers)).tap do |x|
53
+ x.body = JSON.generate(body)
54
+ end
55
+ end
56
+
57
+ def put_for(uri, headers: {}, body: {})
58
+ Net::HTTP::Put.new(uri.path, @default_headers.merge(headers)).tap do |x|
59
+ x.body = JSON.generate(body)
60
+ end
61
+ end
62
+
63
+ def get_for(uri, headers: {}, body: {})
64
+ Net::HTTP::Get.new(uri.path, @default_headers.merge(headers)).tap do |x|
65
+ x.body = JSON.generate(body)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,68 @@
1
+ require 'ats/http_api'
2
+
3
+ module ATS
4
+ module ThreatGrid
5
+ class API
6
+ HEADERS = {
7
+ 'Content-Type' => 'application/json',
8
+ 'User-Agent' => "RubyGems/ATS #{ATS::VERSION}",
9
+ }.freeze
10
+
11
+ attr_reader :http, :profile, :configuration
12
+
13
+ def initialize(
14
+ api: HttpAPI.new(headers: HEADERS),
15
+ profile: :default,
16
+ configuration: ATS.configuration
17
+ )
18
+ @http = api
19
+ @profile = profile.to_s
20
+ @configuration = configuration
21
+ end
22
+
23
+ def whoami
24
+ get("session/whoami")
25
+ end
26
+
27
+ def users
28
+ ATS::ThreatGrid::Users.new(self)
29
+ end
30
+
31
+ def organizations
32
+ ATS::ThreatGrid::Organizations.new(self)
33
+ end
34
+
35
+ def samples
36
+ ATS::ThreatGrid::Samples.new(self)
37
+ end
38
+
39
+ def search
40
+ ATS::ThreatGrid::Search.new(self)
41
+ end
42
+
43
+ def get(url, params: {}, version: 3)
44
+ http.get(build_uri(url, version: version), body: default_payload.merge(params)) do |request, response|
45
+ JSON.parse(response.body, symbolize_names: true)[:data]
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def default_payload
52
+ { api_key: api_key }
53
+ end
54
+
55
+ def build_uri(relative_url, version:)
56
+ URI.parse("#{api_host}/api/v#{version}/#{relative_url}")
57
+ end
58
+
59
+ def api_key
60
+ configuration[profile]['threat_grid']['api_key']
61
+ end
62
+
63
+ def api_host
64
+ configuration[profile]['threat_grid']['api_host']
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,39 @@
1
+ module ATS
2
+ module ThreatGrid
3
+ class Organizations
4
+ attr_reader :api
5
+
6
+ def initialize(api)
7
+ @api = api
8
+ end
9
+
10
+ def list
11
+ api.get("organizations")
12
+ end
13
+
14
+ def search(term)
15
+ api.get("organizations", params: { query: term })
16
+ end
17
+
18
+ def show(id)
19
+ api.get("organizations/#{id}")
20
+ end
21
+
22
+ def users(id)
23
+ api.get("organizations/#{id}/users")
24
+ end
25
+
26
+ def samples(id)
27
+ api.get("organizations/#{id}/samples")
28
+ end
29
+
30
+ def user_activity(id)
31
+ api.get("organizations/#{id}/user-activity")
32
+ end
33
+
34
+ def entitlements(id)
35
+ api.get("organizations/#{id}/entitlements")
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module ATS
2
+ module ThreatGrid
3
+ class Samples
4
+ attr_reader :api
5
+
6
+ def initialize(api)
7
+ @api = api
8
+ end
9
+
10
+ def search(term)
11
+ api.get("samples/search", params: { checksum: term })
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module ATS
2
+ module ThreatGrid
3
+ class Search
4
+ attr_reader :api
5
+
6
+ def initialize(api)
7
+ @api = api
8
+ end
9
+
10
+ def urls(url)
11
+ api.get("search/urls", params: { url: url }, version: 2)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ module ATS
2
+ module ThreatGrid
3
+ class Users
4
+ attr_reader :api
5
+
6
+ def initialize(api)
7
+ @api = api
8
+ end
9
+
10
+ def show(login)
11
+ api.get("users/#{login}")
12
+ end
13
+
14
+ def organization(login)
15
+ api.get("users/#{login}/organization")
16
+ end
17
+
18
+ def activity(login)
19
+ api.get("users/#{login}/activity")
20
+ end
21
+
22
+ def samples(login)
23
+ api.get("users/#{login}/samples")
24
+ end
25
+
26
+ def rate_limit(login)
27
+ api.get("users/#{login}/rate-limit")
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module ATS
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ats
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - mokha
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-03-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.20'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.20'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: A CLI for interacting with ATS.
70
+ email:
71
+ - mo@mokhan.ca
72
+ executables:
73
+ - ats
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - Gemfile
78
+ - Gemfile.lock
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - ats-cli.gemspec
83
+ - exe/ats
84
+ - lib/ats.rb
85
+ - lib/ats/cli.rb
86
+ - lib/ats/cli/threat_grid.rb
87
+ - lib/ats/cli/threat_grid/application.rb
88
+ - lib/ats/cli/threat_grid/command.rb
89
+ - lib/ats/cli/threat_grid/organizations.rb
90
+ - lib/ats/cli/threat_grid/samples.rb
91
+ - lib/ats/cli/threat_grid/search.rb
92
+ - lib/ats/cli/threat_grid/users.rb
93
+ - lib/ats/configuration.rb
94
+ - lib/ats/http_api.rb
95
+ - lib/ats/threat_grid/api.rb
96
+ - lib/ats/threat_grid/organizations.rb
97
+ - lib/ats/threat_grid/samples.rb
98
+ - lib/ats/threat_grid/search.rb
99
+ - lib/ats/threat_grid/users.rb
100
+ - lib/ats/version.rb
101
+ homepage: https://www.mokhan.ca/
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.7.6
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: A CLI for interacting with ATS.
125
+ test_files: []