Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
68479d09
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
68479d09
编写于
11月 15, 2017
作者:
K
Kasper Timm Hansen
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'freeletics-manage-multiple-credential-files'
Fixes
https://github.com/rails/rails/pull/30940
上级
415d0543
7a8728a0
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
337 addition
and
41 deletion
+337
-41
railties/lib/rails/application.rb
railties/lib/rails/application.rb
+35
-4
railties/lib/rails/command/helpers/editor.rb
railties/lib/rails/command/helpers/editor.rb
+33
-0
railties/lib/rails/commands/credentials/credentials_command.rb
...ies/lib/rails/commands/credentials/credentials_command.rb
+8
-21
railties/lib/rails/commands/encrypted/encrypted_command.rb
railties/lib/rails/commands/encrypted/encrypted_command.rb
+77
-0
railties/lib/rails/generators/rails/encrypted_file/encrypted_file_generator.rb
...nerators/rails/encrypted_file/encrypted_file_generator.rb
+38
-0
railties/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb
...ails/encryption_key_file/encryption_key_file_generator.rb
+53
-0
railties/lib/rails/generators/rails/master_key/master_key_generator.rb
...rails/generators/rails/master_key/master_key_generator.rb
+9
-15
railties/test/commands/credentials_test.rb
railties/test/commands/credentials_test.rb
+4
-1
railties/test/commands/encrypted_test.rb
railties/test/commands/encrypted_test.rb
+80
-0
未找到文件。
railties/lib/rails/application.rb
浏览文件 @
68479d09
...
@@ -433,10 +433,41 @@ def secret_key_base
...
@@ -433,10 +433,41 @@ def secret_key_base
# the Rails master key, which is either taken from ENV["RAILS_MASTER_KEY"] or from loading
# the Rails master key, which is either taken from ENV["RAILS_MASTER_KEY"] or from loading
# `config/master.key`.
# `config/master.key`.
def
credentials
def
credentials
@credentials
||=
ActiveSupport
::
EncryptedConfiguration
.
new
\
@credentials
||=
encrypted
(
"config/credentials.yml.enc"
)
config_path:
Rails
.
root
.
join
(
"config/credentials.yml.enc"
),
end
key_path:
Rails
.
root
.
join
(
"config/master.key"
),
env_key:
"RAILS_MASTER_KEY"
# Shorthand to decrypt any encrypted configurations or files.
#
# For any file added with `bin/rails encrypted:edit` call `read` to decrypt
# the file with the master key.
# The master key is either stored in `config/master.key` or `ENV["RAILS_MASTER_KEY"]`.
#
# Rails.application.encrypted("config/mystery_man.key").read
# # => "We've met before, haven't we?"
#
# It's also possible to interpret encrypted YAML files with `config`.
#
# Rails.application.encrypted("config/credentials.yml.enc").config
# # => { next_guys_line: "I don't think so. Where was it you think we met?" }
#
# Any top-level configs are also accessible directly on the return value:
#
# Rails.application.encrypted("config/credentials.yml.enc").next_guys_line
# # => "I don't think so. Where was it you think we met?"
#
# The files or configs can also be encrypted with a custom key. To decrypt with
# a key in the `ENV`, use:
#
# Rails.application.encrypted("config/special_tokens.yml.enc", env_key: "SPECIAL_TOKENS")
#
# Or to decrypt with a file, that should be version control ignored, relative to `Rails.root`:
#
# Rails.application.encrypted("config/special_tokens.yml.enc", key_path: "config/special_tokens.key")
def
encrypted
(
path
,
key_path:
"config/master.key"
,
env_key:
"RAILS_MASTER_KEY"
)
ActiveSupport
::
EncryptedConfiguration
.
new
\
config_path:
Rails
.
root
.
join
(
path
),
key_path:
Rails
.
root
.
join
(
key_path
),
env_key:
env_key
end
end
def
to_app
#:nodoc:
def
to_app
#:nodoc:
...
...
railties/lib/rails/command/helpers/editor.rb
0 → 100644
浏览文件 @
68479d09
require
"active_support/encrypted_file"
module
Rails
module
Command
module
Helpers
module
Editor
private
def
ensure_editor_available
(
command
:)
if
ENV
[
"EDITOR"
].
to_s
.
empty?
say
"No $EDITOR to open file in. Assign one like this:"
say
""
say
%(EDITOR="mate --wait" #{command})
say
""
say
"For editors that fork and exit immediately, it's important to pass a wait flag,"
say
"otherwise the credentials will be saved immediately with no chance to edit."
false
else
true
end
end
def
catch_editing_exceptions
yield
rescue
Interrupt
say
"Aborted changing file: nothing saved."
rescue
ActiveSupport
::
EncryptedFile
::
MissingKeyError
=>
error
say
error
.
message
end
end
end
end
end
railties/lib/rails/commands/credentials/credentials_command.rb
浏览文件 @
68479d09
# frozen_string_literal: true
# frozen_string_literal: true
require
"active_support"
require
"active_support"
require
"rails/command/helpers/editor"
module
Rails
module
Rails
module
Command
module
Command
class
CredentialsCommand
<
Rails
::
Command
::
Base
# :nodoc:
class
CredentialsCommand
<
Rails
::
Command
::
Base
# :nodoc:
include
Helpers
::
Editor
no_commands
do
no_commands
do
def
help
def
help
say
"Usage:
\n
#{
self
.
class
.
banner
}
"
say
"Usage:
\n
#{
self
.
class
.
banner
}
"
...
@@ -16,41 +19,25 @@ def help
...
@@ -16,41 +19,25 @@ def help
def
edit
def
edit
require_application_and_environment!
require_application_and_environment!
ensure_editor_available
||
(
return
)
ensure_editor_available
(
command:
"bin/rails credentials:edit"
)
||
(
return
)
ensure_master_key_has_been_added
ensure_master_key_has_been_added
ensure_credentials_have_been_added
ensure_credentials_have_been_added
change_credentials_in_system_editor
catch_editing_exceptions
do
change_credentials_in_system_editor
end
say
"New credentials encrypted and saved."
say
"New credentials encrypted and saved."
rescue
Interrupt
say
"Aborted changing credentials: nothing saved."
rescue
ActiveSupport
::
EncryptedFile
::
MissingKeyError
=>
error
say
error
.
message
end
end
def
show
def
show
require_application_and_environment!
require_application_and_environment!
say
Rails
.
application
.
credentials
.
read
.
presence
||
say
Rails
.
application
.
credentials
.
read
.
presence
||
"No credentials have been added yet. Use bin/rails credentials:edit to change that."
"No credentials have been added yet. Use bin/rails credentials:edit to change that."
end
end
private
private
def
ensure_editor_available
if
ENV
[
"EDITOR"
].
to_s
.
empty?
say
"No $EDITOR to open credentials in. Assign one like this:"
say
""
say
%(EDITOR="mate --wait" bin/rails credentials:edit)
say
""
say
"For editors that fork and exit immediately, it's important to pass a wait flag,"
say
"otherwise the credentials will be saved immediately with no chance to edit."
false
else
true
end
end
def
ensure_master_key_has_been_added
def
ensure_master_key_has_been_added
master_key_generator
.
add_master_key_file
master_key_generator
.
add_master_key_file
master_key_generator
.
ignore_master_key_file
master_key_generator
.
ignore_master_key_file
...
...
railties/lib/rails/commands/encrypted/encrypted_command.rb
0 → 100644
浏览文件 @
68479d09
# frozen_string_literal: true
require
"pathname"
require
"active_support"
require
"rails/command/helpers/editor"
module
Rails
module
Command
class
EncryptedCommand
<
Rails
::
Command
::
Base
# :nodoc:
include
Helpers
::
Editor
class_option
:key
,
aliases:
"-k"
,
type: :string
,
default:
"config/master.key"
,
desc:
"The Rails.root relative path to the encryption key"
no_commands
do
def
help
say
"Usage:
\n
#{
self
.
class
.
banner
}
"
say
""
end
end
def
edit
(
file_path
)
require_application_and_environment!
ensure_editor_available
(
command:
"bin/rails encrypted:edit"
)
||
(
return
)
ensure_encryption_key_has_been_added
(
options
[
:key
])
ensure_encrypted_file_has_been_added
(
file_path
,
options
[
:key
])
catch_editing_exceptions
do
change_encrypted_file_in_system_editor
(
file_path
,
options
[
:key
])
end
say
"File encrypted and saved."
rescue
ActiveSupport
::
MessageEncryptor
::
InvalidMessage
say
"Couldn't decrypt
#{
file_path
}
. Perhaps you passed the wrong key?"
end
def
show
(
file_path
)
require_application_and_environment!
say
Rails
.
application
.
encrypted
(
file_path
,
key_path:
options
[
:key
]).
read
.
presence
||
"File '
#{
file_path
}
' does not exist. Use bin/rails encrypted:edit
#{
file_path
}
to change that."
end
private
def
ensure_encryption_key_has_been_added
(
key_path
)
encryption_key_file_generator
.
add_key_file
(
key_path
)
encryption_key_file_generator
.
ignore_key_file
(
key_path
)
end
def
ensure_encrypted_file_has_been_added
(
file_path
,
key_path
)
encrypted_file_generator
.
add_encrypted_file_silently
(
file_path
,
key_path
)
end
def
change_encrypted_file_in_system_editor
(
file_path
,
key_path
)
Rails
.
application
.
encrypted
(
file_path
,
key_path:
key_path
).
change
do
|
tmp_path
|
system
(
"
#{
ENV
[
"EDITOR"
]
}
#{
tmp_path
}
"
)
end
end
def
encryption_key_file_generator
require
"rails/generators"
require
"rails/generators/rails/encryption_key_file/encryption_key_file_generator"
Rails
::
Generators
::
EncryptionKeyFileGenerator
.
new
end
def
encrypted_file_generator
require
"rails/generators"
require
"rails/generators/rails/encrypted_file/encrypted_file_generator"
Rails
::
Generators
::
EncryptedFileGenerator
.
new
end
end
end
end
railties/lib/rails/generators/rails/encrypted_file/encrypted_file_generator.rb
0 → 100644
浏览文件 @
68479d09
# frozen_string_literal: true
require
"rails/generators/base"
require
"active_support/encrypted_file"
module
Rails
module
Generators
class
EncryptedFileGenerator
<
Base
def
add_encrypted_file
(
file_path
,
key_path
)
unless
File
.
exist?
(
file_path
)
say
"Adding
#{
file_path
}
to store encrypted content."
say
""
say
"The following content has been encrypted with the encryption key:"
say
""
say
template
,
:on_green
say
""
add_encrypted_file_silently
(
file_path
,
key_path
)
say
"You can edit encrypted file with `bin/rails encrypted:edit
#{
file_path
}
`."
say
""
end
end
def
add_encrypted_file_silently
(
file_path
,
key_path
,
template
=
encrypted_file_template
)
unless
File
.
exist?
(
file_path
)
setup
=
{
content_path:
file_path
,
key_path:
key_path
,
env_key:
"RAILS_MASTER_KEY"
}
ActiveSupport
::
EncryptedFile
.
new
(
setup
).
write
(
template
)
end
end
private
def
encrypted_file_template
"# aws:
\n
# access_key_id: 123
\n
# secret_access_key: 345
\n\n
"
end
end
end
end
railties/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb
0 → 100644
浏览文件 @
68479d09
# frozen_string_literal: true
require
"pathname"
require
"rails/generators/base"
require
"active_support/encrypted_file"
module
Rails
module
Generators
class
EncryptionKeyFileGenerator
<
Base
def
add_key_file
(
key_path
)
key_path
=
Pathname
.
new
(
key_path
)
unless
key_path
.
exist?
key
=
ActiveSupport
::
EncryptedFile
.
generate_key
log
"Adding
#{
key_path
}
to store the encryption key:
#{
key
}
"
log
""
log
"Save this in a password manager your team can access."
log
""
log
"If you lose the key, no one, including you, can access anything encrypted with it."
log
""
add_key_file_silently
(
key_path
,
key
)
log
""
end
end
def
add_key_file_silently
(
key_path
,
key
=
nil
)
create_file
key_path
,
key
||
ActiveSupport
::
EncryptedFile
.
generate_key
end
def
ignore_key_file
(
key_path
,
ignore:
key_ignore
(
key_path
))
if
File
.
exist?
(
".gitignore"
)
unless
File
.
read
(
".gitignore"
).
include?
(
ignore
)
log
"Ignoring
#{
key_path
}
so it won't end up in Git history:"
log
""
append_to_file
".gitignore"
,
ignore
log
""
end
else
log
"IMPORTANT: Don't commit
#{
key_path
}
. Add this to your ignore file:"
log
ignore
,
:on_green
log
""
end
end
private
def
key_ignore
(
key_path
)
[
""
,
"/
#{
key_path
}
"
,
""
].
join
(
"
\n
"
)
end
end
end
end
railties/lib/rails/generators/rails/master_key/master_key_generator.rb
浏览文件 @
68479d09
# frozen_string_literal: true
# frozen_string_literal: true
require
"rails/generators/base"
require
"pathname"
require
"pathname"
require
"rails/generators/base"
require
"rails/generators/rails/encryption_key_file/encryption_key_file_generator"
require
"active_support/encrypted_file"
require
"active_support/encrypted_file"
module
Rails
module
Rails
...
@@ -20,31 +21,24 @@ def add_master_key_file
...
@@ -20,31 +21,24 @@ def add_master_key_file
log
"If you lose the key, no one, including you, can access anything encrypted with it."
log
"If you lose the key, no one, including you, can access anything encrypted with it."
log
""
log
""
add_master_key_file_silently
key
add_master_key_file_silently
(
key
)
log
""
log
""
end
end
end
end
def
add_master_key_file_silently
(
key
=
nil
)
def
add_master_key_file_silently
(
key
=
nil
)
create_file
MASTER_KEY_PATH
,
key
||
ActiveSupport
::
EncryptedFile
.
generate_key
key_file_generator
.
add_key_file_silently
(
MASTER_KEY_PATH
,
key
)
end
end
def
ignore_master_key_file
def
ignore_master_key_file
if
File
.
exist?
(
".gitignore"
)
key_file_generator
.
ignore_key_file
(
MASTER_KEY_PATH
,
ignore:
key_ignore
)
unless
File
.
read
(
".gitignore"
).
include?
(
key_ignore
)
log
"Ignoring
#{
MASTER_KEY_PATH
}
so it won't end up in Git history:"
log
""
append_to_file
".gitignore"
,
key_ignore
log
""
end
else
log
"IMPORTANT: Don't commit
#{
MASTER_KEY_PATH
}
. Add this to your ignore file:"
log
key_ignore
,
:on_green
log
""
end
end
end
private
private
def
key_file_generator
EncryptionKeyFileGenerator
.
new
end
def
key_ignore
def
key_ignore
[
""
,
"# Ignore master key for decrypting credentials and more."
,
"/
#{
MASTER_KEY_PATH
}
"
,
""
].
join
(
"
\n
"
)
[
""
,
"# Ignore master key for decrypting credentials and more."
,
"/
#{
MASTER_KEY_PATH
}
"
,
""
].
join
(
"
\n
"
)
end
end
...
...
railties/test/commands/credentials_test.rb
浏览文件 @
68479d09
...
@@ -13,7 +13,10 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
...
@@ -13,7 +13,10 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
teardown
{
teardown_app
}
teardown
{
teardown_app
}
test
"edit without editor gives hint"
do
test
"edit without editor gives hint"
do
assert_match
"No $EDITOR to open credentials in"
,
run_edit_command
(
editor:
""
)
run_edit_command
(
editor:
""
).
tap
do
|
output
|
assert_match
"No $EDITOR to open file in"
,
output
assert_match
"bin/rails credentials:edit"
,
output
end
end
end
test
"edit credentials"
do
test
"edit credentials"
do
...
...
railties/test/commands/encrypted_test.rb
0 → 100644
浏览文件 @
68479d09
# frozen_string_literal: true
require
"isolation/abstract_unit"
require
"env_helpers"
require
"rails/command"
require
"rails/commands/encrypted/encrypted_command"
class
Rails::Command::EncryptedCommandTest
<
ActiveSupport
::
TestCase
include
ActiveSupport
::
Testing
::
Isolation
,
EnvHelpers
setup
:build_app
teardown
:teardown_app
test
"edit without editor gives hint"
do
run_edit_command
(
"config/tokens.yml.enc"
,
editor:
""
).
tap
do
|
output
|
assert_match
"No $EDITOR to open file in"
,
output
assert_match
"bin/rails encrypted:edit"
,
output
end
end
test
"edit encrypted file"
do
# Run twice to ensure file can be reread after first edit pass.
2
.
times
do
assert_match
(
/access_key_id: 123/
,
run_edit_command
(
"config/tokens.yml.enc"
))
end
end
test
"edit command does not add master key to gitignore when already exist"
do
run_edit_command
(
"config/tokens.yml.enc"
)
Dir
.
chdir
(
app_path
)
do
assert_match
"/config/master.key"
,
File
.
read
(
".gitignore"
)
end
end
test
"edit encrypts file with custom key"
do
run_edit_command
(
"config/tokens.yml.enc"
,
key:
"config/tokens.key"
)
Dir
.
chdir
(
app_path
)
do
assert
File
.
exist?
(
"config/tokens.yml.enc"
)
assert
File
.
exist?
(
"config/tokens.key"
)
assert_match
"/config/tokens.key"
,
File
.
read
(
".gitignore"
)
end
assert_match
(
/access_key_id: 123/
,
run_edit_command
(
"config/tokens.yml.enc"
,
key:
"config/tokens.key"
))
end
test
"show encrypted file with custom key"
do
run_edit_command
(
"config/tokens.yml.enc"
,
key:
"config/tokens.key"
)
assert_match
(
/access_key_id: 123/
,
run_show_command
(
"config/tokens.yml.enc"
,
key:
"config/tokens.key"
))
end
test
"won't corrupt encrypted file when passed wrong key"
do
run_edit_command
(
"config/tokens.yml.enc"
,
key:
"config/tokens.key"
)
assert_match
"passed the wrong key"
,
run_edit_command
(
"config/tokens.yml.enc"
,
allow_failure:
true
)
assert_match
(
/access_key_id: 123/
,
run_show_command
(
"config/tokens.yml.enc"
,
key:
"config/tokens.key"
))
end
private
def
run_edit_command
(
file
,
key:
nil
,
editor:
"cat"
,
**
options
)
switch_env
(
"EDITOR"
,
editor
)
do
rails
"encrypted:edit"
,
prepare_args
(
file
,
key
),
**
options
end
end
def
run_show_command
(
file
,
key:
nil
)
rails
"encrypted:show"
,
prepare_args
(
file
,
key
)
end
def
prepare_args
(
file
,
key
)
args
=
[
file
]
args
.
push
(
"--key"
,
key
)
if
key
args
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录