skull_island 1.2.7 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +18 -1
- data/lib/skull_island/resources/access_control_list.rb +101 -0
- data/lib/skull_island/resources/consumer.rb +37 -0
- data/lib/skull_island/resources/plugin.rb +13 -8
- data/lib/skull_island/version.rb +1 -1
- data/lib/skull_island.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83a5a4bbb01bcbd6b9837e72533d2ce4ef7b7515435da663a5f098e2ac64dde0
|
4
|
+
data.tar.gz: 227036f85eb431f3a7feab16e24c994d7702e168df5e773b53c6a89ed79368a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fecb0e599904792539a4656d7bea043a14a0eb7f90c5fc6f59b450f32b1cbeb326fab1837a445df107536fb750ad83b4eda0f446b9231aaaebe19bcc3f7861c8
|
7
|
+
data.tar.gz: '039460f3aacc5981e3f820210dee37888990bb7930baa142eef457d10fe04d0a977ef955f5dd2b9169ffa78867879c0fe0a9ffe590db198a556bf1f3397251d5'
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -85,6 +85,10 @@ skull_island export --verbose /path/to/export.yml
|
|
85
85
|
|
86
86
|
Exporting, by default, exports the entire configuration of a Kong gateway, but will strip out special meta-data tags added by Skull Island to track projects. If, instead, you'd like to export **only** the configuration for a specific project, you can add `--project foo` (where `foo` is the name of your project) to export only those resources associated with it and maintain the special key in the exported YAML.
|
87
87
|
|
88
|
+
#### Exporting Credentials
|
89
|
+
|
90
|
+
For most credential types, exporting works as expected (you'll see the plaintext value in the exported YAML). With `BasicauthCredential`s, however, this is not the case. This isn't a limitation of `skull_island`; rather, it is the [expected behavior](https://github.com/Kong/kong/issues/4237) of the Admin API developers. This tool, when exporting these credentials, can only provide the salted-SHA1 hash of the password, and it does so by wrapping it in a special `hash{}` notation. This allows `skull_island` to distinguish between changing the value to the literal string and comparing the _hashed_ values. The import process is also smart enough to compare plaintext to hashed values returned from the API for existing values, so it won't recreate credentials every run.
|
91
|
+
|
88
92
|
### Importing
|
89
93
|
|
90
94
|
Skull Island also supports importing configurations (both partial and full) from a YAML + ERB document:
|
@@ -182,6 +186,8 @@ certificates: []
|
|
182
186
|
consumers:
|
183
187
|
- username: foo
|
184
188
|
custom_id: foo
|
189
|
+
acls:
|
190
|
+
- group: searchusers
|
185
191
|
credentials:
|
186
192
|
key-auth:
|
187
193
|
- key: q90r8908w09rqw9jfj09jq0f8y389
|
@@ -233,6 +239,13 @@ plugins:
|
|
233
239
|
- x-api-key
|
234
240
|
run_on_preflight: true
|
235
241
|
service: "<%= lookup :service, 'search_api' %>"
|
242
|
+
- name: acl
|
243
|
+
enabled: true
|
244
|
+
config:
|
245
|
+
hide_groups_header: false
|
246
|
+
whitelist:
|
247
|
+
- searchusers
|
248
|
+
service: "<%= lookup :service, 'search_api' %>"
|
236
249
|
```
|
237
250
|
|
238
251
|
All top-level keys (other than `version` and `project`) require an Array as a parameter, either by providing a list of entries or an empty Array (`[]`). The above shows how to use the `lookup()` function to refer to another resource. This "looks up" the resource type (`service` in this case) by `name` (`search_api` in this case) and resolves its `id`. This function can also be used to lookup a `route` or `upstream` by its `name`, or a `consumer` by its `username`. Note that Kong itself doesn't _require_ `route` resources to have unique names, so you'll need to enforce that practice yourself for `lookup` to be useful for Routes.
|
@@ -376,7 +389,7 @@ resource.created_at
|
|
376
389
|
# => #<DateTime: 2018-07-17T12:51:28+00:00 ((2458317j,46288s,0n),+0s,2299161j)>
|
377
390
|
```
|
378
391
|
|
379
|
-
#### Consumers (
|
392
|
+
#### Consumers (along with their Access Control Lists and Credentials)
|
380
393
|
|
381
394
|
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.
|
382
395
|
|
@@ -397,6 +410,8 @@ resource.created_at
|
|
397
410
|
# => #<DateTime: 2018-07-17T12:51:28+00:00 ((2458317j,46288s,0n),+0s,2299161j)>
|
398
411
|
resource.plugins
|
399
412
|
# => #<SkullIsland::ResourceCollection:0x00007f9f1e564f3e...
|
413
|
+
resource.acls
|
414
|
+
# => #<SkullIsland::ResourceCollection:0x00007f9f1e765b3c...
|
400
415
|
resource.credentials
|
401
416
|
# => {}
|
402
417
|
resource.add_credential!(key: '932948e89e09e2989d8092') # adds a KeyauthCredential
|
@@ -411,6 +426,8 @@ resource.credentials['basic-auth']
|
|
411
426
|
# => #<SkullIsland::ResourceCollection:0x00007f9f1e564f3f...
|
412
427
|
resource.credentials['basic-auth'].first.username
|
413
428
|
# => "test"
|
429
|
+
resource.add_acl!(group: 'somegroup')
|
430
|
+
# => true
|
414
431
|
```
|
415
432
|
|
416
433
|
#### Plugins
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SkullIsland
|
4
|
+
# Resource classes go here...
|
5
|
+
module Resources
|
6
|
+
# The ACL resource class
|
7
|
+
#
|
8
|
+
# @see https://docs.konghq.com/hub/kong-inc/acl/ ACL API definition
|
9
|
+
class AccessControlList < Resource
|
10
|
+
property :group, validate: true
|
11
|
+
property(
|
12
|
+
:consumer,
|
13
|
+
required: true, validate: true, preprocess: true, postprocess: true
|
14
|
+
)
|
15
|
+
property :created_at, read_only: true, postprocess: true
|
16
|
+
|
17
|
+
def self.batch_import(data, verbose: false, test: false)
|
18
|
+
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
19
|
+
|
20
|
+
known_ids = []
|
21
|
+
|
22
|
+
data.each_with_index do |resource_data, index|
|
23
|
+
resource = new
|
24
|
+
resource.delayed_set(:group, resource_data, 'group')
|
25
|
+
resource.delayed_set(:consumer, resource_data, 'consumer')
|
26
|
+
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
27
|
+
known_ids << resource.id
|
28
|
+
end
|
29
|
+
|
30
|
+
known_ids
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.relative_uri
|
34
|
+
'acls'
|
35
|
+
end
|
36
|
+
|
37
|
+
def relative_uri
|
38
|
+
consumer ? "#{consumer.relative_uri}/acls/#{id}" : nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def save_uri
|
42
|
+
consumer ? "#{consumer.relative_uri}/acls" : nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def export(options = {})
|
46
|
+
hash = { 'group' => group }
|
47
|
+
hash['consumer'] = "<%= lookup :consumer, '#{consumer.username}' %>" if consumer
|
48
|
+
[*options[:exclude]].each do |exclude|
|
49
|
+
hash.delete(exclude.to_s)
|
50
|
+
end
|
51
|
+
[*options[:include]].each do |inc|
|
52
|
+
hash[inc.to_s] = send(inc.to_sym)
|
53
|
+
end
|
54
|
+
hash.reject { |_, value| value.nil? }
|
55
|
+
end
|
56
|
+
|
57
|
+
# Keys can't be updated, only created or deleted
|
58
|
+
def modified_existing?
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
def project
|
63
|
+
consumer ? consumer.project : nil
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def postprocess_consumer(value)
|
69
|
+
if value.is_a?(Hash)
|
70
|
+
Consumer.new(
|
71
|
+
entity: value,
|
72
|
+
lazy: true,
|
73
|
+
tainted: false
|
74
|
+
)
|
75
|
+
else
|
76
|
+
value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def preprocess_consumer(input)
|
81
|
+
if input.is_a?(Hash)
|
82
|
+
input
|
83
|
+
else
|
84
|
+
{ 'id' => input.id }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Used to validate {#consumer} on set
|
89
|
+
def validate_consumer(value)
|
90
|
+
# allow either a Consumer object or a Hash
|
91
|
+
value.is_a?(Consumer) || value.is_a?(Hash)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Used to validate {#group} on set
|
95
|
+
def validate_group(value)
|
96
|
+
# allow a String
|
97
|
+
value.is_a?(String)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -17,6 +17,7 @@ module SkullIsland
|
|
17
17
|
# rubocop:disable Metrics/CyclomaticComplexity
|
18
18
|
# rubocop:disable Metrics/PerceivedComplexity
|
19
19
|
# rubocop:disable Metrics/AbcSize
|
20
|
+
# rubocop:disable Metrics/MethodLength
|
20
21
|
def self.batch_import(data, verbose: false, test: false, project: nil, time: nil)
|
21
22
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
22
23
|
|
@@ -57,6 +58,14 @@ module SkullIsland
|
|
57
58
|
test: test
|
58
59
|
)
|
59
60
|
|
61
|
+
known_acls = AccessControlList.batch_import(
|
62
|
+
(
|
63
|
+
resource_data.dig('acls') || []
|
64
|
+
).map { |t| t.merge('consumer' => { 'id' => resource.id }) },
|
65
|
+
verbose: verbose,
|
66
|
+
test: test
|
67
|
+
)
|
68
|
+
|
60
69
|
next unless project
|
61
70
|
|
62
71
|
basic_creds = BasicauthCredential.all.select { |c| c.consumer == resource }
|
@@ -76,11 +85,38 @@ module SkullIsland
|
|
76
85
|
puts "[WARN] ! Removing #{res.class.name} (#{res.id})"
|
77
86
|
res.destroy
|
78
87
|
end
|
88
|
+
|
89
|
+
acls = AccessControlList.all.select { |acl| acl.consumer == resource }
|
90
|
+
acls.reject { |res| known_acls.include?(res.id) }.map do |res|
|
91
|
+
puts "[WARN] ! Removing #{res.class.name} (#{res.id})"
|
92
|
+
res.destroy
|
93
|
+
end
|
79
94
|
end
|
80
95
|
# rubocop:enable Metrics/BlockLength
|
81
96
|
|
82
97
|
cleanup_except(project, known_ids) if project
|
83
98
|
end
|
99
|
+
# rubocop:enable Metrics/MethodLength
|
100
|
+
|
101
|
+
def acls
|
102
|
+
AccessControlList.where(:consumer, self, api_client: api_client)
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_acl!(details)
|
106
|
+
r = if details.is_a?(AccessControlList)
|
107
|
+
details
|
108
|
+
elsif details.is_a?(String)
|
109
|
+
resource = AccessControlList.new(api_client: api_client)
|
110
|
+
resource.group = details
|
111
|
+
resource
|
112
|
+
else
|
113
|
+
resource = AccessControlList.new(api_client: api_client)
|
114
|
+
resource.group = details[:group]
|
115
|
+
resource
|
116
|
+
end
|
117
|
+
r.consumer = self
|
118
|
+
r.save
|
119
|
+
end
|
84
120
|
|
85
121
|
def add_credential!(details)
|
86
122
|
r = if [BasicauthCredential, JWTCredential, KeyauthCredential].include? details.class
|
@@ -130,6 +166,7 @@ module SkullIsland
|
|
130
166
|
hash = { 'username' => username, 'custom_id' => custom_id }
|
131
167
|
creds = credentials_for_export
|
132
168
|
hash['credentials'] = creds unless creds.empty?
|
169
|
+
hash['acls'] = acls.map { |acl| acl.export(exclude: 'consumer') } unless acls.empty?
|
133
170
|
hash['tags'] = tags unless tags.empty?
|
134
171
|
[*options[:exclude]].each do |exclude|
|
135
172
|
hash.delete(exclude.to_s)
|
@@ -59,11 +59,12 @@ module SkullIsland
|
|
59
59
|
super.reject { |k| %i[run_on].include? k }
|
60
60
|
end
|
61
61
|
|
62
|
+
# rubocop:disable Metrics/AbcSize
|
62
63
|
def export(options = {})
|
63
64
|
hash = {
|
64
65
|
'name' => name,
|
65
66
|
'enabled' => enabled?,
|
66
|
-
'config' => config.deep_sort
|
67
|
+
'config' => config.deep_sort.compact
|
67
68
|
}
|
68
69
|
hash['consumer'] = "<%= lookup :consumer, '#{consumer.username}' %>" if consumer
|
69
70
|
hash['route'] = "<%= lookup :route, '#{route.name}' %>" if route
|
@@ -78,6 +79,7 @@ module SkullIsland
|
|
78
79
|
hash.reject { |_, value| value.nil? }
|
79
80
|
end
|
80
81
|
|
82
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
81
83
|
# rubocop:disable Metrics/PerceivedComplexity
|
82
84
|
def modified_existing?
|
83
85
|
return false unless new?
|
@@ -86,14 +88,15 @@ module SkullIsland
|
|
86
88
|
same_name = self.class.where(:name, name)
|
87
89
|
return false if same_name.size.zero?
|
88
90
|
|
89
|
-
same_name_and_consumer = same_name.where(:consumer, consumer)
|
90
|
-
same_name_and_route = same_name.where(:route, route)
|
91
|
-
same_name_and_service = same_name.where(:service, service)
|
92
|
-
|
91
|
+
same_name_and_consumer = consumer ? same_name.where(:consumer, consumer) : nil
|
92
|
+
same_name_and_route = route ? same_name.where(:route, route) : nil
|
93
|
+
same_name_and_service = service ? same_name.where(:service, service) : nil
|
94
|
+
|
95
|
+
existing = if same_name_and_consumer && same_name_and_consumer.size == 1
|
93
96
|
same_name_and_consumer.first
|
94
|
-
elsif same_name_and_route.size == 1
|
97
|
+
elsif same_name_and_route && same_name_and_route.size == 1
|
95
98
|
same_name_and_route.first
|
96
|
-
elsif same_name_and_service.size == 1
|
99
|
+
elsif same_name_and_service && same_name_and_service.size == 1
|
97
100
|
same_name_and_service.first
|
98
101
|
end
|
99
102
|
if existing
|
@@ -104,6 +107,8 @@ module SkullIsland
|
|
104
107
|
end
|
105
108
|
end
|
106
109
|
# rubocop:enable Metrics/PerceivedComplexity
|
110
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
111
|
+
# rubocop:enable Metrics/AbcSize
|
107
112
|
|
108
113
|
private
|
109
114
|
|
@@ -112,7 +117,7 @@ module SkullIsland
|
|
112
117
|
end
|
113
118
|
|
114
119
|
def postprocess_config(value)
|
115
|
-
value.deep_sort
|
120
|
+
value.deep_sort.compact
|
116
121
|
end
|
117
122
|
|
118
123
|
def postprocess_consumer(value)
|
data/lib/skull_island/version.rb
CHANGED
data/lib/skull_island.rb
CHANGED
@@ -45,6 +45,7 @@ require 'skull_island/helpers/resource_class'
|
|
45
45
|
require 'skull_island/helpers/migration'
|
46
46
|
require 'skull_island/validations/resource'
|
47
47
|
require 'skull_island/resource'
|
48
|
+
require 'skull_island/resources/access_control_list'
|
48
49
|
require 'skull_island/resources/certificate'
|
49
50
|
require 'skull_island/resources/basicauth_credential'
|
50
51
|
require 'skull_island/resources/jwt_credential'
|
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.2.
|
4
|
+
version: 1.2.8
|
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-09-
|
11
|
+
date: 2019-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deepsort
|
@@ -249,6 +249,7 @@ files:
|
|
249
249
|
- lib/skull_island/lru_cache.rb
|
250
250
|
- lib/skull_island/resource.rb
|
251
251
|
- lib/skull_island/resource_collection.rb
|
252
|
+
- lib/skull_island/resources/access_control_list.rb
|
252
253
|
- lib/skull_island/resources/basicauth_credential.rb
|
253
254
|
- lib/skull_island/resources/certificate.rb
|
254
255
|
- lib/skull_island/resources/consumer.rb
|