Skip to content

Commit

Permalink
initial work for the relay server and client (#1164)
Browse files Browse the repository at this point in the history
* VSecM Relay Client and Server: WIP

* initial work for relay service and also change of links in assets
  • Loading branch information
v0lkan authored Oct 9, 2024
1 parent 0bffb89 commit 84a5ccc
Show file tree
Hide file tree
Showing 30 changed files with 662 additions and 45 deletions.
113 changes: 113 additions & 0 deletions app/relay-client/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package main

import (
"context"
"fmt"
"io/ioutil"
"net/http"
"time"

"github.com/spiffe/go-spiffe/v2/spiffeid"
"github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig"
"github.com/spiffe/go-spiffe/v2/workloadapi"
"github.com/vmware-tanzu/secrets-manager/core/crypto"
"github.com/vmware-tanzu/secrets-manager/core/env"
log "github.com/vmware-tanzu/secrets-manager/core/log/std"
"github.com/vmware-tanzu/secrets-manager/core/validation"
)

func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

cid := crypto.Id()

source, err := workloadapi.NewX509Source(
ctx,
workloadapi.WithClientOptions(
workloadapi.WithAddr(env.SpiffeSocketUrl()),
),
)

if err != nil {
log.FatalLn(&cid, "Unable to fetch X.509 Bundle", err.Error())
return
}

if source == nil {
log.FatalLn(&cid, "Could not find source")
return
}

svid, err := source.GetX509SVID()
if err != nil {
log.FatalLn(&cid, "Unable to get X.509 SVID from source bundle", err.Error())
return
}

if svid == nil {
log.FatalLn(&cid, "Could not find SVID in source bundle")
return
}

svidId := svid.ID
if !validation.IsRelayClient(svidId.String()) {
log.FatalLn(
&cid,
"SpiffeId check: RelayClient:bootstrap: I don't know you, and it's crazy:",
svidId.String(),
)
return
}

authorizer := tlsconfig.AdaptMatcher(func(id spiffeid.ID) error {
if validation.IsRelayServer(id.String()) {
return nil
}

return fmt.Errorf(
"TLS Config: I don't know you, and it's crazy '%s'", id.String(),
)
})

tlsConfig := tlsconfig.MTLSClientConfig(source, source, authorizer)
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
}

serverURL := env.RelayServerUrl()

for {
err := sendPostRequest(client, serverURL, cid)
if err != nil {
log.WarnLn(&cid, "Failed to send POST request:", err.Error())
}

time.Sleep(30 * time.Second) // Wait for 30 seconds before sending the next request
}
}

func sendPostRequest(client *http.Client, url string, cid string) error {
req, err := http.NewRequest("POST", url, nil)
if err != nil {
return fmt.Errorf("failed to create request: %v", err)
}

resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("failed to read response body: %v", err)
}

log.DebugLn(&cid, "Response status:", resp.Status)
log.DebugLn(&cid, "Response body:", string(body))

return nil
}
130 changes: 130 additions & 0 deletions app/relay-server/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package main

import (
"context"
"fmt"
"github.com/spiffe/go-spiffe/v2/spiffeid"
"github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig"
"github.com/spiffe/go-spiffe/v2/workloadapi"
"github.com/vmware-tanzu/secrets-manager/core/env"
"github.com/vmware-tanzu/secrets-manager/core/validation"
s "github.com/vmware-tanzu/secrets-manager/lib/spiffe"
"io"
"net/http"

"github.com/vmware-tanzu/secrets-manager/core/crypto"
log "github.com/vmware-tanzu/secrets-manager/core/log/std"
)

func fallback(
cid string, r *http.Request, w http.ResponseWriter,
) {
log.DebugLn(&cid, "Handler: route mismatch:", r.RequestURI)

w.WriteHeader(http.StatusBadRequest)
_, err := io.WriteString(w, "")
if err != nil {
log.WarnLn(&cid, "Problem writing response:", err.Error())
}
}

func success(
cid string, r *http.Request, w http.ResponseWriter,
) {
w.WriteHeader(http.StatusOK)
_, err := io.WriteString(w, "OK "+r.URL.Path)
if err != nil {
log.WarnLn(&cid, "Problem writing response:", err.Error())
}
}

func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

cid := crypto.Id()

source, err := workloadapi.NewX509Source(
ctx,
workloadapi.WithClientOptions(
workloadapi.WithAddr(env.SpiffeSocketUrl()),
),
)

if err != nil {
log.FatalLn(&cid, "Unable to fetch X.509 Bundle", err.Error())
return
}

if source == nil {
log.FatalLn(&cid, "Could not find source")
return
}

svid, err := source.GetX509SVID()
if err != nil {
log.FatalLn(&cid, "Unable to get X.509 SVID from source bundle", err.Error())
return
}

if svid == nil {
log.FatalLn(&cid, "Could not find SVID in source bundle")
return
}

svidId := svid.ID
if !validation.IsRelayServer(svidId.String()) {
log.FatalLn(
&cid,
"SpiffeId check: RelayServer:bootstrap: I don't know you, and it's crazy:",
svidId.String(),
)
return
}

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
cid := crypto.Id()

validation.EnsureRelayServer(source)

id, err := s.IdFromRequest(r)

if err != nil {
log.WarnLn(&cid, "Handler: blocking insecure svid", id, err)

fallback(cid, r, w)

return
}

sid := s.IdAsString(r)

p := r.URL.Path
m := r.Method
log.DebugLn(
&cid,
"Handler: got svid:", sid, "path", p, "method", m)

success(cid, r, w)
})

