Merge pull request #4921 from dokku/apps-filter

Add ability to filter returnable apps
This commit is contained in:
Jose Diaz-Gonzalez
2022-02-27 17:33:14 -05:00
committed by GitHub
25 changed files with 144 additions and 45 deletions

View File

@@ -2367,3 +2367,44 @@ shift 2
[[ "$SSH_NAME" == "default" && $1 == plugin:* ]] && exit 1
exit 0
```
### `user-auth-app`
This is a special plugin trigger that is executed when listing apps or checking if an app exists. All Dokku commands should check if an app exists at least once before interacting with them so as not to circumvent the check.
Note that the trigger should exit `0`, and each non-empty line on stdout is captured as a valid app name.
The `SSH_USER` is the original ssh user. If you are running remote commands, this user will typically be `dokku`, and as such should not be trusted when checking permissions. If you are connected via ssh as a different user who then invokes `dokku`, the value of this variable will be that user's name (`root`, `myuser`, etc.).
The `SSH_NAME` is the `NAME` variable set via the `sshcommand acl-add` command. For reference, the following command can be run as the root user to specify a specific `NAME` for a given ssh key:
```shell
sshcommand acl-add dokku NAME < $PATH_TO_SSH_KEY
```
Note that the `NAME` value is set at the first ssh key match. If an ssh key is set in the `/home/dokku/.ssh/authorized_keys` multiple times, the first match will decide the value.
- Description: Allows you to deny access to a Dokku app by either ssh user or associated ssh-command NAME user.
- Invoked by: `dokku`
- Arguments: `$SSH_USER $SSH_NAME $DOKKU_COMMAND`
- Example:
```shell
#!/usr/bin/env bash
# hide any apps with the prefix "admin"
# if the logged in user (SSH_USER) or SSH_NAME is not `root`
main() {
declare SSH_USER="$1" SSH_NAME="$2" ARGS=("${@:3}")
for arg in "${ARGS[@]}"; do
if [[ "$arg" == admin-* ]] && [[ "$SSH_USER" != "root" ]] && [[ "$SSH_NAME" != "root" ]]; then
continue
fi
echo "${arg}"
done
}
main "$@"
```

View File

@@ -0,0 +1 @@
hook

View File

@@ -9,7 +9,6 @@ cmd-builder-dockerfile-report() {
declare cmd="builder-dockerfile:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
INFO_FLAG="$APP"
@@ -21,7 +20,7 @@ cmd-builder-dockerfile-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-builder-dockerfile-report-single "$app" "$INFO_FLAG" | tee || true
done
else

View File

@@ -9,7 +9,6 @@ cmd-builder-pack-report() {
declare cmd="builder-pack:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
INFO_FLAG="$APP"
@@ -21,7 +20,7 @@ cmd-builder-pack-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-builder-pack-report-single "$app" "$INFO_FLAG" | tee || true
done
else

View File

@@ -9,7 +9,6 @@ cmd-certs-report() {
declare cmd="certs:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
INFO_FLAG="$APP"
@@ -21,7 +20,7 @@ cmd-certs-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-certs-report-single "$app" "$INFO_FLAG" | tee || true
done
else

View File

@@ -6,13 +6,10 @@ source "$PLUGIN_AVAILABLE_PATH/config/functions"
migrate_checks_vars_0_5_0() {
declare desc="migrates deprecated CHECKS config variables to simplified counter part introduced in 0.5.x"
local APPS="$(dokku_apps)"
local GLOBAL_SKIP_ALL_CHECKS=$(config_get --global DOKKU_SKIP_ALL_CHECKS || true)
local GLOBAL_SKIP_DEFAULT_CHECKS=$(config_get --global DOKKU_SKIP_DEFAULT_CHECKS || true)
local app
for app in $APPS; do
for app in $(dokku_apps); do
local APP_SKIP_ALL_CHECKS=$(config_get "$app" DOKKU_SKIP_ALL_CHECKS || true)
local APP_SKIP_DEFAULT_CHECKS=$(config_get "$app" DOKKU_SKIP_DEFAULT_CHECKS || true)
@@ -37,11 +34,8 @@ migrate_checks_vars_0_5_0() {
migrate_checks_vars_0_6_0() {
declare desc="migrates CHECKS config variables from 0.5.x to support fully-disabled zero-downtime checks"
local APPS="$(dokku_apps)"
local app
for app in $APPS; do
for app in $(dokku_apps); do
local APP_DOKKU_CHECKS_ENABLED=$(config_get "$app" DOKKU_CHECKS_ENABLED || true)
if [[ $APP_DOKKU_CHECKS_ENABLED ]]; then
dokku_log_info1 "Migrating zero downtime env variables to 0.6.x. The following variables will be migrated"

View File

@@ -9,7 +9,6 @@ cmd-checks-report() {
declare cmd="checks:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
INFO_FLAG="$APP"
@@ -21,7 +20,7 @@ cmd-checks-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-checks-report-single "$app" "$INFO_FLAG" | tee || true
done
else

View File

@@ -1,4 +1,4 @@
TRIGGERS = triggers/core-post-deploy triggers/install triggers/post-delete
TRIGGERS = triggers/app-list triggers/core-post-deploy triggers/install triggers/post-delete
BUILD = prop common triggers
PLUGIN_NAME = common

View File

@@ -244,12 +244,12 @@ func GetRunningImageTag(appName string, imageTag string) (string, error) {
}
// DokkuApps returns a list of all local apps
func DokkuApps() (apps []string, err error) {
func DokkuApps() ([]string, error) {
apps := []string{}
dokkuRoot := MustGetEnv("DOKKU_ROOT")
files, err := ioutil.ReadDir(dokkuRoot)
if err != nil {
err = fmt.Errorf("You haven't deployed any applications yet")
return
return apps, fmt.Errorf("You haven't deployed any applications yet")
}
for _, f := range files {
@@ -264,11 +264,10 @@ func DokkuApps() (apps []string, err error) {
}
if len(apps) == 0 {
err = fmt.Errorf("You haven't deployed any applications yet")
return
return apps, fmt.Errorf("You haven't deployed any applications yet")
}
return
return filterApps(apps)
}
// GetAppImageName returns image identifier for a given app, tag tuple. validate if tag is presented

View File

@@ -87,6 +87,7 @@ func TestCommonDokkuAppsError(t *testing.T) {
func TestCommonDokkuApps(t *testing.T) {
RegisterTestingT(t)
os.Setenv("PLUGIN_ENABLED_PATH", "/var/lib/dokku/plugins/enabled")
Expect(setupTestApp()).To(Succeed())
apps, err := DokkuApps()
Expect(err).NotTo(HaveOccurred())

View File

@@ -17,8 +17,11 @@ has_tty() {
dokku_apps() {
declare desc="prints list of all local apps"
local INSTALLED_APPS=$(find "$DOKKU_ROOT" -follow -maxdepth 1 -mindepth 1 -type d ! -name '.*' -printf "%f\n" 2>/dev/null | sort) || (dokku_log_fail "You haven't deployed any applications yet")
[[ $INSTALLED_APPS ]] && echo "$INSTALLED_APPS"
local INSTALLED_APPS="$(plugn trigger app-list)"
if [[ -z "$INSTALLED_APPS" ]]; then
dokku_log_fail "You haven't deployed any applications yet"
fi
echo "$INSTALLED_APPS"
}
dokku_version() {

View File

@@ -0,0 +1,44 @@
package common
import (
"fmt"
"os"
"strings"
)
func filterApps(apps []string) ([]string, error) {
if !PlugnTriggerExists("user-auth-app") {
return apps, nil
}
sshUser := os.Getenv("SSH_USER")
if sshUser == "" {
sshUser = os.Getenv("USER")
}
sshName := os.Getenv("SSH_NAME")
if sshName == "" {
sshName = "default"
}
args := append([]string{sshUser, sshName}, apps...)
b, _ := PlugnTriggerOutput("user-auth-app", args...)
filteredApps := strings.Split(strings.TrimSpace(string(b[:])), "\n")
filteredApps = removeEmptyEntries(filteredApps)
if len(filteredApps) == 0 {
return filteredApps, fmt.Errorf("You haven't deployed any applications yet")
}
return filteredApps, nil
}
func removeEmptyEntries(s []string) []string {
var r []string
for _, str := range s {
if str != "" {
r = append(r, str)
}
}
return r
}

View File

@@ -17,6 +17,8 @@ func main() {
var err error
switch trigger {
case "app-list":
err = common.TriggerAppList()
case "core-post-deploy":
appName := flag.Arg(0)
err = common.TriggerCorePostDeploy(appName)

View File

@@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/codeskyblue/go-sh"
@@ -128,3 +129,19 @@ func PlugnTriggerSetup(triggerName string, args ...string) *sh.Session {
}
return sh.Command("plugn", shellArgs...)
}
// PlugnTriggerExists returns whether a plugin trigger exists (ignoring the existence of any within the 20_events plugin)
func PlugnTriggerExists(triggerName string) bool {
pluginPath := MustGetEnv("PLUGIN_ENABLED_PATH")
glob := filepath.Join(pluginPath, "*", triggerName)
exists := false
files, _ := filepath.Glob(glob)
for _, file := range files {
plugin := strings.Trim(strings.TrimPrefix(strings.TrimSuffix(file, "/"+triggerName), pluginPath), "/")
if plugin != "20_events" {
exists = true
break
}
}
return exists
}

View File

@@ -5,6 +5,16 @@ import (
"os"
)
// TriggerAppList outputs each app name to stdout on a newline
func TriggerAppList() error {
apps, _ := DokkuApps()
for _, app := range apps {
Log(app)
}
return nil
}
// TriggerCorePostDeploy associates the container with a specified network
func TriggerCorePostDeploy(appName string) error {
quiet := os.Getenv("DOKKU_QUIET_OUTPUT")

View File

@@ -9,7 +9,6 @@ cmd-docker-options-report() {
declare cmd="docker-options:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
INFO_FLAG="$APP"
@@ -21,7 +20,7 @@ cmd-docker-options-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-docker-options-report-single "$app" "$INFO_FLAG" | tee || true
done
else

View File

@@ -8,9 +8,8 @@ trigger-domains-install() {
declare trigger="install"
shopt -s nullglob
for app in $DOKKU_ROOT/*/CONTAINER; do
APP=$(basename "$(dirname "$app")")
domains_setup "$APP"
for app in $(dokku_apps); do
domains_setup "$app"
done
}

View File

@@ -9,7 +9,6 @@ cmd-domains-report() {
declare cmd="domains:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ "$APP" == "--global" ]]; then
cmd-domains-report-single "$APP" "$INFO_FLAG"
@@ -26,7 +25,7 @@ cmd-domains-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-domains-report-single "$app" "$INFO_FLAG" | tee || true
done
else

View File

@@ -18,7 +18,6 @@ trigger-git-install() {
migrate_git_vars_0_12_0() {
declare desc="migrates git config variables from 0.11.x"
local APPS="$(dokku_apps)"
local DOKKU_DEPLOY_BRANCH app
DOKKU_DEPLOY_BRANCH=$(config_get --global DOKKU_DEPLOY_BRANCH || true)
@@ -27,7 +26,7 @@ migrate_git_vars_0_12_0() {
DOKKU_QUIET_OUTPUT=1 config_unset --global DOKKU_DEPLOY_BRANCH || true
fi
for app in $APPS; do
for app in $(dokku_apps); do
DOKKU_DEPLOY_BRANCH=$(config_get "$app" DOKKU_DEPLOY_BRANCH || true)
if [[ -n "$DOKKU_DEPLOY_BRANCH" ]]; then
fn-plugin-property-write "git" "$app" "deploy-branch" "$DOKKU_DEPLOY_BRANCH"

View File

@@ -222,7 +222,6 @@ cmd-git-report() {
declare cmd="git:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
INFO_FLAG="$APP"
@@ -234,7 +233,7 @@ cmd-git-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-git-report-single "$app" "$INFO_FLAG" | tee || true
done
else

View File

@@ -5,7 +5,7 @@ go 1.16
require (
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
github.com/dokku/dokku/plugins/docker-options v0.0.0-20210208020425-f7beb3d95ddd
github.com/dokku/dokku/plugins/docker-options v0.0.0-00010101000000-000000000000
github.com/joncalhoun/qson v0.0.0-20200422171543-84433dcd3da0
github.com/spf13/pflag v1.0.5
)

View File

@@ -11,7 +11,6 @@ cmd-nginx-report() {
declare cmd="nginx:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
INFO_FLAG="$APP"
@@ -23,7 +22,7 @@ cmd-nginx-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-nginx-report-single "$app" "$INFO_FLAG" | tee || true
done
else

View File

@@ -6,9 +6,8 @@ import (
"path/filepath"
"strings"
dockeroptions "github.com/dokku/dokku/plugins/docker-options"
"github.com/dokku/dokku/plugins/common"
dockeroptions "github.com/dokku/dokku/plugins/docker-options"
"github.com/gofrs/flock"
)

View File

@@ -10,7 +10,6 @@ cmd-scheduler-docker-local-report() {
declare cmd="scheduler-docker-local:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
INFO_FLAG="$APP"
@@ -22,7 +21,7 @@ cmd-scheduler-docker-local-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-scheduler-docker-local-report-single "$app" "$INFO_FLAG" | tee || true
done
else

View File

@@ -66,7 +66,6 @@ cmd-storage-report() {
declare cmd="storage:report"
[[ "$1" == "$cmd" ]] && shift 1
declare APP="$1" INFO_FLAG="$2"
local INSTALLED_APPS=$(dokku_apps)
if [[ -n "$APP" ]] && [[ "$APP" == --* ]]; then
INFO_FLAG="$APP"
@@ -78,7 +77,7 @@ cmd-storage-report() {
fi
if [[ -z "$APP" ]]; then
for app in $INSTALLED_APPS; do
for app in $(dokku_apps); do
cmd-storage-report-single "$app" "$INFO_FLAG" | tee || true
done
else