Newer
Older
// Package main provides a utility program to launch the Dex container process with an optional
// templating step (provided by gomplate).
//
// This was originally written as a shell script, but we rewrote it as a Go program so that it could
// run as a raw binary in a distroless container.
package main
import (
"fmt"
"os"
"os/exec"
"strings"
"syscall"
)
func main() {
// Note that this docker-entrypoint program is args[0], and it is provided with the true process
// args.
args := os.Args[1:]
if len(args) == 0 {
fmt.Println("error: no args passed to entrypoint")
os.Exit(1)
}
if err := run(args, realExec, realWhich, realGomplate); err != nil {
fmt.Println("error:", err.Error())
os.Exit(1)
}
}
func realExec(args ...string) error {
argv0, err := exec.LookPath(args[0])
if err != nil {
return fmt.Errorf("cannot lookup path for command %s: %w", args[0], err)
}
if err := syscall.Exec(argv0, args, os.Environ()); err != nil {
return fmt.Errorf("cannot exec command %s (%q): %w", args, argv0, err)
}
return nil
}
func realWhich(path string) string {
fullPath, err := exec.LookPath(path)
if err != nil {
return ""
}
return fullPath
}
func realGomplate(path string) (string, error) {
tmpFile, err := os.CreateTemp("/tmp", "dex.config.yaml-*")
if err != nil {
return "", fmt.Errorf("cannot create temp file: %w", err)
}
cmd := exec.Command("gomplate", "-f", path, "-o", tmpFile.Name())
// TODO(nabokihms): Workaround to run gomplate from a non-root directory in distroless images
// gomplate tries to access CWD on start, see: https://github.com/hairyhenderson/gomplate/pull/2202
cmd.Dir = "/etc/dex"
output, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("error executing gomplate: %w, (output: %q)", err, string(output))
}
return tmpFile.Name(), nil
}
func run(args []string, execFunc func(...string) error, whichFunc func(string) string, gomplateFunc func(string) (string, error)) error {
if args[0] != "dex" && args[0] != whichFunc("dex") {
}
if args[1] != "serve" {
}
newArgs := []string{}
for _, tplCandidate := range args {
if hasSuffixes(tplCandidate, ".tpl", ".tmpl", ".yaml") {
fileName, err := gomplateFunc(tplCandidate)
if err != nil {
return err
}
newArgs = append(newArgs, fileName)
} else {
newArgs = append(newArgs, tplCandidate)
}
}