Ejemplo n.º 1
0
func (s *S) TestListCertRoutes(c *C) {
	api := s.newTestAPIServer(c)
	defer api.Close()

	srv1 := httptest.NewServer(httpTestHandler("1"))
	defer srv1.Close()
	l := s.newHTTPListener(c)
	defer l.Close()
	domain := "oof.example.org"
	r := addHTTPRouteForDomain(domain, c, l)

	tlsCert, err := tlscert.Generate([]string{domain})
	c.Assert(err, IsNil)
	cert := &router.Certificate{
		Routes: []string{r.ID},
		Cert:   tlsCert.Cert,
		Key:    tlsCert.PrivateKey,
	}
	err = api.CreateCert(cert)
	c.Assert(err, IsNil)

	gotRoutes, err := api.ListCertRoutes(cert.ID)
	c.Assert(err, IsNil)
	c.Assert(len(gotRoutes), Equals, 1)
	gotRoute := gotRoutes[0]
	c.Assert(gotRoute.ID, Equals, r.ID)
	c.Assert(gotRoute.Certificate, IsNil)
}
Ejemplo n.º 2
0
func (a *GenTLSCertAction) Run(s *State) (err error) {
	data := &tlscert.Cert{}
	s.StepData[a.ID] = data

	a.CACert = interpolate(s, a.CACert)
	a.Cert = interpolate(s, a.Cert)
	a.PrivateKey = interpolate(s, a.PrivateKey)
	if a.CACert != "" && a.Cert != "" && a.PrivateKey != "" {
		data.CACert = a.CACert
		data.Cert = a.Cert
		data.PrivateKey = a.PrivateKey

		// calculate cert pin
		b, _ := pem.Decode([]byte(data.Cert))
		sha := sha256.Sum256(b.Bytes)
		data.Pin = base64.StdEncoding.EncodeToString(sha[:])
		return nil
	}

	for i, h := range a.Hosts {
		a.Hosts[i] = interpolate(s, h)
	}
	c, err := tlscert.Generate(a.Hosts)
	if err != nil {
		return err
	}
	data.CACert = c.CACert
	data.Cert = c.Cert
	data.Pin = c.Pin
	data.PrivateKey = c.PrivateKey

	return err
}
Ejemplo n.º 3
0
func (s *S) TestListCerts(c *C) {
	api := s.newTestAPIServer(c)
	defer api.Close()

	srv1 := httptest.NewServer(httpTestHandler("1"))
	defer srv1.Close()
	l := s.newHTTPListener(c)
	defer l.Close()
	domain := "oof.example.org"
	r := addHTTPRouteForDomain(domain, c, l)

	tlsCert, err := tlscert.Generate([]string{domain})
	c.Assert(err, IsNil)
	cert := &router.Certificate{
		Routes: []string{r.ID},
		Cert:   tlsCert.Cert,
		Key:    tlsCert.PrivateKey,
	}
	err = api.CreateCert(cert)
	c.Assert(err, IsNil)

	gotCerts, err := api.ListCerts()
	c.Assert(err, IsNil)
	c.Assert(len(gotCerts), Equals, 2)
	gotCert := gotCerts[1] // the first cert was created with the route
	c.Assert(gotCert.ID, Equals, cert.ID)
	c.Assert(gotCert.Cert, Equals, cert.Cert)
	c.Assert(gotCert.Key, Equals, cert.Key)
	c.Assert(gotCert.Routes, DeepEquals, cert.Routes)
}
Ejemplo n.º 4
0
func (s *S) TestAddHTTPRouteWithInvalidCert(c *C) {
	l := s.newHTTPListener(c)
	defer l.Close()

	c1, _ := tlscert.Generate([]string{"1.example.com"})
	c2, _ := tlscert.Generate([]string{"2.example.com"})

	err := l.AddRoute(router.HTTPRoute{
		Domain:  "example.com",
		Service: "test",
		Certificate: &router.Certificate{
			Cert: c1.Cert,
			Key:  c2.PrivateKey,
		},
	}.ToRoute())
	c.Assert(err, Not(IsNil))
}
Ejemplo n.º 5
0
func refreshTLSConfigForDomain(domain string) *tlscert.Cert {
	tlsCertsMux.Lock()
	defer tlsCertsMux.Unlock()
	domain = normalizeDomain(domain)
	c, err := tlscert.Generate([]string{domain})
	if err != nil {
		panic(err)
	}
	tlsCerts[domain] = c
	return c
}
Ejemplo n.º 6
0
func (m *migration) generateTLSCert() (*tlscert.Cert, error) {
	hosts := []string{
		m.dm.Domain,
		fmt.Sprintf("*.%s", m.dm.Domain),
	}
	cert, err := tlscert.Generate(hosts)
	if err != nil {
		return nil, err
	}
	if _, err := m.db.Query("UPDATE domain_migrations SET tls_cert = $1 WHERE migration_id = $2", cert, m.dm.ID); err != nil {
		return nil, err
	}
	return cert, nil
}
Ejemplo n.º 7
0
func tlsConfigForDomain(domain string) ([]byte, []byte) {
	tlsCertsMux.Lock()
	defer tlsCertsMux.Unlock()
	domain = strings.ToLower(domain)
	if d, _, err := net.SplitHostPort(domain); err == nil {
		domain = d
	}
	if strings.HasSuffix(domain, ".example.com") {
		domain = "example.com"
	}
	if c, ok := tlsCerts[domain]; ok {
		return []byte(c.CACert), []byte(c.PrivateKey)
	}
	c, err := tlscert.Generate([]string{domain})
	if err != nil {
		panic(err)
	}
	tlsCerts[domain] = c
	return []byte(c.Cert), []byte(c.PrivateKey)
}
Ejemplo n.º 8
0
func tlsConfigForDomain(domain string) *tlscert.Cert {
	tlsCertsMux.Lock()
	defer tlsCertsMux.Unlock()
	domain = normalizeDomain(domain)
	parts := strings.SplitAfter(domain, ".")
	wildcard := "*."
	for i := 1; i < len(parts); i++ {
		wildcard += parts[i]
	}
	if c, ok := tlsCerts[domain]; ok {
		return c
	}
	if c, ok := tlsCerts[wildcard]; ok {
		return c
	}
	c, err := tlscert.Generate([]string{domain})
	if err != nil {
		panic(err)
	}
	tlsCerts[domain] = c
	return c
}
Ejemplo n.º 9
0
func (s *CLISuite) TestRoute(t *c.C) {
	client := s.controllerClient(t)
	app := s.newCliTestApp(t)
	defer app.cleanup()

	// The router API does not currently give us a "read your own writes"
	// guarantee, so we must retry a few times if we don't get the expected
	// result.
	assertRouteContains := func(str string, contained bool) {
		var res *CmdResult
		attempt.Strategy{
			Total: 10 * time.Second,
			Delay: 500 * time.Millisecond,
		}.Run(func() error {
			res = app.flynn("route")
			if contained == strings.Contains(res.Output, str) {
				return nil
			}
			return errors.New("unexpected output")
		})
		if contained {
			t.Assert(res, SuccessfulOutputContains, str)
		} else {
			t.Assert(res, c.Not(SuccessfulOutputContains), str)
		}
	}

	// flynn route add http
	route := random.String(32) + ".dev"
	newRoute := app.flynn("route", "add", "http", route)
	t.Assert(newRoute, Succeeds)
	routeID := strings.TrimSpace(newRoute.Output)
	assertRouteContains(routeID, true)

	// ensure sticky and leader flags default to not set
	routes, err := client.RouteList(app.name)
	t.Assert(err, c.IsNil)
	var found bool
	for _, r := range routes {
		if fmt.Sprintf("%s/%s", r.Type, r.ID) != routeID {
			continue
		}
		t.Assert(r.Sticky, c.Equals, false)
		t.Assert(r.Leader, c.Equals, false)
		found = true
		break
	}
	t.Assert(found, c.Equals, true, c.Commentf("didn't find route"))

	// flynn route add http --sticky --leader
	route = random.String(32) + ".dev"
	newRoute = app.flynn("route", "add", "http", "--sticky", route, "--leader")
	t.Assert(newRoute, Succeeds)
	routeID = strings.TrimSpace(newRoute.Output)
	assertRouteContains(routeID, true)

	// duplicate http route
	dupRoute := app.flynn("route", "add", "http", "--sticky", route)
	t.Assert(dupRoute, c.Not(Succeeds))
	t.Assert(dupRoute.Output, c.Equals, "conflict: Duplicate route\n")

	// ensure sticky and leader flags are set
	routes, err = client.RouteList(app.name)
	t.Assert(err, c.IsNil)
	for _, r := range routes {
		if fmt.Sprintf("%s/%s", r.Type, r.ID) != routeID {
			continue
		}
		t.Assert(r.Sticky, c.Equals, true)
		t.Assert(r.Leader, c.Equals, true)
		found = true
		break
	}
	t.Assert(found, c.Equals, true, c.Commentf("didn't find route"))

	// flynn route update --no-sticky
	newRoute = app.flynn("route", "update", routeID, "--no-sticky")
	t.Assert(newRoute, Succeeds)
	r, err := client.GetRoute(app.id, routeID)
	t.Assert(err, c.IsNil)
	t.Assert(r.Sticky, c.Equals, false)

	// flynn route update --no-leader
	newRoute = app.flynn("route", "update", routeID, "--no-leader")
	t.Assert(newRoute, Succeeds)
	r, err = client.GetRoute(app.id, routeID)
	t.Assert(err, c.IsNil)
	t.Assert(r.Leader, c.Equals, false)

	// flynn route update --service
	newRoute = app.flynn("route", "update", routeID, "--service", "foo")
	t.Assert(newRoute, Succeeds)
	r, err = client.GetRoute(app.id, routeID)
	t.Assert(err, c.IsNil)
	t.Assert(r.Service, c.Equals, "foo")
	t.Assert(r.Sticky, c.Equals, false)

	// flynn route update --sticky
	newRoute = app.flynn("route", "update", routeID, "--sticky")
	t.Assert(newRoute, Succeeds)
	r, err = client.GetRoute(app.id, routeID)
	t.Assert(err, c.IsNil)
	t.Assert(r.Sticky, c.Equals, true)
	t.Assert(r.Service, c.Equals, "foo")

	// flynn route update --leader
	newRoute = app.flynn("route", "update", routeID, "--leader")
	t.Assert(newRoute, Succeeds)
	r, err = client.GetRoute(app.id, routeID)
	t.Assert(err, c.IsNil)
	t.Assert(r.Leader, c.Equals, true)
	t.Assert(r.Service, c.Equals, "foo")

	// flynn route add domain path
	pathRoute := app.flynn("route", "add", "http", route+"/path/")
	t.Assert(pathRoute, Succeeds)
	pathRouteID := strings.TrimSpace(pathRoute.Output)
	assertRouteContains(pathRouteID, true)

	// flynn route add domain path duplicate
	dupRoute = app.flynn("route", "add", "http", route+"/path/")
	t.Assert(dupRoute, c.Not(Succeeds))
	t.Assert(dupRoute.Output, c.Equals, "conflict: Duplicate route\n")

	// flynn route add domain path without trailing should correct to trailing
	noTrailingRoute := app.flynn("route", "add", "http", route+"/path2")
	t.Assert(noTrailingRoute, Succeeds)
	noTrailingRouteID := strings.TrimSpace(noTrailingRoute.Output)
	assertRouteContains(noTrailingRouteID, true)
	// flynn route should show the corrected trailing path
	assertRouteContains("/path2/", true)

	// flynn route remove should fail because of dependent route
	delFail := app.flynn("route", "remove", routeID)
	t.Assert(delFail, c.Not(Succeeds))

	// But removing the dependent route and then the default route should work
	t.Assert(app.flynn("route", "remove", pathRouteID), Succeeds)
	assertRouteContains(pathRouteID, false)
	t.Assert(app.flynn("route", "remove", noTrailingRouteID), Succeeds)
	assertRouteContains(noTrailingRouteID, false)
	t.Assert(app.flynn("route", "remove", routeID), Succeeds)
	assertRouteContains(routeID, false)

	// flynn route add tcp
	tcpRoute := app.flynn("route", "add", "tcp")
	t.Assert(tcpRoute, Succeeds)
	routeID = strings.Split(tcpRoute.Output, " ")[0]
	assertRouteContains(routeID, true)

	// flynn route add tcp --port
	portRoute := app.flynn("route", "add", "tcp", "--port", "9999")
	t.Assert(portRoute, Succeeds)
	routeID = strings.Split(portRoute.Output, " ")[0]
	port := strings.Split(portRoute.Output, " ")[4]
	t.Assert(port, c.Equals, "9999\n")
	assertRouteContains(routeID, true)

	// flynn route update --service
	portRoute = app.flynn("route", "update", routeID, "--service", "foo")
	t.Assert(portRoute, Succeeds)
	r, err = client.GetRoute(app.id, routeID)
	t.Assert(err, c.IsNil)
	t.Assert(r.Service, c.Equals, "foo")

	// flynn route remove
	t.Assert(app.flynn("route", "remove", routeID), Succeeds)
	assertRouteContains(routeID, false)

	writeTemp := func(data, prefix string) (string, error) {
		f, err := ioutil.TempFile(os.TempDir(), fmt.Sprintf("flynn-test-%s", prefix))
		t.Assert(err, c.IsNil)
		_, err = f.WriteString(data)
		t.Assert(err, c.IsNil)
		stat, err := f.Stat()
		t.Assert(err, c.IsNil)
		return filepath.Join(os.TempDir(), stat.Name()), nil
	}

	// flynn route add http with tls cert
	cert, err := tlscert.Generate([]string{"example.com"})
	t.Assert(err, c.IsNil)
	certPath, err := writeTemp(cert.Cert, "tls-cert")
	t.Assert(err, c.IsNil)
	keyPath, err := writeTemp(cert.PrivateKey, "tls-key")
	certRoute := app.flynn("route", "add", "http", "--tls-cert", certPath, "--tls-key", keyPath, "example.com")
	t.Assert(certRoute, Succeeds)
	routeID = strings.TrimSpace(certRoute.Output)
	r, err = client.GetRoute(app.id, routeID)
	t.Assert(err, c.IsNil)
	t.Assert(r.Domain, c.Equals, "example.com")
	t.Assert(r.Certificate, c.NotNil)
	t.Assert(r.Certificate.Cert, c.Equals, strings.Trim(cert.Cert, "\n"))
	t.Assert(r.Certificate.Key, c.Equals, strings.Trim(cert.PrivateKey, "\n"))

	// flynn route update tls cert
	cert, err = tlscert.Generate([]string{"example.com"})
	t.Assert(err, c.IsNil)
	certPath, err = writeTemp(cert.Cert, "tls-cert")
	t.Assert(err, c.IsNil)
	keyPath, err = writeTemp(cert.PrivateKey, "tls-key")
	certRoute = app.flynn("route", "update", routeID, "--tls-cert", certPath, "--tls-key", keyPath)
	t.Assert(certRoute, Succeeds)
	r, err = client.GetRoute(app.id, routeID)
	t.Assert(err, c.IsNil)
	t.Assert(r.Domain, c.Equals, "example.com")
	t.Assert(r.Certificate, c.NotNil)
	t.Assert(r.Certificate.Cert, c.Equals, strings.Trim(cert.Cert, "\n"))
	t.Assert(r.Certificate.Key, c.Equals, strings.Trim(cert.PrivateKey, "\n"))

	// flynn route remove
	t.Assert(app.flynn("route", "remove", routeID), Succeeds)
	assertRouteContains(routeID, false)
}