Browse Source

Vendor new syslog library with TLS support.

The syslog package in the stdlib is not maintained anymore.

Signed-off-by: David Calavera <david.calavera@gmail.com>
David Calavera 9 years ago
parent
commit
145f020122

+ 1 - 0
hack/vendor.sh

@@ -23,6 +23,7 @@ clone git golang.org/x/net 47990a1ba55743e6ef1affd3a14e5bac8553615d https://gith
 clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3
 clone git github.com/docker/go-connections v0.1.2
 clone git github.com/docker/engine-api v0.1.3
+clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de
 
 #get libnetwork packages
 clone git github.com/docker/libnetwork 9f0563ea8f430d8828553aac97161cbff4056436

+ 1 - 0
vendor/src/github.com/RackSec/srslog/.gitignore

@@ -0,0 +1 @@
+.cover

+ 13 - 0
vendor/src/github.com/RackSec/srslog/.travis.yml

@@ -0,0 +1,13 @@
+sudo: required
+dist: trusty
+group: edge
+language: go
+go:
+- 1.5
+script:
+- |
+  go get ./...
+  go test -v ./...
+notifications:
+  slack:
+    secure: dtDue9gP6CRR1jYjEf6raXXFak3QKGcCFvCf5mfvv5XScdpmc3udwgqc5TdyjC0goaC9OK/4jTcCD30dYZm/u6ux3E9mo3xwMl2xRLHx76p5r9rSQtloH19BDwA2+A+bpDfFQVz05k2YXuTiGSvNMMdwzx+Dr294Sl/z43RFB4+b9/R/6LlFpRW89IwftvpLAFnBy4K/ZcspQzKM+rQfQTL5Kk+iZ/KBsuR/VziDq6MoJ8t43i4ee8vwS06vFBKDbUiZ4FIZpLgc2RAL5qso5aWRKYXL6waXfoKHZWKPe0w4+9IY1rDJxG1jEb7YGgcbLaF9xzPRRs2b2yO/c87FKpkh6PDgYHfLjpgXotCoojZrL4p1x6MI1ldJr3NhARGPxS9r4liB9n6Y5nD+ErXi1IMf55fuUHcPY27Jc0ySeLFeM6cIWJ8OhFejCgGw6a5DnnmJo0PqopsaBDHhadpLejT1+K6bL2iGkT4SLcVNuRGLs+VyuNf1+5XpkWZvy32vquO7SZOngLLBv+GIem+t3fWm0Z9s/0i1uRCQei1iUutlYjoV/LBd35H2rhob4B5phIuJin9kb0zbHf6HnaoN0CtN8r0d8G5CZiInVlG5Xcid5Byb4dddf5U2EJTDuCMVyyiM7tcnfjqw9UbVYNxtYM9SzcqIq+uVqM8pYL9xSec=

+ 50 - 0
vendor/src/github.com/RackSec/srslog/CODE_OF_CONDUCT.md

