yaml_csp_config 1.0.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +276 -0
- data/Rakefile +29 -0
- data/lib/generators/USAGE +3 -0
- data/lib/generators/install_generator.rb +17 -0
- data/lib/generators/templates/content_security_policy.yml +26 -0
- data/lib/generators/templates/yaml_csp_config.rb +20 -0
- data/lib/tasks/yaml_csp_config_tasks.rake +20 -0
- data/lib/yaml_csp_config.rb +35 -0
- data/lib/yaml_csp_config/csp_ext.rb +10 -0
- data/lib/yaml_csp_config/railtie.rb +10 -0
- data/lib/yaml_csp_config/version.rb +5 -0
- data/lib/yaml_csp_config/yaml_loader.rb +119 -0
- metadata +127 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7c1a15cf473158e7caa531c124ef6d3b916aea37e2935836e091d45e1a577005
|
4
|
+
data.tar.gz: d58ca4a23c4f0c9a00c083b3fc53bb05436de96e53f2eb0c49ebbaaecf89553b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b3086d40d76804167f12b22bed3efa8e50267f8e6060a7715769e7fc0a949e5c5bf3a6c0f2e2173c7b5401d76c83a6385e320916d43b7f4cc043848542311c57
|
7
|
+
data.tar.gz: 0d83c01baa01b4026b0da4c804bdfe3adf1ae3ed2a196d85dc6b10b36cb662306f645a6620382b7b182d8dcf732324e9debc65fc88195247ad1492c725dfdece
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2020 Stephen Ierodiaconou
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,276 @@
|
|
1
|
+
# `yaml_csp_config`: Rails content security policy configuration in YAML
|
2
|
+
|
3
|
+
### What?
|
4
|
+
|
5
|
+
This Rails plugin gem is designed to allow you to be able to specify your content security policy
|
6
|
+
for Rails 5.2+ in a YAML file, instead of using the Rails DSL.
|
7
|
+
|
8
|
+
This makes the configuration of your content security policy more akin to configuring other things
|
9
|
+
through YAML files.
|
10
|
+
|
11
|
+
The gem also contains a extra few features. These allow you to add content security policy configuration
|
12
|
+
via environment variables, either by configuring a specific addition for a specific directive or by
|
13
|
+
configuring the name of a group of configurations to be applied from the configuration file in the
|
14
|
+
application. This is useful for deployed environments where the content security policy may be slightly
|
15
|
+
different per deployment.
|
16
|
+
|
17
|
+
### Why?
|
18
|
+
|
19
|
+
* Configure your CSP in YAML
|
20
|
+
* Provide additional CSP configuration which is applied according to environment variables
|
21
|
+
|
22
|
+
## Example
|
23
|
+
|
24
|
+
Below is an artificial example of a security policy before and after converting DSL to YAML,
|
25
|
+
making use of YAML aliases to allow sharing of policy configurations:
|
26
|
+
|
27
|
+
### Before (Without this gem):
|
28
|
+
|
29
|
+
`config/initializers/content_security_policy.rb`
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
GOOGLE_STATIC = ["https://*.googleapis.com", "https://*.gstatic.com"].freeze
|
33
|
+
|
34
|
+
CSP_SCRIPT_HOSTS = %w[
|
35
|
+
https://cdnjs.cloudflare.com
|
36
|
+
https://www.google-analytics.com
|
37
|
+
https://maps.googleapis.com
|
38
|
+
].freeze
|
39
|
+
|
40
|
+
CSP_FONT_HOSTS = (["https://fonts.gstatic.com"] + GOOGLE_STATIC).freeze
|
41
|
+
|
42
|
+
CSP_IMAGE_HOSTS = (["https://s3.amazonaws.com"] + GOOGLE_STATIC).freeze
|
43
|
+
|
44
|
+
CSP_WEBPACKER_HOST = "http://localhost:3035"
|
45
|
+
|
46
|
+
CSP_DEV_CONNECT_SRC = %w[
|
47
|
+
http://localhost:3035
|
48
|
+
ws://localhost:3000
|
49
|
+
ws://localhost:3035
|
50
|
+
ws://127.0.0.1:35729
|
51
|
+
].freeze
|
52
|
+
|
53
|
+
CSP_REVIEW_CONNECT_SRC = %w[
|
54
|
+
wss://*.herokuapp.com
|
55
|
+
].freeze
|
56
|
+
|
57
|
+
Rails.application.config.content_security_policy do |policy|
|
58
|
+
policy.report_uri("/csp-violation-report-endpoint")
|
59
|
+
|
60
|
+
policy.default_src(:self)
|
61
|
+
|
62
|
+
policy.object_src(:none)
|
63
|
+
|
64
|
+
policy.font_src(:self, *CSP_FONT_HOSTS)
|
65
|
+
|
66
|
+
policy.style_src(:self, :data, :unsafe_inline)
|
67
|
+
|
68
|
+
if Rails.env.development?
|
69
|
+
policy.img_src(:self, :data, CSP_WEBPACKER_HOST, *CSP_IMAGE_HOSTS)
|
70
|
+
|
71
|
+
policy.script_src(:self, :unsafe_eval, CSP_WEBPACKER_HOST, *CSP_SCRIPT_HOSTS)
|
72
|
+
|
73
|
+
policy.connect_src(:self, *CSP_DEV_CONNECT_SRC)
|
74
|
+
else
|
75
|
+
policy.img_src(:self, :data, *CSP_IMAGE_HOSTS)
|
76
|
+
|
77
|
+
policy.script_src(:self, *CSP_SCRIPT_HOSTS)
|
78
|
+
|
79
|
+
if ENV["IN_REVIEW_APP"].present?
|
80
|
+
policy.connect_src(:self, *CSP_REVIEW_CONNECT_SRC)
|
81
|
+
else
|
82
|
+
policy.connect_src(:self)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# ...
|
88
|
+
```
|
89
|
+
|
90
|
+
### After (With this gem):
|
91
|
+
|
92
|
+
`config/content_security_policy.yml`
|
93
|
+
|
94
|
+
```yaml
|
95
|
+
self_and_data_uri_policy: &SELF_AND_DATA
|
96
|
+
- :self
|
97
|
+
- :data
|
98
|
+
|
99
|
+
google_static_hosts: &GOOGLE_STATIC
|
100
|
+
- https://*.googleapis.com
|
101
|
+
- https://*.gstatic.com
|
102
|
+
|
103
|
+
content_security_policy:
|
104
|
+
# Base config
|
105
|
+
report_uri: "/csp-violation-report-endpoint"
|
106
|
+
|
107
|
+
default_src: :self
|
108
|
+
|
109
|
+
object_src: :none
|
110
|
+
|
111
|
+
font_src:
|
112
|
+
- :self
|
113
|
+
- *GOOGLE_STATIC
|
114
|
+
- https://fonts.gstatic.com
|
115
|
+
|
116
|
+
style_src:
|
117
|
+
- *SELF_AND_DATA
|
118
|
+
- :unsafe_inline
|
119
|
+
|
120
|
+
img_src:
|
121
|
+
- *SELF_AND_DATA
|
122
|
+
- *GOOGLE_STATIC
|
123
|
+
- https://s3.amazonaws.com
|
124
|
+
|
125
|
+
script_src:
|
126
|
+
- :self
|
127
|
+
- https://cdnjs.cloudflare.com
|
128
|
+
- https://www.google-analytics.com
|
129
|
+
- https://maps.googleapis.com
|
130
|
+
|
131
|
+
connect_src:
|
132
|
+
- :self
|
133
|
+
|
134
|
+
development:
|
135
|
+
img_src:
|
136
|
+
- http://localhost:3035
|
137
|
+
|
138
|
+
script_src:
|
139
|
+
- http://localhost:3035
|
140
|
+
|
141
|
+
connect_src:
|
142
|
+
- http://localhost:3035
|
143
|
+
- ws://localhost:3000
|
144
|
+
- ws://localhost:3035
|
145
|
+
- ws://127.0.0.1:35729
|
146
|
+
|
147
|
+
review_apps:
|
148
|
+
connect_src:
|
149
|
+
- wss://*.herokuapp.com
|
150
|
+
```
|
151
|
+
|
152
|
+
|
153
|
+
## Installation
|
154
|
+
Add to your Gemfile:
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
gem 'yaml_csp_config'
|
158
|
+
```
|
159
|
+
|
160
|
+
Or install it yourself as:
|
161
|
+
```bash
|
162
|
+
$ gem install yaml_csp_config
|
163
|
+
```
|
164
|
+
Then run the **generator to add the initializer**
|
165
|
+
|
166
|
+
rails yaml_csp_config:install
|
167
|
+
|
168
|
+
|
169
|
+
## Usage
|
170
|
+
|
171
|
+
### `ActionDispatch::ContentSecurityPolicy.load_from_file`
|
172
|
+
|
173
|
+
`YamlCspConfig` extends `ActionDispatch::ContentSecurityPolicy` with a method to
|
174
|
+
load configuration from a YAML file. By default the initializer will add the `load_from_file`
|
175
|
+
instance method and call it on initialisation.
|
176
|
+
|
177
|
+
If you wish instead to call it explicitly make sure to comment it out from the initializer.
|
178
|
+
|
179
|
+
### YAML file format
|
180
|
+
|
181
|
+
**Note: The YAML file can also be an ERB template.**
|
182
|
+
|
183
|
+
The file must contain at at least the 'base' configuration group, containing the base or common CSP
|
184
|
+
configuration.
|
185
|
+
|
186
|
+
This key of this group by default is `content_security_policy` but can be configured via the `yaml_config_base_key`
|
187
|
+
config value in the initializer.
|
188
|
+
|
189
|
+
Directive configurations are then specified as keys named after the directive
|
190
|
+
(see `YamlCspConfig::YamlLoader::DIRECTIVES` for a list) and then either an array of policy values,
|
191
|
+
or a single value (note that if you use aliases you may end up creating nested arrays of values this
|
192
|
+
is no problem as it will be flattened). Values can either be strings or symbols.
|
193
|
+
|
194
|
+
```yaml
|
195
|
+
# example
|
196
|
+
content_security_policy:
|
197
|
+
object_src: :none
|
198
|
+
connect_src:
|
199
|
+
- :self
|
200
|
+
font_src: *SELF_AND_DATA
|
201
|
+
script_src:
|
202
|
+
- :self
|
203
|
+
- *GOOGLE
|
204
|
+
img_src: "host"
|
205
|
+
```
|
206
|
+
|
207
|
+
The file can contain any number of other configuration groups. If the group is named after an environment of your Rails
|
208
|
+
application it will be mixed in automatically if the application is running in that environment.
|
209
|
+
|
210
|
+
### Adding to configuration based on current Rails environment
|
211
|
+
|
212
|
+
A configuration group named after rails environment will be mixed in in that environment:
|
213
|
+
|
214
|
+
```yaml
|
215
|
+
# example
|
216
|
+
development:
|
217
|
+
connect_src: "host.dev"
|
218
|
+
test:
|
219
|
+
connect_src: "host.test"
|
220
|
+
```
|
221
|
+
|
222
|
+
### Adding a named configuration group using an environment variable
|
223
|
+
|
224
|
+
The name of the environment variable that can be set with the name of the group to add is by default
|
225
|
+
`CSP_CONFIGURATION_GROUP_KEY`. It can be changed using the configuration variable `default_env_var_group_key`
|
226
|
+
from the initializer.
|
227
|
+
|
228
|
+
for example given the following environment variables set on the application's environmentY
|
229
|
+
|
230
|
+
CSP_CONFIGURATION_GROUP_KEY=staging_app
|
231
|
+
|
232
|
+
the following configuration group will be mixed in:
|
233
|
+
|
234
|
+
```yaml
|
235
|
+
# example
|
236
|
+
staging_app:
|
237
|
+
connect_src: "host.staging"
|
238
|
+
```
|
239
|
+
|
240
|
+
### Adding to configuration based with environment variables
|
241
|
+
|
242
|
+
The CSP configuration can also be extended directly by environment variables. The environment variable names are
|
243
|
+
prefixed with a standard prefix. This prefix is by default `CSP_CONFIGURATION_ADDITIONS_`. It can be changed using
|
244
|
+
the configuration variable `default_env_var_additions_key_prefix` from the initializer.
|
245
|
+
|
246
|
+
After the prefix comes the name of the directive in uppercase. The value of the environment variable will then be added
|
247
|
+
automatically to the configuration of that directive.
|
248
|
+
|
249
|
+
For example:
|
250
|
+
|
251
|
+
CSP_CONFIGURATION_ADDITIONS_SCRIPT_SRC=host.cdn
|
252
|
+
|
253
|
+
will add `host.cdn` to the `script_src` directive.
|
254
|
+
|
255
|
+
## Run type check (RBS & steep)
|
256
|
+
|
257
|
+
First copy the signatures for Rails from `https://github.com/pocke/rbs_rails/tree/master/assets/sig`
|
258
|
+
to the project `sig/rbs_rails` directory. Then run
|
259
|
+
|
260
|
+
bundle exec steep check
|
261
|
+
|
262
|
+
## Run tests
|
263
|
+
|
264
|
+
./bin/test
|
265
|
+
|
266
|
+
## License
|
267
|
+
|
268
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
269
|
+
|
270
|
+
## Contributing
|
271
|
+
|
272
|
+
Contributors welcome! Any contribution appreciated Pull requests, issues, and feature requests.
|
273
|
+
|
274
|
+
## Contributors
|
275
|
+
|
276
|
+
[Stephen Ierodiaconou](https://github.com/stevegeek/)
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "bundler/setup"
|
5
|
+
rescue LoadError
|
6
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
7
|
+
end
|
8
|
+
|
9
|
+
require "rdoc/task"
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = "rdoc"
|
13
|
+
rdoc.title = "YamlCspConfig"
|
14
|
+
rdoc.options << "--line-numbers"
|
15
|
+
rdoc.rdoc_files.include("README.md")
|
16
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
17
|
+
end
|
18
|
+
|
19
|
+
require "bundler/gem_tasks"
|
20
|
+
|
21
|
+
require "rake/testtask"
|
22
|
+
|
23
|
+
Rake::TestTask.new(:test) do |t|
|
24
|
+
t.libs << "test"
|
25
|
+
t.pattern = "test/**/*_test.rb"
|
26
|
+
t.verbose = false
|
27
|
+
end
|
28
|
+
|
29
|
+
task default: :test
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators/base"
|
4
|
+
|
5
|
+
module YamlCspConfig
|
6
|
+
module Generators
|
7
|
+
# The Install generator `yaml_csp_config:install`
|
8
|
+
class InstallGenerator < Rails::Generators::Base
|
9
|
+
source_root File.expand_path(__dir__)
|
10
|
+
|
11
|
+
desc "Creates an initial basic YAML configuration, an initializer and configures Rails to use the gem."
|
12
|
+
|
13
|
+
copy_file "yaml_csp_config.rb", "config/initializers/yaml_csp_config.rb"
|
14
|
+
copy_file "content_security_policy.yml", "config/content_security_policy.yml"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Base config example
|
2
|
+
content_security_policy:
|
3
|
+
report_uri: "/csp-violation-report-endpoint"
|
4
|
+
|
5
|
+
default_src: :self
|
6
|
+
|
7
|
+
object_src: :none
|
8
|
+
|
9
|
+
connect_src:
|
10
|
+
- :self
|
11
|
+
|
12
|
+
font_src:
|
13
|
+
- :self
|
14
|
+
- :data
|
15
|
+
|
16
|
+
script_src:
|
17
|
+
- :self
|
18
|
+
|
19
|
+
img_src:
|
20
|
+
- :self
|
21
|
+
- :data
|
22
|
+
|
23
|
+
# In 'development' Rails env
|
24
|
+
development:
|
25
|
+
script_src:
|
26
|
+
- :unsafe_eval
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
YamlCspConfig.configure do |config|
|
4
|
+
# The path to the configuration file
|
5
|
+
# config.configuration_file_path = Rails.root.join("config", "content_security_policy.yml")
|
6
|
+
|
7
|
+
# The prefix to the environment variables that can be used to add to specific directives, for example
|
8
|
+
# `CSP_CONFIGURATION_ADDITIONS_SCRIPT_SRC = 'self https://host'`
|
9
|
+
# config.default_env_var_additions_key_prefix = "CSP_CONFIGURATION_ADDITIONS_"
|
10
|
+
|
11
|
+
# The environment variable that contains the name of the YAML k/v group to add to the base rules.
|
12
|
+
# If this is set any rules in the given named group will add to the default base ones.
|
13
|
+
# config.default_env_var_group_key = "CSP_CONFIGURATION_GROUP_KEY"
|
14
|
+
|
15
|
+
# The route the YAML file key which contains the base rules.
|
16
|
+
# config.yaml_config_base_key = "content_security_policy"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Load the configuration file and configure the content security policy.
|
20
|
+
Rails.application.config.content_security_policy(&:load_from_yml)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
desc "Output the final CSP configuration in this environment"
|
4
|
+
namespace :yaml_csp_config do
|
5
|
+
task view: :environment do
|
6
|
+
YamlCspConfig.configure
|
7
|
+
policy = ActionDispatch::ContentSecurityPolicy.new.load_from_yml
|
8
|
+
puts "\nDirective\t\t: Directive Value"
|
9
|
+
puts "---------\t\t ---------------"
|
10
|
+
policy.directives.each do |k, v|
|
11
|
+
puts "#{k}\t\t: #{v.join(' ')}"
|
12
|
+
end
|
13
|
+
|
14
|
+
puts "\n\nConfiguration\t\t: Value"
|
15
|
+
puts "-------------\t\t -----"
|
16
|
+
YamlCspConfig.configuration.instance_variables.each do |k|
|
17
|
+
puts "#{k[1..]}\t\t: '#{YamlCspConfig.configuration.instance_variable_get(k)}'"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml_csp_config/railtie"
|
4
|
+
require "yaml_csp_config/csp_ext"
|
5
|
+
require "yaml_csp_config/yaml_loader"
|
6
|
+
|
7
|
+
# Exposes a configuration class for initializer
|
8
|
+
module YamlCspConfig
|
9
|
+
class << self
|
10
|
+
attr_reader :configuration
|
11
|
+
|
12
|
+
def configure
|
13
|
+
@configuration ||= Configuration.new
|
14
|
+
yield(configuration) if block_given?
|
15
|
+
configuration
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Configuration class for initializer
|
20
|
+
class Configuration
|
21
|
+
# @dynamic configuration_file_path, yaml_config_base_key
|
22
|
+
attr_accessor :configuration_file_path,
|
23
|
+
:yaml_config_base_key
|
24
|
+
# @dynamic default_env_var_additions_key_prefix, default_env_var_group_key
|
25
|
+
attr_accessor :default_env_var_additions_key_prefix,
|
26
|
+
:default_env_var_group_key
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@configuration_file_path = Rails.root.join("config", "content_security_policy.yml")
|
30
|
+
@default_env_var_additions_key_prefix = "CSP_CONFIGURATION_ADDITIONS_"
|
31
|
+
@default_env_var_group_key = "CSP_CONFIGURATION_GROUP_KEY"
|
32
|
+
@yaml_config_base_key = "content_security_policy"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module YamlCspConfig
|
4
|
+
# The entity that is responsible for loading the YAML and applying overrides
|
5
|
+
class YamlLoader
|
6
|
+
DIRECTIVES = %i[
|
7
|
+
base_uri
|
8
|
+
child_src
|
9
|
+
connect_src
|
10
|
+
default_src
|
11
|
+
font_src
|
12
|
+
form_action
|
13
|
+
frame_ancestors
|
14
|
+
frame_src
|
15
|
+
img_src
|
16
|
+
manifest_src
|
17
|
+
media_src
|
18
|
+
object_src
|
19
|
+
prefetch_src
|
20
|
+
script_src
|
21
|
+
style_src
|
22
|
+
worker_src
|
23
|
+
].freeze
|
24
|
+
|
25
|
+
class << self
|
26
|
+
def call(policy, config_file = YamlCspConfig.configuration.configuration_file_path)
|
27
|
+
new(policy, config_file).configure
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(
|
32
|
+
policy,
|
33
|
+
config_file_path,
|
34
|
+
group_key: YamlCspConfig.configuration.default_env_var_group_key,
|
35
|
+
var_key_prefix: YamlCspConfig.configuration.default_env_var_additions_key_prefix
|
36
|
+
)
|
37
|
+
raise ArgumentError, "Config file doesn't exist" unless File.exist?(config_file_path)
|
38
|
+
|
39
|
+
@policy = policy
|
40
|
+
@config_file_path = config_file_path
|
41
|
+
@env_var_group_key = group_key
|
42
|
+
@env_var_key_prefix = var_key_prefix
|
43
|
+
end
|
44
|
+
|
45
|
+
def configure
|
46
|
+
configure_with_overrides.each do |rule, values|
|
47
|
+
unless policy.respond_to?(rule.to_sym)
|
48
|
+
raise StandardError, "A CSP configuration was defined for an unsupported directive/setting: #{rule}"
|
49
|
+
end
|
50
|
+
|
51
|
+
policy.send(rule, *values)
|
52
|
+
end
|
53
|
+
|
54
|
+
policy
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
attr_reader :policy, :config_file_path, :env_var_group_key, :env_var_key_prefix
|
60
|
+
|
61
|
+
def raw_configuration
|
62
|
+
parsed = ERB.new(File.read(config_file_path.to_s)).result(binding)
|
63
|
+
YAML.safe_load(parsed, permitted_classes: [Symbol], aliases: true)
|
64
|
+
end
|
65
|
+
|
66
|
+
def configure_with_overrides
|
67
|
+
config = raw_configuration
|
68
|
+
policies = config[config_key_base].transform_values { |v| parse_policies_config(v) }
|
69
|
+
env_var_direct_override(
|
70
|
+
env_var_group_override(
|
71
|
+
config,
|
72
|
+
env_override(config, policies)
|
73
|
+
)
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Override with any Rails env specific config
|
78
|
+
def env_override(config, policies)
|
79
|
+
d = config[Rails.env.to_s]
|
80
|
+
return policies unless d
|
81
|
+
raise(StandardError, "The config is invalid for env #{Rails.env}") unless d.is_a?(Hash)
|
82
|
+
d.each { |k, v| add_to_csp(policies, k, v) }
|
83
|
+
policies
|
84
|
+
end
|
85
|
+
|
86
|
+
# Optional an overriding config group can be specified by name in an environment variable
|
87
|
+
def env_var_group_override(config, policies)
|
88
|
+
group_name = ENV[env_var_group_key]
|
89
|
+
return policies if group_name.nil? || group_name.empty? || group_name == Rails.env
|
90
|
+
d = config[group_name]
|
91
|
+
raise(StandardError, "The config is invalid for #{group_name}") unless d.is_a?(Hash)
|
92
|
+
d.each { |k, v| add_to_csp(policies, k, v) }
|
93
|
+
policies
|
94
|
+
end
|
95
|
+
|
96
|
+
# Allow environment variables to add to rules
|
97
|
+
def env_var_direct_override(policies)
|
98
|
+
DIRECTIVES.each do |rule|
|
99
|
+
d = rule.to_s
|
100
|
+
k = env_var_key_prefix + d.upcase
|
101
|
+
add_to_csp(policies, d, ENV[k].split(" ")) if ENV[k].present?
|
102
|
+
end
|
103
|
+
policies
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_to_csp(policies, rule, value)
|
107
|
+
policies[rule] ||= []
|
108
|
+
policies[rule] += parse_policies_config(value)
|
109
|
+
end
|
110
|
+
|
111
|
+
def parse_policies_config(policy)
|
112
|
+
Array.wrap(policy).flatten
|
113
|
+
end
|
114
|
+
|
115
|
+
def config_key_base
|
116
|
+
@config_key_base ||= YamlCspConfig.configuration.yaml_config_base_key.to_s
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yaml_csp_config
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Ierodiaconou
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-09-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rbs_rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: steep
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: The CSP configuration can also be extended by environment variables.
|
84
|
+
email:
|
85
|
+
- stevegeek@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- MIT-LICENSE
|
91
|
+
- README.md
|
92
|
+
- Rakefile
|
93
|
+
- lib/generators/USAGE
|
94
|
+
- lib/generators/install_generator.rb
|
95
|
+
- lib/generators/templates/content_security_policy.yml
|
96
|
+
- lib/generators/templates/yaml_csp_config.rb
|
97
|
+
- lib/tasks/yaml_csp_config_tasks.rake
|
98
|
+
- lib/yaml_csp_config.rb
|
99
|
+
- lib/yaml_csp_config/csp_ext.rb
|
100
|
+
- lib/yaml_csp_config/railtie.rb
|
101
|
+
- lib/yaml_csp_config/version.rb
|
102
|
+
- lib/yaml_csp_config/yaml_loader.rb
|
103
|
+
homepage: https://github.com/stevegeek/yaml_csp_config
|
104
|
+
licenses:
|
105
|
+
- MIT
|
106
|
+
metadata: {}
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '2.6'
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
requirements: []
|
122
|
+
rubygems_version: 3.0.3
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: yaml_csp_config provides you with a way to manage your Rails CSP configuration
|
126
|
+
via a YAML file.
|
127
|
+
test_files: []
|