Support requiring TLS for API access
Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
@@ -117,7 +117,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{MinVersion: tls.VersionTLS13}
|
||||
if conf.Warewulf.EnableTLS() {
|
||||
if conf.Warewulf.TLSEnabled() {
|
||||
caCert, err := os.ReadFile("/warewulf/tls/warewulf.crt")
|
||||
if err != nil {
|
||||
wwlog.Error("failed to read ca cert: %s", err)
|
||||
@@ -260,7 +260,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
||||
|
||||
port := conf.Warewulf.Port
|
||||
scheme := "http"
|
||||
if conf.Warewulf.EnableTLS() {
|
||||
if conf.Warewulf.TLSEnabled() {
|
||||
port = conf.Warewulf.TlsPort
|
||||
scheme = "https"
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !conf.Warewulf.EnableTLS() {
|
||||
if !conf.Warewulf.TLSEnabled() {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "TLS is not enabled in warewulf.conf\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ func (n IPNet) IPNet() net.IPNet {
|
||||
|
||||
type APIConf struct {
|
||||
EnabledP *bool `yaml:"enabled,omitempty" default:"false"`
|
||||
TLSEnabledP *bool `yaml:"tls,omitempty"`
|
||||
AllowedNets []IPNet `yaml:"allowed subnets,omitempty" default:"[\"127.0.0.0/8\", \"::1/128\"]"`
|
||||
}
|
||||
|
||||
@@ -49,3 +50,7 @@ func (conf *APIConf) Unmarshal(unmarshal func(interface{}) error) error {
|
||||
func (conf APIConf) Enabled() bool {
|
||||
return util.BoolP(conf.EnabledP)
|
||||
}
|
||||
|
||||
func (conf APIConf) TLSEnabled() bool {
|
||||
return util.BoolP(conf.TLSEnabledP)
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ type WarewulfConf struct {
|
||||
Port int `yaml:"port,omitempty" default:"9873"`
|
||||
TlsPort int `yaml:"tls port,omitempty" default:"9874"`
|
||||
SecureP *bool `yaml:"secure,omitempty" default:"true"`
|
||||
EnableTLSP *bool `yaml:"tls,omitempty" default:"false"`
|
||||
TLSEnabledP *bool `yaml:"tls,omitempty"`
|
||||
UpdateInterval int `yaml:"update interval,omitempty" default:"60"`
|
||||
AutobuildOverlaysP *bool `yaml:"autobuild overlays,omitempty" default:"true"`
|
||||
EnableHostOverlayP *bool `yaml:"host overlay,omitempty" default:"true"`
|
||||
@@ -56,8 +56,8 @@ func (conf WarewulfConf) Secure() bool {
|
||||
return util.BoolP(conf.SecureP)
|
||||
}
|
||||
|
||||
func (conf WarewulfConf) EnableTLS() bool {
|
||||
return util.BoolP(conf.EnableTLSP)
|
||||
func (conf WarewulfConf) TLSEnabled() bool {
|
||||
return util.BoolP(conf.TLSEnabledP)
|
||||
}
|
||||
|
||||
func (conf WarewulfConf) AutobuildOverlays() bool {
|
||||
|
||||
@@ -17,7 +17,6 @@ func TestParse(t *testing.T) {
|
||||
result: `
|
||||
warewulf:
|
||||
autobuild overlays: true
|
||||
tls: false
|
||||
grubboot: false
|
||||
host overlay: true
|
||||
port: 9873
|
||||
@@ -65,7 +64,6 @@ network: 192.168.0.0
|
||||
netmask: 255.255.255.0
|
||||
warewulf:
|
||||
autobuild overlays: true
|
||||
tls: false
|
||||
grubboot: false
|
||||
host overlay: true
|
||||
port: 9873
|
||||
@@ -115,7 +113,6 @@ network: 192.168.0.0
|
||||
netmask: 255.255.0.0
|
||||
warewulf:
|
||||
autobuild overlays: true
|
||||
tls: false
|
||||
grubboot: false
|
||||
host overlay: true
|
||||
port: 9873
|
||||
@@ -162,7 +159,6 @@ ipaddr6: "2001:db8::1"
|
||||
prefixlen6: "64"
|
||||
warewulf:
|
||||
autobuild overlays: true
|
||||
tls: false
|
||||
grubboot: false
|
||||
host overlay: true
|
||||
port: 9873
|
||||
@@ -238,7 +234,6 @@ netmask: 255.255.255.0
|
||||
network: 192.168.200.0
|
||||
warewulf:
|
||||
autobuild overlays: true
|
||||
tls: false
|
||||
grubboot: false
|
||||
host overlay: true
|
||||
port: 9873
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
// Returns true if new keys were generated.
|
||||
func TLS(force bool) (bool, error) {
|
||||
conf := warewulfconf.Get()
|
||||
if !conf.Warewulf.EnableTLS() {
|
||||
if !conf.Warewulf.TLSEnabled() {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ func buildTemplateVars(conf *warewulfconf.WarewulfYaml, rinfo parsedRequest, rem
|
||||
Ipaddr: conf.Ipaddr,
|
||||
Ipaddr6: ipaddr6,
|
||||
Port: strconv.Itoa(conf.Warewulf.Port),
|
||||
TLS: conf.Warewulf.EnableTLS(),
|
||||
TLS: conf.Warewulf.TLSEnabled(),
|
||||
Authority: authority,
|
||||
Hostname: remoteNode.Id(),
|
||||
Hwaddr: rinfo.hwaddr,
|
||||
|
||||
@@ -95,7 +95,7 @@ func HandleSystemOverlay(w http.ResponseWriter, req *http.Request) {
|
||||
// If TLS is enabled, returns 403 Forbidden for plain-HTTP requests.
|
||||
// If an explicit ?overlay= list is present, delegates to HandleOverlayList.
|
||||
func HandleRuntimeOverlay(w http.ResponseWriter, req *http.Request) {
|
||||
if config.Get().Warewulf.EnableTLS() && req.TLS == nil {
|
||||
if config.Get().Warewulf.TLSEnabled() && req.TLS == nil {
|
||||
wwlog.Denied("runtime overlay requested over insecure connection")
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
|
||||
@@ -37,6 +37,17 @@ func (h *slashFix) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.mux.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func requireTLS(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.TLS == nil {
|
||||
wwlog.Denied("API request over insecure connection")
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func configureRootHandler(apiHandler http.Handler) *slashFix {
|
||||
var wwHandler http.ServeMux
|
||||
wwHandler.HandleFunc("/provision/", warewulfd.HandleProvision)
|
||||
@@ -89,13 +100,16 @@ func RunServer() error {
|
||||
var apiHandler http.Handler
|
||||
if conf.API != nil && conf.API.Enabled() {
|
||||
apiHandler = api.Handler(auth, conf.API.AllowedIPNets())
|
||||
if conf.API.TLSEnabled() {
|
||||
apiHandler = requireTLS(apiHandler)
|
||||
}
|
||||
}
|
||||
|
||||
httpHandler := configureRootHandler(apiHandler)
|
||||
|
||||
errChan := make(chan error, 2)
|
||||
|
||||
if conf.Warewulf.EnableTLS() {
|
||||
if conf.Warewulf.TLSEnabled() {
|
||||
key := path.Join(conf.Paths.Sysconfdir, "warewulf", "tls", "warewulf.key")
|
||||
crt := path.Join(conf.Paths.Sysconfdir, "warewulf", "tls", "warewulf.crt")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user