-
-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
861 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
.build | ||
customize.yaml | ||
frontend/api.html | ||
frontend/app.css | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#!/usr/bin/env bash | ||
set -euo pipefail | ||
|
||
osarch=( | ||
darwin/amd64 | ||
darwin/arm64 | ||
linux/amd64 | ||
linux/arm | ||
linux/arm64 | ||
windows/amd64 | ||
) | ||
|
||
function go_package() { | ||
cd "${4}" | ||
|
||
local outname="${3}" | ||
[[ $1 == windows ]] && outname="${3}.exe" | ||
|
||
log "=> Building ${3} for ${1}/${2}..." | ||
CGO_ENABLED=0 GOARCH=$2 GOOS=$1 go build \ | ||
-ldflags "-s -w -X main.version=${version}" \ | ||
-mod=readonly \ | ||
-trimpath \ | ||
-o "${outname}" | ||
|
||
if [[ $1 == linux ]]; then | ||
log "=> Packging ${3} as ${3}_${1}_${2}.tgz..." | ||
tar -czf "${builddir}/${3}_${1}_${2}.tgz" "${outname}" | ||
else | ||
log "=> Packging ${3} as ${3}_${1}_${2}.zip..." | ||
zip "${builddir}/${3}_${1}_${2}.zip" "${outname}" | ||
fi | ||
|
||
rm "${outname}" | ||
} | ||
|
||
function go_package_all() { | ||
for oa in "${osarch[@]}"; do | ||
local os=$(cut -d / -f 1 <<<"${oa}") | ||
local arch=$(cut -d / -f 2 <<<"${oa}") | ||
(go_package "${os}" "${arch}" "${1}" "${2}") | ||
done | ||
} | ||
|
||
function log() { | ||
echo "[$(date +%H:%M:%S)] $@" >&2 | ||
} | ||
|
||
root=$(pwd) | ||
builddir="${root}/.build" | ||
version="$(git describe --tags --always || echo dev)" | ||
|
||
log "Building version ${version}..." | ||
|
||
log "Resetting output directory..." | ||
rm -rf "${builddir}" | ||
mkdir -p "${builddir}" | ||
|
||
log "Building API-Server..." | ||
go_package_all "ots" "." | ||
|
||
log "Building OTS-CLI..." | ||
go_package_all "ots-cli" "./cmd/ots-cli" | ||
|
||
log "Generating SHA256SUMS file..." | ||
(cd "${builddir}" && sha256sum * | tee SHA256SUMS) |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ots-cli |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"mime" | ||
"os" | ||
"path" | ||
|
||
"github.com/Luzifer/ots/pkg/client" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var createCmd = &cobra.Command{ | ||
Use: "create [-f file]... [--instance url] [--secret-from file]", | ||
Short: "Create a new encrypted secret in the given OTS instance", | ||
Long: "", | ||
Example: `echo "I'm a very secret secret" | ots-cli create`, | ||
Args: cobra.NoArgs, | ||
RunE: createRunE, | ||
} | ||
|
||
func init() { | ||
createCmd.Flags().Duration("expire", 0, "When to expire the secret (0 to use server-default)") | ||
createCmd.Flags().String("instance", "https://ots.fyi/", "Instance to create the secret with") | ||
createCmd.Flags().StringSliceP("file", "f", nil, "File(s) to attach to the secret") | ||
createCmd.Flags().String("secret-from", "-", `File to read the secret content from ("-" for STDIN)`) | ||
rootCmd.AddCommand(createCmd) | ||
} | ||
|
||
func createRunE(cmd *cobra.Command, _ []string) error { | ||
var secret client.Secret | ||
|
||
// Read the secret content | ||
logrus.Info("reading secret content...") | ||
secretSourceName, err := cmd.Flags().GetString("secret-from") | ||
if err != nil { | ||
return fmt.Errorf("getting secret-from flag: %w", err) | ||
} | ||
|
||
var secretSource io.Reader | ||
if secretSourceName == "-" { | ||
secretSource = os.Stdin | ||
} else { | ||
f, err := os.Open(secretSourceName) //#nosec:G304 // Opening user specified file is intended | ||
if err != nil { | ||
return fmt.Errorf("opening secret-from file: %w", err) | ||
} | ||
defer f.Close() //nolint:errcheck // The file will be force-closed by program exit | ||
secretSource = f | ||
} | ||
|
||
secretContent, err := io.ReadAll(secretSource) | ||
if err != nil { | ||
return fmt.Errorf("reading secret content: %w", err) | ||
} | ||
secret.Secret = string(secretContent) | ||
|
||
// Attach any file given | ||
files, err := cmd.Flags().GetStringSlice("file") | ||
if err != nil { | ||
return fmt.Errorf("getting file flag: %w", err) | ||
} | ||
for _, f := range files { | ||
logrus.WithField("file", f).Info("attaching file...") | ||
content, err := os.ReadFile(f) //#nosec:G304 // Opening user specified file is intended | ||
if err != nil { | ||
return fmt.Errorf("reading attachment %q: %w", f, err) | ||
} | ||
|
||
secret.Attachments = append(secret.Attachments, client.SecretAttachment{ | ||
Name: f, | ||
Type: mime.TypeByExtension(path.Ext(f)), | ||
Content: content, | ||
}) | ||
} | ||
|
||
// Create the secret | ||
logrus.Info("creating the secret...") | ||
instanceURL, err := cmd.Flags().GetString("instance") | ||
if err != nil { | ||
return fmt.Errorf("getting instance flag: %w", err) | ||
} | ||
|
||
expire, err := cmd.Flags().GetDuration("expire") | ||
if err != nil { | ||
return fmt.Errorf("getting expire flag: %w", err) | ||
} | ||
|
||
secretURL, expiresAt, err := client.Create(instanceURL, secret, expire) | ||
if err != nil { | ||
return fmt.Errorf("creating secret: %w", err) | ||
} | ||
|
||
// Tell them where to find the secret | ||
if expiresAt.IsZero() { | ||
logrus.Info("secret created, see URL below") | ||
} else { | ||
logrus.WithField("expires-at", expiresAt).Info("secret created, see URL below") | ||
} | ||
fmt.Println(secretURL) //nolint:forbidigo // Output intended for STDOUT | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"io/fs" | ||
"os" | ||
"path" | ||
"strings" | ||
|
||
"github.com/Luzifer/ots/pkg/client" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
const storeFileMode = 0o600 // We assume the attached file to be a secret | ||
|
||
var fetchCmd = &cobra.Command{ | ||
Use: "fetch url", | ||
Short: "Retrieves a secret from the instance by its URL", | ||
Long: "", | ||
Args: cobra.ExactArgs(1), | ||
RunE: fetchRunE, | ||
} | ||
|
||
func init() { | ||
fetchCmd.Flags().String("file-dir", ".", "Where to put files attached to the secret") | ||
rootCmd.AddCommand(fetchCmd) | ||
} | ||
|
||
func checkDirWritable(dir string) error { | ||
tmpFile := path.Join(dir, ".ots-cli.tmp") | ||
if err := os.WriteFile(tmpFile, []byte(""), storeFileMode); err != nil { | ||
return fmt.Errorf("writing tmp-file: %w", err) | ||
} | ||
defer os.Remove(tmpFile) //nolint:errcheck // We don't really care | ||
|
||
return nil | ||
} | ||
|
||
func fetchRunE(cmd *cobra.Command, args []string) error { | ||
fileDir, err := cmd.Flags().GetString("file-dir") | ||
if err != nil { | ||
return fmt.Errorf("getting file-dir parameter: %w", err) | ||
} | ||
|
||
// First lets check whether we potentially can write files | ||
if err := checkDirWritable(fileDir); err != nil { | ||
return fmt.Errorf("checking for directory write: %w", err) | ||
} | ||
|
||
logrus.Info("fetching secret...") | ||
secret, err := client.Fetch(args[0]) | ||
if err != nil { | ||
return fmt.Errorf("fetching secret") | ||
} | ||
|
||
for _, f := range secret.Attachments { | ||
logrus.WithField("file", f.Name).Info("storing file...") | ||
if err = storeAttachment(fileDir, f); err != nil { | ||
return fmt.Errorf("saving file to disk: %w", err) | ||
} | ||
} | ||
|
||
fmt.Println(secret.Secret) //nolint:forbidigo // Output intended for STDOUT | ||
|
||
return nil | ||
} | ||
|
||
func storeAttachment(dir string, f client.SecretAttachment) error { | ||
// First lets find a free file name to save the file as | ||
var ( | ||
fileNameFragments = strings.SplitN(f.Name, ".", 2) //nolint:gomnd | ||
i int | ||
storeName = path.Join(dir, f.Name) | ||
storeNameTpl string | ||
) | ||
|
||
if len(fileNameFragments) == 1 { | ||
storeNameTpl = fmt.Sprintf("%s (%%d)", fileNameFragments[0]) | ||
} else { | ||
storeNameTpl = fmt.Sprintf("%s (%%d).%s", fileNameFragments[0], fileNameFragments[1]) | ||
} | ||
|
||
for _, err := os.Stat(storeName); !errors.Is(err, fs.ErrNotExist); _, err = os.Stat(storeName) { | ||
i++ | ||
storeName = fmt.Sprintf(storeNameTpl, i) | ||
} | ||
|
||
// So we finally found a filename we can use | ||
if err := os.WriteFile(storeName, f.Content, storeFileMode); err != nil { | ||
return fmt.Errorf("writing file: %w", err) | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.