mirror of
https://github.com/openfaas/faasd.git
synced 2025-06-21 08:26:32 +00:00
Adds secrets support and binding of secrets at runtime to functions. Files are written in plain-text to a 0644 permission folder which can only be read by root and the containers requesting the secret through the OpenFaaS API. Tested by deploying an alpine function using "cat" as its fprocess. Happy to revisit at a later date and look into encryption at rest. This should be on-par with using Kubernetes in its default unencrypted state. Fixes: #29 Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
79 lines
2.0 KiB
Go
79 lines
2.0 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/alexellis/faasd/pkg/service"
|
|
"github.com/containerd/containerd"
|
|
"github.com/containerd/containerd/namespaces"
|
|
gocni "github.com/containerd/go-cni"
|
|
"github.com/openfaas/faas-provider/types"
|
|
)
|
|
|
|
func MakeUpdateHandler(client *containerd.Client, cni gocni.CNI, secretMountPath string) func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if r.Body == nil {
|
|
http.Error(w, "expected a body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
body, _ := ioutil.ReadAll(r.Body)
|
|
log.Printf("[Update] request: %s\n", string(body))
|
|
|
|
req := types.FunctionDeployment{}
|
|
err := json.Unmarshal(body, &req)
|
|
if err != nil {
|
|
log.Printf("[Update] error parsing input: %s\n", err)
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
|
|
return
|
|
}
|
|
name := req.Service
|
|
|
|
function, err := GetFunction(client, name)
|
|
if err != nil {
|
|
msg := fmt.Sprintf("service %s not found", name)
|
|
log.Printf("[Update] %s\n", msg)
|
|
http.Error(w, msg, http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
err = validateSecrets(secretMountPath, req.Secrets)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
}
|
|
|
|
ctx := namespaces.WithNamespace(context.Background(), FunctionNamespace)
|
|
if function.replicas != 0 {
|
|
err = DeleteCNINetwork(ctx, cni, client, name)
|
|
if err != nil {
|
|
log.Printf("[Update] error removing CNI network for %s, %s\n", name, err)
|
|
}
|
|
}
|
|
|
|
containerErr := service.Remove(ctx, client, name)
|
|
if containerErr != nil {
|
|
log.Printf("[Update] error removing %s, %s\n", name, containerErr)
|
|
http.Error(w, containerErr.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
deployErr := deploy(ctx, req, client, cni, secretMountPath)
|
|
if deployErr != nil {
|
|
log.Printf("[Update] error deploying %s, error: %s\n", name, deployErr)
|
|
http.Error(w, deployErr.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
}
|
|
|
|
}
|