Skip to content
This repository has been archived by the owner on Jul 30, 2020. It is now read-only.

Commit

Permalink
rget: server: refactor hostpolicy into a module function
Browse files Browse the repository at this point in the history
the hostpolicy is really critical code so refactor it into a separate
package and add tests.
  • Loading branch information
Brandon Philips committed Aug 1, 2019
1 parent 558be66 commit 46d49a0
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 53 deletions.
58 changes: 5 additions & 53 deletions rget/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ package cmd

import (
"context"
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"

"github.com/spf13/cobra"
githttp "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
Expand Down Expand Up @@ -146,64 +144,18 @@ func server(cmd *cobra.Command, args []string) {
panic(err)
}

hostPolicyNoLog := func(ctx context.Context, host string) (autocert.Policy, error) {
if rgetwellknown.PublicServiceHost == host {
return autocert.Policy{CommonName: host}, nil
}

if !strings.HasSuffix(host, "."+rgetwellknown.PublicServiceHost) {
return autocert.Policy{}, fmt.Errorf("not in TLD %v", rgetwellknown.PublicServiceHost)
}

key := strings.TrimSuffix(host, "."+rgetwellknown.PublicServiceHost)

// Reduce to the shortest domain
parts := strings.Split(key, ".")
if len(parts) == 0 {
return autocert.Policy{}, errors.New("common name empty")
}
key = parts[0]

matches, err := pubgc.Prefix(ctx, key)
if err != nil {
return autocert.Policy{}, err
}

if len(matches) != 1 {
fmt.Printf("unknown merkle prefix %v for %v\n", key, host)
}

content, err := pubgc.Get(ctx, matches[0])
if err != nil {
fmt.Printf("unknown merkle prefix %v for %v\n", key, host)
// TODO(philips): leak a nicer error
return autocert.Policy{}, err
}

sums := rgethash.FromSHA256SumFile(string(content))

p := autocert.Policy{
CommonName: sums.ShortDomain() + "." + rgetwellknown.PublicServiceHost,
DNSNames: []string{
matches[1] + "." + rgetwellknown.PublicServiceHost,
sums.Domain() + "." + rgetwellknown.PublicServiceHost,
},
}

return p, nil
}
hostPolicy := rgethash.HostPolicyFunc(pubgc)

hostPolicy := func(ctx context.Context, host string) (autocert.Policy, error) {
fmt.Printf("hostPolicy called %v\n", host)
policy, err := hostPolicyNoLog(ctx, host)
fmt.Printf("hostPolicy err %v\n", err)
hostPolicyLog := func(ctx context.Context, host string) (autocert.Policy, error) {
policy, err := hostPolicy(ctx, host)
fmt.Printf("hostPolicy: %v err: %v\n", policy, err)
return policy, err
}

m := &autocert.Manager{
Cache: privgc,
Prompt: autocert.AcceptTOS,
HostPolicy: hostPolicy,
HostPolicy: hostPolicyLog,
Email: "letsencrypt@merklecounty.com",
}
s := &http.Server{
Expand Down
69 changes: 69 additions & 0 deletions rgethash/sgethash.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import (
"github.com/google/trillian/merkle"
"github.com/google/trillian/merkle/rfc6962"
"golang.org/x/net/context/ctxhttp"

"github.com/merklecounty/rget/autocert"
"github.com/merklecounty/rget/gitcache"
"github.com/merklecounty/rget/rgetwellknown"
)

type URLSum struct {
Expand Down Expand Up @@ -120,3 +124,68 @@ func readerDigest(r io.Reader) (sum []byte, err error) {

return sum, nil
}

var (
ErrCommonNameEmpty error
ErrUnknownMerklePrefix error
)

func init() {
ErrCommonNameEmpty = fmt.Errorf("common name empty")
ErrUnknownMerklePrefix = fmt.Errorf("unknown merkle prefix")
}

// HostPolicyFunc returns a HostPolicy that returns Policies
// based on Sums that exist in the GitCache repo
func HostPolicyFunc(pubgc *gitcache.GitCache) autocert.HostPolicy {
hostPolicy := func(ctx context.Context, host string) (autocert.Policy, error) {
if rgetwellknown.PublicServiceHost == host {
return autocert.Policy{CommonName: host}, nil
}

if !strings.HasSuffix(host, "."+rgetwellknown.PublicServiceHost) {
return autocert.Policy{}, fmt.Errorf("not in TLD %v", rgetwellknown.PublicServiceHost)
}

key := strings.TrimSuffix(host, "."+rgetwellknown.PublicServiceHost)

// Reduce to the shortest domain
parts := strings.Split(key, ".")
if len(parts) == 0 {
return autocert.Policy{}, ErrCommonNameEmpty
}
key = parts[0]

matches, err := pubgc.Prefix(ctx, key)
if err != nil {
return autocert.Policy{}, err
}

fmt.Printf("%v %v\n", matches, len(matches))

if len(matches) != 1 {
return autocert.Policy{}, ErrUnknownMerklePrefix
}

content, err := pubgc.Get(ctx, matches[0])
if err != nil {
fmt.Printf("unknown merkle prefix %v for %v\n", key, host)
// TODO(philips): leak a nicer error
return autocert.Policy{}, err
}

sums := FromSHA256SumFile(string(content))

p := autocert.Policy{
CommonName: sums.ShortDomain() + "." + rgetwellknown.PublicServiceHost,
DNSNames: []string{
matches[0] + "." + rgetwellknown.PublicServiceHost,
sums.Domain() + "." + rgetwellknown.PublicServiceHost,
},
}

return p, nil
}

return hostPolicy
}
86 changes: 86 additions & 0 deletions rgethash/sgethash_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package rgethash

import (
"context"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"testing"

"github.com/merklecounty/rget/autocert"
"github.com/merklecounty/rget/gitcache"
"github.com/merklecounty/rget/internal/testutil"
"github.com/merklecounty/rget/rgetwellknown"
)

func TestDomain(t *testing.T) {
Expand All @@ -28,3 +38,79 @@ func TestDomain(t *testing.T) {
}
}
}

func TestHostPolicy(t *testing.T) {
testCases := []struct {
put bool
input string
value []byte
expect autocert.Policy
wantErr error
}{
{
true,
"cd83cf8f413393d30d53626c5f17f9ae.af90c0ab70bffa127b54cdb82d3c1499.v0-0-6.rget.merklecounty.github.com",
[]byte(`d4cb7fc206cbd147b3397c1e1b88513831c9780fc9675bebc300112365979465 rget-v0.0.6-linux-arm.tar.gz
7239591ab580c911738130cc62d8a5cd9c6c05c79fa7abfdf32bad0d68a70844 rget-v0.0.6-windows-amd64.tar.gz
18908181de67376c12b7e34de7c3e4aeaddc24cebab8c7d8115cf31dfbe236f2 rget-v0.0.6-linux-amd64.tar.gz
38c6ee23c7f5fbdc7ef207dda25d8e030c8300fa94d71b6b4adc878af9343ba8 rget-v0.0.6-linux-arm64.tar.gz
5b64ee638b847ca72dc1d029437d69e987d439ff420135241687975c6ca2484a rget-v0.0.6-darwin-amd64.tar.gz`),
autocert.Policy{
CommonName: "cd83cf8f413393d30d53626c5f17f9ae.recorder.merklecounty.com",
DNSNames: []string{
"cd83cf8f413393d30d53626c5f17f9ae.af90c0ab70bffa127b54cdb82d3c1499.v0-0-6.rget.merklecounty.github.com.recorder.merklecounty.com",
"cd83cf8f413393d30d53626c5f17f9ae.af90c0ab70bffa127b54cdb82d3c1499.recorder.merklecounty.com",
},
},
nil,
},
{
false,
"67568fff9faa4928c8bd4dd4aeb1a31d.74e766a21475966740ecbf12685e6821cd83cf8f413393d30d53626c5f17f9ae.af90c0ab70bffa127b54cdb82d3c1499.v0-0-6.rget.merklecounty.github.com",
[]byte{1},
autocert.Policy{},
ErrUnknownMerklePrefix,
},
}

dir, err := ioutil.TempDir("", "TestHostPolicy")
if err != nil {
t.Fatal(err)
}
os.RemoveAll(dir)

url := filepath.Join(dir, "repo")

gitURL := testutil.EmptyGitRepo(t, url)

gc, err := gitcache.NewGitCache(gitURL, nil, filepath.Join(dir, "cache"))
if err != nil {
t.Fatal(err)
}

hp := HostPolicyFunc(gc)

ctx := context.Background()

for ti, tt := range testCases {
if tt.put {
if err := gc.Put(ctx, tt.input, tt.value); err != nil {
t.Errorf("%d: put domain %v: %v", ti, tt.input, err)
}
}

p, err := hp(ctx, tt.input+"."+rgetwellknown.PublicServiceHost)
switch {
case err != tt.wantErr:
t.Fatalf("%d: want %v got %v %v", ti, tt.wantErr, err, p)
case tt.wantErr != nil:
continue
case err != nil:
t.Errorf("%d: policy %v: %v", ti, tt.input, err)
}

if !reflect.DeepEqual(tt.expect, p) {
t.Errorf("%d: policies don't match want\n\t%v\n got\n\t%v\n", ti, tt.expect, p)
}
}
}

0 comments on commit 46d49a0

Please sign in to comment.