blob: 696f9e3611c5be44e778b9272b1a9139b43e1f7c [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package secrets
import (
"context"
"encoding/json"
"fmt"
"go.chromium.org/luci/lucictx"
"log"
"net/http"
"strconv"
"strings"
)
// A mapping of test name to associated secret.
type testSecrets map[string]string
// Serves the secret associated to a test, where the request's URL is of the
// form "/<test name>".
func (secrets testSecrets) serveSecret(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
testName := strings.TrimPrefix(r.URL.Path, "/")
secret, ok := secrets[testName]
if !ok {
log.Printf("There is no secret to serve for \"%s\"\n", testName)
w.WriteHeader(http.StatusNotFound)
return
}
log.Printf("Serving secret for \"%s\"\n", testName)
w.WriteHeader(http.StatusOK)
w.Write([]byte(secret))
}
// Parses out tests secrets serialized in the LUCI_CONTEXT JSON under the
// "secret_bytes" key.
func getSecrets(ctx context.Context) (*testSecrets, error) {
swarming := lucictx.GetSwarming(ctx)
if swarming == nil {
return nil, fmt.Errorf("GetSwarming() returned a null value.")
}
secrets := new(testSecrets)
err := json.Unmarshal(swarming.SecretBytes, secrets)
return secrets, err
}
// Starts a server to serve test secrets at localhost:<|port|>.
func StartSecretsServer(ctx context.Context, port int) {
secrets, err := getSecrets(ctx)
if err != nil {
log.Printf("Unable to find secrets: %v\n", err)
return
}
log.Printf("Setting up secrets server at localhost:%d\n", port)
s := &http.Server{
Addr: ":" + strconv.Itoa(port),
Handler: http.HandlerFunc(secrets.serveSecret),
}
go func() {
if err := s.ListenAndServe(); err != nil {
log.Print(err)
}
}()
go func() {
select {
case <-ctx.Done():
log.Printf("Shutting down secrets server at localhost:%d\n", port)
if err := s.Shutdown(context.Background()); err != nil {
log.Print(err)
}
default:
}
}()
}