ruby-taxii2 0.3.1 → 0.3.2

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
  SHA256:
3
- metadata.gz: fc528f87e1d77992648872b73b304cadd0770fcd61104a013b968da7c6db8712
4
- data.tar.gz: d84191bbf3ef2aa98e43e6ab76c73e63f277387141bd406f5ee670b6a1c1b879
3
+ metadata.gz: 59094f4d94c54c1468ac70bb38ed293f0d7faa99b4626d409742060c48b0bd74
4
+ data.tar.gz: c7d004ebbb8774848c1874db3ebc93f4f27eccc5662193d9ed5c0e2cb3872c40
5
5
  SHA512:
6
- metadata.gz: ca13340ef9443169c8aafba8ee2181398eb1c26c8544c463508236d717ea1697eec8627fc23b6f34391356bd6816f71eee28c50aea2ea06b8a259b4d3f36a6ac
7
- data.tar.gz: eaee116e0eb3ddae02329cd3c6287b81ad00bf80bb7ac3afb961fd5dcda7f2d53ceb0927230b041f38e43fce2c227cdd2ede6b9189376d69879dd8648276f4fb
6
+ metadata.gz: 325da7bd11690bf0837a17809526cd051c3482dbae094af1740b2561b0a5492809ea51ff093f568d63eba48a196eb363b5d56491b50bdde7de2a025f2a852d0b
7
+ data.tar.gz: 7ab0a2f04941f2884c9c5a3100b4991f414b37e84f3a6d6aaf1733d3ccaeafe2f9399a54cbfc1e80e42f9eea670db8695ec740d854310ad02b90cd7408cd11b6
@@ -7,12 +7,18 @@ on:
7
7
  jobs:
8
8
  build:
9
9
  name: RSpec
10
- runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ os: [ubuntu-latest, windows-latest]
13
+ ruby: ['2.7', '3.0', '3.1', head]
14
+ runs-on: ${{ matrix.os }}
11
15
  steps:
12
16
  - uses: actions/checkout@v3
13
17
  - name: Set up Ruby
14
18
  uses: ruby/setup-ruby@v1
15
19
  with:
16
- ruby-version: 3.1.2
20
+ ruby-version: ${{ matrix.ruby }}
21
+ bundler: latest
17
22
  - run: bundle
18
23
  - run: bundle exec rspec
24
+ - run: bundle exec gem build
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
  /spec/fixtures/spec_ca/
11
11
  /tmp/
12
12
  /vendor/bundle/
13
+ *.gem
data/README.md CHANGED
@@ -9,7 +9,7 @@ Currently under development - likely to break at a moment's notice.
9
9
  Add this line to your application's Gemfile:
10
10
 
11
11
  ```ruby
12
- gem 'ruby-taxii'
12
+ gem 'ruby-taxii2'
13
13
  ```
14
14
 
15
15
  And then execute:
@@ -18,14 +18,49 @@ And then execute:
18
18
 
19
19
  Or install it yourself as:
20
20
 
21
- $ gem install ruby-taxii
21
+ $ gem install ruby-taxii2
22
22
 
23
23
  ## Usage
24
24
 
25
+ ```ruby
26
+ require 'taxii'
27
+
28
+ # You can use a json file configuration
29
+ # client = Taxii::configure(config: 'my.config.json')
30
+ # or a direct configuration
31
+ client = Taxii::configure(user: 'user', pass: 'pass', url: 'url')
32
+ collections = client.discover_collections
33
+
34
+ # List collections (name, type and availability)
35
+ puts "Listing collections:"
36
+ collections.each do |collection|
37
+ puts "#{collection['@collection_name']} #{collection['@collection_type']} #{collection['@available']}"
38
+ end
39
+
40
+ # Pick up the first available collection
41
+ collection_name = collections.find{ |collection| collection['@available'] == 'true' }['@collection_name']
42
+
43
+ puts "Retrieving data for collection: #{collection_name}"
44
+ poll_request_message = Taxii::Messages::PollRequest.new(
45
+ collection_name: collection_name,
46
+ poll_parameters: Taxii::Messages::Parameters::Poll.new(response_type: 'FULL')
47
+ )
48
+
49
+ client.get_content_blocks(poll_request_message).each do |message|
50
+ begin
51
+ # Try to parse the response as a Content_Block
52
+ pp Taxii::Messages::ContentBlock.new(message)
53
+ # You can also convert it to json
54
+ # pp Taxii::Messages::ContentBlock.new(message).as_json
55
+ rescue
56
+ puts 'This is not a ContentBlock'
57
+ end
58
+ end
59
+ ```
25
60
 
