Skip to content

Commit

Permalink
Merge pull request #321 from ampproject/master
Browse files Browse the repository at this point in the history
Snapshot version 2 from master.
  • Loading branch information
twifkak authored Jun 18, 2019
2 parents fadd618 + 4e25755 commit 581d266
Show file tree
Hide file tree
Showing 94 changed files with 3,835 additions and 1,855 deletions.
24 changes: 9 additions & 15 deletions Gopkg.lock

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

2 changes: 2 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
# unused-packages = true


ignored = ["google.golang.org/grpc"]

[prune]
go-tests = true
unused-packages = true
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,21 @@ that:
possible for attackers to exploit it without intercepting the network path,
for up to 7 days.

#### Testing productionization without a valid certificate

It is possible to test an otherwise fully production configuration without
obtaining a certificate with the `CanSignHttpExchanges` extension. `amppkg`
still needs to perform OCSP verification, so the Issuer CA must be valid (i.e. no
self-signed certificates). e.g. You can use a certificate from [Let's Encrypt](https://letsencrypt.org/).

Running `amppkg` with the `-invalidcert` flag will skip the check for
`CanSignHttpExchanges`. This flag is not necessary when using the
`-development` flag.

Chrome can be configured to allow these invalid certificates with the
*Allow Signed HTTP Exchange certificates without extension* experiment:
chrome://flags/#allow-sxg-certs-without-extension

#### Redundancy

If you need to load balance across multiple instances of `amppkg`, you'll want
Expand Down
10 changes: 8 additions & 2 deletions amppkg.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,16 @@ CertFile = './pems/cert.pem'
KeyFile = './pems/privkey.pem'

# The path to a file where the OCSP response will be cached. The parent
# directory should exist, but the file need not. If this is a network-mounted
# file, it should support shared/exclusive locking.
# directory should exist, but the file need not. A dedicated lock file will be
# created in the same directory as this file, sharing the same name but with
# extension .lock appended. The filesystem must support shared and exclusive
# locking; consider this especially when utilizing network-mounted storage.
OCSPCache = '/tmp/amppkg-ocsp'

# The list of request header names to be forwarded in a fetch request.
# Hop-by-hop headers, conditional request headers and Via cannot be included.
ForwardedRequestHeaders = []

# This is a simple level of validation, to guard against accidental
# misconfiguration of the reverse proxy that sits in front of the packager.
#
Expand Down
42 changes: 24 additions & 18 deletions cmd/amppkg/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ import (
"log"
"net/http"
"net/url"
"path"
"time"

"github.com/WICG/webpackage/go/signedexchange"
"github.com/julienschmidt/httprouter"
"github.com/pkg/errors"

"github.com/ampproject/amppackager/packager/certcache"
"github.com/ampproject/amppackager/packager/mux"
"github.com/ampproject/amppackager/packager/rtv"
"github.com/ampproject/amppackager/packager/signer"
"github.com/ampproject/amppackager/packager/util"
"github.com/ampproject/amppackager/packager/validitymap"
"github.com/ampproject/amppackager/packager/rtv"
)

var flagConfig = flag.String("config", "amppkg.toml", "Path to the config toml file.")
var flagDevelopment = flag.Bool("development", false, "True if this is a development server.")
var flagInvalidCert = flag.Bool("invalidcert", false, "True if invalid certificate intentionally used in production.")

// Prints errors returned by pkg/errors with stack traces.
func die(err interface{}) { log.Fatalf("%+v", err) }
Expand Down Expand Up @@ -90,16 +90,25 @@ func main() {
if certs == nil || len(certs) == 0 {
die(fmt.Sprintf("no cert found in %s", config.CertFile))
}
if !*flagDevelopment && !util.CanSignHttpExchanges(certs[0]) {
die("cert is missing CanSignHttpExchanges extension")
if err := util.CanSignHttpExchanges(certs[0], time.Now()); err != nil {
if *flagDevelopment || *flagInvalidCert {
log.Println("WARNING:", err)
} else {
die(err)
}
}
// TODO(twifkak): Verify that certs[0] covers all the signing domains in the config.

key, err := util.ParsePrivateKey(keyPem)
if err != nil {
die(errors.Wrapf(err, "parsing %s", config.KeyFile))
}
// TODO(twifkak): Verify that key matches certs[0].

for _, urlSet := range config.URLSet {
domain := urlSet.Sign.Domain
if err := util.CertificateMatches(certs[0], key, domain); err != nil {
die(errors.Wrapf(err, "checking %s", config.CertFile))
}
}

validityMap, err := validitymap.New()
if err != nil {
Expand All @@ -125,20 +134,14 @@ func main() {
}
}

packager, err := signer.New(certs[0], key, config.URLSet, rtvCache, certCache.IsHealthy,
overrideBaseURL, /*requireHeaders=*/!*flagDevelopment)
signer, err := signer.New(certs[0], key, config.URLSet, rtvCache, certCache.IsHealthy,
overrideBaseURL, /*requireHeaders=*/!*flagDevelopment, config.ForwardedRequestHeaders)
if err != nil {
die(errors.Wrap(err, "building packager"))
die(errors.Wrap(err, "building signer"))
}

// TODO(twifkak): Make log output configurable.
mux := httprouter.New()
mux.RedirectTrailingSlash = false
mux.RedirectFixedPath = false
mux.GET(util.ValidityMapPath, validityMap.ServeHTTP)
mux.GET("/priv/doc", packager.ServeHTTP)
mux.GET("/priv/doc/*signURL", packager.ServeHTTP)
mux.GET(path.Join(util.CertURLPrefix, ":certName"), certCache.ServeHTTP)

addr := ""
if config.LocalOnly {
addr = "localhost"
Expand All @@ -148,7 +151,7 @@ func main() {
Addr: addr,
// Don't use DefaultServeMux, per
// https://blog.cloudflare.com/exposing-go-on-the-internet/.
Handler: logIntercept{mux},
Handler: logIntercept{mux.New(certCache, signer, validityMap)},
ReadTimeout: 10 * time.Second,
ReadHeaderTimeout: 5 * time.Second,
// If needing to stream the response, disable WriteTimeout and
Expand All @@ -170,6 +173,9 @@ func main() {
if *flagDevelopment {
log.Println("WARNING: Running in development, using SXG key for TLS. This won't work in production.")
log.Fatal(server.ListenAndServeTLS(config.CertFile, config.KeyFile))
} else if *flagInvalidCert {
log.Println("WARNING: Running in production without valid signing certificate. Signed exchanges will not be valid.")
log.Fatal(server.ListenAndServe())
} else {
log.Fatal(server.ListenAndServe())
}
Expand Down
5 changes: 5 additions & 0 deletions cmd/gateway_server/gateway/compile_proto.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh

export PATH=$PATH:$HOME/go/bin/

protoc -I . ./gateway.proto --go_out=plugins=grpc:. --proto_path .
Loading

0 comments on commit 581d266

Please sign in to comment.