global 0.2.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/tests.yml +24 -0
- data/.rubocop.yml +110 -0
- data/.ruby-version +1 -1
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +3 -6
- data/README.md +275 -66
- data/Rakefile +10 -2
- data/bin/console +15 -0
- data/global.gemspec +20 -22
- data/lib/global/backend/aws_parameter_store.rb +110 -0
- data/lib/global/backend/filesystem.rb +91 -0
- data/lib/global/backend/gcp_secret_manager.rb +137 -0
- data/lib/global/base.rb +40 -60
- data/lib/global/configuration.rb +25 -18
- data/lib/global/version.rb +4 -2
- data/lib/global.rb +5 -2
- data/spec/files/aws.test.yml +3 -0
- data/spec/files/aws.yml +6 -0
- data/spec/global/backend/aws_parameter_store_spec.rb +48 -0
- data/spec/global/backend/gcp_secret_manager_spec.rb +39 -0
- data/spec/global/configuration_spec.rb +88 -74
- data/spec/global_spec.rb +53 -70
- data/spec/merge_backends_spec.rb +23 -0
- data/spec/spec_helper.rb +9 -6
- metadata +68 -30
- data/.travis.yml +0 -30
- data/app/assets/javascripts/global-js.js.erb +0 -2
- data/lib/global/engine.rb +0 -78
- data/spec/global/global_js_spec.rb +0 -114
- data/spec/support/javascript_helper.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0da470ddbf97c73984898898bbada287d1fef733da1059016dbe7021a6b4e55a
|
4
|
+
data.tar.gz: b5cf15fb7e5a9e4e9cb7b30a0bf1265a374693d6f1423b95940976c9beeca3f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbd030fd6ced5e6e3f0d47d75d14f59e16a69411814b1432f0bf66fb03444950006a87b86eed155f758c4a5535eb6e8d9d870edbecdc26c9a66b2a9230384e82
|
7
|
+
data.tar.gz: b99c7b6c92c33324834ad7fd92c75606a9abddbe7d8fe0fbe22b344013000a49073ece171b8063713b370d2c6526c6c0eee928584c90317e5592034506bc3790
|
@@ -0,0 +1,24 @@
|
|
1
|
+
name: Runs linter and tests
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
linters_and_tests:
|
7
|
+
runs-on: ${{ matrix.os }}-latest
|
8
|
+
continue-on-error: ${{ matrix.experimental == true }}
|
9
|
+
name: Linter and tests on ${{ matrix.os }}-ruby-${{ matrix.ruby-version }}
|
10
|
+
strategy:
|
11
|
+
matrix:
|
12
|
+
os: [ubuntu, macos]
|
13
|
+
ruby-version: ['3.1', '3.0', '2.7', '2.6', '2.5']
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v2
|
16
|
+
|
17
|
+
- name: Set up Ruby
|
18
|
+
uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: ${{ matrix.ruby-version }}
|
21
|
+
bundler-cache: true
|
22
|
+
|
23
|
+
- name: Runs linter and tests
|
24
|
+
run: bundle exec rake
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
Metrics/MethodLength:
|
2
|
+
Enabled: true
|
3
|
+
Max: 11
|
4
|
+
|
5
|
+
Layout/EmptyLinesAroundBlockBody:
|
6
|
+
Enabled: false
|
7
|
+
|
8
|
+
Layout/SpaceInsideBlockBraces:
|
9
|
+
Enabled: true
|
10
|
+
EnforcedStyle: space
|
11
|
+
EnforcedStyleForEmptyBraces: no_space
|
12
|
+
SpaceBeforeBlockParameters: true
|
13
|
+
|
14
|
+
Layout/SpaceBeforeBlockBraces:
|
15
|
+
Enabled: true
|
16
|
+
EnforcedStyle: space
|
17
|
+
EnforcedStyleForEmptyBraces: space
|
18
|
+
|
19
|
+
Layout/SpaceInsideHashLiteralBraces:
|
20
|
+
Enabled: true
|
21
|
+
EnforcedStyle: compact
|
22
|
+
EnforcedStyleForEmptyBraces: no_space
|
23
|
+
|
24
|
+
Layout/EmptyLinesAroundClassBody:
|
25
|
+
Enabled: true
|
26
|
+
EnforcedStyle: empty_lines_except_namespace
|
27
|
+
|
28
|
+
Layout/EmptyLinesAroundModuleBody:
|
29
|
+
Enabled: true
|
30
|
+
EnforcedStyle: empty_lines_except_namespace
|
31
|
+
|
32
|
+
Layout/MultilineMethodCallIndentation:
|
33
|
+
Enabled: true
|
34
|
+
EnforcedStyle: indented
|
35
|
+
|
36
|
+
Layout/HashAlignment:
|
37
|
+
Enabled: true
|
38
|
+
EnforcedLastArgumentHashStyle: always_ignore
|
39
|
+
|
40
|
+
Lint/RaiseException:
|
41
|
+
Enabled: true
|
42
|
+
|
43
|
+
Lint/StructNewOverride:
|
44
|
+
Enabled: true
|
45
|
+
|
46
|
+
Style/RaiseArgs:
|
47
|
+
EnforcedStyle: compact
|
48
|
+
|
49
|
+
Style/YodaCondition:
|
50
|
+
Enabled: false
|
51
|
+
|
52
|
+
Style/FrozenStringLiteralComment:
|
53
|
+
Enabled: true
|
54
|
+
EnforcedStyle: always
|
55
|
+
|
56
|
+
Style/HashEachMethods:
|
57
|
+
Enabled: true
|
58
|
+
|
59
|
+
Style/HashTransformKeys:
|
60
|
+
Enabled: true
|
61
|
+
|
62
|
+
Style/HashTransformValues:
|
63
|
+
Enabled: true
|
64
|
+
|
65
|
+
Style/RegexpLiteral:
|
66
|
+
Enabled: true
|
67
|
+
EnforcedStyle: slashes
|
68
|
+
AllowInnerSlashes: false
|
69
|
+
|
70
|
+
Layout/FirstHashElementIndentation:
|
71
|
+
EnforcedStyle: consistent
|
72
|
+
|
73
|
+
Style/Documentation:
|
74
|
+
Enabled: false
|
75
|
+
|
76
|
+
Style/SafeNavigation:
|
77
|
+
Enabled: true
|
78
|
+
AllowedMethods:
|
79
|
+
- present?
|
80
|
+
- blank?
|
81
|
+
- presence
|
82
|
+
|
83
|
+
Lint/AmbiguousBlockAssociation:
|
84
|
+
Exclude:
|
85
|
+
- "spec/**/*"
|
86
|
+
|
87
|
+
Naming/PredicateName:
|
88
|
+
Exclude:
|
89
|
+
- "spec/**/*"
|
90
|
+
|
91
|
+
Style/NumericPredicate:
|
92
|
+
Exclude:
|
93
|
+
- "spec/**/*"
|
94
|
+
|
95
|
+
Metrics/BlockLength:
|
96
|
+
Exclude:
|
97
|
+
- "spec/**/*"
|
98
|
+
|
99
|
+
Layout/LineLength:
|
100
|
+
Max: 120
|
101
|
+
Exclude:
|
102
|
+
- "spec/**/*"
|
103
|
+
|
104
|
+
Metrics/AbcSize:
|
105
|
+
Max: 22
|
106
|
+
Exclude:
|
107
|
+
- "spec/**/*"
|
108
|
+
|
109
|
+
Style/ModuleFunction:
|
110
|
+
EnforcedStyle: extend_self
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.6
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at leopard.not.a@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [https://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: https://contributor-covenant.org
|
74
|
+
[version]: https://contributor-covenant.org/version/1/4/
|
data/Gemfile
CHANGED
@@ -1,9 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
# Specify your gem's dependencies in global.gemspec
|
4
6
|
gemspec
|
5
|
-
|
6
|
-
if RUBY_VERSION < "2.2.2"
|
7
|
-
# activesupport 5+ requires MRI 2.2.2+
|
8
|
-
gem "activesupport", "< 5.0.0"
|
9
|
-
end
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
# Global [![
|
1
|
+
# Global [![Runs linter and tests](https://github.com/railsware/global/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/railsware/global/actions/workflows/tests.yml) [![Code Climate](https://codeclimate.com/github/railsware/global.png)](https://codeclimate.com/github/railsware/global)
|
2
2
|
|
3
|
-
The 'global' gem provides accessor methods for your configuration data and share configuration across backend and frontend.
|
3
|
+
The 'global' gem provides accessor methods for your configuration data and share configuration across backend and frontend.
|
4
|
+
|
5
|
+
The data can be stored in [YAML](https://yaml.org) files on disk, or in the [AWS SSM Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html).
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -10,36 +12,73 @@ Add to Gemfile:
|
|
10
12
|
gem 'global'
|
11
13
|
```
|
12
14
|
|
15
|
+
Refer to the documentation on your chosen backend class for other dependencies.
|
16
|
+
|
13
17
|
## Configuration
|
14
18
|
|
19
|
+
Refer to the documentation on your chosen backend class for configuration options.
|
20
|
+
|
15
21
|
```ruby
|
16
|
-
> Global.environment
|
17
|
-
> Global.config_directory = "PATH_TO_DIRECTORY_WITH_FILES"
|
22
|
+
> Global.backend(:filesystem, environment: "YOUR_ENV_HERE", path: "PATH_TO_DIRECTORY_WITH_FILES")
|
18
23
|
```
|
19
24
|
|
20
25
|
Or you can use `configure` block:
|
21
26
|
|
22
27
|
```ruby
|
23
28
|
Global.configure do |config|
|
24
|
-
config.environment
|
25
|
-
|
29
|
+
config.backend :filesystem, environment: "YOUR_ENV_HERE", path: "PATH_TO_DIRECTORY_WITH_FILES"
|
30
|
+
# set up multiple backends and have them merged together:
|
31
|
+
config.backend :aws_parameter_store, prefix: '/prod/MyApp/'
|
32
|
+
config.backend :gcp_secret_manager, prefix: 'prod-myapp-', project_id: 'example'
|
26
33
|
end
|
27
34
|
```
|
28
35
|
|
29
|
-
|
36
|
+
### Using multiple backends
|
37
|
+
|
38
|
+
Sometimes it is practical to store some configuration data on disk (and perhaps, commit it to source control), but
|
39
|
+
keep some other data in a secure remote location. Which is why you can use more than one backend with Global.
|
40
|
+
|
41
|
+
You can declare as many backends as you want; the configuration trees from the backends are deep-merged together,
|
42
|
+
so that the backend declared later overwrites specific keys in the backend declared prior:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
Global.configure do |config|
|
46
|
+
config.backend :foo # loads tree { credentials: { hostname: 'api.com', username: 'dev', password: 'dev' } }
|
47
|
+
config.backend :bar # loads tree { credentials: { username: 'xxx', password: 'yyy' } }
|
48
|
+
end
|
49
|
+
|
50
|
+
Global.credentials.hostname # => 'api.com'
|
51
|
+
Global.credentials.username # => 'xxx'
|
52
|
+
Global.credentials.password # => 'yyy'
|
53
|
+
```
|
54
|
+
|
55
|
+
For Rails, put initialization into `config/initializers/global.rb`.
|
56
|
+
|
57
|
+
There are some sensible defaults, check your backend class for documentation.
|
30
58
|
|
31
59
|
```ruby
|
32
60
|
Global.configure do |config|
|
33
|
-
config.
|
34
|
-
config.config_directory = Rails.root.join('config/global').to_s
|
61
|
+
config.backend :filesystem
|
35
62
|
end
|
36
63
|
```
|
37
64
|
|
65
|
+
### Filesystem storage
|
66
|
+
|
67
|
+
The `yaml_whitelist_classes` configuration allows you to deserialize other classes from your `.yml`
|
68
|
+
|
69
|
+
### AWS Parameter Store
|
70
|
+
|
71
|
+
The `aws_options` configuration allows you to customize the AWS credentials and connection.
|
72
|
+
|
73
|
+
### Google Cloud Secret Manager
|
74
|
+
|
75
|
+
The `gcp_options` configuration allows you to customize the Google Cloud credentials and timeout.
|
76
|
+
|
38
77
|
## Usage
|
39
78
|
|
40
|
-
###
|
79
|
+
### Filesystem
|
41
80
|
|
42
|
-
|
81
|
+
For file `config/global/hosts.yml`:
|
43
82
|
|
44
83
|
```yml
|
45
84
|
test:
|
@@ -62,9 +101,28 @@ In the development environment we now have:
|
|
62
101
|
=> "api.localhost"
|
63
102
|
```
|
64
103
|
|
65
|
-
|
104
|
+
#### Deserialize other classes from `.yml`
|
66
105
|
|
67
|
-
Config file `config/global/
|
106
|
+
Config file `config/global/validations.yml`:
|
107
|
+
|
108
|
+
```yml
|
109
|
+
default:
|
110
|
+
regexp:
|
111
|
+
email: !ruby/regexp /.@.+\../
|
112
|
+
```
|
113
|
+
|
114
|
+
Ensure that `Regexp` is included in the `yaml_whitelist_classes` array
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
Global.validations.regexp.email === 'mail@example.com'
|
118
|
+
=> true
|
119
|
+
```
|
120
|
+
|
121
|
+
#### Per-environment sections
|
122
|
+
|
123
|
+
You can define environment sections at the top level of every individual YAML file
|
124
|
+
|
125
|
+
For example, having a config file `config/global/web/basic_auth.yml` with:
|
68
126
|
|
69
127
|
```yml
|
70
128
|
test:
|
@@ -78,7 +136,7 @@ production:
|
|
78
136
|
password: supersecret
|
79
137
|
```
|
80
138
|
|
81
|
-
|
139
|
+
You get the correct configuration in development
|
82
140
|
|
83
141
|
```ruby
|
84
142
|
> Global.web.basic_auth
|
@@ -87,7 +145,7 @@ After that in development environment we have:
|
|
87
145
|
=> "development_user"
|
88
146
|
```
|
89
147
|
|
90
|
-
|
148
|
+
#### Default section
|
91
149
|
|
92
150
|
Config file example:
|
93
151
|
|
@@ -102,9 +160,10 @@ production:
|
|
102
160
|
|
103
161
|
Data from the default section is used until it's overridden in a specific environment.
|
104
162
|
|
105
|
-
|
163
|
+
#### Nested configurations
|
106
164
|
|
107
165
|
Config file `global/nested.yml` with:
|
166
|
+
|
108
167
|
```yml
|
109
168
|
test:
|
110
169
|
group:
|
@@ -124,8 +183,41 @@ Nested options can then be accessed as follows:
|
|
124
183
|
=> "development value"
|
125
184
|
```
|
126
185
|
|
186
|
+
#### Environment files
|
187
|
+
|
188
|
+
Config file `global/aws.yml` with:
|
189
|
+
```yml
|
190
|
+
:default:
|
191
|
+
activated: false
|
127
192
|
|
128
|
-
|
193
|
+
staging:
|
194
|
+
activated: true
|
195
|
+
api_key: 'nothing'
|
196
|
+
|
197
|
+
```
|
198
|
+
|
199
|
+
And file `global/aws.production.yml` with:
|
200
|
+
```yml
|
201
|
+
:activated: true
|
202
|
+
:api_key: 'some api key'
|
203
|
+
:api_secret: 'some secret'
|
204
|
+
|
205
|
+
```
|
206
|
+
|
207
|
+
Provide such configuration on `Global.environment = 'production'` environment:
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
> Global.aws.activated
|
211
|
+
=> true
|
212
|
+
> Global.aws.api_key
|
213
|
+
=> 'some api key'
|
214
|
+
> Global.aws.api_secret
|
215
|
+
=> 'some secret'
|
216
|
+
```
|
217
|
+
|
218
|
+
**Warning**: files with dot(s) in name will be skipped by Global (except this env files).
|
219
|
+
|
220
|
+
#### ERB support
|
129
221
|
|
130
222
|
Config file `global/file_name.yml` with:
|
131
223
|
|
@@ -145,79 +237,191 @@ As a result, in the development environment we have:
|
|
145
237
|
=> 4
|
146
238
|
```
|
147
239
|
|
148
|
-
###
|
240
|
+
### AWS Parameter Store
|
241
|
+
|
242
|
+
Parameter Store is a secure configuration storage with at-rest encryption. Access is controlled through AWS IAM. You do not need to be hosted on AWS to use Parameter Store.
|
243
|
+
|
244
|
+
Refer to the [official documentation](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) to set up the store.
|
245
|
+
|
246
|
+
Some steps you will need to follow:
|
247
|
+
|
248
|
+
- Allocate an AWS IAM role for your app.
|
249
|
+
- Create an IAM user for the role and pass credentials in standard AWS env vars (applications on Fargate get roles automatically).
|
250
|
+
- Choose a prefix for the parameters. By default, the prefix is `/environment_name/AppClassName/`. You can change it with backend parameters (prefer to use '/' as separator).
|
251
|
+
- Allow the role to read parameters from AWS SSM. Scope access by the prefix that you're going to use.
|
252
|
+
- If you will use encrypted parameters: create a KMS key and allow the role to decrypt using the key.
|
253
|
+
- Create parameters in Parameter Store. Use encryption for sensitive data like private keys and API credentials.
|
254
|
+
|
255
|
+
#### Usage with Go
|
256
|
+
|
257
|
+
You can reuse the same configuration in your Go services. For this, we developed a Go module that loads the same configuration tree into Go structs.
|
258
|
+
|
259
|
+
See [github.com/railsware/go-global](https://github.com/railsware/go-global) for further instructions.
|
260
|
+
|
261
|
+
#### Configuration examples
|
262
|
+
|
263
|
+
Backend setup:
|
149
264
|
|
150
265
|
```ruby
|
151
|
-
|
266
|
+
# in config/environments/development.rb
|
267
|
+
# you don't need to go to Parameter Store for dev machines
|
268
|
+
Global.backend(:filesystem)
|
269
|
+
|
270
|
+
# in config/environments/production.rb
|
271
|
+
# enterprise grade protection for your secrets
|
272
|
+
Global.backend(:aws_parameter_store, app_name: 'my_big_app')
|
152
273
|
```
|
153
274
|
|
154
|
-
|
275
|
+
Create parameters:
|
155
276
|
|
156
|
-
|
277
|
+
```
|
278
|
+
/production/my_big_app/basic_auth/username => "bill"
|
279
|
+
/production/my_big_app/basic_auth/password => "secret" # make sure to encrypt this one!
|
280
|
+
/production/my_big_app/api_endpoint => "https://api.myapp.com"
|
281
|
+
```
|
282
|
+
|
283
|
+
Get configuration in the app:
|
157
284
|
|
158
285
|
```ruby
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
286
|
+
# Encrypted parameters are automatically decrypted:
|
287
|
+
> Global.basic_auth.password
|
288
|
+
=> "secret"
|
289
|
+
> Global.api_endpoint
|
290
|
+
=> "https://api.myapp.com"
|
164
291
|
```
|
165
|
-
By default all files are excluded due to security reasons. Don't include files which contain protected information like api keys or credentials.
|
166
292
|
|
167
|
-
|
293
|
+
### Google Cloud Secret Manager
|
168
294
|
|
169
|
-
|
170
|
-
|
171
|
-
= require global-js
|
172
|
-
*/
|
173
|
-
```
|
295
|
+
Google Cloud Secret Manager allows you to store, manage, and access secrets as binary blobs or text strings. With the appropriate permissions, you can view the contents of the secret.
|
296
|
+
Google Cloud Secret Manager works well for storing configuration information such as database passwords, API keys, or TLS certificates needed by an application at runtime.
|
174
297
|
|
175
|
-
|
298
|
+
Refer to the [official documentation](https://cloud.google.com/secret-manager/docs) to set up the secret manager.
|
176
299
|
|
177
|
-
|
300
|
+
Some steps you will need to follow:
|
178
301
|
|
179
|
-
|
302
|
+
- Choose a prefix for the secret key name. By default, the prefix is `environment_name-AppClassName-`. You can change it with backend parameters (prefer to use '-' as separator).
|
180
303
|
|
181
|
-
|
182
|
-
# app/assets/javascripts/admin/global.js.erb
|
183
|
-
<%= Global.generate_js(namespace: "AdminSettings", only: %w(admin hosts)) %>
|
304
|
+
#### Configuration examples
|
184
305
|
|
185
|
-
|
186
|
-
#= require admin/global
|
187
|
-
```
|
306
|
+
Backend setup:
|
188
307
|
|
189
|
-
```
|
190
|
-
#
|
191
|
-
|
308
|
+
```ruby
|
309
|
+
# in config/environments/development.rb
|
310
|
+
# you don't need to go to Parameter Store for dev machines
|
311
|
+
Global.backend(:filesystem)
|
192
312
|
|
193
|
-
#
|
194
|
-
|
313
|
+
# in config/environments/production.rb
|
314
|
+
# enterprise grade protection for your secrets
|
315
|
+
Global.backend(:gcp_secret_manager, prefix: 'prod-myapp-', project_id: 'example')
|
195
316
|
```
|
196
317
|
|
197
|
-
|
318
|
+
Create secrets:
|
198
319
|
|
199
|
-
|
320
|
+
```
|
321
|
+
prod-myapp-basic_auth-username => "bill"
|
322
|
+
prod-myapp-basic_auth-password => "secret"
|
323
|
+
prod-myapp-api_endpoint => "https://api.myapp.com"
|
324
|
+
```
|
200
325
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
326
|
+
Get configuration in the app:
|
327
|
+
|
328
|
+
```ruby
|
329
|
+
# Encrypted parameters are automatically decrypted:
|
330
|
+
> Global.basic_auth.password
|
331
|
+
=> "secret"
|
332
|
+
> Global.api_endpoint
|
333
|
+
=> "https://api.myapp.com"
|
208
334
|
```
|
209
|
-
After that in development environment we have:
|
210
335
|
|
211
|
-
|
212
|
-
|
213
|
-
|
336
|
+
### Reload configuration data
|
337
|
+
|
338
|
+
```ruby
|
339
|
+
> Global.reload!
|
214
340
|
```
|
215
341
|
|
216
|
-
|
342
|
+
## Using YAML configuration files with Rails Webpacker
|
343
|
+
|
344
|
+
If you use the `:filesystem` backend, you can reuse the same configuration files on the frontend:
|
345
|
+
|
346
|
+
Add [js-yaml](https://www.npmjs.com/package/js-yaml) npm package to `package.json` (use command `yarn add js-yaml`).
|
347
|
+
|
348
|
+
Then create a file at `config/webpacker/global/index.js` with the following:
|
349
|
+
|
350
|
+
```js
|
351
|
+
const yaml = require('js-yaml')
|
352
|
+
const fs = require('fs')
|
353
|
+
const path = require('path')
|
354
|
+
|
355
|
+
const FILE_ENV_SPLIT = '.'
|
356
|
+
const YAML_EXT = '.yml'
|
217
357
|
|
218
|
-
|
219
|
-
|
220
|
-
|
358
|
+
let globalConfig = {
|
359
|
+
environment: null,
|
360
|
+
configDirectory: null
|
361
|
+
}
|
362
|
+
|
363
|
+
const globalConfigure = (options = {}) => {
|
364
|
+
globalConfig = Object.assign({}, globalConfig, options)
|
365
|
+
}
|
366
|
+
|
367
|
+
const getGlobalConfig = (key) => {
|
368
|
+
let config = {}
|
369
|
+
const filename = path.join(globalConfig.configDirectory, `${key}${YAML_EXT}`)
|
370
|
+
if (fs.existsSync(filename)) {
|
371
|
+
const configurations = yaml.safeLoad(fs.readFileSync(filename, 'utf8'))
|
372
|
+
config = Object.assign({}, config, configurations['default'] || {})
|
373
|
+
config = Object.assign({}, config, configurations[globalConfig.environment] || {})
|
374
|
+
|
375
|
+
const envFilename = path.join(globalConfig.configDirectory, `${key}${FILE_ENV_SPLIT}${globalConfig.environment}${YAML_EXT}`)
|
376
|
+
if (fs.existsSync(envFilename)) {
|
377
|
+
const envConfigurations = yaml.safeLoad(fs.readFileSync(envFilename, 'utf8'))
|
378
|
+
config = Object.assign({}, config, envConfigurations || {})
|
379
|
+
}
|
380
|
+
}
|
381
|
+
return config
|
382
|
+
}
|
383
|
+
|
384
|
+
module.exports = {
|
385
|
+
globalConfigure,
|
386
|
+
getGlobalConfig
|
387
|
+
}
|
388
|
+
```
|
389
|
+
|
390
|
+
After this, modify file `config/webpacker/environment.js`:
|
391
|
+
|
392
|
+
```js
|
393
|
+
const path = require('path')
|
394
|
+
const {environment} = require('@rails/webpacker')
|
395
|
+
const {globalConfigure, getGlobalConfig} = require('./global')
|
396
|
+
|
397
|
+
globalConfigure({
|
398
|
+
environment: process.env.RAILS_ENV || 'development',
|
399
|
+
configDirectory: path.resolve(__dirname, '../global')
|
400
|
+
})
|
401
|
+
|
402
|
+
const sentrySettings = getGlobalConfig('sentry')
|
403
|
+
|
404
|
+
environment.plugins.prepend('Environment', new webpack.EnvironmentPlugin({
|
405
|
+
GLOBAL_SENTRY_ENABLED: sentrySettings.enabled,
|
406
|
+
GLOBAL_SENTRY_JS_KEY: sentrySettings.js,
|
407
|
+
...
|
408
|
+
}))
|
409
|
+
|
410
|
+
...
|
411
|
+
|
412
|
+
module.exports = environment
|
413
|
+
```
|
414
|
+
|
415
|
+
Now you can use these `process.env` keys in your code:
|
416
|
+
|
417
|
+
```js
|
418
|
+
import {init} from '@sentry/browser'
|
419
|
+
|
420
|
+
if (process.env.GLOBAL_SENTRY_ENABLED) {
|
421
|
+
init({
|
422
|
+
dsn: process.env.GLOBAL_SENTRY_JS_KEY
|
423
|
+
})
|
424
|
+
}
|
221
425
|
```
|
222
426
|
|
223
427
|
## Contributing to global
|
@@ -230,7 +434,12 @@ Global.hosts.web
|
|
230
434
|
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
231
435
|
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
232
436
|
|
233
|
-
|
437
|
+
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/railsware/global/blob/master/CODE_OF_CONDUCT.md).
|
438
|
+
|
439
|
+
## License
|
440
|
+
|
441
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
234
442
|
|
235
|
-
|
443
|
+
## Code of Conduct
|
236
444
|
|
445
|
+
Everyone interacting in the Global project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/railsware/global/blob/master/CODE_OF_CONDUCT.md).
|