Skip to content
This repository has been archived by the owner on Apr 20, 2021. It is now read-only.
/ gravel Public archive

Integration environment for Let's Encrypt.

License

Notifications You must be signed in to change notification settings

cloud-gov/gravel

Repository files navigation

Documentation

Gravel

Gravel is an integration environment for Let's Encrypt.

If you're wondering why it's called Gravel, the reference ACME server is called Boulder, and it has a development server for infrastructure testing called Pebble, since it's smaller than Boulder. Well, Gravel is smaller than a Pebble.

The project came from Pebble#241 as both a tool and thought experiment on what an integration environment for Let's Encrypt would look like.

As part of that, the core of this project is a hard fork from Pebble at 7228963, so it's license is MPL-2.0. While this is a work of employees of the United States Government and our specific contributions are public domain, MPL-2.0's requirements require us to keep it licensed as MPL-2.0. For more information on this policy, see this document.

Consuming It

For the most part, consuming the integration environment is pretty straightforward.

package main

import (
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"fmt"
	"time"

	"github.com/18f/gravel"
	"github.com/go-acme/lego/v3/certcrypto"
	"github.com/go-acme/lego/v3/certificate"
	"github.com/go-acme/lego/v3/challenge/dns01"
	"github.com/go-acme/lego/v3/lego"
	"github.com/go-acme/lego/v3/registration"
)

type MyUser struct {
	Email        string
	Registration *registration.Resource
	key          crypto.PrivateKey
}

func (u *MyUser) GetEmail() string {
	return u.Email
}
func (u MyUser) GetRegistration() *registration.Resource {
	return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
	return u.key
}

func main() {

	opts := gravel.NewDefaultGravelOpts()
	opts.VAOpts.CustomResolverAddress = fmt.Sprintf("localhost:%d", opts.DnsOpts.DnsPort)
	g, _ := gravel.New(opts)

	// start the servers.
	go g.StartDnsServer()
	go g.StartWebServer()
	time.Sleep(3 * time.Second)

	privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)

	myuser := MyUser{
		Email: "[email protected]",
		key:   privateKey,
	}

	config := lego.NewConfig(&myuser)
	config.HTTPClient = g.Client
	config.Certificate.KeyType = certcrypto.RSA2048
	config.CADirURL = fmt.Sprintf("https://%s%s", g.Opts.ListenAddress, g.Opts.WfeOpts.DirectoryPath)

	client, _ := lego.NewClient(config)

	_ = client.Challenge.SetDNS01Provider(
		g.Opts.DnsOpts.Provider,
		dns01.AddRecursiveNameservers([]string{
			fmt.Sprintf("127.0.0.1:%d", g.Opts.DnsOpts.DnsPort),
		}),
		dns01.WrapPreCheck(g.DnsServer.PreCheck))

	reg, _ := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})

	myuser.Registration = reg

	request := certificate.ObtainRequest{
		Domains: []string{"test.service"},
		Bundle:  true,
	}

	certificates, _ := client.Certificate.Obtain(request)

	// do something with your valid certificate pair.
}

See the documentation on all the hooks and features available.

Developing

For the most part, it's pretty straightfoward, you can run tests with go test -v ./....

Releases

No releases published

Packages

No packages published

Languages