26
61
  ## Development
27
62
 
28
63
 
29
64
  ## Contributing
30
65
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/ryanbreed/ruby-taxii.
66
+ Bug reports and pull requests are welcome on GitHub at https://github.com/crondaemon/ruby-taxii2.
data/lib/taxii/client.rb CHANGED
@@ -14,7 +14,7 @@ module Taxii
14
14
  end
15
15
  end
16
16
 
17
- def build_request(url: self.url,payload: {}, format: Taxii::Messages::TAXII_11_HEADERS)
17
+ def build_request(url: self.url, payload: {}, format: Taxii::Messages::TAXII_11_HEADERS)
18
18
  RestClient::Request.new(
19
19
  method: :post,
20
20
  url: url,
@@ -33,7 +33,7 @@ module Taxii
33
33
 
34
34
  def get_service_address(service_name)
35
35
  service = discover_services.find do |svc|
36
- svc['@service_type']==service_name && svc['@available']=='true'
36
+ svc['@service_type'] == service_name && svc['@available'] == 'true'
37
37
  end
38
38
  service.nil? ? nil : service['Address']
39
39
  end
@@ -61,11 +61,18 @@ module Taxii
61
61
  @poll_service_url ||= get_service_address('POLL')
62
62
  end
63
63
 
64
- def discover_feeds(url=self.collection_management_service_url)
64
+ def discover_feeds(url = self.collection_management_service_url)
65
65
  msg = Taxii::Messages::FeedInformationRequest.new.to_xml
66
66
  http = build_request(url: url, payload: msg, format: Taxii::Messages::TAXII_10_HEADERS)
67
67
  parsed = xml.parse(http.execute.body)
68
- parsed['Feed_Information_Response'].fetch('Feed',[])
68
+ parsed['Feed_Information_Response'].fetch('Feed', [])
69
+ end
70
+
71
+ def discover_collections(url = self.collection_management_service_url)
72
+ msg = Taxii::Messages::CollectionInformationRequest.new.to_xml
73
+ http = build_request(url: url, payload: msg, format: Taxii::Messages::TAXII_10_HEADERS)
74
+ parsed = xml.parse(http.execute.body)
75
+ parsed['Collection_Information_Response'].fetch('Collection', [])
69
76
  end
70
77
 
71
78
  def scheme_protocol
@@ -0,0 +1,18 @@
1
+ module Taxii
2
+ module Messages
3
+ class CollectionInformationRequest < 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:Collection_Information_Request/': to_h}, key_converter: :none)
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ require 'json'
2
+
3
+ module Taxii
4
+ module Messages
5
+ class ContentBlock < Hashie::Dash
6
+ def initialize(body)
7
+ parsed = Nori.new(strip_namespaces: true).parse(body)
8
+ @body = parsed['Content_Block']['Content']
9
+ @body
10
+ end
11
+
12
+ def to_s
13
+ @body.to_s
14
+ end
15
+
16
+ def inspect
17
+ self.to_s
18
+ end
19
+
20
+ def as_json
21
+ JSON.parse(@body)
22
+ end
23
+
24
+ def pretty_print(pp)
25
+ puts self.to_s
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ module Taxii
2
+ module Messages
3
+ class PollFulfillmentRequest < Hashie::Dash
4
+ include Hashie::Extensions::Coercion
5
+
6
+ property :collection_name, default: 'system.Default'
7
+ property :result_id
8
+ property :result_part_number
9
+ property :message_id, default: -> { Taxii::Messages.generate_id }
10
+
11
+ def to_h
12
+ NAMESPACE_ATTRIBUTES.merge({
13
+ '@message_id': message_id,
14
+ '@collection_name': collection_name,
15
+ '@result_id': result_id,
16
+ '@result_part_number': result_part_number,
17
+ })
18
+ end
19
+
20
+ def to_xml
21
+ Gyoku.xml({'taxii_11:Poll_Fulfillment': to_h}, key_converter: :none)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -21,7 +21,7 @@ module Taxii
21
21
  if exclusive_begin_timestamp.nil?
22
22
  {}
23
23
  else
24
- {'Exclusive_Begin_Timestamp': exclusive_begin_timestamp.strftime(TS_FORMAT)}
24
+ {'taxii_11:Exclusive_Begin_Timestamp': exclusive_begin_timestamp.strftime(TS_FORMAT)}
25
25
  end
26
26
  end
27
27
 
@@ -29,7 +29,7 @@ module Taxii
29
29
  if inclusive_end_timestamp.nil?
30
30
  {}
31
31
  else
32
- {'Inclusive_End_Timestamp': inclusive_end_timestamp.strftime(TS_FORMAT)}
32
+ {'taxii_11:Inclusive_End_Timestamp': inclusive_end_timestamp.strftime(TS_FORMAT)}
33
33
  end
34
34
  end
35
35
  def requested_info
@@ -3,26 +3,62 @@ module Taxii
3
3
  include Client
4
4
 
5
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'
6
+ POLL_RESPONSE_PATH = '/taxii_11:Poll_Response'
7
+ CONTENT_XPATH = "#{POLL_RESPONSE_PATH}/taxii_11:Content_Block/taxii_11:Content"
7
8
 
8
- def get( poll_request_message, url: self.poll_service_url)
9
+ def get(poll_request_message, url: self.poll_service_url)
9
10
  msg = format_request(poll_request_message)
10
11
  build_request(url: url, payload: msg).execute
11
12
  end
12
13
 
13
- def get_content_blocks( poll_request_message,
14
+ def get_content_blocks(poll_request_message,
14
15
  url: self.poll_service_url,
15
- xpath: CONTENT_XPATH )
16
+ xpath: CONTENT_XPATH)
16
17
  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) }
