ruby-taxii2 0.3.1

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
+ SHA256:
3
+ metadata.gz: fc528f87e1d77992648872b73b304cadd0770fcd61104a013b968da7c6db8712
4
+ data.tar.gz: d84191bbf3ef2aa98e43e6ab76c73e63f277387141bd406f5ee670b6a1c1b879
5
+ SHA512:
6
+ metadata.gz: ca13340ef9443169c8aafba8ee2181398eb1c26c8544c463508236d717ea1697eec8627fc23b6f34391356bd6816f71eee28c50aea2ea06b8a259b4d3f36a6ac
7
+ data.tar.gz: eaee116e0eb3ddae02329cd3c6287b81ad00bf80bb7ac3afb961fd5dcda7f2d53ceb0927230b041f38e43fce2c227cdd2ede6b9189376d69879dd8648276f4fb
@@ -0,0 +1,18 @@
1
+ name: Ruby Gem
2
+
3
+ on:
4
+ push:
5
+ branches: '**'
6
+
7
+ jobs:
8
+ build:
9
+ name: RSpec
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v3
13
+ - name: Set up Ruby
14
+ uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: 3.1.2
17
+ - run: bundle
18
+ - run: bundle exec rspec
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ .DS_Store
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /spec/fixtures/spec_ca/
11
+ /tmp/
12
+ /vendor/bundle/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ruby-taxii.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,55 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ guard :bundler do
19
+ require 'guard/bundler'
20
+ require 'guard/bundler/verify'
21
+ helper = Guard::Bundler::Verify.new
22
+
23
+ files = ['Gemfile']
24
+ files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) }
25
+
26
+ # Assume files are symlinked from somewhere
27
+ files.each { |file| watch(helper.real_path(file)) }
28
+ end
29
+
30
+ # Note: The cmd option is now required due to the increasing number of ways
31
+ # rspec may be run, below are examples of the most common uses.
32
+ # * bundler: 'bundle exec rspec'
33
+ # * bundler binstubs: 'bin/rspec'
34
+ # * spring: 'bin/rspec' (This will use spring if running and you have
35
+ # installed the spring binstubs per the docs)
36
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
37
+ # * 'just' rspec: 'rspec'
38
+
39
+ guard :rspec, cmd: "bundle exec rspec" do
40
+ require "guard/rspec/dsl"
41
+ dsl = Guard::RSpec::Dsl.new(self)
42
+
43
+ # Feel free to open issues for suggestions and improvements
44
+
45
+ # RSpec files
46
+ rspec = dsl.rspec
47
+ watch(rspec.spec_helper) { rspec.spec_dir }
48
+ watch(rspec.spec_support) { rspec.spec_dir }
49
+ watch(rspec.spec_files)
50
+
51
+ # Ruby files
52
+ ruby = dsl.ruby
53
+ dsl.watch_spec_files_for(ruby.lib_files)
54
+
55
+ end
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Ruby::Taxii
2
+
3
+ Ruby TAXII client
4
+
5
+ Currently under development - likely to break at a moment's notice.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'ruby-taxii'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install ruby-taxii
22
+
23
+ ## Usage
24
+
25
+
26
+ ## Development
27
+
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ryanbreed/ruby-taxii.
data/Rakefile ADDED
@@ -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
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ruby/taxii"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,82 @@
1
+ module Taxii
2
+ module Client
3
+ def self.included(klass)
4
+ klass.class_eval do
5
+ attr_accessor :url, :user, :pass, :client_cert, :client_key, :ca_cert
6
+ attr_reader :xml
7
+ def initialize(*args)
8
+ Hash[*args].each {|k,v| self.send(format('%s=',k),v)}
9
+ @user ||= 'admin'
10
+ @pass ||= 'avalanche'
11
+ @xml = Nori.new(strip_namespaces: true)
12
+ self
13
+ end
14
+ end
15
+ end
16
+
17
+ def build_request(url: self.url,payload: {}, format: Taxii::Messages::TAXII_11_HEADERS)
18
+ RestClient::Request.new(
19
+ method: :post,
20
+ url: url,
21
+ user: user,
22
+ password: pass,
23
+ payload: payload,
24
+ timeout: nil,
25
+ headers: {
26
+ 'X-Taxii-Services' => 'urn:taxii.mitre.org:services:1.1',
27
+ :content_type => 'application/xml',
28
+ :accept => 'application/xml'
29
+ }.merge(format)
30
+ .merge(scheme_protocol)
31
+ )
32
+ end
33
+
34
+ def get_service_address(service_name)
35
+ service = discover_services.find do |svc|
36
+ svc['@service_type']==service_name && svc['@available']=='true'
37
+ end
38
+ service.nil? ? nil : service['Address']
39
+ end
40
+
41
+ def discover_services
42
+ payload = Taxii::Messages::DiscoveryRequest.new.to_xml
43
+ response = build_request(url: self.url, payload: payload).execute
44
+ parsed = xml.parse(response.body)
45
+ parsed['Discovery_Response'].fetch('Service_Instance',[])
46
+ end
47
+
48
+ def discovery_service_url
49
+ self.url
50
+ end
51
+
52
+ def inbox_service_url
53
+ @inbox_service_url ||= get_service_address('INBOX')
54
+ end
55
+
56
+ def collection_management_service_url
57
+ @collection_management_service_url ||= get_service_address('COLLECTION_MANAGEMENT')
58
+ end
59
+
60
+ def poll_service_url
61
+ @poll_service_url ||= get_service_address('POLL')
62
+ end
63
+
64
+ def discover_feeds(url=self.collection_management_service_url)
65
+ msg = Taxii::Messages::FeedInformationRequest.new.to_xml
66
+ http = build_request(url: url, payload: msg, format: Taxii::Messages::TAXII_10_HEADERS)
67
+ parsed = xml.parse(http.execute.body)
68
+ parsed['Feed_Information_Response'].fetch('Feed',[])
69
+ end
70
+
71
+ def scheme_protocol
72
+ case URI.parse(url).scheme
73
+ when "http"
74
+ { 'X-Taxii-Protocol' => 'urn:taxii.mitre.org:protocol:http:1.0' }
75
+ when "https"
76
+ { 'X-Taxii-Protocol' => 'urn:taxii.mitre.org:protocol:https:1.0' }
77
+ else
78
+ {}
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,17 @@
1
+ module Taxii
2
+ module Messages
3
+ class DiscoveryRequest < Hashie::Dash
4
+ property :message_id, default: -> { Taxii::Messages.generate_id }
5
+
6
+ def to_h
7
+ Taxii::Messages::NAMESPACE_ATTRIBUTES.merge({
8
+ '@message_id': message_id
9
+ })
10
+ end
11
+
12
+ def to_xml
13
+ Gyoku.xml({'taxii_11:Discovery_Request/': to_h}, key_converter: :none)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ module Taxii
2
+ module Messages
3
+ class FeedInformationRequest < Hashie::Dash
4
+ property :message_id, default: -> { Taxii::Messages.generate_id }
5
+
6
+ def to_h
7
+ Taxii::Messages::NAMESPACE_ATTRIBUTES.merge({
8
+ '@message_id': message_id
9
+ })
10
+ end
11
+
12
+ def to_xml
13
+ Gyoku.xml({'taxii:Feed_Information_Request/': to_h}, key_converter: :none)
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ module Taxii
2
+ module Messages
3
+ module Parameters
4
+ class Delivery
5
+ attr_accessor :protocol_binding, :address, :message_binding
6
+ def intialize(*args)
7
+ Hash[*args].each {|k,v| self.send(format('%s=',k),v)}
8
+ self
9
+ end
10
+ end
11
+
12
+ class Poll < Hashie::Dash
13
+ property :allow_asynch, default: false
14
+ property :response_type, default: 'COUNT_ONLY'
15
+ property :content_binding
16
+
17
+ def response_type=(type)
18
+ unless %w{ FULL COUNT_ONLY }.include?(type)
19
+ fail ArgumentError, "#{type} must be FULL or COUNT_ONLY"
20
+ end
21
+ @response_type=type
22
+ end
23
+
24
+ def to_h
25
+ {
26
+ '@allow_asynch': allow_asynch,
27
+ 'taxii_11:Response_Type': response_type
28
+ }
29
+ end
30
+ def to_xml
31
+ content_hash = if content_binding.nil?
32
+ self.to_h
33
+ else
34
+ self.to_h.merge('taxii_11:Content_Binding!': content_binding)
35
+ end
36
+
37
+ Gyoku.xml({'taxii_11:Poll_Parameters': content_hash}, key_converter: :none)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,58 @@
1
+ module Taxii
2
+ module Messages
3
+ class PollRequest < Hashie::Dash
4
+ include Hashie::Extensions::Coercion
5
+
6
+ property :collection_name, default: 'system.Default'
7
+ property :message_id, default: -> { Taxii::Messages.generate_id }
8
+ property :exclusive_begin_timestamp
9
+ property :inclusive_end_timestamp
10
+ property :subscription_id
11
+ property :poll_parameters,
12
+ required: -> { subscription_id.nil? },
13
+ default: Taxii::Messages::Parameters::Poll.new
14
+ property :query
15
+ property :delivery_parameters
16
+
17
+ coerce_key :exclusive_begin_timestamp, Time
18
+ coerce_key :inclusive_end_timestamp, Time
19
+
20
+ def requested_begin
21
+ if exclusive_begin_timestamp.nil?
22
+ {}
23
+ else
24
+ {'Exclusive_Begin_Timestamp': exclusive_begin_timestamp.strftime(TS_FORMAT)}
25
+ end
26
+ end
27
+
28
+ def requested_end
29
+ if inclusive_end_timestamp.nil?
30
+ {}
31
+ else
32
+ {'Inclusive_End_Timestamp': inclusive_end_timestamp.strftime(TS_FORMAT)}
33
+ end
34
+ end
35
+ def requested_info
36
+ if subscription_id.nil?
37
+ {'taxii_11:Poll_Parameters': poll_parameters.to_h}
38
+ else
39
+ {'taxii_11:Subscription_ID': subscription_id}
40
+ end
41
+ end
42
+
43
+ def to_h
44
+ NAMESPACE_ATTRIBUTES.merge({
45
+ '@message_id': message_id,
46
+ '@collection_name': collection_name
47
+ }).merge(requested_begin)
48
+ .merge(requested_end)
49
+ .merge(requested_info)
50
+ end
51
+
52
+ def to_xml
53
+ Gyoku.xml({'taxii_11:Poll_Request': to_h}, key_converter: :none)
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,25 @@
1
+ module Taxii
2
+ module Messages
3
+ TAXII_11_HEADERS = {
4
+ 'X-Taxii-Accept' => 'urn:taxii.mitre.org:message:xml:1.1',
5
+ 'X-Taxii-Content-Type' => 'urn:taxii.mitre.org:message:xml:1.1'
6
+ }
7
+
8
+ TAXII_10_HEADERS = {
9
+ 'X-Taxii-Accept' => 'urn:taxii.mitre.org:message:xml:1.0',
10
+ 'X-Taxii-Content-Type' => 'urn:taxii.mitre.org:message:xml:1.0'
11
+ }
12
+
13
+ NAMESPACE_ATTRIBUTES = {
14
+ '@xmlns:taxii' => 'http://taxii.mitre.org/messages/taxii_xml_binding-1',
15
+ '@xmlns:taxii_11' => 'http://taxii.mitre.org/messages/taxii_xml_binding-1.1',
16
+ '@xmlns:tdq' => 'http://taxii.mitre.org/query/taxii_default_query-1'
17
+ }
18
+
19
+ TS_FORMAT='%Y-%m-%dT%H:%M:%S%:z'
20
+
21
+ def self.generate_id
22
+ format('%012d%08d',Time.new.to_i,$$)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ # STILL DOOMED TO FAILURE. I WILL KEEP THIS AS A WARNING TO
2
+ # SIMILARLY TERRIBLE CODE
3
+ module Taxii
4
+ module MessageParsers
5
+ class PollResponse < Nokogiri::XML::SAX::Document
6
+ def package_data
7
+ @package_data ||= []
8
+ end
9
+ def capture
10
+ @capture.nil? ? @capture = false : @capture
11
+ end
12
+ def capture=(flag)
13
+ @capture=flag
14
+ end
15
+ def start_element(name, attrs=[])
16
+ if name.match(/taxii_11:Content_Block/)
17
+ STDERR.puts 'START Content_Block'
18
+ self.capture=true
19
+ end
20
+ end
21
+ def characters(str)
22
+ self.package_data << str
23
+ end
24
+ def end_element(name, attrs=[])
25
+ if name.match(/taxii_11:Content_Block/)
26
+ STDERR.puts 'END Content_Block'
27
+ self.capture=false
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ module Taxii
2
+ class PollClient
3
+ include Client
4
+
5
+ PARSE_OPTIONS = Nokogiri::XML::ParseOptions::DEFAULT_XML | Nokogiri::XML::ParseOptions::NOBLANKS
6
+ CONTENT_XPATH = '/taxii_11:Poll_Response/taxii_11:Content_Block/taxii_11:Content'
7
+
8
+ def get( poll_request_message, url: self.poll_service_url)
9
+ msg = format_request(poll_request_message)
10
+ build_request(url: url, payload: msg).execute
11
+ end
12
+
13
+ def get_content_blocks( poll_request_message,
14
+ url: self.poll_service_url,
15
+ xpath: CONTENT_XPATH )
16
+ response = self.get(poll_request_message, url: url)
17
+ content_xml = Nokogiri::XML(response.body,nil,nil,PARSE_OPTIONS)
18
+ content_xml.xpath(xpath).flat_map { |blk| blk.children.map(&:to_s) }
19
+ end
20
+
21
+ def format_request(request_message)
22
+ case request_message
23
+ when String
24
+ request_message
25
+ when Taxii::Messages::PollRequest
26
+ request_message.to_xml
27
+ else
28
+ fail ArgumentError, 'request message must be String or PollRequest'
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,15 @@
1
+ module Taxii
2
+ module TimeExtensions
3
+ def coerce(val)
4
+ case val
5
+ when Integer
6
+ Time.at(val)
7
+ when String
8
+ Time.parse(val)
9
+ else
10
+ val
11
+ end
12
+ end
13
+ end
14
+ end
15
+ Time.extend(Taxii::TimeExtensions)
@@ -0,0 +1,3 @@
1
+ module Taxii
2
+ VERSION = '0.3.1'
3
+ end
data/lib/taxii.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'hashie'
2
+ require 'nokogiri'
3
+ require 'rest-client'
4
+ require 'uri'
5
+ require 'nori'
6
+ require 'gyoku'
7
+
8
+ require 'taxii/version'
9
+ require 'taxii/time_extensions'
10
+ require 'taxii/messages'
11
+ require 'taxii/messages/parameters'
12
+ require 'taxii/messages/discovery_request'
13
+ require 'taxii/messages/poll_request'
14
+ require 'taxii/messages/feed_information_request'
15
+ require 'taxii/client'
16
+ require 'taxii/poll_client'
17
+
18
+ module Taxii
19
+ def self.configure(config: File.join(ENV['HOME'],'.taxii.json'), client: PollClient)
20
+ configuration = JSON.parse(File.read(config))
21
+ client.new(configuration)
22
+ end
23
+
24
+ def self.hail
25
+ PollClient.new(user: 'guest', pass: 'guest', url: 'http://hailataxii.com/taxii-discovery-service')
26
+ end
27
+
28
+ def self.yeti
29
+ PollClient.new(user: 'guest', pass: 'guest', url: 'http://taxiitest.mitre.org/services/discovery/')
30
+ end
31
+
32
+ end
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'taxii/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'ruby-taxii2'
8
+ spec.version = Taxii::VERSION
9
+ spec.authors = ['Dario Lombardo']
10
+ spec.email = ['lomato@gmail.com']
11
+
12
+ spec.summary = %q{ ruby taxii client }
13
+ spec.description = %q{ implement api-alike for python libtaxii https://github.com/TAXIIProject/libtaxii }
14
+ spec.homepage = 'https://github.com/crondaemon/ruby-taxii2'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = 'exe'
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'nokogiri'
22
+ spec.add_dependency 'nori'
23
+ spec.add_dependency 'gyoku'
24
+ spec.add_dependency 'hashie'
25
+ spec.add_dependency 'rest-client'
26
+
27
+ spec.add_development_dependency 'bundler', '~> 2.3'
28
+ spec.add_development_dependency 'rake', '~> 13.0'
29
+ spec.add_development_dependency 'rspec'
30
+ spec.add_development_dependency 'guard'
31
+ spec.add_development_dependency 'guard-rspec'
32
+ spec.add_development_dependency 'guard-bundler'
33
+ spec.add_development_dependency 'simplecov'
34
+ spec.add_development_dependency 'vcr'
35
+ spec.add_development_dependency 'webmock'
36
+ end
metadata ADDED
@@ -0,0 +1,259 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-taxii2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Dario Lombardo
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-05-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nori
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: gyoku
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: hashie
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
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: rest-client
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
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '13.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '13.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: guard-rspec
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: guard-bundler
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: simplecov
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: vcr
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: webmock
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ description: " implement api-alike for python libtaxii https://github.com/TAXIIProject/libtaxii "
210
+ email:
211
+ - lomato@gmail.com
212
+ executables: []
213
+ extensions: []
214
+ extra_rdoc_files: []
215
+ files:
216
+ - ".github/workflows/rspec.yml"
217
+ - ".gitignore"
218
+ - ".rspec"
219
+ - Gemfile
220
+ - Guardfile
221
+ - README.md
222
+ - Rakefile
223
+ - bin/console
224
+ - bin/setup
225
+ - lib/taxii.rb
226
+ - lib/taxii/client.rb
227
+ - lib/taxii/messages.rb
228
+ - lib/taxii/messages/discovery_request.rb
229
+ - lib/taxii/messages/feed_information_request.rb
230
+ - lib/taxii/messages/parameters.rb
231
+ - lib/taxii/messages/poll_request.rb
232
+ - lib/taxii/parsers/sax_poll_response.rb
233
+ - lib/taxii/poll_client.rb
234
+ - lib/taxii/time_extensions.rb
235
+ - lib/taxii/version.rb
236
+ - ruby-taxii.gemspec
237
+ homepage: https://github.com/crondaemon/ruby-taxii2
238
+ licenses: []
239
+ metadata: {}
240
+ post_install_message:
241
+ rdoc_options: []
242
+ require_paths:
243
+ - lib
244
+ required_ruby_version: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - ">="
247
+ - !ruby/object:Gem::Version
248
+ version: '0'
249
+ required_rubygems_version: !ruby/object:Gem::Requirement
250
+ requirements:
251
+ - - ">="
252
+ - !ruby/object:Gem::Version
253
+ version: '0'
254
+ requirements: []
255
+ rubygems_version: 3.3.7
256
+ signing_key:
257
+ specification_version: 4
258
+ summary: ruby taxii client
259
+ test_files: []