skull_island 1.1.1 → 1.1.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: 2599c9fbc76abcc4be21923b95477c784515165c3891aa5155d7a9d88c5c887b
4
- data.tar.gz: df6f3715f49a4a6cb09118bd446f1c7097fa7d0228dfce497e7396e63921e13c
3
+ metadata.gz: 0cadf0fd8b018522876070d358219f78a94ee7fe5ff94efe1045a961758783ba
4
+ data.tar.gz: 1fb907a4a66a77c9c22ff58ad5c1544001e124c49e8c34610dbcbadaf86da2df
5
5
  SHA512:
6
- metadata.gz: 70be200f4e3721d42c820176d16350e705c40c38254876322181a1509538b0e7612156fbb2ddb29b9a8bdfab522ec8452046b346a2fe059a3bd838f4f2c578bc
7
- data.tar.gz: 7c426dfbf53dbb080ed5211c14ce22b0d5ef78aa06a8e27c1fd1d91b1534065f77554ffc93edc56728fec870aa8bdd591ed10d1fcadf454c4372f897e16f03bf
6
+ metadata.gz: 8324088d97171e7c91205b09f219391827542b23e8635b06f77793b6cff7e86ec1dab1a0d431f25a8d39b03dff38344db961f4cf8944dac9be9d23a470a23c93
7
+ data.tar.gz: 876b5971f3955f88baa89dbb2f6395e52130a0b58625ad56f6d38c08402dba437760d7fa4e3dd4769b4bf0a43942717314065a717b13ecd7be8fd5fb52f7dfa6
data/.rubocop.yml CHANGED
@@ -8,10 +8,10 @@ Metrics/LineLength:
8
8
  Max: 100
9
9
 
10
10
  Metrics/ClassLength:
11
- Max: 170
11
+ Max: 175
12
12
 
13
13
  Metrics/ModuleLength:
14
- Max: 170
14
+ Max: 175
15
15
  Exclude:
16
16
  - 'lib/skull_island/helpers/resource.rb'
17
17
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- skull_island (1.1.1)
4
+ skull_island (1.1.2)
5
5
  deepsort (~> 0.4)
6
6
  erubi (~> 1.8)
7
7
  json (~> 2.1)
