~alazarte/uploader

0453a720e18ccf0d340e1d8c545874aca495a9d9 — Alejandro Lazarte 6 months ago 1261d63
allow secret rotation after each upload instead of timeout

Better to not be guessing how much time has passed since the service
started running. When interval is bigger than zero, rotate after
specified minutes. But when zero, rotate after a successful upload.
1 files changed, 40 insertions(+), 20 deletions(-)

M main.go
M main.go => main.go +40 -20
@@ 13,17 13,23 @@ import (

var (
	outputPath      string
	originalSecret  string
	secretsFilepath string
	secrets         []string
	currentSecret   string
	port            string
	interval        int
	interval        uint

	// secret things
	secretOriginal string
	secrets        []string
	secretCurrent  string
	secretIndex    int
	rot            rotator
)

type test struct{}
type rotator struct {
	rotate func()
}

func (t test) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func upload(w http.ResponseWriter, r *http.Request) {
	// upload only 10 Mb
	if err := r.ParseMultipartForm(10 << 20); err != nil {
		log.Println(err)


@@ 31,8 37,8 @@ func (t test) ServeHTTP(w http.ResponseWriter, r *http.Request) {
		return
	}

	if secret, ok := r.MultipartForm.Value["secret"]; !ok || secret[0] != currentSecret {
		log.Println("invalid secret:", secret[0])
	if secret, ok := r.MultipartForm.Value["secret"]; !ok || secret[0] != secretCurrent {
		log.Println("invalid secret:", secret[0], ", current is:", secretCurrent)
		w.WriteHeader(http.StatusUnauthorized)
		return
	}


@@ 69,6 75,8 @@ func (t test) ServeHTTP(w http.ResponseWriter, r *http.Request) {
			return
		}
		log.Println("save file, size:", n)

		rot.rotate()
	}
}



@@ 76,7 84,7 @@ func init() {
	flag.StringVar(&outputPath, "output", "", "path to where store uploaded files")
	flag.StringVar(&secretsFilepath, "secrets", "", "file with the secrets stored separated with ,: secret1,secret2...")
	flag.StringVar(&port, "port", "8080", "listening port")
	flag.IntVar(&interval, "interval", 3600, "interval between secret rotation in seconds")
	flag.UintVar(&interval, "interval", 0, "if bigger than zero, use as interval between secret rotation in minutes")
	flag.Parse()

	if outputPath == "" || secretsFilepath == "" {


@@ 104,21 112,33 @@ func init() {
	fmt.Println("secrets are:", secrets)

	i := 0
	go func() {
		for {
			if i == len(secrets) {
				i = 0
	if interval > 0 {
		go func() {
			for {
				if i == len(secrets) {
					i = 0
				}
				secretCurrent = secrets[i]
				log.Println("current secret:", secretCurrent)
				time.Sleep(time.Duration(interval) * time.Minute)
				i += 1
			}
			log.Println("current secret:", secrets[i])
			currentSecret = secrets[i]
			time.Sleep(time.Duration(interval) * time.Second)
			i += 1
		}()
		rot.rotate = func() {
			log.Println("fake rotator, current secret is:", secretCurrent)
		}
	}()
	} else {
		rot.rotate = func() {
			secretCurrent = secrets[secretIndex]
			log.Println("current secret:", secretCurrent)
			secretIndex++
		}
	}
	rot.rotate()
}

func main() {
	t := test{}
	log.Printf("listening on port %s\n", port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), t))
	http.HandleFunc("/", upload)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}