57 lines
1.8 KiB
Go
57 lines
1.8 KiB
Go
package runnerbootstrap
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httputil"
|
|
"net/url"
|
|
|
|
"github.com/spiffe/go-spiffe/v2/spiffeid"
|
|
"github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig"
|
|
"github.com/spiffe/go-spiffe/v2/workloadapi"
|
|
)
|
|
|
|
type Proxy struct {
|
|
Handler http.Handler
|
|
source *workloadapi.X509Source
|
|
}
|
|
|
|
// NewProxy obtains rotating X509-SVIDs from the Workload API and authorizes
|
|
// one exact controller identity. The official Runner talks plain HTTP only to
|
|
// this executor-local handler.
|
|
func NewProxy(ctx context.Context, facadeURL, facadeSPIFFEID, workloadAPIAddr string) (*Proxy, error) {
|
|
target, err := url.Parse(facadeURL)
|
|
if err != nil || target.Scheme != "https" || target.Host == "" {
|
|
return nil, fmt.Errorf("runner facade URL must be an absolute https URL")
|
|
}
|
|
serverID, err := spiffeid.FromString(facadeSPIFFEID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parse runner facade SPIFFE ID: %w", err)
|
|
}
|
|
options := []workloadapi.X509SourceOption{}
|
|
if workloadAPIAddr != "" {
|
|
options = append(options, workloadapi.WithClientOptions(workloadapi.WithAddr(workloadAPIAddr)))
|
|
}
|
|
source, err := workloadapi.NewX509Source(ctx, options...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("open SPIFFE Workload API X509 source: %w", err)
|
|
}
|
|
transport := http.DefaultTransport.(*http.Transport).Clone()
|
|
transport.TLSClientConfig = tlsconfig.MTLSClientConfig(source, source, tlsconfig.AuthorizeID(serverID))
|
|
return &Proxy{Handler: NewProxyHandler(target, transport), source: source}, nil
|
|
}
|
|
|
|
func NewProxyHandler(target *url.URL, transport http.RoundTripper) http.Handler {
|
|
proxy := httputil.NewSingleHostReverseProxy(target)
|
|
proxy.Transport = transport
|
|
return proxy
|
|
}
|
|
|
|
func (p *Proxy) Close() error {
|
|
if p == nil || p.source == nil {
|
|
return nil
|
|
}
|
|
return p.source.Close()
|
|
}
|