func (s *RsyslogSuite) TestRsyslogCert(c *gc.C) { st, m := s.st, s.machine err := s.machine.SetProviderAddresses(network.NewAddress("example.com")) c.Assert(err, jc.ErrorIsNil) worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, m.Tag(), "", []string{"0.1.2.3"}) c.Assert(err, jc.ErrorIsNil) defer func() { c.Assert(worker.Wait(), gc.IsNil) }() defer worker.Kill() waitForFile(c, filepath.Join(*rsyslog.LogDir, "rsyslog-cert.pem")) rsyslogCertPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "rsyslog-cert.pem")) c.Assert(err, jc.ErrorIsNil) cert, err := cert.ParseCert(string(rsyslogCertPEM)) c.Assert(err, jc.ErrorIsNil) c.Assert(cert.DNSNames, gc.DeepEquals, []string{"example.com", "*"}) subject := cert.Subject c.Assert(subject.CommonName, gc.Equals, "*") c.Assert(subject.Organization, gc.DeepEquals, []string{"juju"}) issuer := cert.Issuer c.Assert(issuer.CommonName, gc.Equals, "juju-generated CA for environment \"rsyslog\"") c.Assert(issuer.Organization, gc.DeepEquals, []string{"juju"}) }
func (s *RsyslogSuite) TestModeForwarding(c *gc.C) { err := s.APIState.Client().EnvironmentSet(map[string]interface{}{ "rsyslog-ca-cert": coretesting.CACert, "rsyslog-ca-key": coretesting.CAKey, }) c.Assert(err, jc.ErrorIsNil) st, m := s.OpenAPIAsNewMachine(c, state.JobHostUnits) addrs := []string{"0.1.2.3", "0.2.4.6"} worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeForwarding, m.Tag(), "foo", addrs, s.ConfDir()) c.Assert(err, jc.ErrorIsNil) defer func() { c.Assert(worker.Wait(), gc.IsNil) }() defer worker.Kill() // We should get a ca-cert.pem with the contents introduced into state config. dirname := filepath.Join(s.ConfDir()+"-foo", "rsyslog") waitForFile(c, filepath.Join(dirname, "ca-cert.pem")) caCertPEM, err := ioutil.ReadFile(filepath.Join(dirname, "ca-cert.pem")) c.Assert(err, jc.ErrorIsNil) c.Assert(string(caCertPEM), gc.DeepEquals, coretesting.CACert) c.Assert(*rsyslog.SyslogTargets, gc.HasLen, 2) s.mu.Lock() tags := s.dialTags s.mu.Unlock() for _, dialTag := range tags { c.Check(dialTag, gc.Equals, "juju-foo-"+m.Tag().String()) } }
func (s *RsyslogSuite) TestStartStop(c *gc.C) { st, m := s.OpenAPIAsNewMachine(c, state.JobHostUnits) worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeForwarding, m.Tag(), "", []string{"0.1.2.3"}) c.Assert(err, jc.ErrorIsNil) worker.Kill() c.Assert(worker.Wait(), gc.IsNil) }
// TestModeAccumulateCertsExist is a regression test for // https://bugs.launchpad.net/juju-core/+bug/1464335, // where the CA certs existing (in local provider) at // bootstrap caused the worker to not publish to state. func (s *RsyslogSuite) TestModeAccumulateCertsExistOnDisk(c *gc.C) { dirname := filepath.Join(s.ConfDir(), "rsyslog") err := os.MkdirAll(dirname, 0755) c.Assert(err, jc.ErrorIsNil) err = ioutil.WriteFile(filepath.Join(dirname, "ca-cert.pem"), nil, 0644) c.Assert(err, jc.ErrorIsNil) st, m := s.st, s.machine worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, m.Tag(), "", nil, s.ConfDir()) c.Assert(err, jc.ErrorIsNil) // The worker should create certs and publish to state during setup, // so we can kill and wait and be confident that the task is done. worker.Kill() c.Assert(worker.Wait(), jc.ErrorIsNil) // The CA cert and key should have been published to state. cfg, err := s.State.EnvironConfig() c.Assert(err, jc.ErrorIsNil) c.Assert(cfg.AllAttrs()["rsyslog-ca-cert"], gc.NotNil) c.Assert(cfg.AllAttrs()["rsyslog-ca-key"], gc.NotNil) // ca-cert.pem isn't updated on disk until the worker reacts to the // state change. Let's just ensure that rsyslog-ca-cert is a valid // certificate, and no the zero-length string we wrote to ca-cert.pem. caCertPEM := cfg.AllAttrs()["rsyslog-ca-cert"].(string) c.Assert(err, jc.ErrorIsNil) block, _ := pem.Decode([]byte(caCertPEM)) c.Assert(block, gc.NotNil) _, err = x509.ParseCertificate(block.Bytes) c.Assert(err, jc.ErrorIsNil) }
// testNamespace starts a worker and ensures that // the rsyslog config file has the expected filename, // and the appropriate log dir is used. func (s *RsyslogSuite) testNamespace(c *gc.C, st *api.State, tag names.Tag, namespace, expectedFilename, expectedLogDir string) { restarted := make(chan struct{}, 2) // once for create, once for teardown s.PatchValue(rsyslog.RestartRsyslog, func() error { restarted <- struct{}{} return nil }) err := os.MkdirAll(expectedLogDir, 0755) c.Assert(err, jc.ErrorIsNil) worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, tag, namespace, []string{"0.1.2.3"}) c.Assert(err, jc.ErrorIsNil) defer func() { c.Assert(worker.Wait(), gc.IsNil) }() defer worker.Kill() // change the API HostPorts to trigger an rsyslog restart newHostPorts := network.NewHostPorts(6541, "127.0.0.1") err = s.State.SetAPIHostPorts([][]network.HostPort{newHostPorts}) c.Assert(err, jc.ErrorIsNil) // Wait for rsyslog to be restarted, so we can check to see // what the name of the config file is. waitForRestart(c, restarted) // Ensure that ca-cert.pem gets written to the expected log dir. waitForFile(c, filepath.Join(expectedLogDir, "ca-cert.pem")) dir, err := os.Open(*rsyslog.RsyslogConfDir) c.Assert(err, jc.ErrorIsNil) names, err := dir.Readdirnames(-1) dir.Close() c.Assert(err, jc.ErrorIsNil) c.Assert(names, gc.HasLen, 1) c.Assert(names[0], gc.Equals, expectedFilename) }
func (s *RsyslogSuite) TestModeAccumulate(c *gc.C) { st, m := s.st, s.machine worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, m.Tag().String(), "", nil) c.Assert(err, gc.IsNil) defer func() { c.Assert(worker.Wait(), gc.IsNil) }() defer worker.Kill() waitForFile(c, filepath.Join(*rsyslog.LogDir, "ca-cert.pem")) // We should have ca-cert.pem, rsyslog-cert.pem, and rsyslog-key.pem. caCertPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "ca-cert.pem")) c.Assert(err, gc.IsNil) rsyslogCertPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "rsyslog-cert.pem")) c.Assert(err, gc.IsNil) rsyslogKeyPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "rsyslog-key.pem")) c.Assert(err, gc.IsNil) _, _, err = cert.ParseCertAndKey(string(rsyslogCertPEM), string(rsyslogKeyPEM)) c.Assert(err, gc.IsNil) err = cert.Verify(string(rsyslogCertPEM), string(caCertPEM), time.Now().UTC()) c.Assert(err, gc.IsNil) // Verify rsyslog configuration. waitForFile(c, filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf")) rsyslogConf, err := ioutil.ReadFile(filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf")) c.Assert(err, gc.IsNil) syslogPort := s.Conn.Environ.Config().SyslogPort() syslogConfig := syslog.NewAccumulateConfig(m.Tag().String(), *rsyslog.LogDir, syslogPort, "", []string{}) syslogConfig.ConfigDir = *rsyslog.RsyslogConfDir rendered, err := syslogConfig.Render() c.Assert(err, gc.IsNil) c.Assert(string(rsyslogConf), gc.DeepEquals, string(rendered)) }
func (s *RsyslogSuite) TestModeForwarding(c *gc.C) { err := s.APIState.Client().EnvironmentSet(map[string]interface{}{"rsyslog-ca-cert": coretesting.CACert}) c.Assert(err, gc.IsNil) st, m := s.OpenAPIAsNewMachine(c, state.JobHostUnits) addrs := []string{"0.1.2.3", "0.2.4.6"} worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeForwarding, m.Tag().String(), "", addrs) c.Assert(err, gc.IsNil) defer func() { c.Assert(worker.Wait(), gc.IsNil) }() defer worker.Kill() // We should get a ca-cert.pem with the contents introduced into state config. waitForFile(c, filepath.Join(*rsyslog.LogDir, "ca-cert.pem")) caCertPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "ca-cert.pem")) c.Assert(err, gc.IsNil) c.Assert(string(caCertPEM), gc.DeepEquals, coretesting.CACert) // Verify rsyslog configuration. waitForFile(c, filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf")) rsyslogConf, err := ioutil.ReadFile(filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf")) c.Assert(err, gc.IsNil) syslogPort := s.Conn.Environ.Config().SyslogPort() syslogConfig := syslog.NewForwardConfig(m.Tag().String(), *rsyslog.LogDir, syslogPort, "", addrs) syslogConfig.ConfigDir = *rsyslog.RsyslogConfDir rendered, err := syslogConfig.Render() c.Assert(err, gc.IsNil) c.Assert(string(rsyslogConf), gc.DeepEquals, string(rendered)) }
func (s *RsyslogSuite) TestTearDown(c *gc.C) { st, m := s.st, s.machine worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, m.Tag(), "", []string{"0.1.2.3"}) c.Assert(err, jc.ErrorIsNil) confFile := filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf") // On worker teardown, the rsyslog config file should be removed. defer func() { _, err := os.Stat(confFile) c.Assert(err, jc.Satisfies, os.IsNotExist) }() defer func() { c.Assert(worker.Wait(), gc.IsNil) }() defer worker.Kill() waitForFile(c, confFile) }
func (s *RsyslogSuite) TestModeAccumulate(c *gc.C) { st, m := s.st, s.machine worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeAccumulate, m.Tag(), "", nil, s.ConfDir()) c.Assert(err, jc.ErrorIsNil) defer func() { c.Assert(worker.Wait(), gc.IsNil) }() defer worker.Kill() dirname := filepath.Join(s.ConfDir(), "rsyslog") waitForFile(c, filepath.Join(dirname, "ca-cert.pem")) // We should have ca-cert.pem, rsyslog-cert.pem, and rsyslog-key.pem. caCertPEM, err := ioutil.ReadFile(filepath.Join(dirname, "ca-cert.pem")) c.Assert(err, jc.ErrorIsNil) rsyslogCertPEM, err := ioutil.ReadFile(filepath.Join(dirname, "rsyslog-cert.pem")) c.Assert(err, jc.ErrorIsNil) rsyslogKeyPEM, err := ioutil.ReadFile(filepath.Join(dirname, "rsyslog-key.pem")) c.Assert(err, jc.ErrorIsNil) _, _, err = cert.ParseCertAndKey(string(rsyslogCertPEM), string(rsyslogKeyPEM)) c.Assert(err, jc.ErrorIsNil) err = cert.Verify(string(rsyslogCertPEM), string(caCertPEM), time.Now().UTC()) c.Assert(err, jc.ErrorIsNil) // Verify rsyslog configuration. waitForFile(c, filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf")) rsyslogConf, err := ioutil.ReadFile(filepath.Join(*rsyslog.RsyslogConfDir, "25-juju.conf")) c.Assert(err, jc.ErrorIsNil) syslogPort := s.Environ.Config().SyslogPort() syslogConfig := &syslog.SyslogConfig{ LogFileName: m.Tag().String(), LogDir: *rsyslog.LogDir, Port: syslogPort, Namespace: "", StateServerAddresses: []string{}, } syslog.NewAccumulateConfig(syslogConfig) syslogConfig.ConfigDir = *rsyslog.RsyslogConfDir syslogConfig.JujuConfigDir = filepath.Join(s.ConfDir(), "rsyslog") rendered, err := syslogConfig.Render() c.Assert(err, jc.ErrorIsNil) c.Assert(string(rsyslogConf), gc.DeepEquals, string(rendered)) // Verify logrotate files assertPathExists(c, filepath.Join(dirname, "logrotate.conf")) assertPathExists(c, filepath.Join(dirname, "logrotate.run")) }
func (s *RsyslogSuite) TestModeForwarding(c *gc.C) { err := s.APIState.Client().EnvironmentSet(map[string]interface{}{"rsyslog-ca-cert": coretesting.CACert}) c.Assert(err, gc.IsNil) st, m := s.OpenAPIAsNewMachine(c, state.JobHostUnits) addrs := []string{"0.1.2.3", "0.2.4.6"} worker, err := rsyslog.NewRsyslogConfigWorker(st.Rsyslog(), rsyslog.RsyslogModeForwarding, m.Tag(), "", addrs) c.Assert(err, gc.IsNil) defer func() { c.Assert(worker.Wait(), gc.IsNil) }() defer worker.Kill() // We should get a ca-cert.pem with the contents introduced into state config. waitForFile(c, filepath.Join(*rsyslog.LogDir, "ca-cert.pem")) caCertPEM, err := ioutil.ReadFile(filepath.Join(*rsyslog.LogDir, "ca-cert.pem")) c.Assert(err, gc.IsNil) c.Assert(string(caCertPEM), gc.DeepEquals, coretesting.CACert) c.Assert(*rsyslog.SyslogTargets, gc.HasLen, 2) }
func HookExecutionLock(dataDir string) (*fslock.Lock, error) { lockDir := filepath.Join(dataDir, "locks") return fslock.NewLock(lockDir, "uniter-hook-execution") } // NewRsyslogConfigWorker creates and returns a new // RsyslogConfigWorker based on the specified configuration // parameters. var NewRsyslogConfigWorker = func(st *apirsyslog.State, agentConfig agent.Config, mode rsyslog.RsyslogMode) (worker.Worker, error) { tag := agentConfig.Tag() namespace := agentConfig.Value(agent.Namespace) addrs, err := agentConfig.APIAddresses() if err != nil { return nil, err } return rsyslog.NewRsyslogConfigWorker(st, mode, tag, namespace, addrs, agent.DefaultPaths.ConfDir) } // ParamsStateServingInfoToStateStateServingInfo converts a // params.StateServingInfo to a state.StateServingInfo. func ParamsStateServingInfoToStateStateServingInfo(i params.StateServingInfo) state.StateServingInfo { return state.StateServingInfo{ APIPort: i.APIPort, StatePort: i.StatePort, Cert: i.Cert, PrivateKey: i.PrivateKey, CAPrivateKey: i.CAPrivateKey, SharedSecret: i.SharedSecret, SystemIdentity: i.SystemIdentity, } }
} // newDeployContext gives the tests the opportunity to create a deployer.Context // that can be used for testing so as to avoid (1) deploying units to the system // running the tests and (2) get access to the *State used internally, so that // tests can be run without waiting for the 5s watcher refresh time to which we would // otherwise be restricted. var newDeployContext = func(st *apideployer.State, agentConfig agent.Config) deployer.Context { return deployer.NewSimpleContext(agentConfig, st) } // newRsyslogConfigWorker creates and returns a new RsyslogConfigWorker // based on the specified configuration parameters. var newRsyslogConfigWorker = func(st *apirsyslog.State, agentConfig agent.Config, mode rsyslog.RsyslogMode) (worker.Worker, error) { tag := agentConfig.Tag() namespace := agentConfig.Value(agent.Namespace) addrs, err := agentConfig.APIAddresses() if err != nil { return nil, err } return rsyslog.NewRsyslogConfigWorker(st, mode, tag, namespace, addrs) } // hookExecutionLock returns an *fslock.Lock suitable for use as a unit // hook execution lock. Other workers may also use this lock if they // require isolation from hook execution. func hookExecutionLock(dataDir string) (*fslock.Lock, error) { lockDir := filepath.Join(dataDir, "locks") return fslock.NewLock(lockDir, "uniter-hook-execution") }
func HookExecutionLock(dataDir string) (*fslock.Lock, error) { lockDir := filepath.Join(dataDir, "locks") return fslock.NewLock(lockDir, "uniter-hook-execution") } // NewRsyslogConfigWorker creates and returns a new // RsyslogConfigWorker based on the specified configuration // parameters. var NewRsyslogConfigWorker = func(st *apirsyslog.State, agentConfig agent.Config, mode rsyslog.RsyslogMode) (worker.Worker, error) { tag := agentConfig.Tag() namespace := agentConfig.Value(agent.Namespace) addrs, err := agentConfig.APIAddresses() if err != nil { return nil, err } return rsyslog.NewRsyslogConfigWorker(st, mode, tag, namespace, addrs, agentConfig.DataDir()) } // ParamsStateServingInfoToStateStateServingInfo converts a // params.StateServingInfo to a state.StateServingInfo. func ParamsStateServingInfoToStateStateServingInfo(i params.StateServingInfo) state.StateServingInfo { return state.StateServingInfo{ APIPort: i.APIPort, StatePort: i.StatePort, Cert: i.Cert, PrivateKey: i.PrivateKey, CAPrivateKey: i.CAPrivateKey, SharedSecret: i.SharedSecret, SystemIdentity: i.SystemIdentity, } }