api keys: add IP whitelist and API permission system.

Add the ability to restrict API keys so that they can only be used with
certain IP addresses or certain API endpoints.

Restricting your key is useful to limit damage in case it gets leaked or
stolen. For example, if your key is on a remote server and it gets
hacked, or if you accidentally check-in your key to Github.

Restricting your key's API permissions is useful if a third-party app or
script wants your key, but you don't want to give full access to your
account.

If you're an app or userscript developer, and your app needs an API key
from the user, you should only request a key with the minimum
permissions needed by your app.

If you have a privileged account, and you have scripts running under
your account, you are highly encouraged to restrict your key to limit
damage in case your key gets leaked or stolen.
This commit is contained in:
evazion
2021-02-14 18:05:32 -06:00
parent a6707fbfa2
commit 25fda1ecc2
19 changed files with 286 additions and 32 deletions

View File

@@ -4,13 +4,10 @@ class ApiKeysControllerTest < ActionDispatch::IntegrationTest
context "An api keys controller" do
setup do
@user = create(:user)
@api_key = create(:api_key, user: @user)
end
context "#index action" do
setup do
@api_key = create(:api_key, user: @user)
end
should "let a user see their own API keys" do
get_auth user_api_keys_path(@user.id), @user
@@ -40,20 +37,54 @@ class ApiKeysControllerTest < ActionDispatch::IntegrationTest
end
end
context "#new action" do
should "render for a Member user" do
get_auth new_user_api_key_path(@user.id), @user
assert_response :success
end
should "fail for an Anonymous user" do
get new_user_api_key_path(@user.id)
assert_response 403
end
end
context "#create action" do
should "create a new API key" do
post_auth user_api_keys_path(@user.id), @user
post_auth user_api_keys_path(@user.id), @user, params: { api_key: { name: "blah" }}
assert_redirected_to user_api_keys_path(@user.id)
assert_equal(true, @user.api_keys.last.present?)
assert_equal("blah", @user.api_keys.last.name)
end
end
context "#edit action" do
should "render for the API key owner" do
get_auth edit_api_key_path(@api_key.id), @user
assert_response :success
end
should "fail for someone else" do
get_auth edit_api_key_path(@api_key.id), create(:user)
assert_response 403
end
end
context "#update action" do
should "render for the API key owner" do
put_auth api_key_path(@api_key.id), @user, params: { api_key: { name: "blah" }}
assert_redirected_to user_api_keys_path(@user.id)
assert_equal("blah", @api_key.reload.name)
end
should "fail for someone else" do
put_auth api_key_path(@api_key.id), create(:user)
assert_response 403
end
end
context "#destroy" do
setup do
@api_key = create(:api_key, user: @user)
end
should "delete the user's API key" do
delete_auth api_key_path(@api_key.id), @user