skull_island 1.2.7 → 1.2.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|