18
+ @content_xml = Nokogiri::XML(response.body, nil, nil, PARSE_OPTIONS)
19
+
20
+ blocks = response_blocks
21
+
22
+ # We have a muulti-part message
23
+ # http://docs.oasis-open.org/cti/taxii/v1.1.1/cs01/part2-services/taxii-v1.1.1-cs01-part2-services.html#_Toc450734190
24
+ while attribute_more == 'true'
25
+ poll_fulfillment_message = Taxii::Messages::PollFulfillmentRequest.new(
26
+ collection_name: poll_request_message.collection_name,
27
+ result_id: result_id,
28
+ result_part_number: result_part_number + 1)
29
+
30
+ response = self.get(poll_fulfillment_message, url: url)
31
+ @content_xml = Nokogiri::XML(response.body, nil, nil, PARSE_OPTIONS)
32
+
33
+ blocks += response_blocks
34
+ end
35
+
36
+ blocks
37
+ end
38
+
39
+ private
40
+
41
+ def response_blocks
42
+ @content_xml.xpath(POLL_RESPONSE_PATH).flat_map { |blk| blk.children.map(&:to_s) }
43
+ end
44
+
45
+ def attribute_more
46
+ @content_xml.at_xpath(POLL_RESPONSE_PATH).attributes['more'].value
47
+ end
48
+
49
+ def result_id
50
+ @content_xml.at_xpath(POLL_RESPONSE_PATH).attributes['result_id'].value
51
+ end
52
+
53
+ def result_part_number
54
+ @content_xml.at_xpath(POLL_RESPONSE_PATH).attributes['result_part_number'].value.to_i
19
55
  end
