diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..aa6e136 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +# Build +FROM golang:1.18 AS builder + +COPY . /otpauth +WORKDIR /otpauth + +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o build/otpauth + +# Run +FROM scratch + +COPY --from=builder /otpauth/build/otpauth /app/otpauth + +ENTRYPOINT ["/app/otpauth"] diff --git a/README.md b/README.md index ecb7513..469080e 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,12 @@ to plain [otpauth links](https://github.com/google/google-authenticator/wiki/Key ### Flags ``` - -cache string - cache file (default "migration.bin") + -workdir string + working directory to store eventual files (defaults to current one) -eval evaluate otps -http string - serve http (e.g. localhost:6060) + serve http (e.g. :6060) -info display batch info -link string @@ -63,3 +63,26 @@ Will generate: ``` Navigate to http://localhost:6060/ + +## Docker +A Docker container can also be used to run the application by building and running the image as following + +#### Build image +From the current directory run +``` +docker build . -t otpauth:latest +``` + +#### Run container +To start a container from the previously created image run +``` +docker run --name otpauth -p 6060:6060 -v $(pwd)/workdir:/app/workdir --rm otpauth:latest -workdir /app/workdir -http :6060 -link "otpauth-migration://offline?data=CjEKCkhlbGxvId6tvu8SGEV4YW1wbGU6YWxpY2VAZ29vZ2xlLmNvbRoHRXhhbXBsZTAC" +``` +``` +-p 6060:6060 +Map the host 6060 to the containr 6060 + +-v $(pwd)/workdir:/app/workdir +Map the host dir to the containr dir +``` +Navigate to http://localhost:6060/ diff --git a/main.go b/main.go index 582326f..52540f6 100644 --- a/main.go +++ b/main.go @@ -8,10 +8,16 @@ import ( "fmt" "log" "os" + "path/filepath" "github.com/dim13/otpauth/migration" ) +const ( + cacheFilename = "migration.bin" + revFile = "otpauth-migration.png" +) + func migrationData(fname, link string) ([]byte, error) { if link == "" { // read from cache @@ -27,17 +33,24 @@ func migrationData(fname, link string) ([]byte, error) { func main() { var ( - link = flag.String("link", "", "migration link (required)") - cache = flag.String("cache", "migration.bin", "cache file") - http = flag.String("http", "", "serve http (e.g. localhost:6060)") - eval = flag.Bool("eval", false, "evaluate otps") - qr = flag.Bool("qr", false, "generate QR-codes (optauth://)") - rev = flag.Bool("rev", false, "reverse QR-code (otpauth-migration://)") - info = flag.Bool("info", false, "display batch info") + link = flag.String("link", "", "migration link (required)") + workdir = flag.String("workdir", "", "working directory") + http = flag.String("http", "", "serve http (e.g. localhost:6060)") + eval = flag.Bool("eval", false, "evaluate otps") + qr = flag.Bool("qr", false, "generate QR-codes (optauth://)") + rev = flag.Bool("rev", false, "reverse QR-code (otpauth-migration://)") + info = flag.Bool("info", false, "display batch info") ) flag.Parse() - data, err := migrationData(*cache, *link) + if *workdir != "" { + if err := os.MkdirAll(*workdir, 0700); err != nil { + log.Fatal("error creating working directory: ", err) + } + } + + cacheFile := filepath.Join(*workdir, cacheFilename) + data, err := migrationData(cacheFile, *link) if err != nil { log.Fatal("-link parameter or cache file missing: ", err) } @@ -54,12 +67,15 @@ func main() { } case *qr: for _, op := range p.OtpParameters { - if err := migration.PNG(op.FileName()+".png", op.URL()); err != nil { + fileName := op.FileName() + ".png" + qrFile := filepath.Join(*workdir, fileName) + if err := migration.PNG(qrFile, op.URL()); err != nil { log.Fatal("write file: ", err) } } case *rev: - if err := migration.PNG("otpauth-migration.png", migration.URL(data)); err != nil { + revFile := filepath.Join(*workdir, revFile) + if err := migration.PNG(revFile, migration.URL(data)); err != nil { log.Fatal(err) } case *eval: