Implement AUTH. Closes #58

This change makes password authentication required
for redis usage, and removes anonymous access. Users
will need to change their underlying clients to enable
writing the auth token for authenticating, otherwise
requests will fail.

This is a non-optional change, and improves security
for users who wish to expose their redis installations
outside of their network.
This commit is contained in:
Jose Diaz-Gonzalez
2016-08-27 23:39:31 -04:00
parent 92c2957bfc
commit 919832ba2a
7 changed files with 35 additions and 18 deletions

View File

@@ -99,7 +99,7 @@ dokku redis:link lolipop playground
# #
# and the following will be set on the linked application by default # and the following will be set on the linked application by default
# #
# REDIS_URL=redis://dokku-redis-lolipop:6379 # REDIS_URL=redis://lolipop:SOME_PASSWORD@dokku-redis-lolipop:6379
# #
# NOTE: the host exposed here only works internally in docker containers. If # NOTE: the host exposed here only works internally in docker containers. If
# you want your container to be reachable from outside, you should use `expose`. # you want your container to be reachable from outside, you should use `expose`.
@@ -110,7 +110,7 @@ dokku redis:link other_service playground
# since REDIS_URL is already in use, another environment variable will be # since REDIS_URL is already in use, another environment variable will be
# generated automatically # generated automatically
# #
# DOKKU_REDIS_BLUE_URL=redis://dokku-redis-other-service:6379 # DOKKU_REDIS_BLUE_URL=redis://other_service:ANOTHER_PASSWORD@dokku-redis-other-service:6379
# you can then promote the new service to be the primary one # you can then promote the new service to be the primary one
# NOTE: this will restart your app # NOTE: this will restart your app
@@ -120,9 +120,9 @@ dokku redis:promote other_service playground
# another environment variable to hold the previous value if necessary. # another environment variable to hold the previous value if necessary.
# you could end up with the following for example: # you could end up with the following for example:
# #
# REDIS_URL=redis://dokku-redis-other-service:63790 # REDIS_URL=redis://other_service:ANOTHER_PASSWORD@dokku-redis-other-service:63790
# DOKKU_REDIS_BLUE_URL=redis://dokku-redis-other-service:6379 # DOKKU_REDIS_BLUE_URL=redis://other_service:ANOTHER_PASSWORD@dokku-redis-other-service:6379
# DOKKU_REDIS_SILVER_URL=redis://dokku-redis-lolipop:6379/lolipop # DOKKU_REDIS_SILVER_URL=redis://lolipop:SOME_PASSWORD@dokku-redis-lolipop:6379/lolipop
# you can also unlink a redis service # you can also unlink a redis service
# NOTE: this will restart your app and unset related environment variables # NOTE: this will restart your app and unset related environment variables
@@ -156,7 +156,7 @@ dokku redis:link lolipop playground
``` ```
Will cause REDIS_URL to be set as Will cause REDIS_URL to be set as
redis2://dokku-redis-lolipop:6379/lolipop redis2://lolipop:SOME_PASSWORD@dokku-redis-lolipop:6379/lolipop
CAUTION: Changing REDIS_DATABASE_SCHEME after linking will cause dokku to CAUTION: Changing REDIS_DATABASE_SCHEME after linking will cause dokku to
believe the redis is not linked when attempting to use `dokku redis:unlink` believe the redis is not linked when attempting to use `dokku redis:unlink`

View File