20
56
 
21
57
  def format_request(request_message)
22
58
  case request_message
23
59
  when String
24
60
  request_message
25
- when Taxii::Messages::PollRequest
61
+ when Taxii::Messages::PollRequest, Taxii::Messages::PollFulfillmentRequest
26
62
  request_message.to_xml
27
63
  else
28
64
  fail ArgumentError, 'request message must be String or PollRequest'
data/lib/taxii/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Taxii
2
- VERSION = '0.3.1'
2
+ VERSION = '0.3.2'
3
3
  end
data/lib/taxii.rb CHANGED
@@ -4,6 +4,7 @@ require 'rest-client'
4
4
  require 'uri'
5
5
  require 'nori'
6
6
  require 'gyoku'
7
+ require 'json'
7
8
 
8
9
  require 'taxii/version'
9
10
  require 'taxii/time_extensions'
@@ -11,13 +12,29 @@ require 'taxii/messages'
11
12
  require 'taxii/messages/parameters'
12
13
  require 'taxii/messages/discovery_request'
13
14
  require 'taxii/messages/poll_request'
15
+ require 'taxii/messages/poll_fulfillment_request'
14
16
  require 'taxii/messages/feed_information_request'
17
+ require 'taxii/messages/collection_information_request'
18
+ require 'taxii/messages/content_block'
15
19
  require 'taxii/client'
16
20
  require 'taxii/poll_client'
17
21
 
18
22
  module Taxii
19
- def self.configure(config: File.join(ENV['HOME'],'.taxii.json'), client: PollClient)
20
- configuration = JSON.parse(File.read(config))
23
+ def self.configure(options = {})
24
+ client = options.fetch(:client, PollClient)
25
+ config = options.fetch(:config, File.join(ENV['HOME'],'.taxii.json'))
26
+ user = options[:user]
27
+ pass = options[:pass]
28
+ url = options[:url]
29
+
30
+ if user && pass && url
31
+ configuration = { user: user, pass: pass, url: url }
32
+ elsif File.exist?(config)
33
+ configuration = JSON.parse(File.read(config))
34
+ else
35
+ raise('You must provide user+pass+url, ora a config file, or have a default $HOME/.taxii.json')
36
+ end
37
+
21
38
  client.new(configuration)
22
39
  end
23
40
 
data/ruby-taxii.gemspec CHANGED
@@ -33,4 +33,6 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency 'simplecov'
34
34
  spec.add_development_dependency 'vcr'
35
35
  spec.add_development_dependency 'webmock'
36
+ spec.add_development_dependency 'pry'
37
+ spec.add_development_dependency 'pry-byebug'
36
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-taxii2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dario Lombardo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-27 00:00:00.000000000 Z
11
+ date: 2023-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -206,6 +206,34 @@ dependencies:
206
206
  - - ">="
207
207
  - !ruby/object:Gem::Version
208
208
  version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: pry
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: pry-byebug
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
209
237
  description: " implement api-alike for python libtaxii https://github.com/TAXIIProject/libtaxii "
210
238
  email:
211
239
  - lomato@gmail.com
@@ -225,9 +253,12 @@ files:
225
253
  - lib/taxii.rb
226
254
  - lib/taxii/client.rb
227
255
  - lib/taxii/messages.rb
256
+ - lib/taxii/messages/collection_information_request.rb
257
+ - lib/taxii/messages/content_block.rb
228
258
  - lib/taxii/messages/discovery_request.rb
229
259
  - lib/taxii/messages/feed_information_request.rb
230
260
  - lib/taxii/messages/parameters.rb
261
+ - lib/taxii/messages/poll_fulfillment_request.rb
231
262
  - lib/taxii/messages/poll_request.rb
232
263
  - lib/taxii/parsers/sax_poll_response.rb
233
264
  - lib/taxii/poll_client.rb