mirror of
https://github.com/dokku/dokku.git
synced 2025-12-29 00:25:08 +01:00
Merge pull request #2287 from dokku/u2mejc-ssh-keys
Add ssh-keys core plugin
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
DOKKU_VERSION = master
|
||||
|
||||
SSHCOMMAND_URL ?= https://raw.githubusercontent.com/dokku/sshcommand/v0.4.0/sshcommand
|
||||
SSHCOMMAND_URL ?= https://raw.githubusercontent.com/dokku/sshcommand/v0.5.0/sshcommand
|
||||
PLUGN_URL ?= https://github.com/dokku/plugn/releases/download/v0.2.1/plugn_0.2.1_linux_x86_64.tgz
|
||||
SIGIL_URL ?= https://github.com/gliderlabs/sigil/releases/download/v0.4.0/sigil_0.4.0_Linux_x86_64.tgz
|
||||
STACK_URL ?= https://github.com/gliderlabs/herokuish.git
|
||||
|
||||
2
deb.mk
2
deb.mk
@@ -26,7 +26,7 @@ Simplifies running a single command over SSH, and
|
||||
manages authorized keys (ACL) and users in order to do so.
|
||||
endef
|
||||
SSHCOMMAND_REPO_NAME ?= dokku/sshcommand
|
||||
SSHCOMMAND_VERSION ?= 0.4.0
|
||||
SSHCOMMAND_VERSION ?= 0.5.0
|
||||
SSHCOMMAND_ARCHITECTURE = amd64
|
||||
SSHCOMMAND_PACKAGE_NAME = sshcommand_$(SSHCOMMAND_VERSION)_$(SSHCOMMAND_ARCHITECTURE).deb
|
||||
SSHCOMMAND_URL ?= https://raw.githubusercontent.com/dokku/sshcommand/v$(SSHCOMMAND_VERSION)/sshcommand
|
||||
|
||||
@@ -1,40 +1,41 @@
|
||||
# User Management
|
||||
|
||||
While it is possible to use password-based authorization to push to Dokku, it is preferable to use key-based authentication for security.
|
||||
When pushing to Dokku, ssh key based authorization is the preferred authentication method, for ease of use and increased security.
|
||||
|
||||
Users in dokku are managed via the `~/dokku/.ssh/authorized_keys` file. While you *can* manually edit this file, it is **highly** recommended that you follow the below steps to manage users on a dokku server.
|
||||
Users in Dokku are managed via the `~/dokku/.ssh/authorized_keys` file. It is **highly** recommended that you follow the steps below to manage users on a Dokku server.
|
||||
|
||||
## SSHCommand
|
||||
## Dokku ssh-keys command
|
||||
|
||||
Dokku uses the [`sshcommand`](https://github.com/dokku/sshcommand) utility to manage ssh keys for the dokku user. The following is the usage output for sshcommand.
|
||||
The `dokku ssh-keys` command(s) allow you to manage ssh keys used to push to the Dokku server. The following is the usage output for `dokku ssh-keys`:
|
||||
|
||||
```
|
||||
sshcommand create <user> <command> # creates a user forced to run command when SSH connects
|
||||
sshcommand acl-add <user> <ssh-key-name> # adds named SSH key to user from STDIN
|
||||
sshcommand acl-remove <user> <ssh-key-name> # removes SSH key by name
|
||||
sshcommand help # displays the usage help message
|
||||
$ dokku ssh-keys:help
|
||||
Usage: dokku ssh-keys[:COMMAND]
|
||||
|
||||
Manage public ssh keys that are allowed to connect to Dokku
|
||||
|
||||
Additional commands:
|
||||
ssh-keys:add <name> [/path/to/key] Add a new public key by pipe or path
|
||||
ssh-keys:list List of all authorized Dokku public ssh keys
|
||||
ssh-keys Manage public ssh keys that are allowed to connect to Dokku
|
||||
ssh-keys:remove <name> Remove SSH public key by name
|
||||
```
|
||||
|
||||
In dokku's case, the `<user>` section is *always* `dokku`, as this is the system user that the dokku binary performs all it's actions. Keys are given unique names, which can be used in conjunction with the [user-auth](/dokku/development/plugin-triggers/#user-auth) plugin trigger to handle command authorization.
|
||||
Keys are given unique names, which can be used in conjunction with the [user-auth](/dokku/development/plugin-triggers/#user-auth) plugin trigger to handle command authorization. In Dokku's case, the unique _name_ is just for ease of identifying the keys, the ssh (git) user is *always* `dokku`, as this is the system user that the `dokku` binary uses to perform all it's actions.
|
||||
|
||||
## Adding deploy users
|
||||
|
||||
You can add your public key to the dokku user's `~/dokku/.ssh/authorized_keys` file with the following command:
|
||||
You can add your public key to Dokku with the following command:
|
||||
|
||||
`NAME` is the username prefer to use to refer to this particular key. Including the word `admin` in the name will grant the user privileges to add additional keys remotely.
|
||||
|
||||
```shell
|
||||
# from your local machine
|
||||
# replace dokku.me with your domain name or the host's IP
|
||||
# replace root with your server's root user
|
||||
# USER is the username you use to refer to this particular key
|
||||
cat ~/.ssh/id_rsa.pub | ssh root@dokku.me "sudo sshcommand acl-add dokku USER"
|
||||
$ dokku ssh-keys:add <NAME> <PATH/TO/KEY>
|
||||
```
|
||||
|
||||
At it's base, the `sshcommand` *must* be run under a user with sudo access, as it sets keys for the dokku user.
|
||||
|
||||
For instance, if you stored your public key at `~/.ssh/id_rsa.pub-open` and are deploying to EC2 where the default root-enabled user is `ubuntu`, you can run the following command to add your key under the `superuser` username:
|
||||
|
||||
Admin users and root can also add keys remotely:
|
||||
```shell
|
||||
cat ~/.ssh/id_rsa.pub-open | ssh ubuntu@dokku.me "sudo sshcommand acl-add dokku superuser"
|
||||
cat <PATH/TO/KEY> | ssh dokku@dokku.me ssh-keys:add <NAME>
|
||||
```
|
||||
|
||||
If you are using the vagrant installation, you can also use the `make vagrant-acl-add` target to add your public key to dokku (it will use your host username as the `USER`):
|
||||
|
||||
33
plugins/ssh-keys/commands
Executable file
33
plugins/ssh-keys/commands
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
[[ " help ssh-keys:help " == *" $1 "* ]] || exit "$DOKKU_NOT_IMPLEMENTED_EXIT"
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
case "$1" in
|
||||
help | ssh-keys:help)
|
||||
help_content_func () {
|
||||
declare desc="return ssh-keys plugin help content"
|
||||
cat<<help_content
|
||||
ssh-keys, Manage public ssh keys that are allowed to connect to Dokku
|
||||
ssh-keys:list, List of all authorized dokku public ssh keys
|
||||
ssh-keys:add <name> [/path/to/key], Add a new public key by pipe or path
|
||||
ssh-keys:remove <name>, Remove SSH public key by name
|
||||
help_content
|
||||
}
|
||||
|
||||
if [[ $1 = "ssh-keys:help" ]] ; then
|
||||
echo -e 'Usage: dokku ssh-keys[:COMMAND]'
|
||||
echo ''
|
||||
echo 'Manage public ssh keys that are allowed to connect to Dokku'
|
||||
echo ''
|
||||
echo 'Additional commands:'
|
||||
help_content_func | sort | column -c2 -t -s,
|
||||
else
|
||||
help_content_func
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
exit "$DOKKU_NOT_IMPLEMENTED_EXIT"
|
||||
;;
|
||||
|
||||
esac
|
||||
14
plugins/ssh-keys/functions
Executable file
14
plugins/ssh-keys/functions
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
|
||||
verify_ssh_key_file() {
|
||||
declare desc="Test that public key is valid"
|
||||
[[ -s ${DOKKU_ROOT}/.ssh/authorized_keys ]] || dokku_log_fail "No public keys found."
|
||||
ssh-keygen -l -f "${DOKKU_ROOT}/.ssh/authorized_keys" &> /dev/null || dokku_log_fail "${DOKKU_ROOT}/.ssh/authorized_keys failed ssh-keygen check."
|
||||
}
|
||||
|
||||
verify_ssh_key_exists() {
|
||||
declare desc="Test that public key exists"
|
||||
[[ -e ${DOKKU_ROOT}/.ssh/authorized_keys ]] || dokku_log_fail "No public keys found."
|
||||
}
|
||||
4
plugins/ssh-keys/plugin.toml
Normal file
4
plugins/ssh-keys/plugin.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core ssh-keys plugin"
|
||||
version = "0.6.4"
|
||||
[plugin.config]
|
||||
23
plugins/ssh-keys/subcommands/add
Executable file
23
plugins/ssh-keys/subcommands/add
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/ssh-keys/functions"
|
||||
|
||||
add_keys() {
|
||||
declare desc="add a new key via sshcommand"
|
||||
local cmd="ssh-keys:add"
|
||||
shift
|
||||
local name="$1" key_file="$2" key_contents key_from_pipe
|
||||
[[ -p /dev/stdin ]] && read -r key_from_pipe
|
||||
if [[ -n "$key_from_pipe" ]]; then
|
||||
ssh-keygen -lf /dev/stdin <<< "$key_from_pipe" &> /dev/null || dokku_log_fail "Key piped in is not a valid ssh public key"
|
||||
key_contents="$key_from_pipe"
|
||||
elif [[ -n "$key_file" ]]; then
|
||||
key_contents="$(cat "$key_file")"
|
||||
fi
|
||||
[[ -n "$name" && -n "$key_contents" ]] || dokku_log_fail "Two arguments are required if not piping, ie: dokku ssh-keys:add <NAME> <KEY_FILE>"
|
||||
verify_ssh_key_exists
|
||||
echo "$key_contents" | sshcommand acl-add dokku "$name" || dokku_log_fail "sshcommand returned an error: $?"
|
||||
}
|
||||
|
||||
add_keys "$@"
|
||||
13
plugins/ssh-keys/subcommands/list
Executable file
13
plugins/ssh-keys/subcommands/list
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/ssh-keys/functions"
|
||||
|
||||
list_ssh_keys() {
|
||||
declare desc="List ssh key hashes"
|
||||
local cmd="ssh-keys:list"
|
||||
verify_ssh_key_file
|
||||
sshcommand list dokku
|
||||
}
|
||||
|
||||
list_ssh_keys "$@"
|
||||
16
plugins/ssh-keys/subcommands/remove
Executable file
16
plugins/ssh-keys/subcommands/remove
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/ssh-keys/functions"
|
||||
|
||||
remove_key() {
|
||||
declare desc="Removes key from authorized_keys"
|
||||
local cmd="ssh-keys:remove"
|
||||
shift
|
||||
local name="$1"
|
||||
verify_ssh_key_file
|
||||
[[ -z $1 ]] && dokku_log_fail "A name is required to remove a key, ie: dokku ssh-keys:remove <name>"
|
||||
sshcommand acl-remove dokku "$name" || dokku_log_fail "sshcommand returned an error $?"
|
||||
}
|
||||
|
||||
remove_key "$@"
|
||||
13
plugins/ssh-keys/user-auth
Executable file
13
plugins/ssh-keys/user-auth
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
|
||||
check_ssh_keys_user() {
|
||||
declare desc="check user running ssh-keys"
|
||||
local SSH_USER=$1 SSH_NAME=$2
|
||||
[[ "$SSH_USER" == "root" || "$SSH_NAME" == *admin* ]] || dokku_log_fail "You must be root, or a dokku admin, to execute this command"
|
||||
}
|
||||
|
||||
if [[ "$3" == ssh-keys* ]]; then
|
||||
check_ssh_keys_user "$@"
|
||||
fi
|
||||
38
tests/unit/30_ssh_keys.bats
Normal file
38
tests/unit/30_ssh_keys.bats
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
setup() {
|
||||
create_key
|
||||
}
|
||||
|
||||
teardown() {
|
||||
destroy_key
|
||||
}
|
||||
|
||||
@test "(ssh-keys) ssh-keys:add, ssh-keys:list, ssh-keys:remove" {
|
||||
run /bin/bash -c "dokku ssh-keys:add name1 /tmp/testkey.pub"
|
||||
echo "output: "$output
|
||||
echo "status: "$status
|
||||
assert_success
|
||||
run /bin/bash -c "cat /tmp/testkey.pub | dokku ssh-keys:add name2"
|
||||
echo "output: "$output
|
||||
echo "status: "$status
|
||||
assert_success
|
||||
run /bin/bash -c "dokku ssh-keys:list | grep name1 && dokku ssh-keys:list | grep name2"
|
||||
echo "output: "$output
|
||||
echo "status: "$status
|
||||
assert_success
|
||||
run /bin/bash -c "dokku ssh-keys:remove name1"
|
||||
echo "output: "$output
|
||||
echo "status: "$status
|
||||
assert_success
|
||||
run /bin/bash -c "dokku ssh-keys:list | grep name1"
|
||||
echo "output: "$output
|
||||
echo "status: "$status
|
||||
assert_failure
|
||||
run /bin/bash -c "dokku ssh-keys:list | grep name2"
|
||||
echo "output: "$output
|
||||
echo "status: "$status
|
||||
assert_success
|
||||
}
|
||||
@@ -117,6 +117,11 @@ create_app() {
|
||||
dokku apps:create "$TEST_APP"
|
||||
}
|
||||
|
||||
|
||||
create_key() {
|
||||
ssh-keygen -P "" -f /tmp/testkey &> /dev/null
|
||||
}
|
||||
|
||||
destroy_app() {
|
||||
local RC="$1"; local RC=${RC:=0}
|
||||
local APP="$2"; local TEST_APP=${APP:=$TEST_APP}
|
||||
@@ -124,6 +129,10 @@ destroy_app() {
|
||||
return "$RC"
|
||||
}
|
||||
|
||||
destroy_key() {
|
||||
rm -f /tmp/testkey* &> /dev/null || true
|
||||
}
|
||||
|
||||
add_domain() {
|
||||
dokku domains:add "$TEST_APP" "$1"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user