@@ -22,8 +22,12 @@ service_create() {
mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory" mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory"
mkdir -p "$SERVICE_ROOT/data" || dokku_log_fail "Unable to create service data directory" mkdir -p "$SERVICE_ROOT/data" || dokku_log_fail "Unable to create service data directory"
mkdir -p "$SERVICE_ROOT/config" || dokku_log_fail "Unable to create service config directory" mkdir -p "$SERVICE_ROOT/config" || dokku_log_fail "Unable to create service config directory"
touch "$LINKS_FILE"
curl -sSL "https://raw.githubusercontent.com/antirez/redis/${REDIS_IMAGE_VERSION:0:3}/redis.conf" > "$SERVICE_ROOT/config/redis.conf" || dokku_log_fail "Unable to download the default redis.conf to the config directory" curl -sSL "https://raw.githubusercontent.com/antirez/redis/${REDIS_IMAGE_VERSION:0:3}/redis.conf" > "$SERVICE_ROOT/config/redis.conf" || dokku_log_fail "Unable to download the default redis.conf to the config directory"
PASSWORD=$(openssl rand -hex 32)
echo "$PASSWORD" > "$SERVICE_ROOT/PASSWORD"
chmod 640 "$SERVICE_ROOT/PASSWORD"
sed -i.bak "s/# requirepass.*/requirepass ${PASSWORD}/" "$SERVICE_ROOT/config/redis.conf" && rm "$SERVICE_ROOT/config/redis.conf.bak"
touch "$LINKS_FILE"
if [[ -n $REDIS_CUSTOM_ENV ]]; then if [[ -n $REDIS_CUSTOM_ENV ]]; then
echo "$REDIS_CUSTOM_ENV" | tr ';' "\n" > "$SERVICE_ROOT/ENV" echo "$REDIS_CUSTOM_ENV" | tr ';' "\n" > "$SERVICE_ROOT/ENV"
@@ -102,8 +106,10 @@ service_start() {
service_url() { service_url() {
local SERVICE="$1" local SERVICE="$1"
local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
local PASSWORD="$(cat "$SERVICE_ROOT/PASSWORD")"
local SERVICE_ALIAS="$(service_alias "$SERVICE")" local SERVICE_ALIAS="$(service_alias "$SERVICE")"
echo "$PLUGIN_SCHEME://$SERVICE_ALIAS:${PLUGIN_DATASTORE_PORTS[0]}" echo "$PLUGIN_SCHEME://$SERVICE:$PASSWORD@$SERVICE_ALIAS:${PLUGIN_DATASTORE_PORTS[0]}"
} }
update_plugin_scheme_for_app() { update_plugin_scheme_for_app() {

View File

@@ -25,6 +25,7 @@ teardown() {
export ECHO_DOCKER_COMMAND="true" export ECHO_DOCKER_COMMAND="true"
export SSH_TTY=`tty` export SSH_TTY=`tty`
run dokku "$PLUGIN_COMMAND_PREFIX:export" l run dokku "$PLUGIN_COMMAND_PREFIX:export" l
password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
assert_exit_status 0 assert_exit_status 0
assert_output "docker exec dokku.redis.l cat /data/dump.rdb" assert_output "docker exec dokku.redis.l cat /data/dump.rdb"
} }
@@ -33,6 +34,7 @@ teardown() {
export ECHO_DOCKER_COMMAND="true" export ECHO_DOCKER_COMMAND="true"
unset SSH_TTY unset SSH_TTY
run dokku "$PLUGIN_COMMAND_PREFIX:export" l run dokku "$PLUGIN_COMMAND_PREFIX:export" l
password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
assert_exit_status 0 assert_exit_status 0
assert_output "docker exec dokku.redis.l cat /data/dump.rdb" assert_output "docker exec dokku.redis.l cat /data/dump.rdb"
} }

View File

@@ -31,6 +31,7 @@ teardown() {
@test "($PLUGIN_COMMAND_PREFIX:import) success" { @test "($PLUGIN_COMMAND_PREFIX:import) success" {
export ECHO_DOCKER_COMMAND="true" export ECHO_DOCKER_COMMAND="true"
run dokku "$PLUGIN_COMMAND_PREFIX:import" l < "$PLUGIN_DATA_ROOT/fake.rdb" run dokku "$PLUGIN_COMMAND_PREFIX:import" l < "$PLUGIN_DATA_ROOT/fake.rdb"
password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
assert_output "docker run --rm -i -v $PLUGIN_DATA_ROOT/l/data:/data redis:3.2.3 bash -c cat > /data/dump.rdb && chown redis: /data/dump.rdb" assert_output "docker run --rm -i -v $PLUGIN_DATA_ROOT/l/data:/data redis:3.2.3 bash -c cat > /data/dump.rdb && chown redis: /data/dump.rdb"
} }

View File

@@ -21,19 +21,22 @@ teardown() {
@test "($PLUGIN_COMMAND_PREFIX:info) success" { @test "($PLUGIN_COMMAND_PREFIX:info) success" {
run dokku "$PLUGIN_COMMAND_PREFIX:info" l run dokku "$PLUGIN_COMMAND_PREFIX:info" l
assert_contains "${lines[*]}" "redis://dokku-redis-l:6379" password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
assert_contains "${lines[*]}" "redis://l:$password@dokku-redis-l:6379"
} }
@test "($PLUGIN_COMMAND_PREFIX:info) replaces underscores by dash in hostname" { @test "($PLUGIN_COMMAND_PREFIX:info) replaces underscores by dash in hostname" {
dokku "$PLUGIN_COMMAND_PREFIX:create" test_with_underscores dokku "$PLUGIN_COMMAND_PREFIX:create" test_with_underscores
run dokku "$PLUGIN_COMMAND_PREFIX:info" test_with_underscores run dokku "$PLUGIN_COMMAND_PREFIX:info" test_with_underscores
assert_contains "${lines[*]}" "redis://dokku-redis-test-with-underscores:6379" password="$(cat "$PLUGIN_DATA_ROOT/test_with_underscores/PASSWORD")"
assert_contains "${lines[*]}" "redis://test_with_underscores:$password@dokku-redis-test-with-underscores:6379"
dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" test_with_underscores dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" test_with_underscores
} }
@test "($PLUGIN_COMMAND_PREFIX:info) success with flag" { @test "($PLUGIN_COMMAND_PREFIX:info) success with flag" {
run dokku "$PLUGIN_COMMAND_PREFIX:info" l --dsn run dokku "$PLUGIN_COMMAND_PREFIX:info" l --dsn
assert_output "redis://dokku-redis-l:6379" password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
assert_output "redis://l:$password@dokku-redis-l:6379"
run dokku "$PLUGIN_COMMAND_PREFIX:info" l --config-dir run dokku "$PLUGIN_COMMAND_PREFIX:info" l --config-dir
assert_success assert_success

View File

@@ -40,7 +40,8 @@ teardown() {
@test "($PLUGIN_COMMAND_PREFIX:link) exports REDIS_URL to app" { @test "($PLUGIN_COMMAND_PREFIX:link) exports REDIS_URL to app" {
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app
url=$(dokku config:get my_app REDIS_URL) url=$(dokku config:get my_app REDIS_URL)
assert_contains "$url" "redis://dokku-redis-l:6379" password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
assert_contains "$url" "redis://l:$password@dokku-redis-l:6379"
dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app
} }
@@ -63,6 +64,7 @@ teardown() {
dokku config:set my_app REDIS_DATABASE_SCHEME=redis2 dokku config:set my_app REDIS_DATABASE_SCHEME=redis2
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app
url=$(dokku config:get my_app REDIS_URL) url=$(dokku config:get my_app REDIS_URL)
assert_contains "$url" "redis2://dokku-redis-l:6379" password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
assert_contains "$url" "redis2://l:$password@dokku-redis-l:6379"
dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app
} }

View File

@@ -39,22 +39,25 @@ teardown() {
} }
@test "($PLUGIN_COMMAND_PREFIX:promote) changes REDIS_URL" { @test "($PLUGIN_COMMAND_PREFIX:promote) changes REDIS_URL" {
dokku config:set my_app "REDIS_URL=redis://host:6379/db" "DOKKU_REDIS_BLUE_URL=redis://dokku-redis-l:6379" password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
dokku config:set my_app "REDIS_URL=redis://u:p@host:6379/db" "DOKKU_REDIS_BLUE_URL=redis://l:$password@dokku-redis-l:6379"
dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app
url=$(dokku config:get my_app REDIS_URL) url=$(dokku config:get my_app REDIS_URL)
assert_equal "$url" "redis://dokku-redis-l:6379" assert_equal "$url" "redis://l:$password@dokku-redis-l:6379"
} }
@test "($PLUGIN_COMMAND_PREFIX:promote) creates new config url when needed" { @test "($PLUGIN_COMMAND_PREFIX:promote) creates new config url when needed" {
dokku config:set my_app "REDIS_URL=redis://host:6379/db" "DOKKU_REDIS_BLUE_URL=redis://dokku-redis-l:6379" password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
dokku config:set my_app "REDIS_URL=redis://u:p@host:6379/db" "DOKKU_REDIS_BLUE_URL=redis://l:$password@dokku-redis-l:6379"
dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app
run dokku config my_app run dokku config my_app
assert_contains "${lines[*]}" "DOKKU_REDIS_" assert_contains "${lines[*]}" "DOKKU_REDIS_"
} }
@test "($PLUGIN_COMMAND_PREFIX:promote) uses REDIS_DATABASE_SCHEME variable" { @test "($PLUGIN_COMMAND_PREFIX:promote) uses REDIS_DATABASE_SCHEME variable" {
dokku config:set my_app "REDIS_DATABASE_SCHEME=redis2" "REDIS_URL=redis://u:p@host:6379" "DOKKU_REDIS_BLUE_URL=redis2://dokku-redis-l:6379" password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
dokku config:set my_app "REDIS_DATABASE_SCHEME=redis2" "REDIS_URL=redis://u:p@host:6379" "DOKKU_REDIS_BLUE_URL=redis2://l:$password@dokku-redis-l:6379"
dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app
url=$(dokku config:get my_app REDIS_URL) url=$(dokku config:get my_app REDIS_URL)
assert_equal "$url" "redis2://dokku-redis-l:6379" assert_equal "$url" "redis2://l:$password@dokku-redis-l:6379"
} }