Exemple #1
0
func (self *App) Init(config *Config) {
	self.config = config
	tableConfigs := []*table.TableConfig{}
	for _, tableConfig := range config.TableConfigs {
		tableConfigs = append(tableConfigs, &table.TableConfig{
			Name:     tableConfig.Name,
			SqlQuery: tableConfig.SqlQuery,
		})
	}
	self.TableService.Init(tableConfigs, neturl.URL(config.Url), config.User, config.Password)
	app.web.ResetHandlers()
	app.web.Register("/", &TableController{})
	app.web.Register("/", NewPortalController(neturl.URL(config.Url)))
}
Exemple #2
0
func (ep forwardEndpoint) Handler(templates *template.Template, ci inject.CopyInject) httpctx.Handler {
	u := url.URL(ep)
	rp := reverseproxy.NewSingleHostReverseProxy(&u, ci)
	rp.Transport = &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	return rp
}
Exemple #3
0
func (u Url) Validate() report.Report {
	// Empty url is valid, indicates an empty file
	if u.String() == "" {
		return report.Report{}
	}
	switch url.URL(u).Scheme {
	case "http", "https", "oem", "data":
		return report.Report{}
	}

	return report.ReportFromError(ErrInvalidScheme, report.EntryError)
}
Exemple #4
0
func (c *Config) Configure() func(*http.Request, *cache.Datalog) (http.Header, url.URL) {
	return func(req *http.Request, datalog *cache.Datalog) (http.Header, url.URL) {
		if req.TLS != nil {
			datalog.TLS = true
		}

		d := new(types.FQDN)
		d.Set(req.Host)
		servable, _ := c.SearchServable(d.PathToRoot())

		datalog.Owner = servable.Owner
		datalog.Project = servable.Project
		datalog.Vhost = servable.Zone

		header := make(http.Header)
		header.Set("X-Frame-Options", servable.XFO)
		header.Set("X-Content-Type-Options", servable.XCTO)
		header.Set("X-Download-Options", servable.XDO)
		header.Set("X-XSS-Protection", servable.XXSSP)
		//header.Set("Content-Security-Policy",servable.CSP)

		if req.TLS != nil {
			header.Set("Strict-Transport-Security", servable.HSTS)
			if servable.PKP != "" {
				header.Set("Public-Key-Pins", servable.PKP)
			}
		}

		default_proxy := url.URL(c.Proxied)
		candidat_proxy := url.URL(servable.Proxied)
		if candidat_proxy.Host == "" {
			return header, default_proxy
		}
		return header, candidat_proxy
	}
}
Exemple #5
0
func (u Url) Validate() report.Report {
	// Empty url is valid, indicates an empty file
	if u.String() == "" {
		return report.Report{}
	}
	switch url.URL(u).Scheme {
	case "http", "https", "oem":
		return report.Report{}
	case "data":
		if _, err := dataurl.DecodeString(u.String()); err != nil {
			return report.ReportFromError(err, report.EntryError)
		}
		return report.Report{}
	default:
		return report.ReportFromError(ErrInvalidScheme, report.EntryError)
	}
}
Exemple #6
0
// fetchReferencedConfig fetches, renders, and attempts to verify the requested
// config.
func (e Engine) fetchReferencedConfig(cfgRef types.ConfigReference) (types.Config, error) {
	rawCfg, err := util.FetchResource(e.Logger, url.URL(cfgRef.Source))
	if err != nil {
		return types.Config{}, err
	}

	if err := util.AssertValid(cfgRef.Verification, rawCfg); err != nil {
		return types.Config{}, err
	}

	cfg, err := config.Parse(rawCfg)
	if err != nil {
		return types.Config{}, err
	}

	return e.renderConfig(cfg)
}
Exemple #7
0
func RenderFile(l *log.Logger, f types.File) *File {
	var contents []byte
	var err error

	fetch := func() error {
		contents, err = util.FetchResource(l, url.URL(f.Contents.Source))
		return err
	}

	validate := func() error {
		return util.AssertValid(f.Contents.Verification, contents)
	}

	decompress := func() error {
		contents, err = decompressFile(l, f, contents)
		return err
	}

	if l.LogOp(fetch, "fetching file %q", f.Path) != nil {
		return nil
	}
	if l.LogOp(validate, "validating file contents") != nil {
		return nil
	}
	if l.LogOp(decompress, "decompressing file contents") != nil {
		return nil
	}

	return &File{
		Path:     f.Path,
		Contents: []byte(contents),
		Mode:     os.FileMode(f.Mode),
		Uid:      f.User.Id,
		Gid:      f.Group.Id,
	}
}
Exemple #8
0
// Loads state.json from mesos master
func (rg *RecordGenerator) loadFromMaster(ip, port string) (state.State, error) {
	// REFACTOR: state.json security

	var sj state.State
	u := url.URL(rg.stateEndpoint.With(urls.Host(net.JoinHostPort(ip, port))))

	req, err := http.NewRequest("GET", u.String(), nil)
	if err != nil {
		logging.Error.Println(err)
		return state.State{}, err
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("User-Agent", "Mesos-DNS")

	resp, err := rg.httpClient.Do(req)
	if err != nil {
		logging.Error.Println(err)
		return state.State{}, err
	}

	defer errorutil.Ignore(resp.Body.Close)
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logging.Error.Println(err)
		return state.State{}, err
	}

	err = json.Unmarshal(body, &sj)
	if err != nil {
		logging.Error.Println(err)
		return state.State{}, err
	}

	return sj, nil
}
Exemple #9
0
func (ep forwardEndpoint) Handler(templates *template.Template, ci inject.CopyInject) httpctx.Handler {
	u := url.URL(ep)
	return reverseproxy.NewSingleHostReverseProxy(&u, ci)
}
Exemple #10
0
func (u URL) String() string {
	uu := url.URL(u)
	return uu.String()
}
Exemple #11
0
// String implements flag.Value.
func (f logFormatFlag) String() string {
	u := url.URL(f)
	return fmt.Sprintf("%q", u.String())
}
Exemple #12
0
func (u Url) String() string {
	tu := url.URL(u)
	return (&tu).String()
}
Exemple #13
0
func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.ResponseWriter, request *http.Request) {
	// Check that the requested challenge exists within the authorization
	found := false
	var challengeIndex int
	for i, challenge := range authz.Challenges {
		tempURL := url.URL(challenge.URI)
		if tempURL.Path == request.URL.Path && tempURL.RawQuery == request.URL.RawQuery {
			found = true
			challengeIndex = i
			break
		}
	}

	if !found {
		wfe.sendError(response, "Unable to find challenge", request.URL.RawQuery, http.StatusNotFound)
		return
	}

	switch request.Method {
	default:
		wfe.sendError(response, "Method not allowed", "", http.StatusMethodNotAllowed)
		return

	case "POST":
		body, _, currReg, err := wfe.verifyPOST(request, true)
		if err != nil {
			if err == sql.ErrNoRows {
				wfe.sendError(response, "No registration exists matching provided key", err, http.StatusForbidden)
			} else {
				wfe.sendError(response, "Unable to read/verify body", err, http.StatusBadRequest)
			}
			return
		}
		if currReg.Agreement == "" {
			wfe.sendError(response, "Must agree to subscriber agreement before any further actions", nil, http.StatusForbidden)
			return
		}

		var challengeResponse core.Challenge
		if err = json.Unmarshal(body, &challengeResponse); err != nil {
			wfe.sendError(response, "Error unmarshaling authorization", err, http.StatusBadRequest)
			return
		}

		// Check that the registration ID matching the key used matches
		// the registration ID on the authz object
		if currReg.ID != authz.RegistrationID {
			wfe.sendError(response, "User registration ID doesn't match registration ID in authorization",
				fmt.Sprintf("User: %v != Authorization: %v", currReg.ID, authz.RegistrationID),
				http.StatusForbidden)
			return
		}

		// Ask the RA to update this authorization
		updatedAuthz, err := wfe.RA.UpdateAuthorization(authz, challengeIndex, challengeResponse)
		if err != nil {
			wfe.sendError(response, "Unable to update authorization", err, http.StatusInternalServerError)
			return
		}

		challenge := updatedAuthz.Challenges[challengeIndex]
		// assumption: UpdateAuthorization does not modify order of challenges
		jsonReply, err := json.Marshal(challenge)
		if err != nil {
			wfe.sendError(response, "Failed to marshal authz", err, http.StatusInternalServerError)
			return
		}

		authzURL := wfe.AuthzBase + string(authz.ID)
		challengeURL := url.URL(challenge.URI)
		response.Header().Add("Location", challengeURL.String())
		response.Header().Set("Content-Type", "application/json")
		response.Header().Add("Link", link(authzURL, "up"))
		response.WriteHeader(http.StatusAccepted)
		if _, err = response.Write(jsonReply); err != nil {
			wfe.log.Warning(fmt.Sprintf("Could not write response: %s", err))
		}

	}
}
Exemple #14
0
func (d *URL) Get() interface{} {
	return url.URL(*d)
}
Exemple #15
0
// TestOptionsBootFileURL verifies that Options.BootFileURL properly parses
// and returns a URL, if it is available with OptionBootFileURL.
func TestOptionsBootFileURL(t *testing.T) {
	var tests = []struct {
		desc    string
		options Options
		u       *url.URL
		ok      bool
		err     *url.Error
	}{
		{
			desc: "OptionBootFileURL not present in Options map",
		},
		{
			desc: "OptionBootFileURL present in Options map, but invalid URL",
			options: Options{
				OptionBootFileURL: [][]byte{[]byte("http://www.%a0.com/foo")},
			},
			err: &url.Error{
				Op:  "parse",
				URL: "http://www.%a0.com/foo",
			},
		},
		{
			desc: "OptionBootFileURL present in Options map",
			options: Options{
				OptionBootFileURL: [][]byte{[]byte("tftp://192.168.1.1:69")},
			},
			u: &url.URL{
				Scheme: "tftp",
				Host:   "192.168.1.1:69",
			},
			ok: true,
		},
	}

	for i, tt := range tests {
		u, ok, err := tt.options.BootFileURL()
		if err != nil {
			uerr, ok := err.(*url.Error)
			if !ok {
				t.Fatalf("[%02d] test %q, not *url.Error", i, tt.desc)
			}

			if want, got := tt.err.Op, uerr.Op; want != got {
				t.Fatalf("[%02d] test %q, unexpected error Op for Options.BootFileURL(): %v != %v",
					i, tt.desc, want, got)
			}

			continue
		}

		if want, got := tt.ok, ok; want != got {
			t.Fatalf("[%02d] test %q, unexpected ok for Options.BootFileURL(): %v != %v",
				i, tt.desc, want, got)
		}
		if !ok {
			continue
		}

		ttuu := url.URL(*tt.u)
		uu := url.URL(*u)
		if want, got := ttuu.String(), uu.String(); want != got {
			t.Fatalf("[%02d] test %q, unexpected value for Options.BootFileURL(): %v != %v",
				i, tt.desc, want, got)
		}
	}
}
Exemple #16
0
func TestNewRegistration(t *testing.T) {
	wfe := NewWebFrontEndImpl()
	wfe.RA = &MockRegistrationAuthority{}
	wfe.SA = &MockSA{}
	wfe.Stats, _ = statsd.NewNoopClient()
	wfe.SubscriberAgreementURL = "https://letsencrypt.org/be-good"
	responseWriter := httptest.NewRecorder()

	// GET instead of POST should be rejected
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "GET",
	})
	test.AssertEquals(t, responseWriter.Body.String(), "{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Method not allowed\"}")

	// POST, but no body.
	responseWriter.Body.Reset()
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
	})
	test.AssertEquals(t, responseWriter.Body.String(), "{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Unable to read/verify body\"}")

	// POST, but body that isn't valid JWS
	responseWriter.Body.Reset()
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body:   makeBody("hi"),
	})
	test.AssertEquals(t, responseWriter.Body.String(), "{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Unable to read/verify body\"}")

	// POST, Properly JWS-signed, but payload is "foo", not base64-encoded JSON.
	responseWriter.Body.Reset()
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body: makeBody(`
{
    "header": {
        "alg": "RS256",
        "jwk": {
            "e": "AQAB",
            "kty": "RSA",
            "n": "tSwgy3ORGvc7YJI9B2qqkelZRUC6F1S5NwXFvM4w5-M0TsxbFsH5UH6adigV0jzsDJ5imAechcSoOhAh9POceCbPN1sTNwLpNbOLiQQ7RD5mY_pSUHWXNmS9R4NZ3t2fQAzPeW7jOfF0LKuJRGkekx6tXP1uSnNibgpJULNc4208dgBaCHo3mvaE2HV2GmVl1yxwWX5QZZkGQGjNDZYnjFfa2DKVvFs0QbAk21ROm594kAxlRlMMrvqlf24Eq4ERO0ptzpZgm_3j_e4hGRD39gJS7kAzK-j2cacFQ5Qi2Y6wZI2p-FCq_wiYsfEAIkATPBiLKl_6d_Jfcvs_impcXQ"
        }
    },
    "payload": "Zm9vCg",
    "signature": "hRt2eYqBd_MyMRNIh8PEIACoFtmBi7BHTLBaAhpSU6zyDAFdEBaX7us4VB9Vo1afOL03Q8iuoRA0AT4akdV_mQTAQ_jhTcVOAeXPr0tB8b8Q11UPQ0tXJYmU4spAW2SapJIvO50ntUaqU05kZd0qw8-noH1Lja-aNnU-tQII4iYVvlTiRJ5g8_CADsvJqOk6FcHuo2mG643TRnhkAxUtazvHyIHeXMxydMMSrpwUwzMtln4ZJYBNx4QGEq6OhpAD_VSp-w8Lq5HOwGQoNs0bPxH1SGrArt67LFQBfjlVr94E1sn26p4vigXm83nJdNhWAMHHE9iV67xN-r29LT-FjA"
}
		`),
	})
	test.AssertEquals(t,
		responseWriter.Body.String(),
		"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Error unmarshaling JSON\"}")

	// Same signed body, but payload modified by one byte, breaking signature.
	// should fail JWS verification.
	responseWriter.Body.Reset()
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body: makeBody(`
			{
					"header": {
							"alg": "RS256",
							"jwk": {
									"e": "AQAB",
									"kty": "RSA",
									"n": "vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw"
							}
					},
					"payload": "xm9vCg",
					"signature": "RjUQ679fxJgeAJlxqgvDP_sfGZnJ-1RgWF2qmcbnBWljs6h1qp63pLnJOl13u81bP_bCSjaWkelGG8Ymx_X-aQ"
			}
    	`),
	})
	test.AssertEquals(t,
		responseWriter.Body.String(),
		"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Unable to read/verify body\"}")

	responseWriter.Body.Reset()
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body:   makeBody(signRequest(t, "{\"contact\":[\"tel:123456789\"],\"agreement\":\"https://letsencrypt.org/im-bad\"}")),
	})
	test.AssertEquals(t,
		responseWriter.Body.String(),
		"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Provided agreement URL [https://letsencrypt.org/im-bad] does not match current agreement URL [https://letsencrypt.org/be-good]\"}")

	responseWriter.Body.Reset()
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body:   makeBody(signRequest(t, "{\"contact\":[\"tel:123456789\"],\"agreement\":\"https://letsencrypt.org/be-good\"}")),
	})

	test.AssertEquals(t, responseWriter.Body.String(), "{\"key\":{\"kty\":\"RSA\",\"n\":\"z2NsNdHeqAiGdPP8KuxfQXat_uatOK9y12SyGpfKw1sfkizBIsNxERjNDke6Wp9MugN9srN3sr2TDkmQ-gK8lfWo0v1uG_QgzJb1vBdf_hH7aejgETRGLNJZOdaKDsyFnWq1WGJq36zsHcd0qhggTk6zVwqczSxdiWIAZzEakIUZ13KxXvoepYLY0Q-rEEQiuX71e4hvhfeJ4l7m_B-awn22UUVvo3kCqmaRlZT-36vmQhDGoBsoUo1KBEU44jfeK5PbNRk7vDJuH0B7qinr_jczHcvyD-2TtPzKaCioMtNh_VZbPNDaG67sYkQlC15-Ff3HPzKKJW2XvkVG91qMvQ\",\"e\":\"AAEAAQ\"},\"recoveryToken\":\"\",\"contact\":[\"tel:123456789\"],\"agreement\":\"https://letsencrypt.org/be-good\",\"thumbprint\":\"\"}")
	var reg core.Registration
	err := json.Unmarshal([]byte(responseWriter.Body.String()), &reg)
	test.AssertNotError(t, err, "Couldn't unmarshal returned registration object")
	uu := url.URL(reg.Contact[0])
	test.AssertEquals(t, uu.String(), "tel:123456789")
}
// MarshalBinary allocates a byte slice containing the data from a URL.
func (u URL) MarshalBinary() ([]byte, error) {
	uu := url.URL(u)
	return []byte(uu.String()), nil
}
Exemple #18
0
// Get returns the underlying url.URL
func (u *URLFlag) Get() interface{} {
	return url.URL(*u)
}
Exemple #19
0
func (u *AcmeURL) String() string {
	uu := url.URL(*u)
	return uu.String()
}
Exemple #20
0
func (d *URL) String() string {
	var u_d *url.URL
	*u_d = url.URL(*d)
	return u_d.String()
}
Exemple #21
0
func (u AcmeURL) String() string {
	url := url.URL(u)
	return url.String()
}
Exemple #22
0
func (e *Endpoint) String() string {
	u := url.URL(*e)
	return u.String()
}
Exemple #23
0
// MarshalJSON encodes an AcmeURL for transfer
func (u AcmeURL) MarshalJSON() ([]byte, error) {
	uu := url.URL(u)
	return json.Marshal(uu.String())
}
Exemple #24
0
// String reassembles the Resource into a valid URL string.
func (r *Resource) String() string {
	u := url.URL(*r)
	return u.String()
}
func (wfe *WebFrontEndImpl) challenge(authz core.Authorization, response http.ResponseWriter, request *http.Request, logEvent requestEvent) requestEvent {
	// Check that the requested challenge exists within the authorization
	found := false
	var challengeIndex int
	for i, challenge := range authz.Challenges {
		tempURL := url.URL(challenge.URI)
		if tempURL.Path == request.URL.Path && tempURL.RawQuery == request.URL.RawQuery {
			found = true
			challengeIndex = i
			break
		}
	}

	if !found {
		logEvent.Error = "Unable to find challenge"
		wfe.sendError(response, logEvent.Error, request.URL.RawQuery, http.StatusNotFound)
		return logEvent
	}

	switch request.Method {
	case "GET":
		challenge := authz.Challenges[challengeIndex]
		jsonReply, err := json.Marshal(challenge)
		if err != nil {
			logEvent.Error = err.Error()
			// InternalServerError because this is a failure to decode data passed in
			// by the caller, which got it from the DB.
			wfe.sendError(response, "Failed to marshal challenge", err, http.StatusInternalServerError)
			return logEvent
		}

		authzURL := wfe.AuthzBase + string(authz.ID)
		challengeURL := url.URL(challenge.URI)
		response.Header().Add("Location", challengeURL.String())
		response.Header().Set("Content-Type", "application/json")
		response.Header().Add("Link", link(authzURL, "up"))
		response.WriteHeader(http.StatusAccepted)
		if _, err := response.Write(jsonReply); err != nil {
			wfe.log.Warning(fmt.Sprintf("Could not write response: %s", err))
			logEvent.Error = err.Error()
			return logEvent
		}

	case "POST":
		body, _, currReg, err := wfe.verifyPOST(request, true, core.ResourceChallenge)
		if err != nil {
			logEvent.Error = err.Error()
			respMsg := malformedJWS
			respCode := http.StatusBadRequest
			if err == sql.ErrNoRows {
				respMsg = unknownKey
				respCode = http.StatusForbidden
			}
			wfe.sendError(response, respMsg, err, respCode)
			return logEvent
		}
		logEvent.Requester = currReg.ID
		logEvent.Contacts = currReg.Contact
		// Any version of the agreement is acceptable here. Version match is enforced in
		// wfe.Registration when agreeing the first time. Agreement updates happen
		// by mailing subscribers and don't require a registration update.
		if currReg.Agreement == "" {
			logEvent.Error = "Must agree to subscriber agreement before any further actions"
			wfe.sendError(response, logEvent.Error, nil, http.StatusForbidden)
			return logEvent
		}

		// Check that the registration ID matching the key used matches
		// the registration ID on the authz object
		if currReg.ID != authz.RegistrationID {
			logEvent.Error = fmt.Sprintf("User: %v != Authorization: %v", currReg.ID, authz.RegistrationID)
			wfe.sendError(response, "User registration ID doesn't match registration ID in authorization",
				logEvent.Error,
				http.StatusForbidden)
			return logEvent
		}

		var challengeResponse core.Challenge
		if err = json.Unmarshal(body, &challengeResponse); err != nil {
			logEvent.Error = err.Error()
			wfe.sendError(response, "Error unmarshaling challenge response", err, http.StatusBadRequest)
			return logEvent
		}

		// Ask the RA to update this authorization
		updatedAuthz, err := wfe.RA.UpdateAuthorization(authz, challengeIndex, challengeResponse)
		if err != nil {
			logEvent.Error = err.Error()
			wfe.sendError(response, "Unable to update authorization", err, statusCodeFromError(err))
			return logEvent
		}

		challenge := updatedAuthz.Challenges[challengeIndex]
		// assumption: UpdateAuthorization does not modify order of challenges
		jsonReply, err := json.Marshal(challenge)
		if err != nil {
			logEvent.Error = err.Error()
			// StatusInternalServerError because we made the challenges, they should be OK
			wfe.sendError(response, "Failed to marshal challenge", err, http.StatusInternalServerError)
			return logEvent
		}

		authzURL := wfe.AuthzBase + string(authz.ID)
		challengeURL := url.URL(challenge.URI)
		response.Header().Add("Location", challengeURL.String())
		response.Header().Set("Content-Type", "application/json")
		response.Header().Add("Link", link(authzURL, "up"))
		response.WriteHeader(http.StatusAccepted)
		if _, err = response.Write(jsonReply); err != nil {
			logEvent.Error = err.Error()
			wfe.log.Warning(fmt.Sprintf("Could not write response: %s", err))
			return logEvent
		}

	}
	return logEvent
}
Exemple #26
0
func TestNewRegistration(t *testing.T) {
	wfe := setupWFE(t)

	wfe.RA = &MockRegistrationAuthority{}
	wfe.SA = &MockSA{}
	wfe.Stats, _ = statsd.NewNoopClient()
	wfe.SubscriberAgreementURL = agreementURL
	responseWriter := httptest.NewRecorder()

	// GET instead of POST should be rejected
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "GET",
	})
	test.AssertEquals(t, responseWriter.Body.String(), "{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Method not allowed\"}")

	// POST, but no body.
	responseWriter.Body.Reset()
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
	})
	test.AssertEquals(t, responseWriter.Body.String(), "{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Unable to read/verify body\"}")

	// POST, but body that isn't valid JWS
	responseWriter.Body.Reset()
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body:   makeBody("hi"),
	})
	test.AssertEquals(t, responseWriter.Body.String(), "{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Unable to read/verify body\"}")

	key, err := jose.LoadPrivateKey([]byte(test2KeyPrivatePEM))
	test.AssertNotError(t, err, "Failed to load key")
	rsaKey, ok := key.(*rsa.PrivateKey)
	test.Assert(t, ok, "Couldn't load RSA key")
	signer, err := jose.NewSigner("RS256", rsaKey)
	test.AssertNotError(t, err, "Failed to make signer")

	// POST, Properly JWS-signed, but payload is "foo", not base64-encoded JSON.
	responseWriter.Body.Reset()
	nonce, err := wfe.nonceService.Nonce()
	test.AssertNotError(t, err, "Unable to create nonce")
	result, err := signer.Sign([]byte("foo"), nonce)
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body:   makeBody(result.FullSerialize()),
	})
	test.AssertEquals(t,
		responseWriter.Body.String(),
		"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Error unmarshaling JSON\"}")

	// Same signed body, but payload modified by one byte, breaking signature.
	// should fail JWS verification.
	responseWriter.Body.Reset()
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body: makeBody(`
			{
				"header": {
					"alg": "RS256",
					"jwk": {
						"e": "AQAB",
						"kty": "RSA",
						"n": "vd7rZIoTLEe-z1_8G1FcXSw9CQFEJgV4g9V277sER7yx5Qjz_Pkf2YVth6wwwFJEmzc0hoKY-MMYFNwBE4hQHw"
					}
				},
				"payload": "xm9vCg",
				"signature": "RjUQ679fxJgeAJlxqgvDP_sfGZnJ-1RgWF2qmcbnBWljs6h1qp63pLnJOl13u81bP_bCSjaWkelGG8Ymx_X-aQ"
			}
    	`),
	})
	test.AssertEquals(t,
		responseWriter.Body.String(),
		"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Unable to read/verify body\"}")

	responseWriter.Body.Reset()
	nonce, err = wfe.nonceService.Nonce()
	test.AssertNotError(t, err, "Unable to create nonce")
	result, err = signer.Sign(
		[]byte("{\"contact\":[\"tel:123456789\"],\"agreement\":\"https://letsencrypt.org/im-bad\"}"),
		nonce)
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body:   makeBody(result.FullSerialize()),
	})
	test.AssertEquals(t,
		responseWriter.Body.String(),
		"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Provided agreement URL [https://letsencrypt.org/im-bad] does not match current agreement URL ["+agreementURL+"]\"}")

	responseWriter.Body.Reset()
	nonce, err = wfe.nonceService.Nonce()
	test.AssertNotError(t, err, "Unable to create nonce")
	result, err = signer.Sign([]byte("{\"contact\":[\"tel:123456789\"],\"agreement\":\""+agreementURL+"\"}"), nonce)
	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body:   makeBody(result.FullSerialize()),
	})

	test.AssertEquals(t, responseWriter.Body.String(), `{"id":0,"key":{"kty":"RSA","n":"qnARLrT7Xz4gRcKyLdydmCr-ey9OuPImX4X40thk3on26FkMznR3fRjs66eLK7mmPcBZ6uOJseURU6wAaZNmemoYx1dMvqvWWIyiQleHSD7Q8vBrhR6uIoO4jAzJZR-ChzZuSDt7iHN-3xUVspu5XGwXU_MVJZshTwp4TaFx5elHIT_ObnTvTOU3Xhish07AbgZKmWsVbXh5s-CrIicU4OexJPgunWZ_YJJueOKmTvnLlTV4MzKR2oZlBKZ27S0-SfdV_QDx_ydle5oMAyKVtlAV35cyPMIsYNwgUGBCdY_2Uzi5eX0lTc7MPRwz6qR1kip-i59VcGcUQgqHV6Fyqw","e":"AAEAAQ"},"recoveryToken":"","contact":["tel:123456789"],"agreement":"http://example.invalid/terms"}`)
	var reg core.Registration
	err = json.Unmarshal([]byte(responseWriter.Body.String()), &reg)
	test.AssertNotError(t, err, "Couldn't unmarshal returned registration object")
	test.Assert(t, len(reg.Contact) >= 1, "No contact field in registration")
	uu := url.URL(reg.Contact[0])
	test.AssertEquals(t, uu.String(), "tel:123456789")

	test.AssertEquals(
		t, responseWriter.Header().Get("Location"),
		"/acme/reg/0")
	test.AssertEquals(
		t, responseWriter.Header().Get("Link"),
		"</acme/new-authz>;rel=\"next\"")

	key, err = jose.LoadPrivateKey([]byte(test1KeyPrivatePEM))
	test.AssertNotError(t, err, "Failed to load key")
	rsaKey, ok = key.(*rsa.PrivateKey)
	test.Assert(t, ok, "Couldn't load RSA key")
	signer, err = jose.NewSigner("RS256", rsaKey)
	test.AssertNotError(t, err, "Failed to make signer")

	// POST, Valid JSON, Key already in use
	responseWriter.Body.Reset()
	nonce, err = wfe.nonceService.Nonce()
	test.AssertNotError(t, err, "Unable to create nonce")
	result, err = signer.Sign([]byte("{\"contact\":[\"tel:123456789\"],\"agreement\":\""+agreementURL+"\"}"), nonce)

	wfe.NewRegistration(responseWriter, &http.Request{
		Method: "POST",
		Body:   makeBody(result.FullSerialize()),
	})
	test.AssertEquals(t,
		responseWriter.Body.String(),
		"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Registration key is already in use\"}")
}