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
# the Rails master key, which is either taken from ENV["RAILS_MASTER_KEY"] or from loading
# `config/master.key`.
def
credentials
@credentials
||=
ActiveSupport
::
EncryptedConfiguration
.
new
\
config_path:
Rails
.
root
.
join
(
"config/credentials.yml.enc"
),
key_path:
Rails
.
root
.
join
(
"config/master.key"
),
env_key:
"RAILS_MASTER_KEY"
@credentials
||=
encrypted
(
"config/credentials.yml.enc"
)
end
# 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
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
require
"active_support"
require
"rails/command/helpers/editor"
module
Rails
module
Command
class
CredentialsCommand
<
Rails
::
Command
::
Base
# :nodoc:
include
Helpers
::
Editor
no_commands
do
def
help
say
"Usage:
\n
#{
self
.
class
.
banner
}
"
...
...
@@ -16,41 +19,25 @@ def help
def
edit
require_application_and_environment!
ensure_editor_available
||
(
return
)
ensure_editor_available
(
command:
"bin/rails credentials:edit"
)
||
(
return
)
ensure_master_key_has_been_added
ensure_credentials_have_been_added
catch_editing_exceptions
do
change_credentials_in_system_editor
end
say
"New credentials encrypted and saved."
rescue
Interrupt
say
"Aborted changing credentials: nothing saved."
rescue
ActiveSupport
::
EncryptedFile
::
MissingKeyError
=>
error
say
error
.
message
end
def
show
require_application_and_environment!
say
Rails
.
application
.
credentials
.
read
.
presence
||
"No credentials have been added yet. Use bin/rails credentials:edit to change that."
end
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
master_key_generator
.
add_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
require
"rails/generators/base"
require
"pathname"
require
"rails/generators/base"
require
"rails/generators/rails/encryption_key_file/encryption_key_file_generator"
require
"active_support/encrypted_file"
module
Rails
...
...
@@ -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
""
add_master_key_file_silently
key
add_master_key_file_silently
(
key
)
log
""
end
end
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
def
ignore_master_key_file
if
File
.
exist?
(
".gitignore"
)
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
key_file_generator
.
ignore_key_file
(
MASTER_KEY_PATH
,
ignore:
key_ignore
)
end
private
def
key_file_generator
EncryptionKeyFileGenerator
.
new
end
def
key_ignore
[
""
,
"# Ignore master key for decrypting credentials and more."
,
"/
#{
MASTER_KEY_PATH
}
"
,
""
].
join
(
"
\n
"
)
end
...
...
railties/test/commands/credentials_test.rb
浏览文件 @
68479d09
...
...
@@ -13,7 +13,10 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
teardown
{
teardown_app
}
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
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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录