data/README.md CHANGED
@@ -318,10 +318,10 @@ From here, the SDK mostly wraps the attributes described in the [Kong API Docs](
318
318
  resource = Resources::Certificate.new
319
319
 
320
320
  # These attributes can be set and read
321
- resource.cert = '-----BEGIN CERTIFICATE-----...' # PEM-encoded public key
321
+ resource.cert = '-----BEGIN CERTIFICATE-----...' # PEM-encoded public key
322
322
  resource.key = '-----BEGIN RSA PRIVATE KEY-----...' # PEM-encoded private key
323
- resource.snis = ['example.com', 'example.org'] # Array of names for which this cert is valid
324
-
323
+ resource.snis = ['example.com', 'example.org'] # Array of names for which this cert is valid
324
+ resource.tags = ['production', 'example'] # Array of tags
325
325
  resource.save
326
326
 
327
327
  # These attributes are read-only
@@ -333,14 +333,15 @@ resource.created_at
333
333
 
334
334
  #### Consumers (and their Credentials)
335
335
 
336
- Note that for Consumer credentials, only [`key-auth`](https://docs.konghq.com/hub/kong-inc/key-auth/) and [`basic-auth`](https://docs.konghq.com/hub/kong-inc/basic-auth/) are currently supported.
336
+ Note that for Consumer credentials, only [`key-auth`](https://docs.konghq.com/hub/kong-inc/key-auth/), [`jwt`](https://docs.konghq.com/hub/kong-inc/jwt/), and [`basic-auth`](https://docs.konghq.com/hub/kong-inc/basic-auth/) are currently supported.
337
337
 
338
338
  ```ruby
339
339
  resource = Resources::Consumer.new
340
340
 
341
341
  # These attributes can be set and read
342
- resource.custom_id = 'user1' # A string
343
- resource.username = 'user1' # A string
342
+ resource.custom_id = 'user1' # A string
343
+ resource.username = 'user1' # A string
344
+ resource.tags = ['production', 'example'] # Array of tags
344
345
 
345
346
  resource.save
346
347
 
@@ -375,9 +376,10 @@ Note that this doesn't _install_ plugins; it only allows using them.
375
376
  resource = Resources::Plugin.new
376
377
 
377
378
  # These attributes can be set and read
378
- resource.name = 'rate-limiting' # The name of the plugin
379
- resource.enabled = true # A Boolean
379
+ resource.name = 'rate-limiting' # The name of the plugin
380
+ resource.enabled = true # A Boolean
380
381
  resource.config = { 'minute' => 50, 'hour' => 1000 } # A Hash of config keys and values
382
+ resource.tags = ['production', 'example'] # Array of tags
381
383
 
382
384
  # Either reference related resources by ID
383
385
  resource.service = { 'id' => '5fd1z584-1adb-40a5-c042-63b19db49x21' }
@@ -418,6 +420,7 @@ Resources::Plugin.schema('acl')
418
420
  resource = Resources::Route.new
419
421
 
420
422
  # These attributes can be set and read
423
+ resource.name = 'example_route'
421
424
  resource.hosts = ['example.com', 'example.org']
422
425
  resource.protocols = ['https']
423
426
  resource.methods = ['GET', 'POST']
@@ -425,6 +428,19 @@ resource.paths = ['/some/path']
425
428
  resource.regex_priority = 10
426
429
  resource.strip_path = false
427
430
  resource.preserve_host = true
431
+ resource.tags = ['production', 'example']
432
+
433
+ # Or, for TCP/TLS routes
434
+ resource.protocols = ['tcp', 'tls']
435
+ resource.sources = [
436
+ { "ip" => "10.1.0.0/16", "port" => 1234 }
437
+ ]
438
+ resource.destinations = [
439
+ { "ip" => "10.1.0.0/16", "port" => 1234 },
440
+ { "ip" => "10.2.2.2" },
441
+ { "port" => 9123 }
442
+ ]
443
+ resource.snis = ['example.com', 'example.org']
428
444
 
429
445
  # Either reference related resources by ID
430
446
  resource.service = { 'id' => '4e13f54a-bbf1-47a8-8777-255fed7116f2' }
@@ -461,6 +477,7 @@ resource.name = 'example-service'
461
477
  resource.retries = 10
462
478
  resource.read_timeout = 60000
463
479
  resource.write_timeout = 60000
480
+ resource.tags = ['production', 'example']
464
481
 
465
482
  resource.save
466
483
 
@@ -513,6 +530,7 @@ resource.healthchecks = {
513
530
  }
514
531
  }
515
532
  }
533
+ resource.tags = ['production', 'example']
516
534
 
517
535
  resource.save
518
536
 
@@ -5,7 +5,7 @@ module SkullIsland
5
5
  # TODO: Thread safety
6
6
  class Resource
7
7
  attr_accessor :api_client
8
- attr_reader :errors
8
+ attr_reader :errors, :entity
9
9
 
10
10
  include Comparable
11
11
  include Validations::Resource
@@ -30,6 +30,14 @@ module SkullIsland
30
30
  test: test
31
31
  )
32
32
 
33
+ JWTCredential.batch_import(
34
+ (
35
+ resource_data.dig('credentials', 'jwt') || []
36
+ ).map { |t| t.merge('consumer' => { 'id' => resource.id }) },
37
+ verbose: verbose,
38
+ test: test
39
+ )
40
+
33
41
  KeyauthCredential.batch_import(
34
42
  (
35
43
  resource_data.dig('credentials', 'key-auth') || []
@@ -41,9 +49,19 @@ module SkullIsland
41
49
  end
42
50
 
43
51
  # Convenience method to add upstream targets
52
+ # rubocop:disable Metrics/AbcSize
53
+ # rubocop:disable Metrics/CyclomaticComplexity
54
+ # rubocop:disable Metrics/PerceivedComplexity
44
55
  def add_credential!(details)
45
- r = if [BasicauthCredential, KeyauthCredential].include? details.class
56
+ r = if [BasicauthCredential, JWTCredential, KeyauthCredential].include? details.class
46
57
  details
58
+ elsif details.is_a?(Hash) && details.key?(:algorithm)
59
+ cred = JWTCredential.new(api_client: api_client)
60
+ cred.algorithm = details[:algorithm]
61
+ cred.key = details[:key] if details[:key]
62
+ cred.secret = details[:secret] if details[:secret]
63
+ cred.rsa_public_key = details[:rsa_public_key] if details[:rsa_public_key]
64
+ cred
47
65
  elsif details.is_a?(Hash) && details.key?(:key)
48
66
  cred = KeyauthCredential.new(api_client: api_client)
49
67
  cred.key = details[:key]
@@ -58,6 +76,9 @@ module SkullIsland
58
76
  r.consumer = self
59
77
  r.save
60
78
  end
79
+ # rubocop:enable Metrics/AbcSize
80
+ # rubocop:enable Metrics/CyclomaticComplexity
81
+ # rubocop:enable Metrics/PerceivedComplexity
61
82
 
62
83
  def credentials
63
84
  creds = {}
@@ -65,6 +86,8 @@ module SkullIsland
65
86
  creds['key-auth'] = keyauth_creds if keyauth_creds
66
87
  basicauth_creds = BasicauthCredential.where(:consumer, self, api_client: api_client)
67
88
  creds['basic-auth'] = basicauth_creds if basicauth_creds
89
+ jwt_creds = JWTCredential.where(:consumer, self, api_client: api_client)
90
+ creds['jwt'] = jwt_creds if jwt_creds
68
91
  creds
69
92
  end
70
93
 
@@ -112,6 +135,11 @@ module SkullIsland
112
135
  cred.export(exclude: 'consumer')
113
136
  end
114
137
  end
138
+ unless credentials['jwt'].empty?
139
+ creds['jwt'] = credentials['jwt'].collect do |cred|
140
+ cred.export(exclude: 'consumer')
141
+ end
142
+ end
115
143
  unless credentials['basic-auth'].empty?
116
144
  creds['basic-auth'] = credentials['basic-auth'].collect do |cred|
117
145
  cred.export(exclude: 'consumer')
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SkullIsland
4
+ # Resource classes go here...
5
+ module Resources
6
+ # The JWTCredential resource class
7
+ #
8
+ # @see https://docs.konghq.com/hub/kong-inc/jwt/ JWT Authentication details
9
+ class JWTCredential < Resource
10
+ property :algorithm, required: true, validate: true
11
+ property :key, validate: true
12
+ property :secret, validated: true
13
+ property :rsa_public_key, validated: true
14
+ property(
15
+ :consumer,
16
+ required: true, validate: true, preprocess: true, postprocess: true
17
+ )
18
+ property :created_at, read_only: true, postprocess: true
19
+
20
+ def self.batch_import(data, verbose: false, test: false)
21
+ raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
22
+
23
+ data.each_with_index do |resource_data, index|
24
+ resource = new
25
+ resource.algorithm = resource_data['algorithm']
26
+ resource.key = resource_data['key'] if resource_data['key']
27
+ resource.secret = resource_data['secret'] if resource_data['secret']
28
+ if resource_data['rsa_public_key']
29
+ resource.rsa_public_key = resource_data['rsa_public_key']
30
+ end
31
+ resource.delayed_set(:consumer, resource_data, 'consumer')
32
+ resource.import_update_or_skip(index: index, verbose: verbose, test: test)
33
+ end
34
+ end
35
+
36
+ def self.relative_uri
37
+ 'jwts'
38
+ end
39
+
40
+ def relative_uri
41
+ consumer ? "#{consumer.relative_uri}/jwt/#{id}" : nil
42
+ end
43
+
44
+ def save_uri
45
+ consumer ? "#{consumer.relative_uri}/jwt" : nil
46
+ end
47
+
48
+ def export(options = {})
49
+ hash = { 'algorithm' => algorithm }
50
+ hash['key'] = key if key
51
+ hash['secret'] = secret if secret
52
+ hash['rsa_public_key'] = rsa_public_key if rsa_public_key
53
+ hash['consumer'] = "<%= lookup :consumer, '#{consumer.username}' %>" if consumer
54
+ [*options[:exclude]].each do |exclude|
55
+ hash.delete(exclude.to_s)
56
+ end
57
+ [*options[:include]].each do |inc|
58
+ hash[inc.to_s] = send(inc.to_sym)
59
+ end
60
+ hash.reject { |_, value| value.nil? }
61
+ end
62
+
63
+ # Keys can't be updated, only created or deleted
64
+ def modified_existing?
65
+ false
66
+ end
67
+
68
+ private
69
+
70
+ def postprocess_consumer(value)
71
+ if value.is_a?(Hash)
72
+ Consumer.new(
73
+ entity: value,
74
+ lazy: true,
75
+ tainted: false
76
+ )
77
+ else
78
+ value
79
+ end
80
+ end
81
+
82
+ def preprocess_consumer(input)
83
+ if input.is_a?(Hash)
84
+ input
85
+ else
86
+ { 'id' => input.id }
87
+ end
88
+ end
89
+
90
+ # Used to validate {#consumer} on set
91
+ def validate_consumer(value)
92
+ # allow either a Consumer object or a Hash
93
+ value.is_a?(Consumer) || value.is_a?(Hash)
94
+ end
95
+
96
+ # Used to validate {#algorithm} on set
97
+ def validate_algorithm(value)
98
+ # allow a String
99
+ %w[HS256 HS384 HS512 RS256 ES256].include? value
100
+ end
101
+
102
+ # Used to validate {#key} on set
103
+ def validate_key(value)
104
+ # allow a String
105
+ value.is_a?(String)
106
+ end
107
+
108
+ # Used to validate {#secret} on set
109
+ def validate_secret(value)
110
+ # allow a String
111
+ value.is_a?(String)
112
+ end
113
+
114
+ # Used to validate {#rsa_public_key} on set
115
+ def validate_rsa_public_key(value)
116
+ # allow a String
117
+ value.is_a?(String)
118
+ end
119
+ end
120
+ end
121
+ end
@@ -42,6 +42,10 @@ module SkullIsland
42
42
  api_client.get("#{relative_uri}/schema/#{name}")
43
43
  end
44
44
 
45
+ def digest_properties
46
+ super.reject { |k| %i[run_on].include? k }
47
+ end
48
+
45
49
  def export(options = {})
46
50
  hash = {
47
51
  'name' => name,
@@ -30,8 +30,8 @@ module SkullIsland
30
30
  resource.name = rdata['name']
31
31
  resource.slots = rdata['slots'] if rdata['slots']
32
32
  resource.hash_on = rdata['hash_on']
33
- resource.hash_fallback = rdata['hash_fallback']
34
- resource.hash_on_header = rdata['hash_on_header']
33
+ resource.hash_fallback = rdata['hash_fallback'] if rdata['hash_fallback']
34
+ resource.hash_on_header = rdata['hash_on_header'] if rdata['hash_on_header']
35
35
  if rdata['hash_fallback_header']
36
36
  resource.hash_fallback_header = rdata['hash_fallback_header']
37
37
  end
@@ -78,12 +78,7 @@ module SkullIsland
78
78
  end
79
79
 
80
80
  def target(target_id)
81
- UpstreamTarget.new(
82
- entity: { 'id' => target_id, 'upstream' => { 'id' => id } },
83
- lazy: true,
84
- tainted: false,
85
- api_client: api_client
86
- )
81
+ targets.where(id: target_id).first
87
82
  end
88
83
 
89
84
  def targets
@@ -176,10 +171,10 @@ module SkullIsland
176
171
  value.is_a?(String) && [hash_on, hash_fallback].include?('cookie')
177
172
  end
178
173
 
179
- # Used to validate {#hash_cookie_path} on set
180
- def validate_hash_cookie_path(value)
181
- # only String is allowed and only when {#hash_on} or {#hash_fallback} is set to 'cookie'
182
- value.is_a?(String) && [hash_on, hash_fallback].include?('cookie')
174
+ # Used to validate {#hash_on_cookie_path} on set
175
+ def validate_hash_on_cookie_path(value)
176
+ # only String is allowed
177
+ value.is_a?(String)
183
178
  end
184
179
 
185
180
  # Used to validate {#name} on set
@@ -29,6 +29,12 @@ module SkullIsland
29
29
  end
30
30
  end
31
31
 
32
+ def self.all(options = {})
33
+ api_client = options[:api_client] || APIClient.instance
34
+
35
+ Upstream.all(api_client: api_client).map(&:targets).reduce(&:merge)
36
+ end
37
+
32
38
  def self.get(id, options = {})
33
39
  if options[:upstream]&.is_a?(Upstream)
34
40
  options[:upstream].target(id)
@@ -38,6 +44,19 @@ module SkullIsland
38
44
  end
39
45
  end
40
46
 
47
+ # Tests for an existing version of this resource based on its properties rather than its `id`
48
+ def find_by_digest
49
+ result = self.class.where(:digest, digest) # matching digest means the equivalent resource
50
+ if result.size == 1
51
+ @entity = result.first.entity
52
+ @lazy = false
53
+ @tainted = false
54
+ true
55
+ else
56
+ false
57
+ end
58
+ end
59
+
41
60
  def relative_uri
42
61
  upstream ? "#{upstream.relative_uri}/targets/#{id}" : nil
43
62
  end
@@ -111,7 +130,7 @@ module SkullIsland
111
130
  def validate_target(value)
112
131
  # only URIs or specific strings
113
132
  value.is_a?(URI) || (
114
- value.is_a?(String) && value.match?(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}/)
133
+ value.is_a?(String) && value.match?(/[\w\d.-]+:\d{1,5}/)
115
134
  )
116
135
  end
117
136
 
@@ -4,6 +4,6 @@ module SkullIsland
4
4
  VERSION = [
5
5
  1, # Major
6
6
  1, # Minor
7
- 1 # Patch
7
+ 2 # Patch
8
8
  ].join('.')
9
9
  end
data/lib/skull_island.rb CHANGED
@@ -46,6 +46,7 @@ require 'skull_island/validations/resource'
46
46
  require 'skull_island/resource'
47
47
  require 'skull_island/resources/certificate'
48
48
  require 'skull_island/resources/basicauth_credential'
49
+ require 'skull_island/resources/jwt_credential'
49
50
  require 'skull_island/resources/keyauth_credential'
50
51
  require 'skull_island/resources/consumer'
51
52
  require 'skull_island/resources/plugin'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skull_island
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Gnagy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-13 00:00:00.000000000 Z
11
+ date: 2019-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deepsort
@@ -251,6 +251,7 @@ files:
251
251
  - lib/skull_island/resources/basicauth_credential.rb
252
252
  - lib/skull_island/resources/certificate.rb
253
253
  - lib/skull_island/resources/consumer.rb
254
+ - lib/skull_island/resources/jwt_credential.rb
254
255
  - lib/skull_island/resources/keyauth_credential.rb
255
256
  - lib/skull_island/resources/plugin.rb
256
257
  - lib/skull_island/resources/route.rb
@@ -283,7 +284,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
283
284
  - !ruby/object:Gem::Version
284
285
  version: '0'
285
286
  requirements: []
286
- rubygems_version: 3.0.3
287
+ rubygems_version: 3.0.4
287
288
  signing_key:
288
289
  specification_version: 4
289
290
  summary: Ruby SDK for Kong