예제 #1
0
파일: client.go 프로젝트: tommie/acme-go
// IssueCertificate signs a certificate signing request if
// authorized. This function will block until the requst is completed
// by the ACME server.
func (a *ClientAccount) IssueCertificate(csr []byte) (*Certificate, error) {
	d, err := a.directory()
	if err != nil {
		return nil, err
	}

	cbs, resp, err := protocol.PostCertificateIssuance(a.http, d.NewCert, &protocol.CertificateIssuance{
		Resource: protocol.ResourceNewCert,
		CSR:      protocol.DERData(csr),
	})
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusCreated {
		return nil, fmt.Errorf("issue certificate: unexpected HTTP status: %s", resp.Status)
	}

	uri, err := contentLocation(resp)
	// ACME Spec Sec. 6.6 says servers SHOULD provide Content-Location.
	// Boulder does not, so fall back to Location (which is not stable).
	if err == http.ErrNoLocation {
		uri, err = resp.Location()
	}
	if err != nil {
		return nil, err
	}

	if len(cbs) != 0 {
		return &Certificate{
			Bytes:      cbs,
			URI:        uri.String(),
			IssuerURIs: links(resp, "up"),
		}, err
	}

	ra, _ := retryAfter(resp.Header, 1*time.Second)
	time.Sleep(ra)

	return a.Certificate(uri.String())
}
예제 #2
0
파일: client.go 프로젝트: tommie/acme-go
// RevokeCertificate requests a revocation. The given cert should be
// exactly the same as returned by IssueCertificate.
func (a *ClientAccount) RevokeCertificate(cert []byte) error {
	d, err := a.directory()
	if err != nil {
		return err
	}

	req := &protocol.Certificate{
		Resource:    protocol.ResourceRevokeCert,
		Certificate: protocol.DERData(cert),
	}
	resp, err := protocol.PostCertificateRevocation(a.http, d.RevokeCert, req)
	if err != nil {
		return err
	}

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("revoke certificate: unexpected HTTP status: %s", resp.Status)
	}

	return nil
}
예제 #3
0
func TestWriteChallenge(t *testing.T) {
	tsts := []struct {
		in protocol.Challenge

		want []string
		err  error
	}{
		{
			in: &protocol.DNS01Challenge{
				Type:  protocol.ChallengeDNS01,
				Token: "token",
			},

			want: []string{"dns-01", "token", "token.luhDRvWTmOMLRwM2gMkTDdC88jVeIXo9Hm1r_Q6W41Y"},
		},
		{
			in: &protocol.HTTP01Challenge{
				Type:  protocol.ChallengeHTTP01,
				Token: "token",
			},

			want: []string{"http-01", "token", "token.luhDRvWTmOMLRwM2gMkTDdC88jVeIXo9Hm1r_Q6W41Y"},
		},
		{
			in: &protocol.Possession01Challenge{
				Type:  protocol.ChallengePossession01,
				Certs: []protocol.DERData{protocol.DERData("hello"), protocol.DERData("world")},
			},

			want: []string{"proofOfPossession-01", "aGVsbG8=", "d29ybGQ="},
		},
		{
			in: &protocol.TLSSNI01Challenge{
				Type:  protocol.ChallengeTLSSNI01,
				Token: "token",
				N:     2,
			},

			want: []string{
				"tls-sni-01",
				"token",
				"token.luhDRvWTmOMLRwM2gMkTDdC88jVeIXo9Hm1r_Q6W41Y",
				"c6b5052764ef075d8eafa41868fb8e88.1ef567ba3f4a0721a8dd63153c8a079e.acme.invalid",
				"e3e1b3a270c6b5566cb36f9ca4f0939c.af758bfb4ced915161127327053fbbdb.acme.invalid",
			},
		},
		{
			in: &protocol.GenericChallenge{},

			err: fmt.Errorf("unknown challenge type"),
		},
	}
	for _, tst := range tsts {
		var b bytes.Buffer
		cw := csv.NewWriter(&b)

		if err := writeChallenge(cw, tst.in, testJWK); !matchError(err, tst.err) {
			t.Errorf("writeChallenge(%v) err: got %v, want prefix %v", tst.in, err, tst.err)
		}
		cw.Flush()

		cr := csv.NewReader(&b)
		got, err := cr.Read()
		if err != io.EOF && err != nil {
			t.Fatalf("cw.Read failed: %v", err)
		}
		if !reflect.DeepEqual(got, tst.want) {
			t.Errorf("writeChallenge(%v): got %s, want %s", tst.in, got, tst.want)
		}
	}
}