Commit dd831517 authored by ale's avatar ale

Update go-common and other dependencies

parent 0eb2c78d
Pipeline #1416 passed with stages
in 1 minute and 9 seconds
......@@ -40,6 +40,8 @@ type cacheDatum struct {
deadline time.Time
}
var dnsCacheTTL = 1 * time.Minute
type dnsCache struct {
resolver resolver
sf singleflight.Group
......@@ -72,7 +74,7 @@ func (c *dnsCache) update(host string) []string {
c.mx.Lock()
c.cache[host] = cacheDatum{
addrs: addrs,
deadline: time.Now().Add(60 * time.Second),
deadline: time.Now().Add(dnsCacheTTL),
}
c.mx.Unlock()
return addrs, nil
......
package clientutil
import (
"fmt"
"sync"
"time"
)
var dnsWatcherInterval = 1 * time.Minute
// A DNSWatcher monitors a DNS name for changes, constantly attempting
// to resolve it every minute and notifying a channel when the list of
// returned IP addresses changes. All addresses must be in host:port
// format.
type DNSWatcher struct {
hostport string
resolver resolver
addrs []string
updateCh chan []string
stopCh chan struct{}
}
// NewDNSWatcher creates a new DNSWatcher.
func NewDNSWatcher(hostport string) (*DNSWatcher, error) {
return newDNSWatcherWithResolver(hostport, defaultResolver)
}
func newDNSWatcherWithResolver(hostport string, resolver resolver) (*DNSWatcher, error) {
// Resolve names once before returning. Return a fatal error
// when there are no results, as it may indicate a syntax
// error in hostport.
addrs := resolver.ResolveIP(hostport)
if len(addrs) == 0 {
return nil, fmt.Errorf("can't resolve %s", hostport)
}
w := &DNSWatcher{
hostport: hostport,
resolver: resolver,
addrs: addrs,
updateCh: make(chan []string, 10),
stopCh: make(chan struct{}),
}
w.updateCh <- addrs
go w.loop()
return w, nil
}
// Stop the watcher.
func (w *DNSWatcher) Stop() {
close(w.stopCh)
}
// Changes returns a channel where the resolved addresses are sent
// whenever they change.
func (w *DNSWatcher) Changes() <-chan []string {
return w.updateCh
}
func (w *DNSWatcher) check() {
addrs := w.resolver.ResolveIP(w.hostport)
if len(addrs) > 0 && !addrListEqual(addrs, w.addrs) {
w.addrs = addrs
w.updateCh <- addrs
}
}
func (w *DNSWatcher) loop() {
defer close(w.updateCh)
tick := time.NewTicker(dnsWatcherInterval)
defer tick.Stop()
for {
select {
case <-tick.C:
w.check()
case <-w.stopCh:
return
}
}
}
type multiDNSUpdate struct {
hostport string
addrs []string
}
// A MultiDNSWatcher watches multiple addresses for DNS changes. The
// results are merged and returned as a list of addresses.
type MultiDNSWatcher struct {
watchers []*DNSWatcher
addrmap map[string][]string
faninCh chan multiDNSUpdate
updateCh chan []string
}
// NewMultiDNSWatcher creates a new MultiDNSWatcher.
func NewMultiDNSWatcher(hostports []string) (*MultiDNSWatcher, error) {
return newMultiDNSWatcherWithResolver(hostports, defaultResolver)
}
func newMultiDNSWatcherWithResolver(hostports []string, resolver resolver) (*MultiDNSWatcher, error) {
mw := &MultiDNSWatcher{
addrmap: make(map[string][]string),
faninCh: make(chan multiDNSUpdate, 10),
updateCh: make(chan []string, 10),
}
// All the MultiDNSWatcher does is multiplex updates from the
// individual DNSWatchers onto faninCh, then merging those
// updates with all the others and sending the result to
// updateCh.
go func() {
defer close(mw.updateCh)
for up := range mw.faninCh {
mw.addrmap[up.hostport] = up.addrs
mw.updateCh <- mw.allAddrs()
}
}()
var wg sync.WaitGroup
for _, hostport := range hostports {
w, err := newDNSWatcherWithResolver(hostport, resolver)
if err != nil {
return nil, err
}
mw.watchers = append(mw.watchers, w)
wg.Add(1)
go func(hostport string) {
for addrs := range w.Changes() {
mw.faninCh <- multiDNSUpdate{
hostport: hostport,
addrs: addrs,
}
}
wg.Done()
}(hostport)
}
go func() {
wg.Wait()
close(mw.faninCh)
}()
return mw, nil
}
func (mw *MultiDNSWatcher) allAddrs() []string {
var out []string
for _, addrs := range mw.addrmap {
out = append(out, addrs...)
}
return out
}
// Stop the watcher.
func (mw *MultiDNSWatcher) Stop() {
for _, w := range mw.watchers {
w.Stop()
}
}
// Changes returns a channel where the aggregate resolved addresses
// are sent whenever they change.
func (mw *MultiDNSWatcher) Changes() <-chan []string {
return mw.updateCh
}
func addrListEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
tmp := make(map[string]struct{})
for _, aa := range a {
tmp[aa] = struct{}{}
}
for _, bb := range b {
if _, ok := tmp[bb]; !ok {
return false
}
delete(tmp, bb)
}
return len(tmp) == 0
}
......@@ -79,7 +79,7 @@ func NewUNIXSocketServer(socketPath string, h Handler) (*SocketServer, error) {
// NewSystemdSocketServer uses systemd socket activation, receiving
// the open socket as a file descriptor on exec.
func NewSystemdSocketServer(h Handler) (*SocketServer, error) {
listeners, err := activation.Listeners(false)
listeners, err := activation.Listeners()
if err != nil {
return nil, err
}
......
......@@ -7,7 +7,7 @@ import (
"io"
"github.com/lunixbochs/struc"
"github.com/miscreant/miscreant/go"
"github.com/miscreant/miscreant-go"
"golang.org/x/crypto/argon2"
)
......
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite tests="2" failures="0" time="0.000" name="git.autistici.org/id/go-sso">
<properties>
<property name="go.version" value="go1.10.3"></property>
</properties>
<testcase classname="go-sso" name="TestEd25519" time="0.000"></testcase>
<testcase classname="go-sso" name="TestLegacy" time="0.000"></testcase>
</testsuite>
<testsuite tests="1" failures="0" time="0.000" name="git.autistici.org/id/go-sso/cmd/sso-server">
<properties>
<property name="go.version" value="go1.10.3"></property>
</properties>
<testcase classname="sso-server" name="TestMain_LoadConfig" time="0.000"></testcase>
</testsuite>
<testsuite tests="1" failures="0" time="0.000" name="git.autistici.org/id/go-sso/httpsso">
<properties>
<property name="go.version" value="go1.10.3"></property>
</properties>
<testcase classname="httpsso" name="TestSSOWrapper" time="0.010"></testcase>
</testsuite>
<testsuite tests="1" failures="0" time="0.000" name="git.autistici.org/id/go-sso/httputil">
<properties>
<property name="go.version" value="go1.10.3"></property>
</properties>
<testcase classname="httputil" name="TestExpiringSession" time="0.000"></testcase>
</testsuite>
<testsuite tests="1" failures="0" time="0.000" name="git.autistici.org/id/go-sso/proxy">
<properties>
<property name="go.version" value="go1.10.3"></property>
</properties>
<testcase classname="proxy" name="TestProxy" time="0.010"></testcase>
</testsuite>
<testsuite tests="6" failures="0" time="0.000" name="git.autistici.org/id/go-sso/server">
<properties>
<property name="go.version" value="go1.10.3"></property>
</properties>
<testcase classname="server" name="TestHTTP_ServeStaticAsset" time="0.010"></testcase>
<testcase classname="server" name="TestHTTP_Login" time="0.000"></testcase>
<testcase classname="server" name="TestHTTP_LoginOTP" time="0.000"></testcase>
<testcase classname="server" name="TestHTTP_LoginWithKeyStore" time="0.010"></testcase>
<testcase classname="server" name="TestLoginService_Ok" time="0.000"></testcase>
<testcase classname="server" name="TestLoginService_SanityChecks" time="0.000"></testcase>
</testsuite>
</testsuites>
......@@ -77,15 +77,20 @@ func NewHighBiased(epsilon float64) *Stream {
// is guaranteed to be within (Quantile±Epsilon).
//
// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
func NewTargeted(targets map[float64]float64) *Stream {
func NewTargeted(targetMap map[float64]float64) *Stream {
// Convert map to slice to avoid slow iterations on a map.
// ƒ is called on the hot path, so converting the map to a slice
// beforehand results in significant CPU savings.
targets := targetMapToSlice(targetMap)
ƒ := func(s *stream, r float64) float64 {
var m = math.MaxFloat64
var f float64
for quantile, epsilon := range targets {
if quantile*s.n <= r {
f = (2 * epsilon * r) / quantile
for _, t := range targets {
if t.quantile*s.n <= r {
f = (2 * t.epsilon * r) / t.quantile
} else {
f = (2 * epsilon * (s.n - r)) / (1 - quantile)
f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile)
}
if f < m {
m = f
......@@ -96,6 +101,25 @@ func NewTargeted(targets map[float64]float64) *Stream {
return newStream(ƒ)
}
type target struct {
quantile float64
epsilon float64
}
func targetMapToSlice(targetMap map[float64]float64) []target {
targets := make([]target, 0, len(targetMap))
for quantile, epsilon := range targetMap {
t := target{
quantile: quantile,
epsilon: epsilon,
}
targets = append(targets, t)
}
return targets
}
// Stream computes quantiles for a stream of float64s. It is not thread-safe by
// design. Take care when using across multiple goroutines.
type Stream struct {
......
CoreOS Project
Copyright 2018 CoreOS, Inc
This product includes software developed at CoreOS, Inc.
(http://www.coreos.com/).
......@@ -18,18 +18,26 @@ package activation
import (
"os"
"strconv"
"strings"
"syscall"
)
// based on: https://gist.github.com/alberts/4640792
const (
// listenFdsStart corresponds to `SD_LISTEN_FDS_START`.
listenFdsStart = 3
)
// Files returns a slice containing a `os.File` object for each
// file descriptor passed to this process via systemd fd-passing protocol.
//
// The order of the file descriptors is preserved in the returned slice.
// `unsetEnv` is typically set to `true` in order to avoid clashes in
// fd usage and to avoid leaking environment flags to child processes.
func Files(unsetEnv bool) []*os.File {
if unsetEnv {
defer os.Unsetenv("LISTEN_PID")
defer os.Unsetenv("LISTEN_FDS")
defer os.Unsetenv("LISTEN_FDNAMES")
}
pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
......@@ -42,10 +50,17 @@ func Files(unsetEnv bool) []*os.File {
return nil
}
names := strings.Split(os.Getenv("LISTEN_FDNAMES"), ":")
files := make([]*os.File, 0, nfds)
for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ {
syscall.CloseOnExec(fd)
files = append(files, os.NewFile(uintptr(fd), "LISTEN_FD_"+strconv.Itoa(fd)))
name := "LISTEN_FD_" + strconv.Itoa(fd)
offset := fd - listenFdsStart
if offset < len(names) && len(names[offset]) > 0 {
name = names[offset]
}
files = append(files, os.NewFile(uintptr(fd), name))
}
return files
......
......@@ -25,13 +25,33 @@ import (
// The order of the file descriptors is preserved in the returned slice.
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
// corresponding with "udp, tcp, tcp", then the slice would contain {nil, net.Listener, net.Listener}
func Listeners(unsetEnv bool) ([]net.Listener, error) {
files := Files(unsetEnv)
func Listeners() ([]net.Listener, error) {
files := Files(true)
listeners := make([]net.Listener, len(files))
for i, f := range files {
if pc, err := net.FileListener(f); err == nil {
listeners[i] = pc
f.Close()
}
}
return listeners, nil
}
// ListenersWithNames maps a listener name to a set of net.Listener instances.
func ListenersWithNames() (map[string][]net.Listener, error) {
files := Files(true)
listeners := map[string][]net.Listener{}
for _, f := range files {
if pc, err := net.FileListener(f); err == nil {
current, ok := listeners[f.Name()]
if !ok {
listeners[f.Name()] = []net.Listener{pc}
} else {
listeners[f.Name()] = append(current, pc)
}
f.Close()
}
}
return listeners, nil
......@@ -40,8 +60,8 @@ func Listeners(unsetEnv bool) ([]net.Listener, error) {
// TLSListeners returns a slice containing a net.listener for each matching TCP socket type
// passed to this process.
// It uses default Listeners func and forces TCP sockets handlers to use TLS based on tlsConfig.
func TLSListeners(unsetEnv bool, tlsConfig *tls.Config) ([]net.Listener, error) {
listeners, err := Listeners(unsetEnv)
func TLSListeners(tlsConfig *tls.Config) ([]net.Listener, error) {
listeners, err := Listeners()
if listeners == nil || err != nil {
return nil, err
......@@ -58,3 +78,26 @@ func TLSListeners(unsetEnv bool, tlsConfig *tls.Config) ([]net.Listener, error)
return listeners, err
}
// TLSListenersWithNames maps a listener name to a net.Listener with
// the associated TLS configuration.
func TLSListenersWithNames(tlsConfig *tls.Config) (map[string][]net.Listener, error) {
listeners, err := ListenersWithNames()
if listeners == nil || err != nil {
return nil, err
}
if tlsConfig != nil && err == nil {
for _, ll := range listeners {
// Activate TLS only for TCP sockets
for i, l := range ll {
if l.Addr().Network() == "tcp" {
ll[i] = tls.NewListener(l, tlsConfig)
}
}
}
}
return listeners, err
}
......@@ -24,13 +24,14 @@ import (
// The order of the file descriptors is preserved in the returned slice.
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
// corresponding with "udp, tcp, udp", then the slice would contain {net.PacketConn, nil, net.PacketConn}
func PacketConns(unsetEnv bool) ([]net.PacketConn, error) {
files := Files(unsetEnv)
func PacketConns() ([]net.PacketConn, error) {
files := Files(true)
conns := make([]net.PacketConn, len(files))
for i, f := range files {
if pc, err := net.FilePacketConn(f); err == nil {
conns[i] = pc
f.Close()
}
}
return conns, nil
......
// Copyright 2014 Docker, Inc.
// Copyright 2015-2018 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
......@@ -13,7 +14,11 @@
// limitations under the License.
//
// Code forked from Docker project
// Package daemon provides a Go implementation of the sd_notify protocol.
// It can be used to inform systemd of service start-up completion, watchdog
// events, and other status changes.
//
// https://www.freedesktop.org/software/systemd/man/sd_notify.html#Description
package daemon
import (
......@@ -21,6 +26,25 @@ import (
"os"
)
const (
// SdNotifyReady tells the service manager that service startup is finished
// or the service finished loading its configuration.
SdNotifyReady = "READY=1"
// SdNotifyStopping tells the service manager that the service is beginning
// its shutdown.
SdNotifyStopping = "STOPPING=1"
// SdNotifyReloading tells the service manager that this service is
// reloading its configuration. Note that you must call SdNotifyReady when
// it completed reloading.
SdNotifyReloading = "RELOADING=1"
// SdNotifyWatchdog tells the service manager to update the watchdog
// timestamp for the service.
SdNotifyWatchdog = "WATCHDOG=1"
)
// SdNotify sends a message to the init daemon. It is common to ignore the error.
// If `unsetEnvironment` is true, the environment variable `NOTIFY_SOCKET`
// will be unconditionally unset.
......@@ -29,7 +53,7 @@ import (
// (false, nil) - notification not supported (i.e. NOTIFY_SOCKET is unset)
// (false, err) - notification supported, but failure happened (e.g. error connecting to NOTIFY_SOCKET or while sending data)
// (true, nil) - notification supported, data has been sent
func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
func SdNotify(unsetEnvironment bool, state string) (bool, error) {
socketAddr := &net.UnixAddr{
Name: os.Getenv("NOTIFY_SOCKET"),
Net: "unixgram",
......@@ -41,10 +65,9 @@ func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
}
if unsetEnvironment {
err = os.Unsetenv("NOTIFY_SOCKET")
}
if err != nil {
return false, err
if err := os.Unsetenv("NOTIFY_SOCKET"); err != nil {
return false, err
}
}
conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr)
......@@ -54,9 +77,7 @@ func SdNotify(unsetEnvironment bool, state string) (sent bool, err error) {
}
defer conn.Close()
_, err = conn.Write([]byte(state))
// Error sending the message
if err != nil {
if _, err = conn.Write([]byte(state)); err != nil {
return false, err
}
return true, nil
......
......@@ -21,10 +21,11 @@ import (
"time"
)
// SdWatchdogEnabled return watchdog information for a service.
// Process should send daemon.SdNotify("WATCHDOG=1") every time / 2.
// If `unsetEnvironment` is true, the environment variables `WATCHDOG_USEC`
// and `WATCHDOG_PID` will be unconditionally unset.
// SdWatchdogEnabled returns watchdog information for a service.
// Processes should call daemon.SdNotify(false, daemon.SdNotifyWatchdog) every
// time / 2.
// If `unsetEnvironment` is true, the environment variables `WATCHDOG_USEC` and
// `WATCHDOG_PID` will be unconditionally unset.
//
// It returns one of the following:
// (0, nil) - watchdog isn't enabled or we aren't the watched PID.
......
Copyright (c) 2013, The GoGo Authors. All rights reserved.
Protocol Buffers for Go with Gadgets
Go support for Protocol Buffers - Google's data interchange format
Copyright 2010 The Go Authors. All rights reserved.
https://github.com/golang/protobuf
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.
......@@ -38,6 +38,6 @@ test: install generate-test-pbs
generate-test-pbs:
make install
make -C testdata
protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto
make -C test_proto
make -C proto3_proto
make
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2011 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// 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