@@ -0,0 +1,50 @@
+# Contributor Code of Conduct
+
+As contributors and maintainers of this project, and in the interest of
+fostering an open and welcoming community, we pledge to respect all people who
+contribute through reporting issues, posting feature requests, updating
+documentation, submitting pull requests or patches, and other activities.
+
+We are committed to making participation in this project a harassment-free
+experience for everyone, regardless of level of experience, gender, gender
+identity and expression, sexual orientation, disability, personal appearance,
+body size, race, ethnicity, age, religion, or nationality.
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery
+* Personal attacks
+* Trolling or insulting/derogatory comments
+* Public or private harassment
+* Publishing other's private information, such as physical or electronic
+  addresses, without explicit permission
+* Other unethical or unprofessional conduct
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+By adopting this Code of Conduct, project maintainers commit themselves to
+fairly and consistently applying these principles to every aspect of managing
+this project. Project maintainers who do not follow or enforce the Code of
+Conduct may be permanently removed from the project team.
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting a project maintainer at [sirsean@gmail.com]. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. Maintainers are
+obligated to maintain confidentiality with regard to the reporter of an
+incident.
+
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 1.3.0, available at
+[http://contributor-covenant.org/version/1/3/0/][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/3/0/

+ 27 - 0
vendor/src/github.com/RackSec/srslog/LICENSE

@@ -0,0 +1,27 @@
+Copyright (c) 2015 Rackspace. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 131 - 0
vendor/src/github.com/RackSec/srslog/README.md

@@ -0,0 +1,131 @@
+[![Build Status](https://travis-ci.org/RackSec/srslog.svg?branch=master)](https://travis-ci.org/RackSec/srslog)
+
+# srslog
+
+Go has a `syslog` package in the standard library, but it has the following
+shortcomings:
+
+1. It doesn't have TLS support
+2. [According to bradfitz on the Go team, it is no longer being maintained.](https://github.com/golang/go/issues/13449#issuecomment-161204716)
+
+I agree that it doesn't need to be in the standard library. So, I've
+followed Brad's suggestion and have made a separate project to handle syslog.
+
+This code was taken directly from the Go project as a base to start from.
+
+However, this _does_ have TLS support.
+
+# Usage
+
+Basic usage retains the same interface as the original `syslog` package. We
+only added to the interface where required to support new functionality.
+
+Switch from the standard library:
+
+```
+import(
+    //"log/syslog"
+    syslog "github.com/RackSec/srslog"
+)
+```
+
+You can still use it for local syslog:
+
+```
+w, err := syslog.Dial("", "", syslog.LOG_ERR, "testtag")
+```
+
+Or to unencrypted UDP:
+
+```
+w, err := syslog.Dial("udp", "192.168.0.50:514", syslog.LOG_ERR, "testtag")
+```
+
+Or to unencrypted TCP:
+
+```
+w, err := syslog.Dial("tcp", "192.168.0.51:514", syslog.LOG_ERR, "testtag")
+```
+
+But now you can also send messages via TLS-encrypted TCP:
+
+```
+w, err := syslog.DialWithTLSCertPath("tcp+tls", "192.168.0.52:514", syslog.LOG_ERR, "testtag", "/path/to/servercert.pem")
+```
+
+And if you need more control over your TLS configuration :
+
+```
+pool := x509.NewCertPool()
+serverCert, err := ioutil.ReadFile("/path/to/servercert.pem")
+if err != nil {
+    return nil, err
+}
+pool.AppendCertsFromPEM(serverCert)
+config := tls.Config{
+    RootCAs: pool,
+}
+
+w, err := DialWithTLSConfig(network, raddr, priority, tag, &config)
+```
+
+(Note that in both TLS cases, this uses a self-signed certificate, where the
+remote syslog server has the keypair and the client has only the public key.)
+
+And then to write log messages, continue like so:
+
+```
+if err != nil {
+    log.Fatal("failed to connect to syslog:", err)
+}
+defer w.Close()
+
+w.Alert("this is an alert")
+w.Crit("this is critical")
+w.Err("this is an error")
+w.Warning("this is a warning")
+w.Notice("this is a notice")
+w.Info("this is info")
+w.Debug("this is debug")
+w.Write([]byte("these are some bytes"))
+```
+
+# Generating TLS Certificates
+
+We've provided a script that you can use to generate a self-signed keypair:
+
+```
+pip install cryptography
+python script/gen-certs.py
+```
+
+That outputs the public key and private key to standard out. Put those into
+`.pem` files. (And don't put them into any source control. The certificate in
+the `test` directory is used by the unit tests, and please do not actually use
+it anywhere else.)
+
+# Running Tests
+
+Run the tests as usual:
+
+```
+go test
+```
+
+But we've also provided a test coverage script that will show you which
+lines of code are not covered:
+
+```
+script/coverage --html
+```
+
+That will open a new browser tab showing coverage information.
+
+# License
+
+This project uses the New BSD License, the same as the Go project itself.
+
+# Code of Conduct
+
+Please note that this project is released with a Contributor Code of Conduct.
+By participating in this project you agree to abide by its terms.

+ 68 - 0
vendor/src/github.com/RackSec/srslog/constants.go

@@ -0,0 +1,68 @@
+package srslog
+
+import (
+	"errors"
+)
+
+// Priority is a combination of the syslog facility and
+// severity. For example, LOG_ALERT | LOG_FTP sends an alert severity
+// message from the FTP facility. The default severity is LOG_EMERG;
+// the default facility is LOG_KERN.
+type Priority int
+
+const severityMask = 0x07
+const facilityMask = 0xf8
+
+const (
+	// Severity.
+
+	// From /usr/include/sys/syslog.h.
+	// These are the same on Linux, BSD, and OS X.
+	LOG_EMERG Priority = iota
+	LOG_ALERT
+	LOG_CRIT
+	LOG_ERR
+	LOG_WARNING
+	LOG_NOTICE
+	LOG_INFO
+	LOG_DEBUG
+)
+
+const (
+	// Facility.
+
+	// From /usr/include/sys/syslog.h.
+	// These are the same up to LOG_FTP on Linux, BSD, and OS X.
+	LOG_KERN Priority = iota << 3
+	LOG_USER
+	LOG_MAIL
+	LOG_DAEMON
+	LOG_AUTH
+	LOG_SYSLOG
+	LOG_LPR
+	LOG_NEWS
+	LOG_UUCP
+	LOG_CRON
+	LOG_AUTHPRIV
+	LOG_FTP
+	_ // unused
+	_ // unused
+	_ // unused
+	_ // unused
+	LOG_LOCAL0
+	LOG_LOCAL1
+	LOG_LOCAL2
+	LOG_LOCAL3
+	LOG_LOCAL4
+	LOG_LOCAL5
+	LOG_LOCAL6
+	LOG_LOCAL7
+)
+
+func validatePriority(p Priority) error {
+	if p < 0 || p > LOG_LOCAL7|LOG_DEBUG {
+		return errors.New("log/syslog: invalid priority")
+	} else {
+		return nil
+	}
+}

+ 53 - 0
vendor/src/github.com/RackSec/srslog/dialer.go

@@ -0,0 +1,53 @@
+package srslog
+
+import (
+	"crypto/tls"
+	"net"
+)
+
+func (w Writer) getDialer() func() (serverConn, string, error) {
+	dialers := map[string]func() (serverConn, string, error){
+		"":        w.unixDialer,
+		"tcp+tls": w.tlsDialer,
+	}
+	dialer, ok := dialers[w.network]
+	if !ok {
+		dialer = w.basicDialer
+	}
+	return dialer
+}
+
+func (w Writer) unixDialer() (serverConn, string, error) {
+	sc, err := unixSyslog()
+	hostname := w.hostname
+	if hostname == "" {
+		hostname = "localhost"
+	}
+	return sc, hostname, err
+}
+
+func (w Writer) tlsDialer() (serverConn, string, error) {
+	c, err := tls.Dial("tcp", w.raddr, w.tlsConfig)
+	var sc serverConn
+	hostname := w.hostname
+	if err == nil {
+		sc = &netConn{conn: c}
+		if hostname == "" {
+			hostname = c.LocalAddr().String()
+		}
+	}
+	return sc, hostname, err
+}
+
+func (w Writer) basicDialer() (serverConn, string, error) {
+	c, err := net.Dial(w.network, w.raddr)
+	var sc serverConn
+	hostname := w.hostname
+	if err == nil {
+		sc = &netConn{conn: c}
+		if hostname == "" {
+			hostname = c.LocalAddr().String()
+		}
+	}
+	return sc, hostname, err
+}

+ 24 - 0
vendor/src/github.com/RackSec/srslog/net_conn.go

@@ -0,0 +1,24 @@
+package srslog
+
+import (
+	"fmt"
+	"net"
+	"os"
+	"time"
+)
+
+type netConn struct {
+	conn net.Conn
+}
+
+func (n *netConn) writeString(p Priority, hostname, tag, msg string) error {
+	timestamp := time.Now().Format(time.RFC3339)
+	_, err := fmt.Fprintf(n.conn, "<%d>%s %s %s[%d]: %s",
+		p, timestamp, hostname,
+		tag, os.Getpid(), msg)
+	return err
+}
+
+func (n *netConn) close() error {
+	return n.conn.Close()
+}

+ 96 - 0
vendor/src/github.com/RackSec/srslog/srslog.go

@@ -0,0 +1,96 @@
+package srslog
+
+import (
+	"crypto/tls"
+	"crypto/x509"
+	"io/ioutil"
+	"log"
+	"os"
+)
+
+// This interface and the separate syslog_unix.go file exist for
+// Solaris support as implemented by gccgo.  On Solaris you can not
+// simply open a TCP connection to the syslog daemon.  The gccgo
+// sources have a syslog_solaris.go file that implements unixSyslog to
+// return a type that satisfies this interface and simply calls the C
+// library syslog function.
+type serverConn interface {
+	writeString(p Priority, hostname, tag, s string) error
+	close() error
+}
+
+// New establishes a new connection to the system log daemon.  Each
+// write to the returned Writer sends a log message with the given
+// priority and prefix.
+func New(priority Priority, tag string) (w *Writer, err error) {
+	return Dial("", "", priority, tag)
+}
+
+// Dial establishes a connection to a log daemon by connecting to
+// address raddr on the specified network.  Each write to the returned
+// Writer sends a log message with the given facility, severity and
+// tag.
+// If network is empty, Dial will connect to the local syslog server.
+func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) {
+	return DialWithTLSConfig(network, raddr, priority, tag, nil)
+}
+
+// DialWithTLSCertPath establishes a secure connection to a log daemon by connecting to
+// address raddr on the specified network. It uses certPath to load TLS certificates and configure
+// the secure connection.
+func DialWithTLSCertPath(network, raddr string, priority Priority, tag, certPath string) (*Writer, error) {
+	pool := x509.NewCertPool()
+	serverCert, err := ioutil.ReadFile(certPath)
+	if err != nil {
+		return nil, err
+	}
+	pool.AppendCertsFromPEM(serverCert)
+	config := tls.Config{
+		RootCAs: pool,
+	}
+
+	return DialWithTLSConfig(network, raddr, priority, tag, &config)
+}
+
+// DialWithTLSConfig establishes a secure connection to a log daemon by connecting to
+// address raddr on the specified network. It uses tlsConfig to configure the secure connection.
+func DialWithTLSConfig(network, raddr string, priority Priority, tag string, tlsConfig *tls.Config) (*Writer, error) {
+	if err := validatePriority(priority); err != nil {
+		return nil, err
+	}
+
+	if tag == "" {
+		tag = os.Args[0]
+	}
+	hostname, _ := os.Hostname()
+
+	w := &Writer{
+		priority:  priority,
+		tag:       tag,
+		hostname:  hostname,
+		network:   network,
+		raddr:     raddr,
+		tlsConfig: tlsConfig,
+	}
+
+	w.Lock()
+	defer w.Unlock()
+
+	err := w.connect()
+	if err != nil {
+		return nil, err
+	}
+	return w, err
+}
+
+// NewLogger creates a log.Logger whose output is written to
+// the system log service with the specified priority. The logFlag
+// argument is the flag set passed through to log.New to create
+// the Logger.
+func NewLogger(p Priority, logFlag int) (*log.Logger, error) {
+	s, err := New(p, "")
+	if err != nil {
+		return nil, err
+	}
+	return log.New(s, "", logFlag), nil
+}

+ 47 - 0
vendor/src/github.com/RackSec/srslog/srslog_unix.go

@@ -0,0 +1,47 @@
+package srslog
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"os"
+	"time"
+)
+
+// unixSyslog opens a connection to the syslog daemon running on the
+// local machine using a Unix domain socket.
+
+func unixSyslog() (conn serverConn, err error) {
+	logTypes := []string{"unixgram", "unix"}
+	logPaths := []string{"/dev/log", "/var/run/syslog", "/var/run/log"}
+	for _, network := range logTypes {
+		for _, path := range logPaths {
+			conn, err := net.Dial(network, path)
+			if err != nil {
+				continue
+			} else {
+				return &localConn{conn: conn}, nil
+			}
+		}
+	}
+	return nil, errors.New("Unix syslog delivery error")
+}
+
+type localConn struct {
+	conn net.Conn
+}
+
+func (n *localConn) writeString(p Priority, hostname, tag, msg string) error {
+	// Compared to the network form at srslog.netConn, the changes are:
+	//	1. Use time.Stamp instead of time.RFC3339.
+	//	2. Drop the hostname field from the Fprintf.
+	timestamp := time.Now().Format(time.Stamp)
+	_, err := fmt.Fprintf(n.conn, "<%d>%s %s[%d]: %s",
+		p, timestamp,
+		tag, os.Getpid(), msg)
+	return err
+}
+
+func (n *localConn) close() error {
+	return n.conn.Close()
+}

+ 152 - 0
vendor/src/github.com/RackSec/srslog/writer.go

@@ -0,0 +1,152 @@
+package srslog
+
+import (
+	"crypto/tls"
+	"strings"
+	"sync"
+)
+
+// A Writer is a connection to a syslog server.
+type Writer struct {
+	sync.Mutex // guards conn
+
+	priority  Priority
+	tag       string
+	hostname  string
+	network   string
+	raddr     string
+	tlsConfig *tls.Config
+
+	conn serverConn
+}
+
+// connect makes a connection to the syslog server.
+// It must be called with w.mu held.
+func (w *Writer) connect() (err error) {
+	if w.conn != nil {
+		// ignore err from close, it makes sense to continue anyway
+		w.conn.close()
+		w.conn = nil
+	}
+
+	var conn serverConn
+	var hostname string
+	dialer := w.getDialer()
+	conn, hostname, err = dialer()
+	if err == nil {
+		w.conn = conn
+		w.hostname = hostname
+	}
+
+	return
+}
+
+// Write sends a log message to the syslog daemon using the default priority
+// passed into `srslog.New` or the `srslog.Dial*` functions.
+func (w *Writer) Write(b []byte) (int, error) {
+	return w.writeAndRetry(w.priority, string(b))
+}
+
+// Close closes a connection to the syslog daemon.
+func (w *Writer) Close() error {
+	w.Lock()
+	defer w.Unlock()
+
+	if w.conn != nil {
+		err := w.conn.close()
+		w.conn = nil
+		return err
+	}
+	return nil
+}
+
+// Emerg logs a message with severity LOG_EMERG; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Emerg(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_EMERG, m)
+	return err
+}
+
+// Alert logs a message with severity LOG_ALERT; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Alert(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_ALERT, m)
+	return err
+}
+
+// Crit logs a message with severity LOG_CRIT; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Crit(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_CRIT, m)
+	return err
+}
+
+// Err logs a message with severity LOG_ERR; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Err(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_ERR, m)
+	return err
+}
+
+// Warning logs a message with severity LOG_WARNING; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Warning(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_WARNING, m)
+	return err
+}
+
+// Notice logs a message with severity LOG_NOTICE; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Notice(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_NOTICE, m)
+	return err
+}
+
+// Info logs a message with severity LOG_INFO; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Info(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_INFO, m)
+	return err
+}
+
+// Debug logs a message with severity LOG_DEBUG; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Debug(m string) (err error) {
+	_, err = w.writeAndRetry(LOG_DEBUG, m)
+	return err
+}
+
+func (w *Writer) writeAndRetry(p Priority, s string) (int, error) {
+	pr := (w.priority & facilityMask) | (p & severityMask)
+
+	w.Lock()
+	defer w.Unlock()
+
+	if w.conn != nil {
+		if n, err := w.write(pr, s); err == nil {
+			return n, err
+		}
+	}
+	if err := w.connect(); err != nil {
+		return 0, err
+	}
+	return w.write(pr, s)
+}
+
+// write generates and writes a syslog formatted string. The
+// format is as follows: <PRI>TIMESTAMP HOSTNAME TAG[PID]: MSG
+func (w *Writer) write(p Priority, msg string) (int, error) {
+	// ensure it ends in a \n
+	if !strings.HasSuffix(msg, "\n") {
+		msg += "\n"
+	}
+
+	err := w.conn.writeString(p, w.hostname, w.tag, msg)
+	if err != nil {
+		return 0, err
+	}
+	// Note: return the length of the input, not the number of
+	// bytes printed by Fprintf, because this must behave like
+	// an io.Writer.
+	return len(msg), nil
+}