Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

server: enable H2C for HTTP listeners via CLI flag #2739

Merged
merged 2 commits into from Oct 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/run.go
Expand Up @@ -170,6 +170,7 @@ To skip bundle verification, use the --skip-verify flag.
cmdParams.rt.DiagnosticAddrs = runCommand.Flags().StringSlice("diagnostic-addr", []string{}, "set read-only diagnostic listening address of the server for /health and /metric APIs (e.g., [ip]:<port> for TCP, unix://<path> for UNIX domain socket)")
runCommand.Flags().StringVarP(&cmdParams.rt.InsecureAddr, "insecure-addr", "", "", "set insecure listening address of the server")
runCommand.Flags().MarkDeprecated("insecure-addr", "use --addr instead")
runCommand.Flags().BoolVarP(&cmdParams.rt.H2CEnabled, "h2c", "", false, "enable H2C for HTTP listeners")
runCommand.Flags().StringVarP(&cmdParams.rt.OutputFormat, "format", "f", "pretty", "set shell output format, i.e, pretty, json")
runCommand.Flags().BoolVarP(&cmdParams.rt.Watch, "watch", "w", false, "watch command line files for changes")
addMaxErrorsFlag(runCommand.Flags(), &cmdParams.rt.ErrorLimit)
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Expand Up @@ -29,7 +29,9 @@ require (
github.com/spf13/pflag v0.0.0-20181024212040-082b515c9490
github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b
golang.org/x/lint v0.0.0-20181023182221-1baf3a9d7d67
golang.org/x/net v0.0.0-20200927032502-5d4f70055728
golang.org/x/text v0.3.3 // indirect
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72
gopkg.in/fsnotify.v1 v1.4.7
gopkg.in/yaml.v2 v2.2.1
gopkg.in/yaml.v2 v2.2.1 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Expand Up @@ -61,19 +61,31 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b h1:vVRagRXf67ESqAb72hG2C/ZwI8NtJF2u2V76EsuOHGY=
github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b/go.mod h1:HptNXiXVDcJjXe9SqMd0v2FsL9f8dz4GnXgltU6q/co=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/lint v0.0.0-20181023182221-1baf3a9d7d67 h1:I+72n01vnlWdNIgza2K2Ykpj383VsU74Zg9q6Xmnl9Q=
golang.org/x/lint v0.0.0-20181023182221-1baf3a9d7d67/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200927032502-5d4f70055728 h1:5wtQIAulKU5AbLQOkjxl32UufnIOqgBX72pS0AV14H0=
golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These blow the PR size out of proportion 🙄 No idea what to do about that, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dangers of adding new dependencies! 😆

golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563 h1:NIou6eNFigscvKJmsbyez16S2cIS6idossORlFtSt2E=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh338oozWyiFsBRHtrflcws=
Expand Down
5 changes: 5 additions & 0 deletions runtime/runtime.go
Expand Up @@ -84,6 +84,10 @@ type Params struct {
// in addition to Addr if TLS is enabled.
InsecureAddr string

// H2CEnabled flag controls whether OPA will allow H2C (HTTP/2 cleartext) on
// HTTP listeners.
H2CEnabled bool

// Authentication is the type of authentication scheme to use.
Authentication server.AuthenticationScheme

Expand Down Expand Up @@ -317,6 +321,7 @@ func (rt *Runtime) Serve(ctx context.Context) error {
WithPprofEnabled(rt.Params.PprofEnabled).
WithAddresses(*rt.Params.Addrs).
WithInsecureAddress(rt.Params.InsecureAddr).
WithH2CEnabled(rt.Params.H2CEnabled).
WithCertificate(rt.Params.Certificate).
WithCertPool(rt.Params.CertPool).
WithAuthentication(rt.Params.Authentication).
Expand Down
26 changes: 19 additions & 7 deletions server/server.go
Expand Up @@ -26,8 +26,8 @@ import (

"github.com/gorilla/mux"
"github.com/pkg/errors"

iCache "github.com/open-policy-agent/opa/topdown/cache"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"

"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/bundle"
Expand All @@ -41,6 +41,7 @@ import (
"github.com/open-policy-agent/opa/server/writer"
"github.com/open-policy-agent/opa/storage"
"github.com/open-policy-agent/opa/topdown"
iCache "github.com/open-policy-agent/opa/topdown/cache"
"github.com/open-policy-agent/opa/topdown/lineage"
"github.com/open-policy-agent/opa/util"
"github.com/open-policy-agent/opa/version"
Expand Down Expand Up @@ -82,7 +83,7 @@ const (
const pqMaxCacheSize = 100

// map of unsafe builtins
var unsafeBuiltinsMap = map[string]struct{}{ast.HTTPSend.Name: struct{}{}}
var unsafeBuiltinsMap = map[string]struct{}{ast.HTTPSend.Name: {}}

// Server represents an instance of OPA running in server mode.
type Server struct {
Expand All @@ -93,6 +94,7 @@ type Server struct {
addrs []string
diagAddrs []string
insecureAddr string
h2cEnabled bool
authentication AuthenticationScheme
authorization AuthorizationScheme
cert *tls.Certificate
Expand Down Expand Up @@ -132,7 +134,8 @@ func New() *Server {
return &s
}

// Init initializes the server. This function MUST be called before Loop.
// Init initializes the server. This function MUST be called before starting any loops
// from s.Listeners().
func (s *Server) Init(ctx context.Context) (*Server, error) {
s.initRouters()
s.Handler = s.initHandlerAuth(s.Handler)
Expand Down Expand Up @@ -272,6 +275,12 @@ func (s *Server) WithPprofEnabled(pprofEnabled bool) *Server {
return s
}

// WithH2CEnabled sets whether h2c ("HTTP/2 cleartext") is enabled for the http listener
func (s *Server) WithH2CEnabled(enabled bool) *Server {
s.h2cEnabled = enabled
return s
}

// WithDecisionLogger sets the decision logger used by the
// server. DEPRECATED. Use WithDecisionLoggerWithErr instead.
func (s *Server) WithDecisionLogger(logger func(context.Context, *Info)) *Server {
Expand Down Expand Up @@ -498,13 +507,16 @@ func (s *Server) getListener(addr string, h http.Handler, t httpListenerType) (L
}

func (s *Server) getListenerForHTTPServer(u *url.URL, h http.Handler, t httpListenerType) (Loop, httpListener, error) {
httpServer := http.Server{
if s.h2cEnabled {
h2s := &http2.Server{}
h = h2c.NewHandler(h, h2s)
}
h1s := http.Server{
Addr: u.Host,
Handler: h,
}

l := newHTTPListener(&httpServer, t)

l := newHTTPListener(&h1s, t)
return l.ListenAndServe, l, nil
}

Expand Down
68 changes: 68 additions & 0 deletions test/e2e/h2c/h2c_test.go
@@ -0,0 +1,68 @@
package h2c_test

import (
"crypto/tls"
"flag"
"net"
"net/http"
"os"
"testing"

"golang.org/x/net/http2"

"github.com/open-policy-agent/opa/test/e2e"
)

var testRuntime *e2e.TestRuntime

func TestMain(m *testing.M) {
flag.Parse()
testServerParams := e2e.NewAPIServerTestParams()
testServerParams.Addrs = &[]string{":0"}
testServerParams.DiagnosticAddrs = &[]string{":0"}
testServerParams.InsecureAddr = ":0"
testServerParams.H2CEnabled = true

var err error
testRuntime, err = e2e.NewTestRuntime(testServerParams)
if err != nil {
os.Exit(1)
}

os.Exit(testRuntime.RunTests(m))
}

func TestH2CHTTPListeners(t *testing.T) {
// h2c-enabled client
client := http.Client{
Transport: &http2.Transport{
AllowHTTP: true,
DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) {
return net.Dial(network, addr)
},
},
}

addrs := append(testRuntime.Runtime.Addrs(), testRuntime.Runtime.DiagnosticAddrs()...)

if expected, actual := 3, len(addrs); expected != actual {
t.Fatalf("expected %d addresses, found %d", expected, actual)
}

for _, addr := range addrs {
u := "http://" + addr + "/health"

resp, err := client.Get(u)
if err != nil {
t.Fatalf("failed to GET %s: %s", u, err)
}
defer resp.Body.Close()

if expected, actual := http.StatusOK, resp.StatusCode; expected != actual {
t.Errorf("resp status: expected %d, got %d", expected, actual)
}
if expected, actual := 2, resp.ProtoMajor; expected != actual {
t.Errorf("resp.ProtoMajor: expected %d, got %d", expected, actual)
}
}
}
3 changes: 3 additions & 0 deletions vendor/golang.org/x/net/AUTHORS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions vendor/golang.org/x/net/CONTRIBUTORS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions vendor/golang.org/x/net/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions vendor/golang.org/x/net/PATENTS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions vendor/golang.org/x/net/http/httpguts/guts.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.