blob: 5099d02b29684d91c6d9ea2f3adb403d90b930e3 [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"
"crypto/sha256"
"encoding/json"
"log"
"net/http"
"strconv"
"strings"
"go.chromium.org/luci/lucictx"
)
// A mapping of test name to associated secret.
type testSecrets map[string]string
// ServeSecret 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", "application/json")
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)
log.Printf("SHA256 of secret: %x", sha256.Sum256([]byte(secret)))
w.Header().Set("Content-Length", strconv.Itoa(len(secret)))
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 {
swarming := lucictx.GetSwarming(ctx)
if swarming == nil {
return nil
}
secrets := new(testSecrets)
if err := json.Unmarshal(swarming.SecretBytes, secrets); err != nil {
log.Fatalf("secret_bytes provided, but unreadable: %v", err)
}
return secrets
}
// StartSecretsServer starts a server to serve test secrets at localhost:<|port|>.
func StartSecretsServer(ctx context.Context, port int) {
secrets := getSecrets(ctx)
if secrets == nil {
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:
}
}()
}