Skip to content

feat: support ssl key-encrypt-salt rotation#7925

Merged
spacewander merged 12 commits into
apache:masterfrom
juststillthinking:support-ssl-key-encrypt-salt-rotation
Sep 23, 2022
Merged

feat: support ssl key-encrypt-salt rotation#7925
spacewander merged 12 commits into
apache:masterfrom
juststillthinking:support-ssl-key-encrypt-salt-rotation

Conversation

@juststillthinking

Copy link
Copy Markdown
Contributor

Description

Currently, the key_encryption_salt cannot be changed once users use it to encrypt the private key, otherwise, Apache APISIX cannot decrypt the private key correctly. This may become a pain point when the user leaks the salt.
As a user, I can configure multiple key_encryption_salt for Apache APISIX, and Apache APISIX will use them to decrypt private keys in turn

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (If not, please discuss on the APISIX mailing list first)

Comment thread conf/config-default.yaml
key_encrypt_salt: edd1c9f0985e76a2 # If not set, will save origin ssl key into etcd.
# If set this, must be a string of length 16. And it will encrypt ssl key with AES-128-CBC
# !!! So do not change it after saving your ssl, it can't decrypt the ssl keys have be saved if you change !!
key_encrypt_salt: # If not set, will save origin ssl key into etcd.

@membphis membphis Sep 16, 2022

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a breaking change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's backward compatible, we could use 2 ways at the same time

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have test case about this case

Comment thread apisix/ssl.lua Outdated
local aes_with_iv = assert(aes:new(iv, nil, aes.cipher(128, "cbc"), {iv = iv}))
core.table.insert(_aes_128_cbc_with_iv_tbl, aes_with_iv)
else
core.log.error("the key_encrypt_salt does not meet the "

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use , instead of .. as separator

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread apisix/ssl.lua Outdated
if not decrypted then
core.log.error("decrypt ssl key failed. key[", key, "] ")
local aes_128_cbc_with_iv_tbl = get_aes_128_cbc_with_iv()
if core.table.isempty(aes_128_cbc_with_iv_tbl) then

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use # would be better as the table must be array

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread t/admin/ssl4.t Outdated
ngx.say(body)
}
}
--- request

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move the common part to the top like other test files

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread apisix/ssl.lua Outdated

if type_ivs == "table" then
for index, iv in ipairs(ivs) do
if type(iv) == "string" and #iv == 16 then

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread conf/config-default.yaml
key_encrypt_salt: # If not set, will save origin ssl key into etcd.
- edd1c9f0985e76a2 # If set this, must be a string of length 16. And it will encrypt ssl key with AES-128-CBC
# !!! So do not change it after saving your ssl, it can't decrypt the ssl keys have be saved if you change !!
# Only use the first key to encrypt, and decrypt in the order of the array.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is not accurate to describe the field, since the comment says it "must be a string of length 16".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is still wrong.

The key_encrypt_salt should either be a string whose size is 16 or an array whose elements are string, and the size is also 16.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we only recommend using array?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm updating this to a hexadecimal string of length 16. It's technically a 8 byte value in hex representation. Size isn't accurate.

Comment thread apisix/cli/schema.lua Outdated
key_encrypt_salt = {
anyOf = {
{
type = "array",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add length check for the array

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minItems = 1? why need this check?

Comment thread apisix/cli/schema.lua Outdated
maxLength = 16
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add an extra blank line?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread apisix/ssl.lua Outdated
local aes_with_iv = assert(aes:new(iv, nil, aes.cipher(128, "cbc"), {iv = iv}))
core.table.insert(_aes_128_cbc_with_iv_tbl, aes_with_iv)
end
elseif type_ivs == "string" and #ivs == 16 then

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove the #ivs == 16 check as we already checked it in the schema.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread t/admin/ssl4.t
node_listen: 1984
ssl:
key_encrypt_salt: "edd1c9f0985e76a1"
--- response_body eval

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The judgment of the response body does not seem necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a double check, i prefer to leave it there

Comment thread t/admin/ssl4.t Outdated
while true do
local line, err = sock:receive()
if not line then
-- ngx.say("failed to receive response status line: ", err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove redundant comments.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread apisix/cli/schema.lua
}
},
key_encrypt_salt = {
anyOf = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know anyOf can satisfy the schema check but it should be oneOf in this scene?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this is the conventional way in APISIX, it's used everywhere, so i think i should follow this.

Comment thread conf/config-default.yaml
key_encrypt_salt: # If not set, will save origin ssl key into etcd.
- edd1c9f0985e76a2 # If set this, must be a string of length 16. And it will encrypt ssl key with AES-128-CBC
# !!! So do not change it after saving your ssl, it can't decrypt the ssl keys have be saved if you change !!
# Only use the first key to encrypt, and decrypt in the order of the array.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is still wrong.

The key_encrypt_salt should either be a string whose size is 16 or an array whose elements are string, and the size is also 16.

Comment thread apisix/ssl.lua
Comment thread apisix/ssl.lua Outdated


local _aes_128_cbc_with_iv = false
local _aes_128_cbc_with_iv_tbl = false

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to avoid using boolean value as the default value of a table?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@spacewander
spacewander merged commit 20efe29 into apache:master Sep 23, 2022
Liu-Junlin pushed a commit to Liu-Junlin/apisix that referenced this pull request Nov 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants