uplink share subcommand (#1924)

* cmd/uplink: add share command to restrict an api key

This commit is an early bit of work to just implement restricting
macaroon api keys from the command line. It does not convert
api keys to be macaroons in general.

It also does not apply the path restriction caveats appropriately
yet because it does not encrypt them.

* cmd/uplink: fix path encryption for shares

It should now properly encrypt the path prefixes when adding
caveats to a macaroon.

* fix up linting problems

* print summary of caveat and require iso8601

* make clone part more clear
This commit is contained in:
Jeff Wendling 2019-05-14 18:15:12 +00:00 committed by JT Olio
parent eac18352f3
commit 15e74c8c3d
15 changed files with 405 additions and 226 deletions

View File

@ -31,7 +31,7 @@ var cfg UplinkFlags
var cpuProfile = flag.String("profile.cpu", "", "file path of the cpu profile to be created")
var memoryProfile = flag.String("profile.mem", "", "file path of the memory profile to be created")
//RootCmd represents the base CLI command when called without any subcommands
// RootCmd represents the base CLI command when called without any subcommands
var RootCmd = &cobra.Command{
Use: "uplink",
Short: "The Storj client-side CLI",

166
cmd/uplink/cmd/share.go Normal file
View File

@ -0,0 +1,166 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package cmd
import (
"fmt"
"time"
"github.com/gogo/protobuf/proto"
"github.com/spf13/cobra"
"github.com/zeebo/errs"
"storj.io/storj/internal/fpath"
libuplink "storj.io/storj/lib/uplink"
"storj.io/storj/pkg/cfgstruct"
"storj.io/storj/pkg/encryption"
"storj.io/storj/pkg/macaroon"
"storj.io/storj/pkg/process"
)
var shareCfg struct {
DisallowReads bool `default:"false" help:"if true, disallow reads"`
DisallowWrites bool `default:"false" help:"if true, disallow writes"`
DisallowLists bool `default:"false" help:"if true, disallow lists"`
DisallowDeletes bool `default:"false" help:"if true, disallow deletes"`
Readonly bool `default:"false" help:"implies disallow_writes and disallow_deletes"`
Writeonly bool `default:"false" help:"implies disallow_reads and disallow_lists"`
NotBefore string `help:"disallow access before this time"`
NotAfter string `help:"disallow access after this time"`
AllowedPathPrefix []string `help:"whitelist of bucket path prefixes to require"`
}
func init() {
// sadly, we have to use addCmd so that it adds the cfg struct to the flags
// so that we can open projects and buckets. that pulls in so many unnecessary
// flags which makes figuring out the share command really hard. oh well.
shareCmd := addCmd(&cobra.Command{
Use: "share",
Short: "Creates a possibly restricted api key",
RunE: shareMain,
}, RootCmd)
cfgstruct.Bind(shareCmd.Flags(), &shareCfg)
}
const shareISO8601 = "2006-01-02T15:04:05-0700"
func parseHumanDate(date string, now time.Time) (*time.Time, error) {
if date == "" {
return nil, nil
} else if date == "now" {
return &now, nil
} else if date[0] == '+' {
d, err := time.ParseDuration(date[1:])
t := now.Add(d)
return &t, errs.Wrap(err)
} else if date[0] == '-' {
d, err := time.ParseDuration(date[1:])
t := now.Add(-d)
return &t, errs.Wrap(err)
} else {
t, err := time.Parse(shareISO8601, date)
return &t, errs.Wrap(err)
}
}
// shareMain is the function executed when shareCmd is called
func shareMain(cmd *cobra.Command, args []string) (err error) {
ctx := process.Ctx(cmd)
now := time.Now()
notBefore, err := parseHumanDate(shareCfg.NotBefore, now)
if err != nil {
return err
}
notAfter, err := parseHumanDate(shareCfg.NotAfter, now)
if err != nil {
return err
}
// TODO(jeff): we have to have the server side of things expecting macaroons
// before we can change libuplink to use macaroons because of all the tests.
// For now, just use the raw macaroon library.
key, err := macaroon.ParseAPIKey(cfg.Client.APIKey)
if err != nil {
return err
}
caveat := macaroon.NewCaveat()
caveat.DisallowDeletes = shareCfg.DisallowDeletes || shareCfg.Readonly
caveat.DisallowLists = shareCfg.DisallowLists || shareCfg.Writeonly
caveat.DisallowReads = shareCfg.DisallowReads || shareCfg.Writeonly
caveat.DisallowWrites = shareCfg.DisallowWrites || shareCfg.Readonly
caveat.NotBefore = notBefore
caveat.NotAfter = notAfter
var project *libuplink.Project
var access libuplink.EncryptionAccess
copy(access.Key[:], []byte(cfg.Enc.Key))
cache := make(map[string]*libuplink.BucketConfig)
for _, path := range shareCfg.AllowedPathPrefix {
p, err := fpath.New(path)
if err != nil {
return err
}
if p.IsLocal() {
return errs.New("required path must be remote: %q", path)
}
bi, ok := cache[p.Bucket()]
if !ok {
if project == nil {
project, err = cfg.GetProject(ctx)
if err != nil {
return err
}
defer func() { err = errs.Combine(err, project.Close()) }()
}
_, bi, err = project.GetBucketInfo(ctx, p.Bucket())
if err != nil {
return err
}
cache[p.Bucket()] = bi
}
encPath, err := encryption.EncryptPath(path, bi.PathCipher.ToCipher(), &access.Key)
if err != nil {
return err
}
caveat.AllowedPaths = append(caveat.AllowedPaths, &macaroon.Caveat_Path{
Bucket: []byte(p.Bucket()),
EncryptedPathPrefix: []byte(encPath),
})
}
{
// Times don't marshal very well with MarshalTextString, and the nonce doesn't
// matter to humans, so handle those explicitly and then dispatch to the generic
// routine to avoid having to print all the things individually.
caveatCopy := proto.Clone(&caveat).(*macaroon.Caveat)
caveatCopy.Nonce = nil
if caveatCopy.NotBefore != nil {
fmt.Println("not before:", caveatCopy.NotBefore.Truncate(0).Format(shareISO8601))
caveatCopy.NotBefore = nil
}
if caveatCopy.NotAfter != nil {
fmt.Println("not after:", caveatCopy.NotAfter.Truncate(0).Format(shareISO8601))
caveatCopy.NotAfter = nil
}
fmt.Print(proto.MarshalTextString(caveatCopy))
}
key, err = key.Restrict(caveat)
if err != nil {
return err
}
fmt.Println("new key:", key.Serialize())
return nil
}

View File

@ -8,12 +8,12 @@ type APIKey struct {
key string
}
// Serialize serializes the API Key to a string
// Serialize serializes the API key to a string
func (a APIKey) Serialize() string {
return a.key
}
// ParseAPIKey parses an API Key
// ParseAPIKey parses an API key
func ParseAPIKey(val string) (APIKey, error) {
return APIKey{key: val}, nil
}

View File

@ -140,7 +140,7 @@ type ProjectOptions struct {
func (u *Uplink) OpenProject(ctx context.Context, satelliteAddr string, apiKey APIKey, opts *ProjectOptions) (p *Project, err error) {
defer mon.Task()(&ctx)(&err)
metainfo, err := metainfo.NewClient(ctx, u.tc, satelliteAddr, apiKey.key)
metainfo, err := metainfo.NewClient(ctx, u.tc, satelliteAddr, apiKey.Serialize())
if err != nil {
return nil, err
}

View File

@ -153,7 +153,7 @@ func bindConfig(flags FlagSet, prefix string, val reflect.Value, vars map[string
} else {
bindConfig(flags, flagname+".", fieldval, vars, setupCommand, onlyForSetup, isDev)
}
case reflect.Array, reflect.Slice:
case reflect.Array:
digits := len(fmt.Sprint(fieldval.Len()))
for j := 0; j < fieldval.Len(); j++ {
padding := strings.Repeat("0", digits-len(fmt.Sprint(j)))
@ -208,6 +208,8 @@ func bindConfig(flags FlagSet, prefix string, val reflect.Value, vars map[string
val, err := strconv.ParseBool(def)
check(err)
flags.BoolVar(fieldaddr.(*bool), flagname, val, help)
case reflect.TypeOf([]string(nil)):
flags.StringArrayVar(fieldaddr.(*[]string), flagname, nil, help)
default:
panic(fmt.Sprintf("invalid field type: %s", field.Type.String()))
}

View File

@ -19,6 +19,7 @@ type FlagSet interface {
DurationVar(p *time.Duration, name string, value time.Duration, usage string)
Float64Var(p *float64, name string, value float64, usage string)
StringVar(p *string, name string, value string, usage string)
StringArrayVar(p *[]string, name string, value []string, usage string)
Var(val pflag.Value, name string, usage string)
}

View File

@ -5,7 +5,7 @@ package macaroon
import (
"bytes"
time "time"
"time"
"github.com/btcsuite/btcutil/base58"
"github.com/gogo/protobuf/proto"
@ -137,8 +137,8 @@ func (a *APIKey) Tail() []byte {
}
// Serialize serializes the API Key to a string
func (a *APIKey) Serialize() (string, error) {
return base58.CheckEncode(a.mac.Serialize(), 0), nil
func (a *APIKey) Serialize() string {
return base58.CheckEncode(a.mac.Serialize(), 0)
}
// Allows returns true if the provided action is allowed by the caveat.
@ -174,23 +174,11 @@ func (c *Caveat) Allows(action Action) bool {
return false
}
if len(c.Buckets) > 0 {
if len(c.AllowedPaths) > 0 {
found := false
for _, bucket := range c.Buckets {
if bytes.Equal(action.Bucket, bucket) {
found = true
break
}
}
if !found {
return false
}
}
if len(c.EncryptedPathPrefixes) > 0 {
found := false
for _, path := range c.EncryptedPathPrefixes {
if bytes.HasPrefix(action.EncryptedPath, path) {
for _, path := range c.AllowedPaths {
if bytes.Equal(action.Bucket, path.Bucket) &&
bytes.HasPrefix(action.EncryptedPath, path.EncryptedPathPrefix) {
found = true
break
}

View File

@ -19,20 +19,21 @@ func TestSerializeParseRestrictAndCheck(t *testing.T) {
key, err := NewAPIKey(secret)
require.NoError(t, err)
serialized, err := key.Serialize()
require.NoError(t, err)
serialized := key.Serialize()
parsedKey, err := ParseAPIKey(serialized)
require.NoError(t, err)
require.True(t, bytes.Equal(key.Head(), parsedKey.Head()))
require.True(t, bytes.Equal(key.Tail(), parsedKey.Tail()))
restricted, err := key.Restrict(Caveat{
EncryptedPathPrefixes: [][]byte{[]byte("a-test-path")},
AllowedPaths: []*Caveat_Path{{
Bucket: []byte("a-test-bucket"),
EncryptedPathPrefix: []byte("a-test-path"),
}},
})
require.NoError(t, err)
serialized, err = restricted.Serialize()
require.NoError(t, err)
serialized = restricted.Serialize()
parsedKey, err = ParseAPIKey(serialized)
require.NoError(t, err)
require.True(t, bytes.Equal(key.Head(), parsedKey.Head()))
@ -42,11 +43,13 @@ func TestSerializeParseRestrictAndCheck(t *testing.T) {
action1 := Action{
Op: ActionRead,
Time: now,
Bucket: []byte("a-test-bucket"),
EncryptedPath: []byte("a-test-path"),
}
action2 := Action{
Op: ActionRead,
Time: now,
Bucket: []byte("another-test-bucket"),
EncryptedPath: []byte("another-test-path"),
}

17
pkg/macaroon/caveat.go Normal file
View File

@ -0,0 +1,17 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package macaroon
import (
"encoding/binary"
"time"
)
// NewCaveat returns a Caveat with a nonce initialized to the current timestamp
// in nanoseconds.
func NewCaveat() Caveat {
var buf [8]byte
binary.BigEndian.PutUint64(buf[:], uint64(time.Now().UnixNano()))
return Caveat{Nonce: buf[:]}
}

View File

@ -1,4 +1,5 @@
// Copyright (C) 2019 Storj Labs, Inc. // See LICENSE for copying information.
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package macaroon

View File

@ -26,20 +26,20 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type Caveat struct {
// if any of these three are set, disallow that type of access
DisallowReads bool `protobuf:"varint,1,opt,name=disallow_reads,json=disallowReads,proto3" json:"disallow_reads,omitempty"`
DisallowWrites bool `protobuf:"varint,2,opt,name=disallow_writes,json=disallowWrites,proto3" json:"disallow_writes,omitempty"`
DisallowLists bool `protobuf:"varint,3,opt,name=disallow_lists,json=disallowLists,proto3" json:"disallow_lists,omitempty"`
DisallowDeletes bool `protobuf:"varint,4,opt,name=disallow_deletes,json=disallowDeletes,proto3" json:"disallow_deletes,omitempty"`
// if one of these two lists are not empty, restrict accesses
// to the given values
Buckets [][]byte `protobuf:"bytes,10,rep,name=buckets,proto3" json:"buckets,omitempty"`
EncryptedPathPrefixes [][]byte `protobuf:"bytes,11,rep,name=encrypted_path_prefixes,json=encryptedPathPrefixes,proto3" json:"encrypted_path_prefixes,omitempty"`
DisallowReads bool `protobuf:"varint,1,opt,name=disallow_reads,json=disallowReads,proto3" json:"disallow_reads,omitempty"`
DisallowWrites bool `protobuf:"varint,2,opt,name=disallow_writes,json=disallowWrites,proto3" json:"disallow_writes,omitempty"`
DisallowLists bool `protobuf:"varint,3,opt,name=disallow_lists,json=disallowLists,proto3" json:"disallow_lists,omitempty"`
DisallowDeletes bool `protobuf:"varint,4,opt,name=disallow_deletes,json=disallowDeletes,proto3" json:"disallow_deletes,omitempty"`
AllowedPaths []*Caveat_Path `protobuf:"bytes,10,rep,name=allowed_paths,json=allowedPaths,proto3" json:"allowed_paths,omitempty"`
// if set, the validity time window
NotAfter *time.Time `protobuf:"bytes,20,opt,name=not_after,json=notAfter,proto3,stdtime" json:"not_after,omitempty"`
NotBefore *time.Time `protobuf:"bytes,21,opt,name=not_before,json=notBefore,proto3,stdtime" json:"not_before,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
NotAfter *time.Time `protobuf:"bytes,20,opt,name=not_after,json=notAfter,proto3,stdtime" json:"not_after,omitempty"`
NotBefore *time.Time `protobuf:"bytes,21,opt,name=not_before,json=notBefore,proto3,stdtime" json:"not_before,omitempty"`
// nonce is set to some random bytes so that you can make arbitrarily
// many restricted macaroons with the same (or no) restrictions.
Nonce []byte `protobuf:"bytes,30,opt,name=nonce,proto3" json:"nonce,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Caveat) Reset() { *m = Caveat{} }
@ -94,16 +94,9 @@ func (m *Caveat) GetDisallowDeletes() bool {
return false
}
func (m *Caveat) GetBuckets() [][]byte {
func (m *Caveat) GetAllowedPaths() []*Caveat_Path {
if m != nil {
return m.Buckets
}
return nil
}
func (m *Caveat) GetEncryptedPathPrefixes() [][]byte {
if m != nil {
return m.EncryptedPathPrefixes
return m.AllowedPaths
}
return nil
}
@ -122,31 +115,90 @@ func (m *Caveat) GetNotBefore() *time.Time {
return nil
}
func (m *Caveat) GetNonce() []byte {
if m != nil {
return m.Nonce
}
return nil
}
// If any entries exist, require all access to happen in at least
// one of them.
type Caveat_Path struct {
Bucket []byte `protobuf:"bytes,1,opt,name=bucket,proto3" json:"bucket,omitempty"`
EncryptedPathPrefix []byte `protobuf:"bytes,2,opt,name=encrypted_path_prefix,json=encryptedPathPrefix,proto3" json:"encrypted_path_prefix,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Caveat_Path) Reset() { *m = Caveat_Path{} }
func (m *Caveat_Path) String() string { return proto.CompactTextString(m) }
func (*Caveat_Path) ProtoMessage() {}
func (*Caveat_Path) Descriptor() ([]byte, []int) {
return fileDescriptor_d938547f84707355, []int{0, 0}
}
func (m *Caveat_Path) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Caveat_Path.Unmarshal(m, b)
}
func (m *Caveat_Path) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Caveat_Path.Marshal(b, m, deterministic)
}
func (m *Caveat_Path) XXX_Merge(src proto.Message) {
xxx_messageInfo_Caveat_Path.Merge(m, src)
}
func (m *Caveat_Path) XXX_Size() int {
return xxx_messageInfo_Caveat_Path.Size(m)
}
func (m *Caveat_Path) XXX_DiscardUnknown() {
xxx_messageInfo_Caveat_Path.DiscardUnknown(m)
}
var xxx_messageInfo_Caveat_Path proto.InternalMessageInfo
func (m *Caveat_Path) GetBucket() []byte {
if m != nil {
return m.Bucket
}
return nil
}
func (m *Caveat_Path) GetEncryptedPathPrefix() []byte {
if m != nil {
return m.EncryptedPathPrefix
}
return nil
}
func init() {
proto.RegisterType((*Caveat)(nil), "macaroon.Caveat")
proto.RegisterType((*Caveat_Path)(nil), "macaroon.Caveat.Path")
}
func init() { proto.RegisterFile("types.proto", fileDescriptor_d938547f84707355) }
var fileDescriptor_d938547f84707355 = []byte{
// 297 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0x4f, 0x4b, 0xf3, 0x40,
0x10, 0xc6, 0x49, 0x5b, 0xfa, 0xf6, 0x9d, 0xfa, 0x8f, 0xc5, 0xe2, 0xd2, 0x4b, 0x8b, 0x20, 0xd6,
0x4b, 0x0a, 0x0a, 0xde, 0x44, 0xac, 0x1e, 0x3d, 0x94, 0x20, 0x78, 0x0c, 0x9b, 0x66, 0x92, 0x06,
0x93, 0x4c, 0xd8, 0x9d, 0x5a, 0xfb, 0x2d, 0xfc, 0x86, 0x7e, 0x11, 0x0f, 0xb2, 0x1b, 0x13, 0xe8,
0xcd, 0xe3, 0xfc, 0xe6, 0xf7, 0xcc, 0xc0, 0x03, 0x43, 0xde, 0x55, 0x68, 0xfc, 0x4a, 0x13, 0x93,
0x18, 0x14, 0x6a, 0xa5, 0x34, 0x51, 0x39, 0x86, 0x94, 0x52, 0xaa, 0xe9, 0x78, 0x92, 0x12, 0xa5,
0x39, 0xce, 0xdd, 0x14, 0x6d, 0x92, 0x39, 0x67, 0x05, 0x1a, 0x56, 0x45, 0x55, 0x0b, 0xe7, 0xdf,
0x1d, 0xe8, 0x3f, 0xaa, 0x77, 0x54, 0x2c, 0x2e, 0xe0, 0x28, 0xce, 0x8c, 0xca, 0x73, 0xda, 0x86,
0x1a, 0x55, 0x6c, 0xa4, 0x37, 0xf5, 0x66, 0x83, 0xe0, 0xb0, 0xa1, 0x81, 0x85, 0xe2, 0x12, 0x8e,
0x5b, 0x6d, 0xab, 0x33, 0x46, 0x23, 0x3b, 0xce, 0x6b, 0xd3, 0xaf, 0x8e, 0xee, 0xdd, 0xcb, 0x33,
0xc3, 0x46, 0x76, 0xf7, 0xef, 0x3d, 0x5b, 0x28, 0xae, 0xe0, 0xa4, 0xd5, 0x62, 0xcc, 0xd1, 0x1e,
0xec, 0x39, 0xb1, 0xfd, 0xf3, 0x54, 0x63, 0x21, 0xe1, 0x5f, 0xb4, 0x59, 0xbd, 0x21, 0x1b, 0x09,
0xd3, 0xee, 0xec, 0x20, 0x68, 0x46, 0x71, 0x0b, 0x67, 0x58, 0xae, 0xf4, 0xae, 0x62, 0x8c, 0xc3,
0x4a, 0xf1, 0x3a, 0xac, 0x34, 0x26, 0xd9, 0x07, 0x1a, 0x39, 0x74, 0xe6, 0xa8, 0x5d, 0x2f, 0x15,
0xaf, 0x97, 0xbf, 0x4b, 0x71, 0x07, 0xff, 0x4b, 0xe2, 0x50, 0x25, 0x8c, 0x5a, 0x9e, 0x4e, 0xbd,
0xd9, 0xf0, 0x7a, 0xec, 0xd7, 0x9d, 0xf9, 0x4d, 0x67, 0xfe, 0x4b, 0xd3, 0xd9, 0xa2, 0xf7, 0xf9,
0x35, 0xf1, 0x82, 0x41, 0x49, 0xfc, 0x60, 0x13, 0xe2, 0x1e, 0xc0, 0xc6, 0x23, 0x4c, 0x48, 0xa3,
0x1c, 0xfd, 0x31, 0x6f, 0x5f, 0x2e, 0x5c, 0x24, 0xea, 0x3b, 0xe9, 0xe6, 0x27, 0x00, 0x00, 0xff,
0xff, 0xa2, 0x5a, 0x6d, 0xad, 0xcb, 0x01, 0x00, 0x00,
// 343 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x50, 0xc1, 0x4a, 0xeb, 0x40,
0x14, 0x25, 0xaf, 0x7d, 0xa5, 0xef, 0x36, 0x7d, 0xef, 0x31, 0xb6, 0x12, 0xb2, 0xb0, 0x41, 0x10,
0xe3, 0x66, 0x0a, 0x75, 0x27, 0x88, 0x58, 0x5d, 0xba, 0x28, 0x83, 0xe0, 0x32, 0x4c, 0x92, 0x9b,
0x34, 0x98, 0x66, 0xc2, 0xcc, 0xd4, 0xda, 0xbf, 0xf0, 0xd3, 0xfc, 0x03, 0x7f, 0x45, 0x66, 0xd2,
0x04, 0xba, 0x73, 0x79, 0xce, 0x3d, 0xe7, 0xdc, 0x7b, 0x0f, 0x8c, 0xf4, 0xbe, 0x46, 0x45, 0x6b,
0x29, 0xb4, 0x20, 0xc3, 0x0d, 0x4f, 0xb8, 0x14, 0xa2, 0xf2, 0x21, 0x17, 0xb9, 0x68, 0x58, 0x7f,
0x96, 0x0b, 0x91, 0x97, 0x38, 0xb7, 0x28, 0xde, 0x66, 0x73, 0x5d, 0x6c, 0x50, 0x69, 0xbe, 0xa9,
0x1b, 0xc1, 0xf9, 0x67, 0x0f, 0x06, 0x0f, 0xfc, 0x0d, 0xb9, 0x26, 0x17, 0xf0, 0x37, 0x2d, 0x14,
0x2f, 0x4b, 0xb1, 0x8b, 0x24, 0xf2, 0x54, 0x79, 0x4e, 0xe0, 0x84, 0x43, 0x36, 0x6e, 0x59, 0x66,
0x48, 0x72, 0x09, 0xff, 0x3a, 0xd9, 0x4e, 0x16, 0x1a, 0x95, 0xf7, 0xcb, 0xea, 0x3a, 0xf7, 0x8b,
0x65, 0x8f, 0xf2, 0xca, 0x42, 0x69, 0xe5, 0xf5, 0x8e, 0xf3, 0x9e, 0x0c, 0x49, 0xae, 0xe0, 0x7f,
0x27, 0x4b, 0xb1, 0x44, 0x13, 0xd8, 0xb7, 0xc2, 0x6e, 0xcf, 0x63, 0x43, 0x93, 0x1b, 0x18, 0x5b,
0x8c, 0x69, 0x54, 0x73, 0xbd, 0x56, 0x1e, 0x04, 0xbd, 0x70, 0xb4, 0x98, 0xd2, 0xf6, 0x77, 0xda,
0xbc, 0x42, 0x57, 0x5c, 0xaf, 0x99, 0x7b, 0xd0, 0x1a, 0xa0, 0xc8, 0x2d, 0xfc, 0xa9, 0x84, 0x8e,
0x78, 0xa6, 0x51, 0x7a, 0x93, 0xc0, 0x09, 0x47, 0x0b, 0x9f, 0x36, 0xed, 0xd0, 0xb6, 0x1d, 0xfa,
0xdc, 0xb6, 0xb3, 0xec, 0x7f, 0x7c, 0xcd, 0x1c, 0x36, 0xac, 0x84, 0xbe, 0x37, 0x0e, 0x72, 0x07,
0x60, 0xec, 0x31, 0x66, 0x42, 0xa2, 0x37, 0xfd, 0xa1, 0xdf, 0xac, 0x5c, 0x5a, 0x0b, 0x99, 0xc0,
0xef, 0x4a, 0x54, 0x09, 0x7a, 0x67, 0x81, 0x13, 0xba, 0xac, 0x01, 0x3e, 0x83, 0xbe, 0x39, 0x8f,
0x9c, 0xc2, 0x20, 0xde, 0x26, 0xaf, 0xa8, 0x6d, 0xe7, 0x2e, 0x3b, 0x20, 0xb2, 0x80, 0x29, 0x56,
0x89, 0xdc, 0xd7, 0xfa, 0xf0, 0x73, 0x54, 0x4b, 0xcc, 0x8a, 0x77, 0x5b, 0xb9, 0xcb, 0x4e, 0xba,
0xa1, 0x49, 0x59, 0xd9, 0x51, 0x3c, 0xb0, 0xe7, 0x5c, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0xca,
0x7b, 0x7d, 0xfc, 0x1f, 0x02, 0x00, 0x00,
}

View File

@ -15,12 +15,19 @@ message Caveat {
bool disallow_lists = 3;
bool disallow_deletes = 4;
// if one of these two lists are not empty, restrict accesses
// to the given values
repeated bytes buckets = 10;
repeated bytes encrypted_path_prefixes = 11;
// If any entries exist, require all access to happen in at least
// one of them.
message Path {
bytes bucket = 1;
bytes encrypted_path_prefix = 2;
}
repeated Path allowed_paths = 10;
// if set, the validity time window
google.protobuf.Timestamp not_after = 20 [(gogoproto.stdtime) = true];
google.protobuf.Timestamp not_before = 21 [(gogoproto.stdtime) = true];
// nonce is set to some random bytes so that you can make arbitrarily
// many restricted macaroons with the same (or no) restrictions.
bytes nonce = 30;
}

View File

@ -3,11 +3,13 @@
package pb
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "github.com/gogo/protobuf/gogoproto"
import timestamp "github.com/golang/protobuf/ptypes/timestamp"
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
@ -38,6 +40,7 @@ var NodeType_name = map[int32]string{
3: "UPLINK",
4: "BOOTSTRAP",
}
var NodeType_value = map[string]int32{
"INVALID": 0,
"SATELLITE": 1,
@ -49,8 +52,9 @@ var NodeType_value = map[string]int32{
func (x NodeType) String() string {
return proto.EnumName(NodeType_name, int32(x))
}
func (NodeType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{0}
return fileDescriptor_0c843d59d2d938e7, []int{0}
}
// NodeTransport is an enum of possible transports for the overlay network
@ -63,6 +67,7 @@ const (
var NodeTransport_name = map[int32]string{
0: "TCP_TLS_GRPC",
}
var NodeTransport_value = map[string]int32{
"TCP_TLS_GRPC": 0,
}
@ -70,8 +75,9 @@ var NodeTransport_value = map[string]int32{
func (x NodeTransport) String() string {
return proto.EnumName(NodeTransport_name, int32(x))
}
func (NodeTransport) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{1}
return fileDescriptor_0c843d59d2d938e7, []int{1}
}
// TODO move statdb.Update() stuff out of here
@ -89,7 +95,7 @@ func (m *Node) Reset() { *m = Node{} }
func (m *Node) String() string { return proto.CompactTextString(m) }
func (*Node) ProtoMessage() {}
func (*Node) Descriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{0}
return fileDescriptor_0c843d59d2d938e7, []int{0}
}
func (m *Node) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Node.Unmarshal(m, b)
@ -97,8 +103,8 @@ func (m *Node) XXX_Unmarshal(b []byte) error {
func (m *Node) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Node.Marshal(b, m, deterministic)
}
func (dst *Node) XXX_Merge(src proto.Message) {
xxx_messageInfo_Node.Merge(dst, src)
func (m *Node) XXX_Merge(src proto.Message) {
xxx_messageInfo_Node.Merge(m, src)
}
func (m *Node) XXX_Size() int {
return xxx_messageInfo_Node.Size(m)
@ -129,7 +135,7 @@ func (m *NodeAddress) Reset() { *m = NodeAddress{} }
func (m *NodeAddress) String() string { return proto.CompactTextString(m) }
func (*NodeAddress) ProtoMessage() {}
func (*NodeAddress) Descriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{1}
return fileDescriptor_0c843d59d2d938e7, []int{1}
}
func (m *NodeAddress) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeAddress.Unmarshal(m, b)
@ -137,8 +143,8 @@ func (m *NodeAddress) XXX_Unmarshal(b []byte) error {
func (m *NodeAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_NodeAddress.Marshal(b, m, deterministic)
}
func (dst *NodeAddress) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeAddress.Merge(dst, src)
func (m *NodeAddress) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeAddress.Merge(m, src)
}
func (m *NodeAddress) XXX_Size() int {
return xxx_messageInfo_NodeAddress.Size(m)
@ -184,7 +190,7 @@ func (m *NodeStats) Reset() { *m = NodeStats{} }
func (m *NodeStats) String() string { return proto.CompactTextString(m) }
func (*NodeStats) ProtoMessage() {}
func (*NodeStats) Descriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{2}
return fileDescriptor_0c843d59d2d938e7, []int{2}
}
func (m *NodeStats) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeStats.Unmarshal(m, b)
@ -192,8 +198,8 @@ func (m *NodeStats) XXX_Unmarshal(b []byte) error {
func (m *NodeStats) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_NodeStats.Marshal(b, m, deterministic)
}
func (dst *NodeStats) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeStats.Merge(dst, src)
func (m *NodeStats) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeStats.Merge(m, src)
}
func (m *NodeStats) XXX_Size() int {
return xxx_messageInfo_NodeStats.Size(m)
@ -280,7 +286,7 @@ func (m *NodeOperator) Reset() { *m = NodeOperator{} }
func (m *NodeOperator) String() string { return proto.CompactTextString(m) }
func (*NodeOperator) ProtoMessage() {}
func (*NodeOperator) Descriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{3}
return fileDescriptor_0c843d59d2d938e7, []int{3}
}
func (m *NodeOperator) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeOperator.Unmarshal(m, b)
@ -288,8 +294,8 @@ func (m *NodeOperator) XXX_Unmarshal(b []byte) error {
func (m *NodeOperator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_NodeOperator.Marshal(b, m, deterministic)
}
func (dst *NodeOperator) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeOperator.Merge(dst, src)
func (m *NodeOperator) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeOperator.Merge(m, src)
}
func (m *NodeOperator) XXX_Size() int {
return xxx_messageInfo_NodeOperator.Size(m)
@ -327,7 +333,7 @@ func (m *NodeCapacity) Reset() { *m = NodeCapacity{} }
func (m *NodeCapacity) String() string { return proto.CompactTextString(m) }
func (*NodeCapacity) ProtoMessage() {}
func (*NodeCapacity) Descriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{4}
return fileDescriptor_0c843d59d2d938e7, []int{4}
}
func (m *NodeCapacity) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeCapacity.Unmarshal(m, b)
@ -335,8 +341,8 @@ func (m *NodeCapacity) XXX_Unmarshal(b []byte) error {
func (m *NodeCapacity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_NodeCapacity.Marshal(b, m, deterministic)
}
func (dst *NodeCapacity) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeCapacity.Merge(dst, src)
func (m *NodeCapacity) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeCapacity.Merge(m, src)
}
func (m *NodeCapacity) XXX_Size() int {
return xxx_messageInfo_NodeCapacity.Size(m)
@ -374,7 +380,7 @@ func (m *NodeMetadata) Reset() { *m = NodeMetadata{} }
func (m *NodeMetadata) String() string { return proto.CompactTextString(m) }
func (*NodeMetadata) ProtoMessage() {}
func (*NodeMetadata) Descriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{5}
return fileDescriptor_0c843d59d2d938e7, []int{5}
}
func (m *NodeMetadata) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeMetadata.Unmarshal(m, b)
@ -382,8 +388,8 @@ func (m *NodeMetadata) XXX_Unmarshal(b []byte) error {
func (m *NodeMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_NodeMetadata.Marshal(b, m, deterministic)
}
func (dst *NodeMetadata) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeMetadata.Merge(dst, src)
func (m *NodeMetadata) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeMetadata.Merge(m, src)
}
func (m *NodeMetadata) XXX_Size() int {
return xxx_messageInfo_NodeMetadata.Size(m)
@ -421,7 +427,7 @@ func (m *NodeRestrictions) Reset() { *m = NodeRestrictions{} }
func (m *NodeRestrictions) String() string { return proto.CompactTextString(m) }
func (*NodeRestrictions) ProtoMessage() {}
func (*NodeRestrictions) Descriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{6}
return fileDescriptor_0c843d59d2d938e7, []int{6}
}
func (m *NodeRestrictions) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeRestrictions.Unmarshal(m, b)
@ -429,8 +435,8 @@ func (m *NodeRestrictions) XXX_Unmarshal(b []byte) error {
func (m *NodeRestrictions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_NodeRestrictions.Marshal(b, m, deterministic)
}
func (dst *NodeRestrictions) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeRestrictions.Merge(dst, src)
func (m *NodeRestrictions) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeRestrictions.Merge(m, src)
}
func (m *NodeRestrictions) XXX_Size() int {
return xxx_messageInfo_NodeRestrictions.Size(m)
@ -470,7 +476,7 @@ func (m *NodeVersion) Reset() { *m = NodeVersion{} }
func (m *NodeVersion) String() string { return proto.CompactTextString(m) }
func (*NodeVersion) ProtoMessage() {}
func (*NodeVersion) Descriptor() ([]byte, []int) {
return fileDescriptor_node_52aec12f51af5891, []int{7}
return fileDescriptor_0c843d59d2d938e7, []int{7}
}
func (m *NodeVersion) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeVersion.Unmarshal(m, b)
@ -478,8 +484,8 @@ func (m *NodeVersion) XXX_Unmarshal(b []byte) error {
func (m *NodeVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_NodeVersion.Marshal(b, m, deterministic)
}
func (dst *NodeVersion) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeVersion.Merge(dst, src)
func (m *NodeVersion) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeVersion.Merge(m, src)
}
func (m *NodeVersion) XXX_Size() int {
return xxx_messageInfo_NodeVersion.Size(m)
@ -519,6 +525,8 @@ func (m *NodeVersion) GetRelease() bool {
}
func init() {
proto.RegisterEnum("node.NodeType", NodeType_name, NodeType_value)
proto.RegisterEnum("node.NodeTransport", NodeTransport_name, NodeTransport_value)
proto.RegisterType((*Node)(nil), "node.Node")
proto.RegisterType((*NodeAddress)(nil), "node.NodeAddress")
proto.RegisterType((*NodeStats)(nil), "node.NodeStats")
@ -527,13 +535,11 @@ func init() {
proto.RegisterType((*NodeMetadata)(nil), "node.NodeMetadata")
proto.RegisterType((*NodeRestrictions)(nil), "node.NodeRestrictions")
proto.RegisterType((*NodeVersion)(nil), "node.NodeVersion")
proto.RegisterEnum("node.NodeType", NodeType_name, NodeType_value)
proto.RegisterEnum("node.NodeTransport", NodeTransport_name, NodeTransport_value)
}
func init() { proto.RegisterFile("node.proto", fileDescriptor_node_52aec12f51af5891) }
func init() { proto.RegisterFile("node.proto", fileDescriptor_0c843d59d2d938e7) }
var fileDescriptor_node_52aec12f51af5891 = []byte{
var fileDescriptor_0c843d59d2d938e7 = []byte{
// 723 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xdd, 0x6e, 0xea, 0x46,
0x10, 0xc7, 0x63, 0x20, 0x80, 0x87, 0x0f, 0x39, 0x1b, 0x54, 0xa1, 0x54, 0x2d, 0x09, 0x52, 0xd5,

View File

@ -54,7 +54,7 @@ func (x Restriction_Operator) String() string {
}
func (Restriction_Operator) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_61fc82527fbe24ad, []int{8, 0}
return fileDescriptor_61fc82527fbe24ad, []int{6, 0}
}
type Restriction_Operand int32
@ -79,7 +79,7 @@ func (x Restriction_Operand) String() string {
}
func (Restriction_Operand) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_61fc82527fbe24ad, []int{8, 1}
return fileDescriptor_61fc82527fbe24ad, []int{6, 1}
}
type QueryRequest struct {
@ -343,74 +343,6 @@ func (m *InfoResponse) GetVersion() *NodeVersion {
return nil
}
type GraphRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GraphRequest) Reset() { *m = GraphRequest{} }
func (m *GraphRequest) String() string { return proto.CompactTextString(m) }
func (*GraphRequest) ProtoMessage() {}
func (*GraphRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_61fc82527fbe24ad, []int{6}
}
func (m *GraphRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GraphRequest.Unmarshal(m, b)
}
func (m *GraphRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GraphRequest.Marshal(b, m, deterministic)
}
func (m *GraphRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GraphRequest.Merge(m, src)
}
func (m *GraphRequest) XXX_Size() int {
return xxx_messageInfo_GraphRequest.Size(m)
}
func (m *GraphRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GraphRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GraphRequest proto.InternalMessageInfo
type GraphResponse struct {
Graph [][]byte `protobuf:"bytes,1,rep,name=graph,proto3" json:"graph,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GraphResponse) Reset() { *m = GraphResponse{} }
func (m *GraphResponse) String() string { return proto.CompactTextString(m) }
func (*GraphResponse) ProtoMessage() {}
func (*GraphResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_61fc82527fbe24ad, []int{7}
}
func (m *GraphResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GraphResponse.Unmarshal(m, b)
}
func (m *GraphResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GraphResponse.Marshal(b, m, deterministic)
}
func (m *GraphResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_GraphResponse.Merge(m, src)
}
func (m *GraphResponse) XXX_Size() int {
return xxx_messageInfo_GraphResponse.Size(m)
}
func (m *GraphResponse) XXX_DiscardUnknown() {
xxx_messageInfo_GraphResponse.DiscardUnknown(m)
}
var xxx_messageInfo_GraphResponse proto.InternalMessageInfo
func (m *GraphResponse) GetGraph() [][]byte {
if m != nil {
return m.Graph
}
return nil
}
type Restriction struct {
Operator Restriction_Operator `protobuf:"varint,1,opt,name=operator,proto3,enum=overlay.Restriction_Operator" json:"operator,omitempty"`
Operand Restriction_Operand `protobuf:"varint,2,opt,name=operand,proto3,enum=overlay.Restriction_Operand" json:"operand,omitempty"`
@ -424,7 +356,7 @@ func (m *Restriction) Reset() { *m = Restriction{} }
func (m *Restriction) String() string { return proto.CompactTextString(m) }
func (*Restriction) ProtoMessage() {}
func (*Restriction) Descriptor() ([]byte, []int) {
return fileDescriptor_61fc82527fbe24ad, []int{8}
return fileDescriptor_61fc82527fbe24ad, []int{6}
}
func (m *Restriction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Restriction.Unmarshal(m, b)
@ -474,48 +406,44 @@ func init() {
proto.RegisterType((*PingResponse)(nil), "overlay.PingResponse")
proto.RegisterType((*InfoRequest)(nil), "overlay.InfoRequest")
proto.RegisterType((*InfoResponse)(nil), "overlay.InfoResponse")
proto.RegisterType((*GraphRequest)(nil), "overlay.GraphRequest")
proto.RegisterType((*GraphResponse)(nil), "overlay.GraphResponse")
proto.RegisterType((*Restriction)(nil), "overlay.Restriction")
}
func init() { proto.RegisterFile("overlay.proto", fileDescriptor_61fc82527fbe24ad) }
var fileDescriptor_61fc82527fbe24ad = []byte{
// 514 bytes of a gzipped FileDescriptorProto
// 491 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0xdf, 0x8a, 0xd3, 0x40,
0x14, 0xc6, 0x77, 0x9a, 0xfe, 0xf3, 0xf4, 0x0f, 0x71, 0xe8, 0x4a, 0x28, 0x0a, 0x21, 0xa0, 0x14,
0x94, 0x5c, 0x74, 0x65, 0x41, 0xef, 0x5c, 0x1b, 0x6b, 0x71, 0x59, 0xdd, 0x31, 0x28, 0xe8, 0x85,
0xa4, 0xcd, 0x18, 0x83, 0x75, 0x26, 0x4e, 0xa6, 0x85, 0xbc, 0x81, 0x8f, 0xe3, 0x1b, 0xf8, 0x5e,
0x5e, 0xc9, 0x4c, 0x26, 0x69, 0xac, 0x0a, 0x5e, 0x65, 0xce, 0xf9, 0x7e, 0x93, 0x9c, 0xef, 0xf0,
0x05, 0x46, 0x7c, 0x4f, 0xc5, 0x36, 0x2a, 0xfc, 0x4c, 0x70, 0xc9, 0x71, 0xcf, 0x94, 0x53, 0x48,
0x78, 0xc2, 0xcb, 0xe6, 0x14, 0x18, 0x8f, 0x69, 0x79, 0xf6, 0xbe, 0x21, 0x18, 0x5e, 0xef, 0xa8,
0x28, 0x08, 0xfd, 0xba, 0xa3, 0xb9, 0xc4, 0x1e, 0x74, 0x73, 0xca, 0x62, 0x2a, 0x1c, 0xe4, 0xa2,
0xd9, 0x60, 0x0e, 0xbe, 0xa6, 0xaf, 0x78, 0x4c, 0x89, 0x51, 0x14, 0x23, 0x23, 0x91, 0x50, 0xe9,
0xb4, 0xfe, 0x64, 0x4a, 0x05, 0x4f, 0xa0, 0xb3, 0x4d, 0xbf, 0xa4, 0xd2, 0xb1, 0x5c, 0x34, 0xb3,
0x48, 0x59, 0xe0, 0x29, 0xf4, 0xb3, 0x94, 0x25, 0xeb, 0x68, 0xf3, 0xd9, 0x69, 0xbb, 0x68, 0xd6,
0x27, 0x75, 0xed, 0xbd, 0x87, 0x91, 0x99, 0x24, 0xcf, 0x38, 0xcb, 0xe9, 0x7f, 0x8d, 0x72, 0x0f,
0xfa, 0xc2, 0xf0, 0x4e, 0xcb, 0xb5, 0x8e, 0xa8, 0x5a, 0xf3, 0x46, 0x30, 0x78, 0x95, 0xb2, 0xc4,
0xb8, 0xf4, 0xc6, 0x30, 0x2c, 0xcb, 0x83, 0xbc, 0x62, 0x1f, 0x79, 0x25, 0xff, 0x40, 0x30, 0x2c,
0xeb, 0x7a, 0x94, 0xb6, 0x2c, 0x32, 0xaa, 0xfd, 0x8e, 0xe7, 0xe3, 0xc3, 0x27, 0xc2, 0x22, 0xa3,
0x44, 0x6b, 0xd8, 0x87, 0x3e, 0xcf, 0xa8, 0x88, 0x24, 0x17, 0xda, 0xf4, 0x60, 0x8e, 0x0f, 0xdc,
0x4b, 0xa3, 0x90, 0x9a, 0x51, 0xfc, 0x26, 0xca, 0xa2, 0x4d, 0x2a, 0x0b, 0xbd, 0x8b, 0xdf, 0xf8,
0xa7, 0x46, 0x21, 0x35, 0x83, 0xef, 0x43, 0x6f, 0x4f, 0x45, 0x9e, 0x72, 0xe6, 0x74, 0x34, 0x7e,
0xf3, 0x80, 0xbf, 0x29, 0x05, 0x52, 0x11, 0xca, 0xe0, 0x52, 0x44, 0xd9, 0xa7, 0xca, 0xd1, 0x5d,
0x18, 0x99, 0xda, 0x38, 0x9a, 0x40, 0x27, 0x51, 0x0d, 0x07, 0xb9, 0xd6, 0x6c, 0x48, 0xca, 0xc2,
0xfb, 0x89, 0x60, 0x40, 0x68, 0x2e, 0x45, 0xba, 0x91, 0x29, 0x67, 0xf8, 0x51, 0xc3, 0x13, 0xd2,
0xde, 0xef, 0xf8, 0x55, 0xc2, 0x1a, 0x9c, 0xff, 0x17, 0x7b, 0xe7, 0xd0, 0xd3, 0x67, 0x16, 0x9b,
0xad, 0xdd, 0xfe, 0xf7, 0x4d, 0x16, 0x93, 0x0a, 0x56, 0x83, 0xed, 0xa3, 0xed, 0x8e, 0x56, 0xc1,
0xd1, 0x85, 0xf7, 0x10, 0xfa, 0xd5, 0x37, 0x70, 0x17, 0x5a, 0x97, 0xa1, 0x7d, 0xa2, 0x9e, 0xc1,
0xb5, 0x8d, 0xd4, 0x73, 0x19, 0xda, 0x2d, 0xdc, 0x03, 0xeb, 0x32, 0x0c, 0x6c, 0x4b, 0x1d, 0x96,
0x61, 0x60, 0xb7, 0xbd, 0x07, 0xd0, 0x33, 0xef, 0xc7, 0x18, 0xc6, 0xcf, 0x48, 0x10, 0x7c, 0xb8,
0x78, 0x72, 0xb5, 0x78, 0xbb, 0x5a, 0x84, 0xcf, 0xed, 0x13, 0x3c, 0x82, 0x1b, 0xba, 0xb7, 0x58,
0xbd, 0x7e, 0x61, 0xa3, 0xf9, 0x77, 0x04, 0x1d, 0xb5, 0xcc, 0x1c, 0x9f, 0x43, 0x47, 0x47, 0x11,
0x9f, 0xd6, 0x33, 0x37, 0x7f, 0x92, 0xe9, 0xad, 0xe3, 0xb6, 0x59, 0xea, 0x19, 0xb4, 0x55, 0xac,
0xf0, 0xa4, 0xd6, 0x1b, 0xa1, 0x9b, 0x9e, 0x1e, 0x75, 0xcd, 0xa5, 0xc7, 0x6a, 0xe5, 0x9a, 0x50,
0x91, 0x6b, 0xdc, 0x6d, 0x24, 0xb2, 0x71, 0xb7, 0x99, 0xcb, 0x8b, 0xf6, 0xbb, 0x56, 0xb6, 0x5e,
0x77, 0xf5, 0xbf, 0x7c, 0xf6, 0x2b, 0x00, 0x00, 0xff, 0xff, 0xea, 0x68, 0x2a, 0x74, 0xfd, 0x03,
0x00, 0x00,
0x14, 0xc6, 0x77, 0xda, 0x74, 0x13, 0x4f, 0xff, 0x10, 0x87, 0x5d, 0x09, 0x41, 0xa1, 0xe4, 0x42,
0x0a, 0x4a, 0x2e, 0xba, 0xb2, 0xa0, 0x77, 0xae, 0x8d, 0x6b, 0x71, 0x59, 0xdd, 0x31, 0x28, 0xe8,
0x85, 0xa4, 0xcd, 0x18, 0x82, 0x75, 0x26, 0x4e, 0xa6, 0x85, 0xbc, 0x81, 0x8f, 0xe3, 0x1b, 0xf8,
0x5e, 0x5e, 0xc9, 0x4c, 0x26, 0x69, 0xac, 0x0a, 0x5e, 0xcd, 0x9c, 0xf3, 0xfd, 0x4e, 0xe7, 0x9c,
0xd3, 0x2f, 0x30, 0xe6, 0x3b, 0x2a, 0x36, 0x49, 0x15, 0x16, 0x82, 0x4b, 0x8e, 0x6d, 0x13, 0xfa,
0x90, 0xf1, 0x8c, 0xd7, 0x49, 0x1f, 0x18, 0x4f, 0x69, 0x7d, 0x0f, 0xbe, 0x21, 0x18, 0xdd, 0x6c,
0xa9, 0xa8, 0x08, 0xfd, 0xba, 0xa5, 0xa5, 0xc4, 0x01, 0x1c, 0x97, 0x94, 0xa5, 0x54, 0x78, 0x68,
0x8a, 0x66, 0xc3, 0x39, 0x84, 0x9a, 0xbe, 0xe6, 0x29, 0x25, 0x46, 0x51, 0x8c, 0x4c, 0x44, 0x46,
0xa5, 0xd7, 0xfb, 0x93, 0xa9, 0x15, 0x7c, 0x02, 0x83, 0x4d, 0xfe, 0x25, 0x97, 0x5e, 0x7f, 0x8a,
0x66, 0x7d, 0x52, 0x07, 0xd8, 0x07, 0xa7, 0xc8, 0x59, 0xb6, 0x4a, 0xd6, 0x9f, 0x3d, 0x6b, 0x8a,
0x66, 0x0e, 0x69, 0xe3, 0xe0, 0x03, 0x8c, 0x4d, 0x27, 0x65, 0xc1, 0x59, 0x49, 0xff, 0xab, 0x95,
0xfb, 0xe0, 0x08, 0xc3, 0x7b, 0xbd, 0x69, 0xff, 0x80, 0x6a, 0xb5, 0x60, 0x0c, 0xc3, 0xd7, 0x39,
0xcb, 0xcc, 0x94, 0xc1, 0x04, 0x46, 0x75, 0xb8, 0x97, 0x97, 0xec, 0x13, 0x6f, 0xe4, 0x1f, 0x08,
0x46, 0x75, 0xdc, 0xb6, 0x62, 0xc9, 0xaa, 0xa0, 0x7a, 0xde, 0xc9, 0x7c, 0xb2, 0x7f, 0x22, 0xae,
0x0a, 0x4a, 0xb4, 0x86, 0x43, 0x70, 0x78, 0x41, 0x45, 0x22, 0xb9, 0xd0, 0x43, 0x0f, 0xe7, 0x78,
0xcf, 0xbd, 0x32, 0x0a, 0x69, 0x19, 0xc5, 0xaf, 0x93, 0x22, 0x59, 0xe7, 0xb2, 0xd2, 0xbb, 0xf8,
0x8d, 0x7f, 0x66, 0x14, 0xd2, 0x32, 0xf8, 0x01, 0xd8, 0x3b, 0x2a, 0xca, 0x9c, 0x33, 0x6f, 0xa0,
0xf1, 0xdb, 0x7b, 0xfc, 0x6d, 0x2d, 0x90, 0x86, 0x08, 0x7e, 0x22, 0x18, 0x12, 0x5a, 0x4a, 0x91,
0xaf, 0x65, 0xce, 0x19, 0x7e, 0xdc, 0x69, 0x0e, 0xe9, 0x21, 0xee, 0x85, 0x8d, 0x55, 0x3a, 0x5c,
0xf8, 0x97, 0x3e, 0xcf, 0xc1, 0xd6, 0x77, 0x96, 0x9a, 0xf1, 0xef, 0xfe, 0xbb, 0x92, 0xa5, 0xa4,
0x81, 0x95, 0x03, 0x76, 0xc9, 0x66, 0x4b, 0x1b, 0x07, 0xe8, 0x20, 0x78, 0x04, 0x4e, 0xf3, 0x06,
0x3e, 0x86, 0xde, 0x55, 0xec, 0x1e, 0xa9, 0x33, 0xba, 0x71, 0x91, 0x3a, 0x2f, 0x63, 0xb7, 0x87,
0x6d, 0xe8, 0x5f, 0xc5, 0x91, 0xdb, 0x57, 0x97, 0xcb, 0x38, 0x72, 0xad, 0xe0, 0x21, 0xd8, 0xe6,
0xf7, 0x31, 0x86, 0xc9, 0x73, 0x12, 0x45, 0x1f, 0x2f, 0x9e, 0x5e, 0x2f, 0xde, 0x2d, 0x17, 0xf1,
0x0b, 0xf7, 0x08, 0x8f, 0xe1, 0x96, 0xce, 0x2d, 0x96, 0x6f, 0x5e, 0xba, 0x68, 0xfe, 0x1d, 0xc1,
0x40, 0x6d, 0xa5, 0xc4, 0xe7, 0x30, 0xd0, 0x9e, 0xc2, 0xa7, 0x6d, 0xcf, 0x5d, 0xb7, 0xfb, 0x77,
0x0e, 0xd3, 0xe6, 0xff, 0x3e, 0x03, 0x4b, 0xf9, 0x03, 0x9f, 0xb4, 0x7a, 0xc7, 0x3d, 0xfe, 0xe9,
0x41, 0xd6, 0x14, 0x3d, 0x51, 0x2b, 0xd7, 0x84, 0xf2, 0x4e, 0xa7, 0xb6, 0x63, 0xad, 0x4e, 0x6d,
0xd7, 0x60, 0x17, 0xd6, 0xfb, 0x5e, 0xb1, 0x5a, 0x1d, 0xeb, 0x8f, 0xf2, 0xec, 0x57, 0x00, 0x00,
0x00, 0xff, 0xff, 0x6b, 0xb9, 0x2c, 0xac, 0xc6, 0x03, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -153,6 +153,8 @@ func Ctx(cmd *cobra.Command) context.Context {
return ctx
}
var traceOut = flag.String("debug.trace-out", "", "If set, a path to write a process trace SVG to")
func cleanup(cmd *cobra.Command) {
for _, ccmd := range cmd.Commands() {
cleanup(ccmd)
@ -165,8 +167,6 @@ func cleanup(cmd *cobra.Command) {
return
}
traceOut := cmd.Flags().String("debug.trace-out", "", "If set, a path to write a process trace SVG to")
cmd.RunE = func(cmd *cobra.Command, args []string) (err error) {
ctx := context.Background()
defer mon.TaskNamed("root")(&ctx)(&err)
@ -200,14 +200,22 @@ func cleanup(cmd *cobra.Command) {
// flag couldn't be found
brokenKeys = append(brokenKeys, key)
} else {
oldChanged := cmd.Flag(key).Changed
err := cmd.Flags().Set(key, vip.GetString(key))
if err != nil {
// flag couldn't be set
brokenVals = append(brokenVals, key)
flag := cmd.Flag(key)
// It's very hard to support string arrays from pflag
// because there's no way to unset some value. For now
// skip them. They can't be set from viper.
if flag.Value.Type() != "stringArray" {
oldChanged := flag.Changed
err := cmd.Flags().Set(key, vip.GetString(key))
if err != nil {
// flag couldn't be set
brokenVals = append(brokenVals, key)
}
// revert Changed value
flag.Changed = oldChanged
}
// revert Changed value
cmd.Flag(key).Changed = oldChanged
}
}