authorizer := tlsconfig.AdaptMatcher(func(id spiffeid.ID) error {
if validation.IsRelayClient(id.String()) {
return nil
}

return fmt.Errorf(
"TLS Config: I don't know you, and it's crazy '%s'", id.String(),
)
})

tlsConfig := tlsconfig.MTLSServerConfig(source, source, authorizer)
server := &http.Server{
Addr: env.TlsPort(),
TLSConfig: tlsConfig,
}

if err := server.ListenAndServeTLS("", ""); err != nil {
log.FatalLn(&cid, "Failed to listen and serve", err.Error())
}
}
2 changes: 1 addition & 1 deletion community/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
<>/ keep your secrets... secret
```

See <https://vsecm.com/docs/community/> for information about the **VMware
See <https://vsecm.com/community/hello//> for information about the **VMware
Secrets Manager** community, public events, meetings, and more.
8 changes: 8 additions & 0 deletions core/constants/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ const VSecMSentinelInitCommandPath VarName = "VSECM_SENTINEL_INIT_COMMAND_PATH"
const VSecMSentinelInitCommandWaitAfterInitComplete VarName = "VSECM_SENTINEL_INIT_COMMAND_WAIT_AFTER_INIT_COMPLETE"
const VSecMSentinelInitCommandWaitBeforeExec VarName = "VSECM_SENTINEL_INIT_COMMAND_WAIT_BEFORE_EXEC"

const VSecMRelayServerUrl VarName = "VSECM_RELAY_SERVER_URL"

// See ADR-0017 for a discussion about important security considerations when
// using OIDC.

Expand All @@ -73,6 +75,8 @@ const VSecMSidecarMaxPollInterval VarName = "VSECM_SIDECAR_MAX_POLL_INTERVAL"
const VSecMSidecarPollInterval VarName = "VSECM_SIDECAR_POLL_INTERVAL"
const VSecMSidecarSecretsPath VarName = "VSECM_SIDECAR_SECRETS_PATH"
const VSecMSidecarSuccessThreshold VarName = "VSECM_SIDECAR_SUCCESS_THRESHOLD"
const VSecMSpiffeIdPrefixRelayClient VarName = "VSECM_SPIFFEID_PREFIX_RELAY_CLIENT"
const VSecMSpiffeIdPrefixRelayServer VarName = "VSECM_SPIFFEID_PREFIX_RELAY_SERVER"
const VSecMSpiffeIdPrefixSafe VarName = "VSECM_SPIFFEID_PREFIX_SAFE"
const VSecMSpiffeIdPrefixSentinel VarName = "VSECM_SPIFFEID_PREFIX_SENTINEL"
const VSecMSpiffeIdPrefixWorkload VarName = "VSECM_SPIFFEID_PREFIX_WORKLOAD"
Expand Down Expand Up @@ -115,11 +119,15 @@ const VSecMSidecarMaxPollIntervalDefault VarValue = "300000"
const VSecMSidecarPollIntervalDefault VarValue = "20000"
const VSecMSidecarSecretsPathDefault VarValue = "/opt/vsecm/secrets.json"
const VSecMSidecarSuccessThresholdDefault VarValue = "3"
const VSecMSpiffeIdPrefixRelayClientDefault VarValue = "^spiffe://[^/]/workload/vsecm-relay-client/ns/vsecm-system/sa/vsecm-relay-client/n/[^/]+$"
const VSecMSpiffeIdPrefixRelayServerDefault VarValue = "^spiffe://[^/]/workload/vsecm-relay-server/ns/vsecm-system/sa/vsecm-relay-server/n/[^/]+$"
const VSecMSpiffeIdPrefixSafeDefault VarValue = "^spiffe://vsecm.com/workload/vsecm-safe/ns/vsecm-system/sa/vsecm-safe/n/[^/]+$"
const VSecMSpiffeIdPrefixSentinelDefault VarValue = "^spiffe://vsecm.com/workload/vsecm-sentinel/ns/vsecm-system/sa/vsecm-sentinel/n/[^/]+$"
const VSecMSpiffeIdPrefixWorkloadDefault VarValue = "^spiffe://vsecm.com/workload/[^/]+/ns/[^/]+/sa/[^/]+/n/[^/]+$"
const VSecMNameRegExpForWorkloadDefault VarValue = "^spiffe://vsecm.com/workload/([^/]+)/ns/[^/]+/sa/[^/]+/n/[^/]+$"

const VSecMRelayServerUrlDefault VarValue = "https://vsecm-relay.vsecm-system.svc.cluster.local:443/"

type Namespace string

const Default Namespace = "default"
Expand Down
16 changes: 16 additions & 0 deletions core/env/spiffeid.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ func SpiffeIdPrefixForSafe() string {
return p
}

func SpiffeIdPrefixForRelayServer() string {
p := env.Value(env.VSecMSpiffeIdPrefixRelayServer)
if p == "" {
p = string(env.VSecMSpiffeIdPrefixRelayServerDefault)
}
return p
}

func SpiffeIdPrefixForRelayClient() string {
p := env.Value(env.VSecMSpiffeIdPrefixRelayClient)
if p == "" {
p = string(env.VSecMSpiffeIdPrefixRelayClientDefault)
}
return p
}

// SpiffeIdPrefixForWorkload returns the prefix for the Workload's SPIFFE ID.
// The prefix is obtained from the environment variable
// VSECM_SPIFFEID_PREFIX_WORKLOAD.
Expand Down
8 changes: 8 additions & 0 deletions core/env/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ func TlsPort() string {
}
return p
}

func RelayServerUrl() string {
u := env.Value(env.VSecMRelayServerUrl)
if u == "" {
u = string(env.VSecMRelayServerUrlDefault)
}
return u
}
Loading

0 comments on commit 84a5ccc

Please sign in to comment.