// Make sure the staple host cleaned func (s *StaplerSuite) TestStapleReplaced(c *C) { srv := testutils.NewOCSPResponder() defer srv.Close() s.st.beforeUpdateC = make(chan bool) h, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "1h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) c.Assert(err, IsNil) re, err := s.st.StapleHost(h) c.Assert(err, IsNil) c.Assert(re, NotNil) c.Assert(re.Response.Status, Equals, ocsp.Good) beforeId := s.st.v[h.Name].id s.st.kickC <- true // first make sure the fan out channel is at the right place s.st.beforeUpdateC <- true // update settings so the staple will be replaced h2, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "10h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) s.st.StapleHost(h2) afterId := s.st.v[h.Name].id // now allow it to proceed s.st.beforeUpdateC <- true c.Assert(afterId, Not(Equals), beforeId) }
func (s *StaplerSuite) TestCRUD(c *C) { srv := testutils.NewOCSPResponder() defer srv.Close() h, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "1h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) c.Assert(err, IsNil) re, err := s.st.StapleHost(h) c.Assert(err, IsNil) c.Assert(re, NotNil) c.Assert(re.Response.Status, Equals, ocsp.Good) // subsequent call will return cached response other, err := s.st.StapleHost(h) c.Assert(err, IsNil) c.Assert(re, NotNil) c.Assert(other, Equals, re) // delete host hk := engine.HostKey{Name: h.Name} s.st.DeleteHost(hk) c.Assert(len(s.st.v), Equals, 0) // second call succeeds s.st.DeleteHost(hk) }
// Periodic update updated the staple value, we got the notification func (s *StaplerSuite) TestUpdateStapleResult(c *C) { srv := testutils.NewOCSPResponder() defer srv.Close() h, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "1h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) c.Assert(err, IsNil) events := make(chan *StapleUpdated, 1) close := make(chan struct{}) s.st.Subscribe(events, close) re, err := s.st.StapleHost(h) c.Assert(err, IsNil) c.Assert(re, NotNil) c.Assert(re.Response.Status, Equals, ocsp.Good) s.st.kickC <- true var update *StapleUpdated select { case update = <-events: c.Assert(update, NotNil) c.Assert(update.Staple.IsValid(), Equals, true) case <-time.After(100 * time.Millisecond): c.Fatalf("timeout waiting for update") } }
func (cmd *Command) upsertHostAction(c *cli.Context) { host, err := engine.NewHost(c.String("name"), engine.HostSettings{}) if err != nil { cmd.printError(err) return } if c.String("cert") != "" || c.String("privateKey") != "" { keyPair, err := readKeyPair(c.String("cert"), c.String("privateKey")) if err != nil { cmd.printError(fmt.Errorf("failed to read key pair: %s", err)) return } host.Settings.KeyPair = keyPair } host.Settings.OCSP = engine.OCSPSettings{ Enabled: c.Bool("ocsp"), SkipSignatureCheck: c.Bool("ocspSkipCheck"), Period: c.Duration("ocspPeriod").String(), Responders: c.StringSlice("ocspResponder"), } if err := cmd.client.UpsertHost(*host); err != nil { cmd.printError(err) return } cmd.printOk("host added") }
func (n *ng) parseHosts(keyValues []*mvccpb.KeyValue) ([]engine.Host, error) { hosts := []engine.Host{} for _, keyValue := range keyValues { if hostnames := hostnameRegex.FindStringSubmatch(string(keyValue.Key)); len(hostnames) == 2 { hostname := hostnames[1] var sealedHost host if err := json.Unmarshal([]byte(keyValue.Value), &sealedHost); err != nil { return nil, err } var keyPair *engine.KeyPair if len(sealedHost.Settings.KeyPair) != 0 { if err := n.openSealedJSONVal(sealedHost.Settings.KeyPair, &keyPair); err != nil { return nil, err } } host, err := engine.NewHost(hostname, engine.HostSettings{Default: sealedHost.Settings.Default, KeyPair: keyPair, OCSP: sealedHost.Settings.OCSP}) if err != nil { return nil, err } if host.Name != hostname { return nil, fmt.Errorf("Host %s parameters missing", hostname) } hosts = append(hosts, *host) } } return hosts, nil }
func (n *ng) parseHosts(node *etcd.Node) ([]engine.Host, error) { hosts := make([]engine.Host, len(node.Nodes)) for idx, node := range node.Nodes { hostname := suffix(node.Key) for _, node := range node.Nodes { switch suffix(node.Key) { case "host": var sealedHost host if err := json.Unmarshal([]byte(node.Value), &sealedHost); err != nil { return nil, err } var keyPair *engine.KeyPair if len(sealedHost.Settings.KeyPair) != 0 { if err := n.openSealedJSONVal(sealedHost.Settings.KeyPair, &keyPair); err != nil { return nil, err } } host, err := engine.NewHost(hostname, engine.HostSettings{Default: sealedHost.Settings.Default, KeyPair: keyPair, OCSP: sealedHost.Settings.OCSP}) if err != nil { return nil, err } hosts[idx] = *host } } if hosts[idx].Name != hostname { return nil, fmt.Errorf("Host %s parameters missing", hostname) } } return hosts, nil }
func (s *StaplerSuite) TestBadArguments(c *C) { h, err := engine.NewHost("localhost", engine.HostSettings{}) c.Assert(err, IsNil) re, err := s.st.StapleHost(h) c.Assert(err, NotNil) c.Assert(re, IsNil) }
// Update of the settings re-initializes staple func (s *StaplerSuite) TestUpdateSettings(c *C) { srv := testutils.NewOCSPResponder() defer srv.Close() h, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "1h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) c.Assert(err, IsNil) re, err := s.st.StapleHost(h) c.Assert(err, IsNil) c.Assert(re, NotNil) c.Assert(re.Response.Status, Equals, ocsp.Good) id := s.st.v[h.Name].id h2, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "2h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) c.Assert(err, IsNil) re2, err := s.st.StapleHost(h2) c.Assert(err, IsNil) c.Assert(re2, NotNil) c.Assert(re2.Response.Status, Equals, ocsp.Good) // the host stapler has been updated id2 := s.st.v[h.Name].id c.Assert(re2, Not(Equals), re) c.Assert(id2, Not(Equals), id) }
func (s *StaplerSuite) TestStapleFailed(c *C) { srv := testutils.NewOCSPResponder() srv.Close() h, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "1h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) c.Assert(err, IsNil) re, err := s.st.StapleHost(h) c.Assert(err, NotNil) c.Assert(re, IsNil) }
// Responder became unavailable after series of retries func (s *StaplerSuite) TestResponderUnavailable(c *C) { // we are setting up discard channel that will be used by Stapler to notify about discard events s.st.discardC = make(chan bool) srv := testutils.NewOCSPResponder() h, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "1h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) c.Assert(err, IsNil) events := make(chan *StapleUpdated, 1) close := make(chan struct{}) s.st.Subscribe(events, close) re, err := s.st.StapleHost(h) c.Assert(err, IsNil) c.Assert(re, NotNil) c.Assert(re.Response.Status, Equals, ocsp.Good) srv.Close() // The first update did not generate any events, as the time for the next update has not passed s.clock.CurrentTime = s.re.NextUpdate.Add(-1 * time.Hour) s.st.kickC <- true // The server discarded the event because the server is unreachable select { case <-s.st.discardC: case <-time.After(100 * time.Millisecond): c.Fatalf("timeout waiting for discard") } s.clock.CurrentTime = s.re.NextUpdate.Add(time.Hour) s.st.kickC <- true var update *StapleUpdated select { case update = <-events: c.Assert(update, NotNil) c.Assert(update.Err, NotNil) case <-time.After(100 * time.Millisecond): c.Fatalf("timeout waiting for update") } }
func (s *StaplerSuite) TestFanOutUnsubscribe(c *C) { srv := testutils.NewOCSPResponder() defer srv.Close() h, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "1h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) c.Assert(err, IsNil) events := make(chan *StapleUpdated, 1) closeC := make(chan struct{}) s.st.Subscribe(events, closeC) events2 := make(chan *StapleUpdated, 1) closeC2 := make(chan struct{}) s.st.Subscribe(events2, closeC2) re, err := s.st.StapleHost(h) c.Assert(err, IsNil) c.Assert(re, NotNil) c.Assert(re.Response.Status, Equals, ocsp.Good) s.st.kickC <- true // both channels got the update for _, ch := range []chan *StapleUpdated{events, events2} { select { case update := <-ch: c.Assert(update, NotNil) case <-time.After(100 * time.Millisecond): c.Fatalf("timeout waiting for update") } } // unsubscribe first channel, second will still get the notification close(closeC) s.st.kickC <- true select { case update := <-events2: c.Assert(update, NotNil) case <-time.After(100 * time.Millisecond): c.Fatalf("timeout waiting for update") } }
func (n *ng) GetHost(key engine.HostKey) (*engine.Host, error) { hostKey := n.path("hosts", key.Name, "host") var host *host err := n.getJSONVal(hostKey, &host) if err != nil { return nil, err } var keyPair *engine.KeyPair if len(host.Settings.KeyPair) != 0 { if err := n.openSealedJSONVal(host.Settings.KeyPair, &keyPair); err != nil { return nil, err } } return engine.NewHost(key.Name, engine.HostSettings{Default: host.Settings.Default, KeyPair: keyPair, OCSP: host.Settings.OCSP}) }
func (s *StaplerSuite) TestStopInFlightTimers(c *C) { srv := testutils.NewOCSPResponder() defer srv.Close() h, err := engine.NewHost("localhost", engine.HostSettings{ KeyPair: &engine.KeyPair{Key: testutils.LocalhostKey, Cert: testutils.LocalhostCertChain}, OCSP: engine.OCSPSettings{Enabled: true, Period: "1h", Responders: []string{srv.URL}, SkipSignatureCheck: true}, }) c.Assert(err, IsNil) events := make(chan *StapleUpdated, 1) close := make(chan struct{}) s.st.Subscribe(events, close) re, err := s.st.StapleHost(h) c.Assert(err, IsNil) c.Assert(re, NotNil) c.Assert(re.Response.Status, Equals, ocsp.Good) }