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 +4 -4
- data/.rubocop.yml +2 -2
- data/Gemfile.lock +1 -1
- data/README.md +26 -8
- data/lib/skull_island/resource.rb +1 -1
- data/lib/skull_island/resources/consumer.rb +29 -1
- data/lib/skull_island/resources/jwt_credential.rb +121 -0
- data/lib/skull_island/resources/plugin.rb +4 -0
- data/lib/skull_island/resources/upstream.rb +7 -12
- data/lib/skull_island/resources/upstream_target.rb +20 -1
- data/lib/skull_island/version.rb +1 -1
- data/lib/skull_island.rb +1 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0cadf0fd8b018522876070d358219f78a94ee7fe5ff94efe1045a961758783ba
|
4
|
+
data.tar.gz: 1fb907a4a66a77c9c22ff58ad5c1544001e124c49e8c34610dbcbadaf86da2df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8324088d97171e7c91205b09f219391827542b23e8635b06f77793b6cff7e86ec1dab1a0d431f25a8d39b03dff38344db961f4cf8944dac9be9d23a470a23c93
|
7
|
+
data.tar.gz: 876b5971f3955f88baa89dbb2f6395e52130a0b58625ad56f6d38c08402dba437760d7fa4e3dd4769b4bf0a43942717314065a717b13ecd7be8fd5fb52f7dfa6
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
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-----...'
|
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']
|
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'
|
343
|
-
resource.username = 'user1'
|
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'
|
379
|
-
resource.enabled = true
|
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
|
|
@@ -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
|
@@ -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
|
-
|
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 {#
|
180
|
-
def
|
181
|
-
# only String is allowed
|
182
|
-
value.is_a?(String)
|
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?(
|
133
|
+
value.is_a?(String) && value.match?(/[\w\d.-]+:\d{1,5}/)
|
115
134
|
)
|
116
135
|
end
|
117
136
|
|
data/lib/skull_island/version.rb
CHANGED
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.
|
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-
|
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.
|
287
|
+
rubygems_version: 3.0.4
|
287
288
|
signing_key:
|
288
289
|
specification_version: 4
|
289
290
|
summary: Ruby SDK for Kong
|