From fa1319165cb717b8894bb48702e52134571e8e86 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 22 Feb 2017 11:31:00 -0800 Subject: [PATCH 01/62] add initial client api code Signed-off-by: David Lawrence (github: endophage) --- client_api/api/api.pb.go | 252 ++++++++++++++++++ client_api/api/api.proto | 33 +++ client_api/api/client.go | 10 + client_api/api/errors.go | 20 ++ client_api/api/generator.go | 5 + client_api/api/server.go | 124 +++++++++ cmd/client_api/.gitignore | 1 + cmd/client_api/config.toml | 10 + cmd/client_api/main.go | 65 +++++ cmd/client_api/setup/config.go | 73 +++++ utils/transport.go | 121 +++++++++ utils/transport_test.go | 1 + vendor/google.golang.org/grpc/call.go | 38 ++- vendor/google.golang.org/grpc/clientconn.go | 93 ++++++- .../grpc/credentials/credentials.go | 4 +- vendor/google.golang.org/grpc/rpc_util.go | 48 ++++ vendor/google.golang.org/grpc/server.go | 59 ++-- .../google.golang.org/grpc/stats/handlers.go | 114 ++------ vendor/google.golang.org/grpc/stream.go | 91 ++++--- .../grpc/transport/http2_client.go | 37 +-- .../grpc/transport/http2_server.go | 27 +- .../grpc/transport/transport.go | 13 +- 22 files changed, 1029 insertions(+), 210 deletions(-) create mode 100644 client_api/api/api.pb.go create mode 100644 client_api/api/api.proto create mode 100644 client_api/api/client.go create mode 100644 client_api/api/errors.go create mode 100644 client_api/api/generator.go create mode 100644 client_api/api/server.go create mode 100644 cmd/client_api/.gitignore create mode 100644 cmd/client_api/config.toml create mode 100644 cmd/client_api/main.go create mode 100644 cmd/client_api/setup/config.go create mode 100644 utils/transport.go create mode 100644 utils/transport_test.go diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go new file mode 100644 index 000000000..5456bf7c9 --- /dev/null +++ b/client_api/api/api.pb.go @@ -0,0 +1,252 @@ +// Code generated by protoc-gen-go. +// source: api.proto +// DO NOT EDIT! + +/* +Package api is a generated protocol buffer package. + +It is generated from these files: + api.proto + +It has these top-level messages: + TargetAction + BasicResponse +*/ +package api + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// Target message describes a TUF target +type TargetAction struct { + Gun string `protobuf:"bytes,1,opt,name=gun" json:"gun,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` + Length int64 `protobuf:"varint,3,opt,name=length" json:"length,omitempty"` + Hashes map[string][]byte `protobuf:"bytes,4,rep,name=hashes" json:"hashes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"` + Custom []byte `protobuf:"bytes,5,opt,name=custom,proto3" json:"custom,omitempty"` +} + +func (m *TargetAction) Reset() { *m = TargetAction{} } +func (m *TargetAction) String() string { return proto.CompactTextString(m) } +func (*TargetAction) ProtoMessage() {} +func (*TargetAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *TargetAction) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + +func (m *TargetAction) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *TargetAction) GetLength() int64 { + if m != nil { + return m.Length + } + return 0 +} + +func (m *TargetAction) GetHashes() map[string][]byte { + if m != nil { + return m.Hashes + } + return nil +} + +func (m *TargetAction) GetCustom() []byte { + if m != nil { + return m.Custom + } + return nil +} + +// BasicResponse describes a response with a true/false success indicator, +// and if false, an error type and message. See the errors.go file in this +// package for the possible errors and a translation function between the +// BasicResponse object and a concrete error type. +type BasicResponse struct { + Success bool `protobuf:"varint,1,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"` +} + +func (m *BasicResponse) Reset() { *m = BasicResponse{} } +func (m *BasicResponse) String() string { return proto.CompactTextString(m) } +func (*BasicResponse) ProtoMessage() {} +func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *BasicResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *BasicResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +func init() { + proto.RegisterType((*TargetAction)(nil), "api.TargetAction") + proto.RegisterType((*BasicResponse)(nil), "api.BasicResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for Notary service + +type NotaryClient interface { + // AddTarget adds a target to the TUF repository and re-signs. + AddTarget(ctx context.Context, in *TargetAction, opts ...grpc.CallOption) (*BasicResponse, error) + // RemoveTarget deletes a target from the TUF repository and re-signs. It only + // uses the `name` field from the Target object, ignoring all other fields + RemoveTarget(ctx context.Context, in *TargetAction, opts ...grpc.CallOption) (*BasicResponse, error) +} + +type notaryClient struct { + cc *grpc.ClientConn +} + +func NewNotaryClient(cc *grpc.ClientConn) NotaryClient { + return ¬aryClient{cc} +} + +func (c *notaryClient) AddTarget(ctx context.Context, in *TargetAction, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/AddTarget", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) RemoveTarget(ctx context.Context, in *TargetAction, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/RemoveTarget", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for Notary service + +type NotaryServer interface { + // AddTarget adds a target to the TUF repository and re-signs. + AddTarget(context.Context, *TargetAction) (*BasicResponse, error) + // RemoveTarget deletes a target from the TUF repository and re-signs. It only + // uses the `name` field from the Target object, ignoring all other fields + RemoveTarget(context.Context, *TargetAction) (*BasicResponse, error) +} + +func RegisterNotaryServer(s *grpc.Server, srv NotaryServer) { + s.RegisterService(&_Notary_serviceDesc, srv) +} + +func _Notary_AddTarget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TargetAction) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).AddTarget(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/AddTarget", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).AddTarget(ctx, req.(*TargetAction)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_RemoveTarget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TargetAction) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).RemoveTarget(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/RemoveTarget", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).RemoveTarget(ctx, req.(*TargetAction)) + } + return interceptor(ctx, in, info, handler) +} + +var _Notary_serviceDesc = grpc.ServiceDesc{ + ServiceName: "api.Notary", + HandlerType: (*NotaryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "AddTarget", + Handler: _Notary_AddTarget_Handler, + }, + { + MethodName: "RemoveTarget", + Handler: _Notary_RemoveTarget_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "api.proto", +} + +func init() { proto.RegisterFile("api.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 278 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x91, 0x4f, 0x4b, 0xf3, 0x40, + 0x10, 0xc6, 0xdf, 0x6d, 0xda, 0xbc, 0x66, 0x1a, 0x41, 0x07, 0x91, 0xa5, 0x20, 0x84, 0x9c, 0x72, + 0xca, 0xa1, 0x2a, 0xfe, 0xb9, 0x55, 0x11, 0x3c, 0x79, 0x58, 0xfc, 0x02, 0x6b, 0x3a, 0x24, 0xa1, + 0xcd, 0x6e, 0xc8, 0x6e, 0x2a, 0xf9, 0xa2, 0x7e, 0x1e, 0xc9, 0x26, 0x81, 0x8a, 0x27, 0x6f, 0xf3, + 0x9b, 0x99, 0x9d, 0xe7, 0x79, 0x58, 0x08, 0x64, 0x5d, 0xa6, 0x75, 0xa3, 0xad, 0x46, 0x4f, 0xd6, + 0x65, 0xfc, 0xc5, 0x20, 0x7c, 0x97, 0x4d, 0x4e, 0x76, 0x93, 0xd9, 0x52, 0x2b, 0x3c, 0x03, 0x2f, + 0x6f, 0x15, 0x67, 0x11, 0x4b, 0x02, 0xd1, 0x97, 0x88, 0x30, 0x57, 0xb2, 0x22, 0x3e, 0x73, 0x2d, + 0x57, 0xe3, 0x25, 0xf8, 0x7b, 0x52, 0xb9, 0x2d, 0xb8, 0x17, 0xb1, 0xc4, 0x13, 0x23, 0xe1, 0x2d, + 0xf8, 0x85, 0x34, 0x05, 0x19, 0x3e, 0x8f, 0xbc, 0x64, 0xb9, 0xbe, 0x4a, 0x7b, 0xbd, 0x63, 0x81, + 0xf4, 0xd5, 0xcd, 0x5f, 0x94, 0x6d, 0x3a, 0x31, 0x2e, 0xf7, 0xe7, 0xb2, 0xd6, 0x58, 0x5d, 0xf1, + 0x45, 0xc4, 0x92, 0x50, 0x8c, 0xb4, 0x7a, 0x80, 0xe5, 0xd1, 0x7a, 0xef, 0x6d, 0x47, 0xdd, 0xe4, + 0x6d, 0x47, 0x1d, 0x5e, 0xc0, 0xe2, 0x20, 0xf7, 0xed, 0x60, 0x2e, 0x14, 0x03, 0x3c, 0xce, 0xee, + 0x59, 0xfc, 0x0c, 0xa7, 0x4f, 0xd2, 0x94, 0x99, 0x20, 0x53, 0x6b, 0x65, 0x08, 0x39, 0xfc, 0x37, + 0x6d, 0x96, 0x91, 0x31, 0xee, 0xc0, 0x89, 0x98, 0xb0, 0x9f, 0x54, 0x64, 0x8c, 0xcc, 0xa7, 0x8c, + 0x13, 0xae, 0x3f, 0xc1, 0x7f, 0xd3, 0x56, 0x36, 0x1d, 0xde, 0x40, 0xb0, 0xd9, 0x6e, 0x87, 0x20, + 0x78, 0xfe, 0x2b, 0xd5, 0x0a, 0x5d, 0xeb, 0x87, 0x62, 0xfc, 0x0f, 0xef, 0x20, 0x14, 0x54, 0xe9, + 0x03, 0xfd, 0xf1, 0xe1, 0x87, 0xef, 0xbe, 0xe8, 0xfa, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x4d, 0x9e, + 0x39, 0x36, 0xaf, 0x01, 0x00, 0x00, +} diff --git a/client_api/api/api.proto b/client_api/api/api.proto new file mode 100644 index 000000000..fe31e648f --- /dev/null +++ b/client_api/api/api.proto @@ -0,0 +1,33 @@ +syntax = "proto3"; + +package api; + +// Notary Interface +service Notary { + // AddTarget adds a target to the TUF repository and re-signs. + rpc AddTarget(TargetAction) returns (BasicResponse) {} + + // RemoveTarget deletes a target from the TUF repository and re-signs. It only + // uses the `name` field from the Target object, ignoring all other fields + rpc RemoveTarget(TargetAction) returns (BasicResponse) {} +} + +// Target message describes a TUF target. +message TargetAction { + string gun = 1; + string name = 2; + int64 length = 3; + map hashes = 4; + bytes custom = 5; +} + +// BasicResponse describes a response with a true/false success indicator, +// and if false, an error type and message. See the errors.go file in this +// package for the possible errors and a translation function between the +// BasicResponse object and a concrete error type. +message BasicResponse { + bool success = 1; + string message = 2; +} + + diff --git a/client_api/api/client.go b/client_api/api/client.go new file mode 100644 index 000000000..16ade1c48 --- /dev/null +++ b/client_api/api/client.go @@ -0,0 +1,10 @@ +package api + +import "google.golang.org/grpc" + +type Client struct {} + +func NewClient(conn *grpc.ClientConn) (NotaryClient, error) { + + return NewNotaryClient(conn), nil +} diff --git a/client_api/api/errors.go b/client_api/api/errors.go new file mode 100644 index 000000000..976611216 --- /dev/null +++ b/client_api/api/errors.go @@ -0,0 +1,20 @@ +package api + +type ErrUnknown struct { + msg string +} + +func NewErrorUnknown(msg string) error { + return ErrUnknown{msg: msg} +} + +func (err ErrUnknown) Error() string { + return err.msg +} + +func translateAPIError(t string, msg string) error { + switch t{ + default: + return NewErrorUnknown(msg) + } +} \ No newline at end of file diff --git a/client_api/api/generator.go b/client_api/api/generator.go new file mode 100644 index 000000000..f599627b0 --- /dev/null +++ b/client_api/api/generator.go @@ -0,0 +1,5 @@ +package api + +// this file exists solely to allow us to use `go generate` to build our +// compiled GRPC interface for Go. +//go:generate protoc -I ./ ./api.proto --go_out=plugins=grpc:. diff --git a/client_api/api/server.go b/client_api/api/server.go new file mode 100644 index 000000000..7bff82dc9 --- /dev/null +++ b/client_api/api/server.go @@ -0,0 +1,124 @@ +package api + +import ( + "github.com/docker/notary/client" + "github.com/docker/notary/storage" + "github.com/docker/notary/trustpinning" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/utils" + "golang.org/x/net/context" + "google.golang.org/grpc" +) + +// NewServer creates a new instance of a Client API server with a configured +// upstream Notary Server. +func NewServer(upstream string, serverOpts []grpc.ServerOption) (*grpc.Server, error) { + grpcSrv := grpc.NewServer(serverOpts...) + srv := &Server{ + upstream: upstream, + } + RegisterNotaryServer(grpcSrv, srv) + return grpcSrv, nil +} + +type Server struct { + upstream string +} + +func (srv *Server) AddTarget(ctx context.Context, t *TargetAction) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(t.GetGun())) + if err != nil { + return nil, err + } + if err := r.AddTarget( + &client.Target{ + Name: t.GetName(), + Hashes: data.Hashes(t.Hashes), + Length: t.Length, + }, + ); err != nil { + return nil, err + } + if err := publishRepo(r); err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil +} + +func (srv *Server) RemoveTarget(ctx context.Context, t *TargetAction) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(t.GetGun())) + if err != nil { + return nil, err + } + if err := r.RemoveTarget( + t.GetName(), "targets", + ); err != nil { + return nil, err + } + if err := publishRepo(r); err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil +} + +func publishRepo(r *client.NotaryRepository) error { + if err := r.Publish(); err != nil { + if _, ok := err.(client.ErrRepoNotInitialized); !ok { + return err + } + if err := initializeRepo(r); err != nil { + return err + } + return r.Publish() + } + return nil +} + +func initializeRepo(r *client.NotaryRepository) error { + rootKeyList := r.CryptoService.ListKeys(data.CanonicalRootRole) + var rootKeyID string + if len(rootKeyList) < 1 { + rootPublicKey, err := r.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey) + if err != nil { + return err + } + rootKeyID = rootPublicKey.ID() + } else { + // Chooses the first root key available, which is initialization specific + // but should return the HW one first. + rootKeyID = rootKeyList[0] + } + return r.Initialize([]string{rootKeyID}) +} + +func (srv *Server) initRepo(gun data.GUN) (*client.NotaryRepository, error) { + rt, err := utils.GetReadOnlyAuthTransport( + srv.upstream, + []string{gun.String()}, + "", + "", + "/fixtures/root-ca.crt", + ) + if err != nil { + return nil, err + } + return client.NewNotaryRepository( + "/var/lib/clientapi", + gun, + srv.upstream, + rt, + storage.NewMemoryStore(nil), + retriever, + trustpinning.TrustPinConfig{}, + ) +} + +func retriever(keyName, alias string, createNew bool, attempts int) (string, bool, error) { + return "password", false, nil +} diff --git a/cmd/client_api/.gitignore b/cmd/client_api/.gitignore new file mode 100644 index 000000000..254defddb --- /dev/null +++ b/cmd/client_api/.gitignore @@ -0,0 +1 @@ +server diff --git a/cmd/client_api/config.toml b/cmd/client_api/config.toml new file mode 100644 index 000000000..80b5df278 --- /dev/null +++ b/cmd/client_api/config.toml @@ -0,0 +1,10 @@ +[server] +grpc_addr = ":4449" +tls_cert_file = "/fixtures/clientapi-server.crt" +tls_key_file = "/fixtures/clientapi-server.key" + +[logging] +level = "debug" + +[upstream] +addr = "https://notaryserver:4443" diff --git a/cmd/client_api/main.go b/cmd/client_api/main.go new file mode 100644 index 000000000..2baca5514 --- /dev/null +++ b/cmd/client_api/main.go @@ -0,0 +1,65 @@ +package main + +import ( + "flag" + "github.com/Sirupsen/logrus" + "github.com/docker/notary/client_api/api" + "github.com/docker/notary/cmd/client_api/setup" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "net" +) + +var ( + configPath string +) + +func init() { + flag.StringVar( + &configPath, + "config", + "config.toml", + "path to configuration file; supported formats are JSON, YAML, and TOML", + ) + flag.Parse() +} + +func main() { + vc, err := setup.ViperConfig(configPath) + if err != nil { + logrus.Fatal(err) + } + + logrus.SetLevel(logrus.DebugLevel) + + // FIXME: refactor with notary-signer/config.go:getAddrAndTLSConfig() + // and setupGRPCServer() + grpcAddr, tlsConfig, err := setup.GetAddrAndTLSConfig(vc) + if err != nil { + logrus.Fatal("unable to set up TLS: %s", err.Error()) + } + + serverConfig := setup.Config{GRPCAddr: grpcAddr, TLSConfig: tlsConfig} + + upstreamAddr := vc.GetString("upstream.addr") + + lis, err := net.Listen("tcp", serverConfig.GRPCAddr) + if err != nil { + logrus.Fatal("grpc server failed to listen on %s: %v", + serverConfig.GRPCAddr, err) + } + + creds := credentials.NewTLS(serverConfig.TLSConfig) + opts := []grpc.ServerOption{grpc.Creds(creds)} + s, err := api.NewServer(upstreamAddr, opts) + if err != nil { + logrus.Fatal(err) + } + + // grpcServer, lis, err := setup.SetupGRPCServer(serverConfig) + + logrus.Infof("serving on %s", grpcAddr) + if err := s.Serve(lis); err != nil { + } + logrus.Info("server shutting down") +} diff --git a/cmd/client_api/setup/config.go b/cmd/client_api/setup/config.go new file mode 100644 index 000000000..4d9a16832 --- /dev/null +++ b/cmd/client_api/setup/config.go @@ -0,0 +1,73 @@ +package setup + +import ( + "github.com/spf13/viper" + "github.com/Sirupsen/logrus" + "github.com/docker/notary/utils" + "crypto/tls" + "fmt" + "net" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + ghealth "google.golang.org/grpc/health" + healthpb "google.golang.org/grpc/health/grpc_health_v1" +) + +type Config struct { + GRPCAddr string + TLSConfig *tls.Config +} + +func ViperConfig(path string) (*viper.Viper, error) { + vc := viper.New() + setDefaults(vc) + vc.SetConfigFile(path) + err := vc.ReadInConfig() + if err != nil { + return nil, err + } + logrus.Info(vc.AllSettings()) + return vc, nil +} + +// SetDefaults is responsible for setting defaults on the Viper struct +// These should be overridden by a subsequent call to +func setDefaults(vc *viper.Viper) { + vc.SetDefault("upstream.addr", "https://localhost:4443") + vc.SetDefault("server", map[string]string{"addr":":4445"}) +} + +func SetupGRPCServer(serverConfig Config) (*grpc.Server, net.Listener, error) { + + //RPC server setup + hs := ghealth.NewServer() + + lis, err := net.Listen("tcp", serverConfig.GRPCAddr) + if err != nil { + return nil, nil, fmt.Errorf("grpc server failed to listen on %s: %v", + serverConfig.GRPCAddr, err) + } + + creds := credentials.NewTLS(serverConfig.TLSConfig) + opts := []grpc.ServerOption{grpc.Creds(creds)} + grpcServer := grpc.NewServer(opts...) + + healthpb.RegisterHealthServer(grpcServer, hs) + + return grpcServer, lis, nil +} + +func GetAddrAndTLSConfig(configuration *viper.Viper) (string, *tls.Config, error) { + tlsConfig, err := utils.ParseServerTLS(configuration, true) + if err != nil { + return "", nil, fmt.Errorf("unable to set up TLS: %s", err.Error()) + } + + grpcAddr := configuration.GetString("server.grpc_addr") + if grpcAddr == "" { + return "", nil, fmt.Errorf("grpc listen address required for server") + } + + return grpcAddr, tlsConfig, nil +} diff --git a/utils/transport.go b/utils/transport.go new file mode 100644 index 000000000..53a6eb99e --- /dev/null +++ b/utils/transport.go @@ -0,0 +1,121 @@ +package utils + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "net" + "net/http" + "net/url" + "time" + + "github.com/docker/distribution/registry/client/auth" + "github.com/docker/distribution/registry/client/auth/challenge" + "github.com/docker/distribution/registry/client/transport" + "io/ioutil" +) + +// Stolen from a mix of UCP + nautilus signer, some might be able to be cleaned up / streamlined +type credentialStore struct { + username string + password string + refreshTokens map[string]string +} + +func (tcs *credentialStore) Basic(url *url.URL) (string, string) { + return tcs.username, tcs.password +} + +// refresh tokens are the long lived tokens that can be used instead of a password +func (tcs *credentialStore) RefreshToken(u *url.URL, service string) string { + return tcs.refreshTokens[service] +} + +func (tcs *credentialStore) SetRefreshToken(u *url.URL, service string, token string) { + if tcs.refreshTokens != nil { + tcs.refreshTokens[service] = token + } +} + +// GetReadOnlyAuthTransport gets the Garant Auth Transport used to communicate with notary +func GetReadOnlyAuthTransport(server string, scopes []string, username, password, rootCAPath string) (http.RoundTripper, error) { + httpsTransport, err := httpsTransport(rootCAPath, "", "") + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", fmt.Sprintf("%s/v2/", server), nil) + if err != nil { + return nil, err + } + pingClient := &http.Client{ + Transport: httpsTransport, + Timeout: 5 * time.Second, + } + resp, err := pingClient.Do(req) + if err != nil { + return nil, err + } + challengeManager := challenge.NewSimpleManager() + if err := challengeManager.AddResponse(resp); err != nil { + return nil, err + } + + creds := credentialStore{ + username: username, + password: password, + refreshTokens: make(map[string]string), + } + + var scopeObjs []auth.Scope + for _, scopeName := range scopes { + scopeObjs = append(scopeObjs, auth.RepositoryScope{ + Repository: scopeName, + Actions: []string{"pull"}, + }) + } + + // allow setting multiple scopes so we don't have to reauth + tokenHandler := auth.NewTokenHandlerWithOptions(auth.TokenHandlerOptions{ + Transport: httpsTransport, + Credentials: &creds, + Scopes: scopeObjs, + }) + + authedTransport := transport.NewTransport(httpsTransport, auth.NewAuthorizer(challengeManager, tokenHandler)) + return authedTransport, nil +} + +func httpsTransport(caFile, clientCertFile, clientKeyFile string) (*http.Transport, error) { + tlsConfig := &tls.Config{} + transport := http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: tlsConfig, + } + // Override with the system cert pool if the caFile was empty + // TODO(riyazdf): update this code when go-connections updates to use the system cert pool + if caFile == "" { + systemCertPool, err := x509.SystemCertPool() + if err != nil { + return nil, err + } + transport.TLSClientConfig.RootCAs = systemCertPool + } else { + certs, err := ioutil.ReadFile(caFile) + if err != nil { + return nil, err + } + pool := x509.NewCertPool() + if !pool.AppendCertsFromPEM(certs) { + return nil, fmt.Errorf("failed to fully parse %s", caFile) + } + transport.TLSClientConfig.RootCAs = pool + + } + return &transport, nil +} diff --git a/utils/transport_test.go b/utils/transport_test.go new file mode 100644 index 000000000..d4b585bf7 --- /dev/null +++ b/utils/transport_test.go @@ -0,0 +1 @@ +package utils diff --git a/vendor/google.golang.org/grpc/call.go b/vendor/google.golang.org/grpc/call.go index fc8e18afc..81b52be29 100644 --- a/vendor/google.golang.org/grpc/call.go +++ b/vendor/google.golang.org/grpc/call.go @@ -42,6 +42,7 @@ import ( "golang.org/x/net/context" "golang.org/x/net/trace" "google.golang.org/grpc/codes" + "google.golang.org/grpc/peer" "google.golang.org/grpc/stats" "google.golang.org/grpc/transport" ) @@ -66,7 +67,7 @@ func recvResponse(ctx context.Context, dopts dialOptions, t transport.ClientTran } p := &parser{r: stream} var inPayload *stats.InPayload - if stats.On() { + if dopts.copts.StatsHandler != nil { inPayload = &stats.InPayload{ Client: true, } @@ -82,14 +83,17 @@ func recvResponse(ctx context.Context, dopts dialOptions, t transport.ClientTran if inPayload != nil && err == io.EOF && stream.StatusCode() == codes.OK { // TODO in the current implementation, inTrailer may be handled before inPayload in some cases. // Fix the order if necessary. - stats.HandleRPC(ctx, inPayload) + dopts.copts.StatsHandler.HandleRPC(ctx, inPayload) } c.trailerMD = stream.Trailer() + if peer, ok := peer.FromContext(stream.Context()); ok { + c.peer = peer + } return nil } // sendRequest writes out various information of an RPC such as Context and Message. -func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHdr *transport.CallHdr, t transport.ClientTransport, args interface{}, opts *transport.Options) (_ *transport.Stream, err error) { +func sendRequest(ctx context.Context, dopts dialOptions, compressor Compressor, callHdr *transport.CallHdr, t transport.ClientTransport, args interface{}, opts *transport.Options) (_ *transport.Stream, err error) { stream, err := t.NewStream(ctx, callHdr) if err != nil { return nil, err @@ -109,19 +113,19 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd if compressor != nil { cbuf = new(bytes.Buffer) } - if stats.On() { + if dopts.copts.StatsHandler != nil { outPayload = &stats.OutPayload{ Client: true, } } - outBuf, err := encode(codec, args, compressor, cbuf, outPayload) + outBuf, err := encode(dopts.codec, args, compressor, cbuf, outPayload) if err != nil { return nil, Errorf(codes.Internal, "grpc: %v", err) } err = t.Write(stream, outBuf, opts) if err == nil && outPayload != nil { outPayload.SentTime = time.Now() - stats.HandleRPC(ctx, outPayload) + dopts.copts.StatsHandler.HandleRPC(ctx, outPayload) } // t.NewStream(...) could lead to an early rejection of the RPC (e.g., the service/method // does not exist.) so that t.Write could get io.EOF from wait(...). Leave the following @@ -145,6 +149,14 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli func invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (e error) { c := defaultCallInfo + if mc, ok := cc.getMethodConfig(method); ok { + c.failFast = !mc.WaitForReady + if mc.Timeout > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, mc.Timeout) + defer cancel() + } + } for _, o := range opts { if err := o.before(&c); err != nil { return toRPCErr(err) @@ -171,23 +183,24 @@ func invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli } }() } - if stats.On() { - ctx = stats.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method}) + sh := cc.dopts.copts.StatsHandler + if sh != nil { + ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method}) begin := &stats.Begin{ Client: true, BeginTime: time.Now(), FailFast: c.failFast, } - stats.HandleRPC(ctx, begin) + sh.HandleRPC(ctx, begin) } defer func() { - if stats.On() { + if sh != nil { end := &stats.End{ Client: true, EndTime: time.Now(), Error: e, } - stats.HandleRPC(ctx, end) + sh.HandleRPC(ctx, end) } }() topts := &transport.Options{ @@ -211,6 +224,7 @@ func invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli if cc.dopts.cp != nil { callHdr.SendCompress = cc.dopts.cp.Type() } + gopts := BalancerGetOptions{ BlockingWait: !c.failFast, } @@ -232,7 +246,7 @@ func invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli if c.traceInfo.tr != nil { c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true) } - stream, err = sendRequest(ctx, cc.dopts.codec, cc.dopts.cp, callHdr, t, args, topts) + stream, err = sendRequest(ctx, cc.dopts, cc.dopts.cp, callHdr, t, args, topts) if err != nil { if put != nil { put() diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go index f6dab4b77..459ce0b64 100644 --- a/vendor/google.golang.org/grpc/clientconn.go +++ b/vendor/google.golang.org/grpc/clientconn.go @@ -45,6 +45,7 @@ import ( "golang.org/x/net/trace" "google.golang.org/grpc/credentials" "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/stats" "google.golang.org/grpc/transport" ) @@ -54,6 +55,8 @@ var ( ErrClientConnClosing = errors.New("grpc: the client connection is closing") // ErrClientConnTimeout indicates that the ClientConn cannot establish the // underlying connections within the specified timeout. + // DEPRECATED: Please use context.DeadlineExceeded instead. This error will be + // removed in Q1 2017. ErrClientConnTimeout = errors.New("grpc: timed out when dialing") // errNoTransportSecurity indicates that there is no transport security @@ -93,6 +96,7 @@ type dialOptions struct { block bool insecure bool timeout time.Duration + scChan <-chan ServiceConfig copts transport.ConnectOptions } @@ -129,6 +133,13 @@ func WithBalancer(b Balancer) DialOption { } } +// WithServiceConfig returns a DialOption which has a channel to read the service configuration. +func WithServiceConfig(c <-chan ServiceConfig) DialOption { + return func(o *dialOptions) { + o.scChan = c + } +} + // WithBackoffMaxDelay configures the dialer to use the provided maximum delay // when backing off after failed connection attempts. func WithBackoffMaxDelay(md time.Duration) DialOption { @@ -212,6 +223,14 @@ func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption { } } +// WithStatsHandler returns a DialOption that specifies the stats handler +// for all the RPCs and underlying network connections in this ClientConn. +func WithStatsHandler(h stats.Handler) DialOption { + return func(o *dialOptions) { + o.copts.StatsHandler = h + } +} + // FailOnNonTempDialError returns a DialOption that specified if gRPC fails on non-temporary dial errors. // If f is true, and dialer returns a non-temporary error, gRPC will fail the connection to the network // address and won't try to reconnect. @@ -244,6 +263,15 @@ func WithStreamInterceptor(f StreamClientInterceptor) DialOption { } } +// WithAuthority returns a DialOption that specifies the value to be used as +// the :authority pseudo-header. This value only works with WithInsecure and +// has no effect if TransportCredentials are present. +func WithAuthority(a string) DialOption { + return func(o *dialOptions) { + o.copts.Authority = a + } +} + // Dial creates a client connection to the given target. func Dial(target string, opts ...DialOption) (*ClientConn, error) { return DialContext(context.Background(), target, opts...) @@ -260,6 +288,15 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * conns: make(map[Address]*addrConn), } cc.ctx, cc.cancel = context.WithCancel(context.Background()) + for _, opt := range opts { + opt(&cc.dopts) + } + if cc.dopts.timeout > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, cc.dopts.timeout) + defer cancel() + } + defer func() { select { case <-ctx.Done(): @@ -272,10 +309,17 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * } }() - for _, opt := range opts { - opt(&cc.dopts) + if cc.dopts.scChan != nil { + // Wait for the initial service config. + select { + case sc, ok := <-cc.dopts.scChan: + if ok { + cc.sc = sc + } + case <-ctx.Done(): + return nil, ctx.Err() + } } - // Set defaults. if cc.dopts.codec == nil { cc.dopts.codec = protoCodec{} @@ -286,6 +330,8 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * creds := cc.dopts.copts.TransportCredentials if creds != nil && creds.Info().ServerName != "" { cc.authority = creds.Info().ServerName + } else if cc.dopts.insecure && cc.dopts.copts.Authority != "" { + cc.authority = cc.dopts.copts.Authority } else { colonPos := strings.LastIndex(target, ":") if colonPos == -1 { @@ -297,6 +343,9 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * waitC := make(chan error, 1) go func() { var addrs []Address + if cc.dopts.balancer == nil && cc.sc.LB != nil { + cc.dopts.balancer = cc.sc.LB + } if cc.dopts.balancer == nil { // Connect to target directly if balancer is nil. addrs = append(addrs, Address{Addr: target}) @@ -332,10 +381,6 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * } close(waitC) }() - var timeoutCh <-chan time.Time - if cc.dopts.timeout > 0 { - timeoutCh = time.After(cc.dopts.timeout) - } select { case <-ctx.Done(): return nil, ctx.Err() @@ -343,14 +388,17 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * if err != nil { return nil, err } - case <-timeoutCh: - return nil, ErrClientConnTimeout } + // If balancer is nil or balancer.Notify() is nil, ok will be false here. // The lbWatcher goroutine will not be created. if ok { go cc.lbWatcher() } + + if cc.dopts.scChan != nil { + go cc.scWatcher() + } return cc, nil } @@ -397,6 +445,7 @@ type ClientConn struct { dopts dialOptions mu sync.RWMutex + sc ServiceConfig conns map[Address]*addrConn } @@ -435,6 +484,24 @@ func (cc *ClientConn) lbWatcher() { } } +func (cc *ClientConn) scWatcher() { + for { + select { + case sc, ok := <-cc.dopts.scChan: + if !ok { + return + } + cc.mu.Lock() + // TODO: load balance policy runtime change is ignored. + // We may revist this decision in the future. + cc.sc = sc + cc.mu.Unlock() + case <-cc.ctx.Done(): + return + } + } +} + // resetAddrConn creates an addrConn for addr and adds it to cc.conns. // If there is an old addrConn for addr, it will be torn down, using tearDownErr as the reason. // If tearDownErr is nil, errConnDrain will be used instead. @@ -522,6 +589,14 @@ func (cc *ClientConn) resetAddrConn(addr Address, skipWait bool, tearDownErr err return nil } +// TODO: Avoid the locking here. +func (cc *ClientConn) getMethodConfig(method string) (m MethodConfig, ok bool) { + cc.mu.RLock() + defer cc.mu.RUnlock() + m, ok = cc.sc.Methods[method] + return +} + func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) (transport.ClientTransport, func(), error) { var ( ac *addrConn diff --git a/vendor/google.golang.org/grpc/credentials/credentials.go b/vendor/google.golang.org/grpc/credentials/credentials.go index 5555ef024..4d45c3e3c 100644 --- a/vendor/google.golang.org/grpc/credentials/credentials.go +++ b/vendor/google.golang.org/grpc/credentials/credentials.go @@ -165,9 +165,7 @@ func (c *tlsCreds) ClientHandshake(ctx context.Context, addr string, rawConn net case <-ctx.Done(): return nil, nil, ctx.Err() } - // TODO(zhaoq): Omit the auth info for client now. It is more for - // information than anything else. - return conn, nil, nil + return conn, TLSInfo{conn.ConnectionState()}, nil } func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) { diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go index 66d08b5aa..da88dad42 100644 --- a/vendor/google.golang.org/grpc/rpc_util.go +++ b/vendor/google.golang.org/grpc/rpc_util.go @@ -48,6 +48,7 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" + "google.golang.org/grpc/peer" "google.golang.org/grpc/stats" "google.golang.org/grpc/transport" ) @@ -140,6 +141,7 @@ type callInfo struct { failFast bool headerMD metadata.MD trailerMD metadata.MD + peer *peer.Peer traceInfo traceInfo // in trace.go } @@ -183,6 +185,14 @@ func Trailer(md *metadata.MD) CallOption { }) } +// Peer returns a CallOption that retrieves peer information for a +// unary RPC. +func Peer(peer *peer.Peer) CallOption { + return afterCall(func(c *callInfo) { + *peer = *c.peer + }) +} + // FailFast configures the action to take when an RPC is attempted on broken // connections or unreachable servers. If failfast is true, the RPC will fail // immediately. Otherwise, the RPC client will block the call until a @@ -472,6 +482,44 @@ func convertCode(err error) codes.Code { return codes.Unknown } +// MethodConfig defines the configuration recommended by the service providers for a +// particular method. +// This is EXPERIMENTAL and subject to change. +type MethodConfig struct { + // WaitForReady indicates whether RPCs sent to this method should wait until + // the connection is ready by default (!failfast). The value specified via the + // gRPC client API will override the value set here. + WaitForReady bool + // Timeout is the default timeout for RPCs sent to this method. The actual + // deadline used will be the minimum of the value specified here and the value + // set by the application via the gRPC client API. If either one is not set, + // then the other will be used. If neither is set, then the RPC has no deadline. + Timeout time.Duration + // MaxReqSize is the maximum allowed payload size for an individual request in a + // stream (client->server) in bytes. The size which is measured is the serialized + // payload after per-message compression (but before stream compression) in bytes. + // The actual value used is the minumum of the value specified here and the value set + // by the application via the gRPC client API. If either one is not set, then the other + // will be used. If neither is set, then the built-in default is used. + // TODO: support this. + MaxReqSize uint32 + // MaxRespSize is the maximum allowed payload size for an individual response in a + // stream (server->client) in bytes. + // TODO: support this. + MaxRespSize uint32 +} + +// ServiceConfig is provided by the service provider and contains parameters for how +// clients that connect to the service should behave. +// This is EXPERIMENTAL and subject to change. +type ServiceConfig struct { + // LB is the load balancer the service providers recommends. The balancer specified + // via grpc.WithBalancer will override this. + LB Balancer + // Methods contains a map for the methods in this service. + Methods map[string]MethodConfig +} + // SupportPackageIsVersion4 is referenced from generated protocol buffer files // to assert that that code is compatible with this version of the grpc package. // diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index 22aa33bfe..985226d60 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -113,6 +113,7 @@ type options struct { unaryInt UnaryServerInterceptor streamInt StreamServerInterceptor inTapHandle tap.ServerInHandle + statsHandler stats.Handler maxConcurrentStreams uint32 useHandlerImpl bool // use http.Handler-based server } @@ -200,6 +201,13 @@ func InTapHandle(h tap.ServerInHandle) ServerOption { } } +// StatsHandler returns a ServerOption that sets the stats handler for the server. +func StatsHandler(h stats.Handler) ServerOption { + return func(o *options) { + o.statsHandler = h + } +} + // NewServer creates a gRPC server which has no service registered and has not // started to accept requests yet. func NewServer(opt ...ServerOption) *Server { @@ -343,6 +351,7 @@ func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credenti // read gRPC requests and then call the registered handlers to reply to them. // Serve returns when lis.Accept fails with fatal errors. lis will be closed when // this method returns. +// Serve always returns non-nil error. func (s *Server) Serve(lis net.Listener) error { s.mu.Lock() s.printf("serving") @@ -437,9 +446,10 @@ func (s *Server) handleRawConn(rawConn net.Conn) { // transport.NewServerTransport). func (s *Server) serveHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) { config := &transport.ServerConfig{ - MaxStreams: s.opts.maxConcurrentStreams, - AuthInfo: authInfo, - InTapHandle: s.opts.inTapHandle, + MaxStreams: s.opts.maxConcurrentStreams, + AuthInfo: authInfo, + InTapHandle: s.opts.inTapHandle, + StatsHandler: s.opts.statsHandler, } st, err := transport.NewServerTransport("http2", c, config) if err != nil { @@ -566,7 +576,7 @@ func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Str if cp != nil { cbuf = new(bytes.Buffer) } - if stats.On() { + if s.opts.statsHandler != nil { outPayload = &stats.OutPayload{} } p, err := encode(s.opts.codec, msg, cp, cbuf, outPayload) @@ -583,27 +593,28 @@ func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Str err = t.Write(stream, p, opts) if err == nil && outPayload != nil { outPayload.SentTime = time.Now() - stats.HandleRPC(stream.Context(), outPayload) + s.opts.statsHandler.HandleRPC(stream.Context(), outPayload) } return err } func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) { - if stats.On() { + sh := s.opts.statsHandler + if sh != nil { begin := &stats.Begin{ BeginTime: time.Now(), } - stats.HandleRPC(stream.Context(), begin) + sh.HandleRPC(stream.Context(), begin) } defer func() { - if stats.On() { + if sh != nil { end := &stats.End{ EndTime: time.Now(), } if err != nil && err != io.EOF { end.Error = toRPCErr(err) } - stats.HandleRPC(stream.Context(), end) + sh.HandleRPC(stream.Context(), end) } }() if trInfo != nil { @@ -664,7 +675,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. } } var inPayload *stats.InPayload - if stats.On() { + if sh != nil { inPayload = &stats.InPayload{ RecvTime: time.Now(), } @@ -698,7 +709,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. inPayload.Payload = v inPayload.Data = req inPayload.Length = len(req) - stats.HandleRPC(stream.Context(), inPayload) + sh.HandleRPC(stream.Context(), inPayload) } if trInfo != nil { trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true) @@ -755,35 +766,37 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport. } func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc, trInfo *traceInfo) (err error) { - if stats.On() { + sh := s.opts.statsHandler + if sh != nil { begin := &stats.Begin{ BeginTime: time.Now(), } - stats.HandleRPC(stream.Context(), begin) + sh.HandleRPC(stream.Context(), begin) } defer func() { - if stats.On() { + if sh != nil { end := &stats.End{ EndTime: time.Now(), } if err != nil && err != io.EOF { end.Error = toRPCErr(err) } - stats.HandleRPC(stream.Context(), end) + sh.HandleRPC(stream.Context(), end) } }() if s.opts.cp != nil { stream.SetSendCompress(s.opts.cp.Type()) } ss := &serverStream{ - t: t, - s: stream, - p: &parser{r: stream}, - codec: s.opts.codec, - cp: s.opts.cp, - dc: s.opts.dc, - maxMsgSize: s.opts.maxMsgSize, - trInfo: trInfo, + t: t, + s: stream, + p: &parser{r: stream}, + codec: s.opts.codec, + cp: s.opts.cp, + dc: s.opts.dc, + maxMsgSize: s.opts.maxMsgSize, + trInfo: trInfo, + statsHandler: sh, } if ss.cp != nil { ss.cbuf = new(bytes.Buffer) diff --git a/vendor/google.golang.org/grpc/stats/handlers.go b/vendor/google.golang.org/grpc/stats/handlers.go index d41c52442..26e1a8e2f 100644 --- a/vendor/google.golang.org/grpc/stats/handlers.go +++ b/vendor/google.golang.org/grpc/stats/handlers.go @@ -35,10 +35,8 @@ package stats import ( "net" - "sync/atomic" "golang.org/x/net/context" - "google.golang.org/grpc/grpclog" ) // ConnTagInfo defines the relevant information needed by connection context tagger. @@ -56,97 +54,23 @@ type RPCTagInfo struct { FullMethodName string } -var ( - on = new(int32) - rpcHandler func(context.Context, RPCStats) - connHandler func(context.Context, ConnStats) - connTagger func(context.Context, *ConnTagInfo) context.Context - rpcTagger func(context.Context, *RPCTagInfo) context.Context -) - -// HandleRPC processes the RPC stats using the rpc handler registered by the user. -func HandleRPC(ctx context.Context, s RPCStats) { - if rpcHandler == nil { - return - } - rpcHandler(ctx, s) -} - -// RegisterRPCHandler registers the user handler function for RPC stats processing. -// It should be called only once. The later call will overwrite the former value if it is called multiple times. -// This handler function will be called to process the rpc stats. -func RegisterRPCHandler(f func(context.Context, RPCStats)) { - rpcHandler = f -} - -// HandleConn processes the stats using the call back function registered by user. -func HandleConn(ctx context.Context, s ConnStats) { - if connHandler == nil { - return - } - connHandler(ctx, s) -} - -// RegisterConnHandler registers the user handler function for conn stats. -// It should be called only once. The later call will overwrite the former value if it is called multiple times. -// This handler function will be called to process the conn stats. -func RegisterConnHandler(f func(context.Context, ConnStats)) { - connHandler = f -} - -// TagConn calls user registered connection context tagger. -func TagConn(ctx context.Context, info *ConnTagInfo) context.Context { - if connTagger == nil { - return ctx - } - return connTagger(ctx, info) -} - -// RegisterConnTagger registers the user connection context tagger function. -// The connection context tagger can attach some information to the given context. -// The returned context will be used for stats handling. -// For conn stats handling, the context used in connHandler for this -// connection will be derived from the context returned. -// For RPC stats handling, -// - On server side, the context used in rpcHandler for all RPCs on this -// connection will be derived from the context returned. -// - On client side, the context is not derived from the context returned. -func RegisterConnTagger(t func(context.Context, *ConnTagInfo) context.Context) { - connTagger = t -} - -// TagRPC calls the user registered RPC context tagger. -func TagRPC(ctx context.Context, info *RPCTagInfo) context.Context { - if rpcTagger == nil { - return ctx - } - return rpcTagger(ctx, info) -} - -// RegisterRPCTagger registers the user RPC context tagger function. -// The RPC context tagger can attach some information to the given context. -// The context used in stats rpcHandler for this RPC will be derived from the -// context returned. -func RegisterRPCTagger(t func(context.Context, *RPCTagInfo) context.Context) { - rpcTagger = t -} - -// Start starts the stats collection and processing if there is a registered stats handle. -func Start() { - if rpcHandler == nil && connHandler == nil { - grpclog.Println("rpcHandler and connHandler are both nil when starting stats. Stats is not started") - return - } - atomic.StoreInt32(on, 1) -} - -// Stop stops the stats collection and processing. -// Stop does not unregister the handlers. -func Stop() { - atomic.StoreInt32(on, 0) -} - -// On indicates whether the stats collection and processing is on. -func On() bool { - return atomic.CompareAndSwapInt32(on, 1, 1) +// Handler defines the interface for the related stats handling (e.g., RPCs, connections). +type Handler interface { + // TagRPC can attach some information to the given context. + // The returned context is used in the rest lifetime of the RPC. + TagRPC(context.Context, *RPCTagInfo) context.Context + // HandleRPC processes the RPC stats. + HandleRPC(context.Context, RPCStats) + + // TagConn can attach some information to the given context. + // The returned context will be used for stats handling. + // For conn stats handling, the context used in HandleConn for this + // connection will be derived from the context returned. + // For RPC stats handling, + // - On server side, the context used in HandleRPC for all RPCs on this + // connection will be derived from the context returned. + // - On client side, the context is not derived from the context returned. + TagConn(context.Context, *ConnTagInfo) context.Context + // HandleConn processes the Conn stats. + HandleConn(context.Context, ConnStats) } diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go index 1bcd2183a..bb468dc37 100644 --- a/vendor/google.golang.org/grpc/stream.go +++ b/vendor/google.golang.org/grpc/stream.go @@ -107,11 +107,18 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) { var ( - t transport.ClientTransport - s *transport.Stream - put func() + t transport.ClientTransport + s *transport.Stream + put func() + cancel context.CancelFunc ) c := defaultCallInfo + if mc, ok := cc.getMethodConfig(method); ok { + c.failFast = !mc.WaitForReady + if mc.Timeout > 0 { + ctx, cancel = context.WithTimeout(ctx, mc.Timeout) + } + } for _, o := range opts { if err := o.before(&c); err != nil { return nil, toRPCErr(err) @@ -144,23 +151,24 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth } }() } - if stats.On() { - ctx = stats.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method}) + sh := cc.dopts.copts.StatsHandler + if sh != nil { + ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method}) begin := &stats.Begin{ Client: true, BeginTime: time.Now(), FailFast: c.failFast, } - stats.HandleRPC(ctx, begin) + sh.HandleRPC(ctx, begin) } defer func() { - if err != nil && stats.On() { + if err != nil && sh != nil { // Only handle end stats if err != nil. end := &stats.End{ Client: true, Error: err, } - stats.HandleRPC(ctx, end) + sh.HandleRPC(ctx, end) } }() gopts := BalancerGetOptions{ @@ -200,12 +208,13 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth break } cs := &clientStream{ - opts: opts, - c: c, - desc: desc, - codec: cc.dopts.codec, - cp: cc.dopts.cp, - dc: cc.dopts.dc, + opts: opts, + c: c, + desc: desc, + codec: cc.dopts.codec, + cp: cc.dopts.cp, + dc: cc.dopts.dc, + cancel: cancel, put: put, t: t, @@ -215,7 +224,8 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth tracing: EnableTracing, trInfo: trInfo, - statsCtx: ctx, + statsCtx: ctx, + statsHandler: cc.dopts.copts.StatsHandler, } if cc.dopts.cp != nil { cs.cbuf = new(bytes.Buffer) @@ -249,16 +259,17 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth // clientStream implements a client side Stream. type clientStream struct { - opts []CallOption - c callInfo - t transport.ClientTransport - s *transport.Stream - p *parser - desc *StreamDesc - codec Codec - cp Compressor - cbuf *bytes.Buffer - dc Decompressor + opts []CallOption + c callInfo + t transport.ClientTransport + s *transport.Stream + p *parser + desc *StreamDesc + codec Codec + cp Compressor + cbuf *bytes.Buffer + dc Decompressor + cancel context.CancelFunc tracing bool // set to EnableTracing when the clientStream is created. @@ -272,7 +283,8 @@ type clientStream struct { // statsCtx keeps the user context for stats handling. // All stats collection should use the statsCtx (instead of the stream context) // so that all the generated stats for a particular RPC can be associated in the processing phase. - statsCtx context.Context + statsCtx context.Context + statsHandler stats.Handler } func (cs *clientStream) Context() context.Context { @@ -326,7 +338,7 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) { err = toRPCErr(err) }() var outPayload *stats.OutPayload - if stats.On() { + if cs.statsHandler != nil { outPayload = &stats.OutPayload{ Client: true, } @@ -343,14 +355,14 @@ func (cs *clientStream) SendMsg(m interface{}) (err error) { err = cs.t.Write(cs.s, out, &transport.Options{Last: false}) if err == nil && outPayload != nil { outPayload.SentTime = time.Now() - stats.HandleRPC(cs.statsCtx, outPayload) + cs.statsHandler.HandleRPC(cs.statsCtx, outPayload) } return err } func (cs *clientStream) RecvMsg(m interface{}) (err error) { defer func() { - if err != nil && stats.On() { + if err != nil && cs.statsHandler != nil { // Only generate End if err != nil. // If err == nil, it's not the last RecvMsg. // The last RecvMsg gets either an RPC error or io.EOF. @@ -361,11 +373,11 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) { if err != io.EOF { end.Error = toRPCErr(err) } - stats.HandleRPC(cs.statsCtx, end) + cs.statsHandler.HandleRPC(cs.statsCtx, end) } }() var inPayload *stats.InPayload - if stats.On() { + if cs.statsHandler != nil { inPayload = &stats.InPayload{ Client: true, } @@ -386,7 +398,7 @@ func (cs *clientStream) RecvMsg(m interface{}) (err error) { cs.mu.Unlock() } if inPayload != nil { - stats.HandleRPC(cs.statsCtx, inPayload) + cs.statsHandler.HandleRPC(cs.statsCtx, inPayload) } if !cs.desc.ClientStreams || cs.desc.ServerStreams { return @@ -449,6 +461,11 @@ func (cs *clientStream) closeTransportStream(err error) { } func (cs *clientStream) finish(err error) { + defer func() { + if cs.cancel != nil { + cs.cancel() + } + }() cs.mu.Lock() defer cs.mu.Unlock() for _, o := range cs.opts { @@ -506,6 +523,8 @@ type serverStream struct { statusDesc string trInfo *traceInfo + statsHandler stats.Handler + mu sync.Mutex // protects trInfo.tr after the service handler runs. } @@ -548,7 +567,7 @@ func (ss *serverStream) SendMsg(m interface{}) (err error) { } }() var outPayload *stats.OutPayload - if stats.On() { + if ss.statsHandler != nil { outPayload = &stats.OutPayload{} } out, err := encode(ss.codec, m, ss.cp, ss.cbuf, outPayload) @@ -566,7 +585,7 @@ func (ss *serverStream) SendMsg(m interface{}) (err error) { } if outPayload != nil { outPayload.SentTime = time.Now() - stats.HandleRPC(ss.s.Context(), outPayload) + ss.statsHandler.HandleRPC(ss.s.Context(), outPayload) } return nil } @@ -587,7 +606,7 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) { } }() var inPayload *stats.InPayload - if stats.On() { + if ss.statsHandler != nil { inPayload = &stats.InPayload{} } if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxMsgSize, inPayload); err != nil { @@ -600,7 +619,7 @@ func (ss *serverStream) RecvMsg(m interface{}) (err error) { return toRPCErr(err) } if inPayload != nil { - stats.HandleRPC(ss.s.Context(), inPayload) + ss.statsHandler.HandleRPC(ss.s.Context(), inPayload) } return nil } diff --git a/vendor/google.golang.org/grpc/transport/http2_client.go b/vendor/google.golang.org/grpc/transport/http2_client.go index 3936b9cf9..892f8ba67 100644 --- a/vendor/google.golang.org/grpc/transport/http2_client.go +++ b/vendor/google.golang.org/grpc/transport/http2_client.go @@ -99,6 +99,8 @@ type http2Client struct { creds []credentials.PerRPCCredentials + statsHandler stats.Handler + mu sync.Mutex // guard the following variables state transportState // the state of underlying connection activeStreams map[uint32]*Stream @@ -208,6 +210,17 @@ func newHTTP2Client(ctx context.Context, addr TargetInfo, opts ConnectOptions) ( creds: opts.PerRPCCredentials, maxStreams: math.MaxInt32, streamSendQuota: defaultWindowSize, + statsHandler: opts.StatsHandler, + } + if t.statsHandler != nil { + t.ctx = t.statsHandler.TagConn(t.ctx, &stats.ConnTagInfo{ + RemoteAddr: t.remoteAddr, + LocalAddr: t.localAddr, + }) + connBegin := &stats.ConnBegin{ + Client: true, + } + t.statsHandler.HandleConn(t.ctx, connBegin) } // Start the reader goroutine for incoming message. Each transport has // a dedicated goroutine which reads HTTP2 frame from network. Then it @@ -244,16 +257,6 @@ func newHTTP2Client(ctx context.Context, addr TargetInfo, opts ConnectOptions) ( } go t.controller() t.writableChan <- 0 - if stats.On() { - t.ctx = stats.TagConn(t.ctx, &stats.ConnTagInfo{ - RemoteAddr: t.remoteAddr, - LocalAddr: t.localAddr, - }) - connBegin := &stats.ConnBegin{ - Client: true, - } - stats.HandleConn(t.ctx, connBegin) - } return t, nil } @@ -470,7 +473,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea return nil, connectionErrorf(true, err, "transport: %v", err) } } - if stats.On() { + if t.statsHandler != nil { outHeader := &stats.OutHeader{ Client: true, WireLength: bufLen, @@ -479,7 +482,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea LocalAddr: t.localAddr, Compression: callHdr.SendCompress, } - stats.HandleRPC(s.clientStatsCtx, outHeader) + t.statsHandler.HandleRPC(s.clientStatsCtx, outHeader) } t.writableChan <- 0 return s, nil @@ -559,11 +562,11 @@ func (t *http2Client) Close() (err error) { s.mu.Unlock() s.write(recvMsg{err: ErrConnClosing}) } - if stats.On() { + if t.statsHandler != nil { connEnd := &stats.ConnEnd{ Client: true, } - stats.HandleConn(t.ctx, connEnd) + t.statsHandler.HandleConn(t.ctx, connEnd) } return } @@ -911,19 +914,19 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { endStream := frame.StreamEnded() var isHeader bool defer func() { - if stats.On() { + if t.statsHandler != nil { if isHeader { inHeader := &stats.InHeader{ Client: true, WireLength: int(frame.Header().Length), } - stats.HandleRPC(s.clientStatsCtx, inHeader) + t.statsHandler.HandleRPC(s.clientStatsCtx, inHeader) } else { inTrailer := &stats.InTrailer{ Client: true, WireLength: int(frame.Header().Length), } - stats.HandleRPC(s.clientStatsCtx, inTrailer) + t.statsHandler.HandleRPC(s.clientStatsCtx, inTrailer) } } }() diff --git a/vendor/google.golang.org/grpc/transport/http2_server.go b/vendor/google.golang.org/grpc/transport/http2_server.go index 316188e7b..a095dd0e0 100644 --- a/vendor/google.golang.org/grpc/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/transport/http2_server.go @@ -88,6 +88,8 @@ type http2Server struct { // sendQuotaPool provides flow control to outbound message. sendQuotaPool *quotaPool + stats stats.Handler + mu sync.Mutex // guard the following state transportState activeStreams map[uint32]*Stream @@ -146,14 +148,15 @@ func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err shutdownChan: make(chan struct{}), activeStreams: make(map[uint32]*Stream), streamSendQuota: defaultWindowSize, + stats: config.StatsHandler, } - if stats.On() { - t.ctx = stats.TagConn(t.ctx, &stats.ConnTagInfo{ + if t.stats != nil { + t.ctx = t.stats.TagConn(t.ctx, &stats.ConnTagInfo{ RemoteAddr: t.remoteAddr, LocalAddr: t.localAddr, }) connBegin := &stats.ConnBegin{} - stats.HandleConn(t.ctx, connBegin) + t.stats.HandleConn(t.ctx, connBegin) } go t.controller() t.writableChan <- 0 @@ -250,8 +253,8 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( t.updateWindow(s, uint32(n)) } s.ctx = traceCtx(s.ctx, s.method) - if stats.On() { - s.ctx = stats.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method}) + if t.stats != nil { + s.ctx = t.stats.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method}) inHeader := &stats.InHeader{ FullMethod: s.method, RemoteAddr: t.remoteAddr, @@ -259,7 +262,7 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( Compression: s.recvCompress, WireLength: int(frame.Header().Length), } - stats.HandleRPC(s.ctx, inHeader) + t.stats.HandleRPC(s.ctx, inHeader) } handle(s) return @@ -540,11 +543,11 @@ func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error { if err := t.writeHeaders(s, t.hBuf, false); err != nil { return err } - if stats.On() { + if t.stats != nil { outHeader := &stats.OutHeader{ WireLength: bufLen, } - stats.HandleRPC(s.Context(), outHeader) + t.stats.HandleRPC(s.Context(), outHeader) } t.writableChan <- 0 return nil @@ -603,11 +606,11 @@ func (t *http2Server) WriteStatus(s *Stream, statusCode codes.Code, statusDesc s t.Close() return err } - if stats.On() { + if t.stats != nil { outTrailer := &stats.OutTrailer{ WireLength: bufLen, } - stats.HandleRPC(s.Context(), outTrailer) + t.stats.HandleRPC(s.Context(), outTrailer) } t.closeStream(s) t.writableChan <- 0 @@ -789,9 +792,9 @@ func (t *http2Server) Close() (err error) { for _, s := range streams { s.cancel() } - if stats.On() { + if t.stats != nil { connEnd := &stats.ConnEnd{} - stats.HandleConn(t.ctx, connEnd) + t.stats.HandleConn(t.ctx, connEnd) } return } diff --git a/vendor/google.golang.org/grpc/transport/transport.go b/vendor/google.golang.org/grpc/transport/transport.go index 4726bb2ce..caee54a80 100644 --- a/vendor/google.golang.org/grpc/transport/transport.go +++ b/vendor/google.golang.org/grpc/transport/transport.go @@ -48,6 +48,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" + "google.golang.org/grpc/stats" "google.golang.org/grpc/tap" ) @@ -357,9 +358,10 @@ const ( // ServerConfig consists of all the configurations to establish a server transport. type ServerConfig struct { - MaxStreams uint32 - AuthInfo credentials.AuthInfo - InTapHandle tap.ServerInHandle + MaxStreams uint32 + AuthInfo credentials.AuthInfo + InTapHandle tap.ServerInHandle + StatsHandler stats.Handler } // NewServerTransport creates a ServerTransport with conn or non-nil error @@ -372,6 +374,9 @@ func NewServerTransport(protocol string, conn net.Conn, config *ServerConfig) (S type ConnectOptions struct { // UserAgent is the application user agent. UserAgent string + // Authority is the :authority pseudo-header to use. This field has no effect if + // TransportCredentials is set. + Authority string // Dialer specifies how to dial a network address. Dialer func(context.Context, string) (net.Conn, error) // FailOnNonTempDialError specifies if gRPC fails on non-temporary dial errors. @@ -380,6 +385,8 @@ type ConnectOptions struct { PerRPCCredentials []credentials.PerRPCCredentials // TransportCredentials stores the Authenticator required to setup a client connection. TransportCredentials credentials.TransportCredentials + // StatsHandler stores the handler for stats. + StatsHandler stats.Handler } // TargetInfo contains the information of the target such as network address and metadata. From 90660e7ac833e7b2c59d668e09b6129ca2c20c85 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 22 Feb 2017 14:26:21 -0800 Subject: [PATCH 02/62] adding client interface back in Signed-off-by: David Lawrence (github: endophage) --- client/interface.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 client/interface.go diff --git a/client/interface.go b/client/interface.go new file mode 100644 index 000000000..c9a81f6f7 --- /dev/null +++ b/client/interface.go @@ -0,0 +1,42 @@ +package client + +import ( + "github.com/docker/notary/client/changelist" + "github.com/docker/notary/tuf/data" +) + +// Repository represents the set of options that must be supported over a TUF repo. +type Repository interface { + // General management operations + Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error + Publish() error + DeleteTrustData(deleteRemote bool) error + + // Target Operations + AddTarget(target *Target, roles ...data.RoleName) error + RemoveTarget(targetName string, roles ...data.RoleName) error + ListTargets(roles ...data.RoleName) ([]*TargetWithRole, error) + GetTargetByName(name string, roles ...data.RoleName) (*TargetWithRole, error) + GetAllTargetMetadataByName(name string) ([]TargetSignedStruct, error) + + // Changelist operations + GetChangelist() (changelist.Changelist, error) + + // Role operations + ListRoles() ([]RoleWithSignatures, error) + GetDelegationRoles() ([]data.Role, error) + AddDelegation(name data.RoleName, delegationKeys []data.PublicKey, paths []string) error + AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []data.PublicKey) error + AddDelegationPaths(name data.RoleName, paths []string) error + RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error + RemoveDelegationRole(name data.RoleName) error + RemoveDelegationPaths(name data.RoleName, paths []string) error + RemoveDelegationKeys(name data.RoleName, keyIDs []string) error + ClearDelegationPaths(name data.RoleName) error + + // Witness and other re-signing operations + Witness(roles ...data.RoleName) ([]data.RoleName, error) + + // Key Operations + RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error +} From 3fac89bd5f4dc32727ed6e68d64ad8a44c500cd7 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 22 Feb 2017 16:31:43 -0800 Subject: [PATCH 03/62] basic factory for local/remote client Signed-off-by: David Lawrence (github: endophage) --- client/backwards_compatibility_test.go | 8 +- client/client.go | 39 +++--- client/client_test.go | 94 +++++++------- client/interface.go | 6 +- client_api/api/client.go | 155 ++++++++++++++++++++++- client_api/api/errors.go | 8 +- client_api/api/server.go | 33 ++++- cmd/notary/delegations.go | 53 ++------ cmd/notary/keys.go | 20 +-- cmd/notary/keys_test.go | 10 +- cmd/notary/repo_factory.go | 44 +++++++ cmd/notary/tuf.go | 165 +++++-------------------- 12 files changed, 359 insertions(+), 276 deletions(-) create mode 100644 cmd/notary/repo_factory.go diff --git a/client/backwards_compatibility_test.go b/client/backwards_compatibility_test.go index c825200cf..8c43e4442 100644 --- a/client/backwards_compatibility_test.go +++ b/client/backwards_compatibility_test.go @@ -217,10 +217,10 @@ func Test0Dot1RepoFormat(t *testing.T) { require.Len(t, targets, 2) // Also check that we can add/remove keys by rotating keys - oldTargetsKeys := repo.CryptoService.ListKeys(data.CanonicalTargetsRole) + oldTargetsKeys := repo.cryptoService.ListKeys(data.CanonicalTargetsRole) require.NoError(t, repo.RotateKey(data.CanonicalTargetsRole, false, nil)) require.NoError(t, repo.Publish()) - newTargetsKeys := repo.CryptoService.ListKeys(data.CanonicalTargetsRole) + newTargetsKeys := repo.cryptoService.ListKeys(data.CanonicalTargetsRole) require.Len(t, oldTargetsKeys, 1) require.Len(t, newTargetsKeys, 1) @@ -281,10 +281,10 @@ func Test0Dot3RepoFormat(t *testing.T) { require.Equal(t, data.RoleName("targets/releases"), delegations[0].Name) // Also check that we can add/remove keys by rotating keys - oldTargetsKeys := repo.CryptoService.ListKeys(data.CanonicalTargetsRole) + oldTargetsKeys := repo.cryptoService.ListKeys(data.CanonicalTargetsRole) require.NoError(t, repo.RotateKey(data.CanonicalTargetsRole, false, nil)) require.NoError(t, repo.Publish()) - newTargetsKeys := repo.CryptoService.ListKeys(data.CanonicalTargetsRole) + newTargetsKeys := repo.cryptoService.ListKeys(data.CanonicalTargetsRole) require.Len(t, oldTargetsKeys, 1) require.Len(t, newTargetsKeys, 1) diff --git a/client/client.go b/client/client.go index 55a5ba4b7..edbaeffbc 100644 --- a/client/client.go +++ b/client/client.go @@ -44,12 +44,12 @@ type NotaryRepository struct { changelist changelist.Changelist cache store.MetadataStore remoteStore store.RemoteStore - CryptoService signed.CryptoService + cryptoService signed.CryptoService tufRepo *tuf.Repo invalid *tuf.Repo // known data that was parsable but deemed invalid roundTrip http.RoundTripper trustPinning trustpinning.TrustPinConfig - LegacyVersions int // number of versions back to fetch roots to sign with + legacyVersions int // number of versions back to fetch roots to sign with } // NewFileCachedNotaryRepository is a wrapper for NewNotaryRepository that initializes @@ -112,9 +112,9 @@ func NewNotaryRepository(baseDir string, gun data.GUN, baseURL string, remoteSto changelist: cl, cache: cache, remoteStore: remoteStore, - CryptoService: cryptoService, trustPinning: trustPinning, - LegacyVersions: 0, // By default, don't sign with legacy roles + cryptoService: cryptoService, + legacyVersions: 0, // By default, don't sign with legacy roles } return nRepo, nil @@ -179,8 +179,7 @@ func rootCertKey(gun data.GUN, privKey data.PrivateKey) (data.PublicKey, error) // result is only stored on local disk, not published to the server. To do that, // use r.Publish() eventually. func (r *NotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error { - - privKeys, err := getAllPrivKeys(rootKeyIDs, r.CryptoService) + privKeys, err := getAllPrivKeys(rootKeyIDs, r.cryptoService) if err != nil { return err } @@ -230,7 +229,7 @@ func (r *NotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles .. return err } - r.tufRepo = tuf.NewRepo(r.CryptoService) + r.tufRepo = tuf.NewRepo(r.cryptoService) if err := r.tufRepo.InitRoot( rootRole, @@ -267,7 +266,7 @@ func (r *NotaryRepository) initializeRoles(rootKeys []data.PublicKey, localRoles for _, role := range localRoles { // This is currently hardcoding the keys to ECDSA. var key data.PublicKey - key, err = r.CryptoService.Create(role, r.gun, data.ECDSAKey) + key, err = r.cryptoService.Create(role, r.gun, data.ECDSAKey) if err != nil { return } @@ -654,7 +653,7 @@ func (r *NotaryRepository) publish(cl changelist.Changelist) error { updatedFiles := make(map[data.RoleName][]byte) // Fetch old keys to support old clients - legacyKeys, err := r.oldKeysForLegacyClientSupport(r.LegacyVersions, initialPublish) + legacyKeys, err := r.oldKeysForLegacyClientSupport(r.legacyVersions, initialPublish) if err != nil { return err } @@ -812,7 +811,7 @@ func signTargets(updates map[data.RoleName][]byte, repo *tuf.Repo, initialPublis // snapshots are supported, if the snapshot metadata fails to load, that's ok. // This assumes that bootstrapRepo is only used by Publish() or RotateKey() func (r *NotaryRepository) bootstrapRepo() error { - b := tuf.NewRepoBuilder(r.gun, r.CryptoService, r.trustPinning) + b := tuf.NewRepoBuilder(r.gun, r.cryptoService, r.trustPinning) logrus.Debugf("Loading trusted collection.") @@ -947,10 +946,10 @@ func (r *NotaryRepository) bootstrapClient(checkInitialized bool) (*TUFClient, e minVersion := 1 // the old root on disk should not be validated against any trust pinning configuration // because if we have an old root, it itself is the thing that pins trust - oldBuilder := tuf.NewRepoBuilder(r.gun, r.CryptoService, trustpinning.TrustPinConfig{}) + oldBuilder := tuf.NewRepoBuilder(r.gun, r.cryptoService, trustpinning.TrustPinConfig{}) // by default, we want to use the trust pinning configuration on any new root that we download - newBuilder := tuf.NewRepoBuilder(r.gun, r.CryptoService, r.trustPinning) + newBuilder := tuf.NewRepoBuilder(r.gun, r.cryptoService, r.trustPinning) // Try to read root from cache first. We will trust this root until we detect a problem // during update which will cause us to download a new root and perform a rotation. @@ -964,7 +963,7 @@ func (r *NotaryRepository) bootstrapClient(checkInitialized bool) (*TUFClient, e // again, the root on disk is the source of trust pinning, so use an empty trust // pinning configuration - newBuilder = tuf.NewRepoBuilder(r.gun, r.CryptoService, trustpinning.TrustPinConfig{}) + newBuilder = tuf.NewRepoBuilder(r.gun, r.cryptoService, trustpinning.TrustPinConfig{}) if err := newBuilder.Load(data.CanonicalRootRole, rootJSON, minVersion, false); err != nil { // Ok, the old root is expired - we want to download a new one. But we want to use the @@ -1054,7 +1053,7 @@ func (r *NotaryRepository) pubKeyListForRotation(role data.RoleName, serverManag // If no new keys are passed in, we generate one if len(newKeys) == 0 { pubKeyList = make(data.KeyList, 0, 1) - pubKey, err = r.CryptoService.Create(role, r.gun, data.ECDSAKey) + pubKey, err = r.cryptoService.Create(role, r.gun, data.ECDSAKey) pubKeyList = append(pubKeyList, pubKey) } if err != nil { @@ -1065,7 +1064,7 @@ func (r *NotaryRepository) pubKeyListForRotation(role data.RoleName, serverManag if len(newKeys) > 0 { pubKeyList = make(data.KeyList, 0, len(newKeys)) for _, keyID := range newKeys { - pubKey = r.CryptoService.GetKey(keyID) + pubKey = r.cryptoService.GetKey(keyID) if pubKey == nil { return nil, fmt.Errorf("unable to find key: %s", keyID) } @@ -1088,7 +1087,7 @@ func (r *NotaryRepository) pubKeysToCerts(role data.RoleName, pubKeyList data.Ke } for i, pubKey := range pubKeyList { - privKey, loadedRole, err := r.CryptoService.GetPrivateKey(pubKey.ID()) + privKey, loadedRole, err := r.cryptoService.GetPrivateKey(pubKey.ID()) if err != nil { return nil, err } @@ -1163,3 +1162,11 @@ func DeleteTrustData(baseDir string, gun data.GUN, URL string, rt http.RoundTrip } return nil } + +func (r *NotaryRepository) SetLegacyVersions(n int) { + r.legacyVersions = n +} + +func (r *NotaryRepository) CryptoService() signed.CryptoService { + return r.cryptoService +} diff --git a/client/client_test.go b/client/client_test.go index 67cbbbd39..e43fb31cf 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -194,7 +194,7 @@ func createRepoAndKey(t *testing.T, rootType, tempBaseDir, gun, url string) ( tempBaseDir, data.GUN(gun), url, http.DefaultTransport, rec.retriever, trustpinning.TrustPinConfig{}) require.NoError(t, err, "error creating repo: %s", err) - rootPubKey, err := repo.CryptoService.Create(data.CanonicalRootRole, repo.gun, rootType) + rootPubKey, err := repo.cryptoService.Create(data.CanonicalRootRole, repo.gun, rootType) require.NoError(t, err, "error generating root key: %s", err) rec.requireCreated(t, []string{data.CanonicalRootRole.String()}, @@ -316,7 +316,7 @@ func TestInitRepositoryMultipleRootKeys(t *testing.T) { repo, rec, rootPubKeyID := createRepoAndKey( t, data.ECDSAKey, tempBaseDir, "docker.com/notary", ts.URL) - rootPubKey2, err := repo.CryptoService.Create(data.CanonicalRootRole, repo.gun, data.ECDSAKey) + rootPubKey2, err := repo.cryptoService.Create(data.CanonicalRootRole, repo.gun, data.ECDSAKey) require.NoError(t, err, "error generating second root key: %s", err) err = repo.Initialize([]string{rootPubKeyID, rootPubKey2.ID()}, data.CanonicalTimestampRole) @@ -580,7 +580,7 @@ func testInitRepoAttemptsExceeded(t *testing.T, rootType string) { retriever := passphrase.ConstantRetriever("password") repo, err := NewFileCachedNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, retriever, trustpinning.TrustPinConfig{}) require.NoError(t, err, "error creating repo: %s", err) - rootPubKey, err := repo.CryptoService.Create(data.CanonicalRootRole, repo.gun, rootType) + rootPubKey, err := repo.cryptoService.Create(data.CanonicalRootRole, repo.gun, rootType) require.NoError(t, err, "error generating root key: %s", err) retriever = passphrase.ConstantRetriever("incorrect password") @@ -618,7 +618,7 @@ func testInitRepoPasswordInvalid(t *testing.T, rootType string) { retriever := passphrase.ConstantRetriever("password") repo, err := NewFileCachedNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport, retriever, trustpinning.TrustPinConfig{}) require.NoError(t, err, "error creating repo: %s", err) - rootPubKey, err := repo.CryptoService.Create(data.CanonicalRootRole, repo.gun, rootType) + rootPubKey, err := repo.cryptoService.Create(data.CanonicalRootRole, repo.gun, rootType) require.NoError(t, err, "error generating root key: %s", err) // repo.CryptoService’s FileKeyStore caches the unlocked private key, so to test @@ -1046,7 +1046,7 @@ func fakeServerData(t *testing.T, repo *NotaryRepository, mux *http.ServeMux, timestampKey, ok := keys[data.CanonicalTimestampRole.String()] require.True(t, ok) // Add timestamp key via the server's cryptoservice so it can sign - repo.CryptoService.AddKey(data.CanonicalTimestampRole, repo.gun, timestampKey) + repo.cryptoService.AddKey(data.CanonicalTimestampRole, repo.gun, timestampKey) savedTUFRepo := repo.tufRepo // in case this is overwritten @@ -1253,7 +1253,7 @@ func testListTargetWithDelegates(t *testing.T, rootType string) { currentTarget := addTarget(t, repo, "current", "../fixtures/intermediate-ca.crt") // setup delegated targets/level1 role - k, err := repo.CryptoService.Create("targets/level1", repo.gun, rootType) + k, err := repo.cryptoService.Create("targets/level1", repo.gun, rootType) require.NoError(t, err) err = repo.tufRepo.UpdateDelegationKeys("targets/level1", []data.PublicKey{k}, []string{}, 1) require.NoError(t, err) @@ -1263,7 +1263,7 @@ func testListTargetWithDelegates(t *testing.T, rootType string) { otherTarget := addTarget(t, repo, "other", "../fixtures/root-ca.crt", "targets/level1") // setup delegated targets/level2 role - k, err = repo.CryptoService.Create("targets/level2", repo.gun, rootType) + k, err = repo.cryptoService.Create("targets/level2", repo.gun, rootType) require.NoError(t, err) err = repo.tufRepo.UpdateDelegationKeys("targets/level2", []data.PublicKey{k}, []string{}, 1) require.NoError(t, err) @@ -1295,7 +1295,7 @@ func testListTargetWithDelegates(t *testing.T, rootType string) { // setup delegated targets/level1/level2 role separately, which can only modify paths prefixed with "level2" // This is done separately due to target shadowing - k, err = repo.CryptoService.Create("targets/level1/level2", repo.gun, rootType) + k, err = repo.cryptoService.Create("targets/level1/level2", repo.gun, rootType) require.NoError(t, err) err = repo.tufRepo.UpdateDelegationKeys("targets/level1/level2", []data.PublicKey{k}, []string{}, 1) require.NoError(t, err) @@ -1407,7 +1407,7 @@ func TestListTargetRestrictsDelegationPaths(t *testing.T) { require.NoError(t, err, "error creating repository: %s", err) // setup delegated targets/level1 role - k, err := repo.CryptoService.Create("targets/level1", repo.gun, data.ECDSAKey) + k, err := repo.cryptoService.Create("targets/level1", repo.gun, data.ECDSAKey) require.NoError(t, err) err = repo.tufRepo.UpdateDelegationKeys("targets/level1", []data.PublicKey{k}, []string{}, 1) require.NoError(t, err) @@ -1850,11 +1850,11 @@ func testPublishNoOneHasSnapshotKey(t *testing.T, rootType string) { snapshotRole, ok := repo.tufRepo.Root.Signed.Roles[data.CanonicalSnapshotRole] require.True(t, ok) for _, keyID := range snapshotRole.KeyIDs { - repo.CryptoService.RemoveKey(keyID) + repo.cryptoService.RemoveKey(keyID) } // ensure that the cryptoservice no longer has any snapshot keys - require.Len(t, repo.CryptoService.ListKeys(data.CanonicalSnapshotRole), 0) + require.Len(t, repo.cryptoService.ListKeys(data.CanonicalSnapshotRole), 0) // Publish something addTarget(t, repo, "v1", "../fixtures/intermediate-ca.crt") @@ -2002,7 +2002,7 @@ func TestPublishSnapshotLocalKeysCreatedFirst(t *testing.T) { rootPubKey, err := cs.Create(data.CanonicalRootRole, gun, data.ECDSAKey) require.NoError(t, err, "error generating root key: %s", err) - repo.CryptoService = cannotCreateKeys{CryptoService: cs} + repo.cryptoService = cannotCreateKeys{CryptoService: cs} err = repo.Initialize([]string{rootPubKey.ID()}, data.CanonicalSnapshotRole) require.Error(t, err) @@ -2011,12 +2011,12 @@ func TestPublishSnapshotLocalKeysCreatedFirst(t *testing.T) { } func createKey(t *testing.T, repo *NotaryRepository, role data.RoleName, x509 bool) data.PublicKey { - key, err := repo.CryptoService.Create(role, repo.gun, data.ECDSAKey) + key, err := repo.cryptoService.Create(role, repo.gun, data.ECDSAKey) require.NoError(t, err, "error creating key") if x509 { start := time.Now().AddDate(0, 0, -1) - privKey, _, err := repo.CryptoService.GetPrivateKey(key.ID()) + privKey, _, err := repo.cryptoService.GetPrivateKey(key.ID()) require.NoError(t, err) cert, err := cryptoservice.GenerateCertificate( privKey, data.GUN(role), start, start.AddDate(1, 0, 0), @@ -2233,9 +2233,9 @@ func TestPublishTargetsDelegationNoTargetsKeyNeeded(t *testing.T) { rec.clear() // remove targets key - it is not even needed - targetsKeys := repo.CryptoService.ListKeys(data.CanonicalTargetsRole) + targetsKeys := repo.cryptoService.ListKeys(data.CanonicalTargetsRole) require.Len(t, targetsKeys, 1) - require.NoError(t, repo.CryptoService.RemoveKey(targetsKeys[0])) + require.NoError(t, repo.cryptoService.RemoveKey(targetsKeys[0])) requirePublishToRolesSucceeds(t, repo, []data.RoleName{"targets/a/b"}, []data.RoleName{"targets/a/b"}) @@ -2268,11 +2268,11 @@ func TestPublishTargetsDelegationSuccessNeedsToDownloadRoles(t *testing.T) { defer os.RemoveAll(delgRepo.baseDir) // create a key on the owner repo - aKey, err := ownerRepo.CryptoService.Create("targets/a", gun, data.ECDSAKey) + aKey, err := ownerRepo.cryptoService.Create("targets/a", gun, data.ECDSAKey) require.NoError(t, err, "error creating delegation key") // create a key on the delegated repo - bKey, err := delgRepo.CryptoService.Create("targets/a/b", gun, data.ECDSAKey) + bKey, err := delgRepo.cryptoService.Create("targets/a/b", gun, data.ECDSAKey) require.NoError(t, err, "error creating delegation key") // clear metadata and unencrypted private key cache @@ -2333,11 +2333,11 @@ func TestPublishTargetsDelegationFromTwoRepos(t *testing.T) { defer os.RemoveAll(repo2.baseDir) // create keys for each repo - key1, err := repo1.CryptoService.Create("targets/a", repo1.gun, data.ECDSAKey) + key1, err := repo1.cryptoService.Create("targets/a", repo1.gun, data.ECDSAKey) require.NoError(t, err, "error creating delegation key") // create a key on the delegated repo - key2, err := repo2.CryptoService.Create("targets/a", repo2.gun, data.ECDSAKey) + key2, err := repo2.cryptoService.Create("targets/a", repo2.gun, data.ECDSAKey) require.NoError(t, err, "error creating delegation key") // delegation includes both keys @@ -2407,7 +2407,7 @@ func TestPublishRemoveDelegationKeyFromDelegationRole(t *testing.T) { defer os.RemoveAll(delgRepo.baseDir) // create a key on the delegated repo - aKey, err := delgRepo.CryptoService.Create("targets/a", delgRepo.gun, data.ECDSAKey) + aKey, err := delgRepo.cryptoService.Create("targets/a", delgRepo.gun, data.ECDSAKey) require.NoError(t, err, "error creating delegation key") // owner creates delegation, adds the delegated key to it, and publishes it @@ -2422,7 +2422,7 @@ func TestPublishRemoveDelegationKeyFromDelegationRole(t *testing.T) { // owner revokes delegation // note there is no removekeyfromdelegation yet, so here's a hack to do so - newKey, err := ownerRepo.CryptoService.Create("targets/a", ownerRepo.gun, data.ECDSAKey) + newKey, err := ownerRepo.cryptoService.Create("targets/a", ownerRepo.gun, data.ECDSAKey) require.NoError(t, err) tdJSON, err := json.Marshal(&changelist.TUFDelegation{ NewThreshold: 1, @@ -2471,7 +2471,7 @@ func TestPublishRemoveDelegation(t *testing.T) { defer os.RemoveAll(delgRepo.baseDir) // create a key on the delegated repo - aKey, err := delgRepo.CryptoService.Create("targets/a", delgRepo.gun, data.ECDSAKey) + aKey, err := delgRepo.cryptoService.Create("targets/a", delgRepo.gun, data.ECDSAKey) require.NoError(t, err, "error creating delegation key") // owner creates delegation, adds the delegated key to it, and publishes it @@ -2506,7 +2506,7 @@ func TestPublishSucceedsDespiteDelegationCorrupt(t *testing.T) { repo, _ := initializeRepo(t, data.ECDSAKey, "docker.com/notary", ts.URL, false) defer os.RemoveAll(repo.baseDir) - delgKey, err := repo.CryptoService.Create("targets/a", repo.gun, data.ECDSAKey) + delgKey, err := repo.cryptoService.Create("targets/a", repo.gun, data.ECDSAKey) require.NoError(t, err, "error creating delegation key") require.NoError(t, @@ -2529,7 +2529,7 @@ func TestRotateKeyInvalidRole(t *testing.T) { defer os.RemoveAll(repo.baseDir) // create a delegation - pubKey, err := repo.CryptoService.Create("targets/releases", data.GUN("docker.com/notary"), data.ECDSAKey) + pubKey, err := repo.cryptoService.Create("targets/releases", data.GUN("docker.com/notary"), data.ECDSAKey) require.NoError(t, err) require.NoError(t, repo.AddDelegation("targets/releases", []data.PublicKey{pubKey}, []string{""})) require.NoError(t, repo.Publish()) @@ -2680,7 +2680,7 @@ func requireRotationSuccessful(t *testing.T, repo1 *NotaryRepository, keysToRota canonicalID, err := utils.CanonicalKeyID(oldPubKey) require.NoError(t, err) - _, _, err = repo.CryptoService.GetPrivateKey(canonicalID) + _, _, err = repo.cryptoService.GetPrivateKey(canonicalID) switch roleName { case data.CanonicalRootRole: require.NoError(t, err) @@ -2697,7 +2697,7 @@ func requireRotationSuccessful(t *testing.T, repo1 *NotaryRepository, keysToRota canonicalID, err := utils.CanonicalKeyID(pubKey) require.NoError(t, err) - key, _, err := repo.CryptoService.GetPrivateKey(canonicalID) + key, _, err := repo.cryptoService.GetPrivateKey(canonicalID) if isRemoteKey { require.Error(t, err) require.Nil(t, key) @@ -2993,9 +2993,9 @@ func TestRotateRootKeyProvided(t *testing.T) { require.NoError(t, err) // Key loaded from file (just generating it here) - rootPublicKey, err := authorRepo.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey) + rootPublicKey, err := authorRepo.cryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey) require.NoError(t, err) - rootPrivateKey, _, err := authorRepo.CryptoService.GetPrivateKey(rootPublicKey.ID()) + rootPrivateKey, _, err := authorRepo.cryptoService.GetPrivateKey(rootPublicKey.ID()) require.NoError(t, err) // Fail to rotate to bad key @@ -3082,7 +3082,7 @@ func TestRotateRootKeyLegacySupport(t *testing.T) { logRepoTrustRoot(t, "post-rotate", authorRepo) // Rotate root certificate and key again, this time with legacy support - authorRepo.LegacyVersions = SignWithAllOldVersions + authorRepo.SetLegacyVersions(SignWithAllOldVersions) err = authorRepo.RotateKey(data.CanonicalRootRole, false, nil) require.NoError(t, err) logRepoTrustRoot(t, "post-rotate-again", authorRepo) @@ -3175,9 +3175,9 @@ func TestAddDelegationChangefileValid(t *testing.T) { repo, _ := initializeRepo(t, data.ECDSAKey, gun, ts.URL, false) defer os.RemoveAll(repo.baseDir) - targetKeyIds := repo.CryptoService.ListKeys(data.CanonicalTargetsRole) + targetKeyIds := repo.cryptoService.ListKeys(data.CanonicalTargetsRole) require.NotEmpty(t, targetKeyIds) - targetPubKey := repo.CryptoService.GetKey(targetKeyIds[0]) + targetPubKey := repo.cryptoService.GetKey(targetKeyIds[0]) require.NotNil(t, targetPubKey) err := repo.AddDelegation(data.CanonicalRootRole, []data.PublicKey{targetPubKey}, []string{""}) @@ -3213,9 +3213,9 @@ func TestAddDelegationChangefileApplicable(t *testing.T) { repo, _ := initializeRepo(t, data.ECDSAKey, gun, ts.URL, false) defer os.RemoveAll(repo.baseDir) - targetKeyIds := repo.CryptoService.ListKeys(data.CanonicalTargetsRole) + targetKeyIds := repo.cryptoService.ListKeys(data.CanonicalTargetsRole) require.NotEmpty(t, targetKeyIds) - targetPubKey := repo.CryptoService.GetKey(targetKeyIds[0]) + targetPubKey := repo.cryptoService.GetKey(targetKeyIds[0]) require.NotNil(t, targetPubKey) // this hierarchy has to be right to be applied @@ -3245,9 +3245,9 @@ func TestAddDelegationChangefileApplicable(t *testing.T) { // to be propagated. func TestAddDelegationErrorWritingChanges(t *testing.T) { testErrorWritingChangefiles(t, func(repo *NotaryRepository) error { - targetKeyIds := repo.CryptoService.ListKeys(data.CanonicalTargetsRole) + targetKeyIds := repo.cryptoService.ListKeys(data.CanonicalTargetsRole) require.NotEmpty(t, targetKeyIds) - targetPubKey := repo.CryptoService.GetKey(targetKeyIds[0]) + targetPubKey := repo.cryptoService.GetKey(targetKeyIds[0]) require.NotNil(t, targetPubKey) return repo.AddDelegation("targets/a", []data.PublicKey{targetPubKey}, []string{""}) @@ -3264,7 +3264,7 @@ func TestRemoveDelegationChangefileValid(t *testing.T) { repo, rootKeyID := initializeRepo(t, data.ECDSAKey, gun, ts.URL, false) defer os.RemoveAll(repo.baseDir) - rootPubKey := repo.CryptoService.GetKey(rootKeyID) + rootPubKey := repo.cryptoService.GetKey(rootKeyID) require.NotNil(t, rootPubKey) err := repo.RemoveDelegationKeys(data.CanonicalRootRole, []string{rootKeyID}) @@ -3295,7 +3295,7 @@ func TestRemoveDelegationChangefileApplicable(t *testing.T) { repo, rootKeyID := initializeRepo(t, data.ECDSAKey, gun, ts.URL, false) defer os.RemoveAll(repo.baseDir) - rootPubKey := repo.CryptoService.GetKey(rootKeyID) + rootPubKey := repo.cryptoService.GetKey(rootKeyID) require.NotNil(t, rootPubKey) // add a delegation first so it can be removed @@ -3331,7 +3331,7 @@ func TestClearAllPathsDelegationChangefileApplicable(t *testing.T) { repo, rootKeyID := initializeRepo(t, data.ECDSAKey, gun, ts.URL, false) defer os.RemoveAll(repo.baseDir) - rootPubKey := repo.CryptoService.GetKey(rootKeyID) + rootPubKey := repo.cryptoService.GetKey(rootKeyID) require.NotNil(t, rootPubKey) // add a delegation first so it can be removed @@ -3361,10 +3361,10 @@ func TestFullAddDelegationChangefileApplicable(t *testing.T) { repo, rootKeyID := initializeRepo(t, data.ECDSAKey, gun, ts.URL, false) defer os.RemoveAll(repo.baseDir) - rootPubKey := repo.CryptoService.GetKey(rootKeyID) + rootPubKey := repo.cryptoService.GetKey(rootKeyID) require.NotNil(t, rootPubKey) - key2, err := repo.CryptoService.Create("user", repo.gun, data.ECDSAKey) + key2, err := repo.cryptoService.Create("user", repo.gun, data.ECDSAKey) require.NoError(t, err) var delegationName data.RoleName = "targets/a" @@ -3403,10 +3403,10 @@ func TestFullRemoveDelegationChangefileApplicable(t *testing.T) { repo, rootKeyID := initializeRepo(t, data.ECDSAKey, gun, ts.URL, false) defer os.RemoveAll(repo.baseDir) - rootPubKey := repo.CryptoService.GetKey(rootKeyID) + rootPubKey := repo.cryptoService.GetKey(rootKeyID) require.NotNil(t, rootPubKey) - key2, err := repo.CryptoService.Create("user", repo.gun, data.ECDSAKey) + key2, err := repo.cryptoService.Create("user", repo.gun, data.ECDSAKey) require.NoError(t, err) key2CanonicalID, err := utils.CanonicalKeyID(key2) require.NoError(t, err) @@ -3829,7 +3829,7 @@ func TestGetAllTargetInfo(t *testing.T) { targetsCurrentTarget := addTarget(t, repo, "current", "../fixtures/intermediate-ca.crt") // setup delegated targets/level1 role with targets current and other - k, err := repo.CryptoService.Create("targets/level1", repo.gun, rootType) + k, err := repo.cryptoService.Create("targets/level1", repo.gun, rootType) require.NoError(t, err) key1 := k err = repo.tufRepo.UpdateDelegationKeys("targets/level1", []data.PublicKey{k}, []string{}, 1) @@ -3840,7 +3840,7 @@ func TestGetAllTargetInfo(t *testing.T) { level1OtherTarget := addTarget(t, repo, "other", "../fixtures/root-ca.crt", "targets/level1") // setup delegated targets/level2 role with targets current and level2 - k, err = repo.CryptoService.Create("targets/level2", repo.gun, rootType) + k, err = repo.cryptoService.Create("targets/level2", repo.gun, rootType) require.NoError(t, err) key2 := k err = repo.tufRepo.UpdateDelegationKeys("targets/level2", []data.PublicKey{k}, []string{}, 1) @@ -3871,7 +3871,7 @@ func TestGetAllTargetInfo(t *testing.T) { // setup delegated targets/level1/level2 role separately, which can only modify paths prefixed with "level2" // add level2 to targets/level1/level2 - k, err = repo.CryptoService.Create("targets/level1/level2", repo.gun, rootType) + k, err = repo.cryptoService.Create("targets/level1/level2", repo.gun, rootType) require.NoError(t, err) key3 := k err = repo.tufRepo.UpdateDelegationKeys("targets/level1/level2", []data.PublicKey{k}, []string{}, 1) @@ -3901,7 +3901,7 @@ func TestGetAllTargetInfo(t *testing.T) { level2Level2 = expectation{role: "targets/level2", target: "level2"} level1Level2Level2 = expectation{role: "targets/level1/level2", target: "level2"} ) - targetsKey := repo.CryptoService.ListKeys(data.CanonicalTargetsRole)[0] + targetsKey := repo.cryptoService.ListKeys(data.CanonicalTargetsRole)[0] allExpected := map[expectation]TargetSignedStruct{ targetCurrent: { Target: *targetsCurrentTarget, diff --git a/client/interface.go b/client/interface.go index c9a81f6f7..782c66713 100644 --- a/client/interface.go +++ b/client/interface.go @@ -3,6 +3,7 @@ package client import ( "github.com/docker/notary/client/changelist" "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" ) // Repository represents the set of options that must be supported over a TUF repo. @@ -10,7 +11,6 @@ type Repository interface { // General management operations Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error Publish() error - DeleteTrustData(deleteRemote bool) error // Target Operations AddTarget(target *Target, roles ...data.RoleName) error @@ -39,4 +39,8 @@ type Repository interface { // Key Operations RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error + + CryptoService() signed.CryptoService + SetLegacyVersions(int) + GetGUN() string } diff --git a/client_api/api/client.go b/client_api/api/client.go index 16ade1c48..6d15fabbf 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -1,10 +1,157 @@ package api -import "google.golang.org/grpc" +import ( + "google.golang.org/grpc" -type Client struct {} + "github.com/docker/notary/client" + "github.com/docker/notary/client/changelist" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" +) -func NewClient(conn *grpc.ClientConn) (NotaryClient, error) { +type Client struct { + client NotaryClient + cs signed.CryptoService +} + +func NewClient(conn *grpc.ClientConn) *Client { + return &Client{ + client: NewNotaryClient(conn), + } +} + +func (c *Client) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error { + return ErrNotImplemented +} + +func (c *Client) Publish() error { + return ErrNotImplemented +} + +func (c *Client) DeleteTrustData(deleteRemote bool) error { + return ErrNotImplemented +} + +func (c *Client) AddTarget(target *client.Target, roles ...data.RoleName) error { + return ErrNotImplemented +} + +func (c *Client) RemoveTarget(targetName string, roles ...data.RoleName) error { + return ErrNotImplemented +} + +func (c *Client) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) { + return nil, ErrNotImplemented +} + +func (c *Client) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) { + return nil, ErrNotImplemented +} + +func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) { + return nil, ErrNotImplemented +} + +func (c *Client) GetChangelist() (changelist.Changelist, error) { + return nil, ErrNotImplemented +} + +func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { + return nil, ErrNotImplemented +} + +func (c *Client) GetDelegationRoles() ([]data.Role, error) { + return nil, ErrNotImplemented +} + +func (c *Client) AddDelegation(name data.RoleName, delegationKeys []data.PublicKey, paths []string) error { + return ErrNotImplemented +} + +func (c *Client) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []data.PublicKey) error { + return ErrNotImplemented +} + +func (c *Client) AddDelegationPaths(name data.RoleName, paths []string) error { + return ErrNotImplemented +} + +func (c *Client) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error { + return ErrNotImplemented +} + +func (c *Client) RemoveDelegationRole(name data.RoleName) error { + return ErrNotImplemented +} + +func (c *Client) RemoveDelegationPaths(name data.RoleName, paths []string) error { + return ErrNotImplemented +} + +func (c *Client) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error { + return ErrNotImplemented +} + +func (c *Client) ClearDelegationPaths(name data.RoleName) error { + return ErrNotImplemented +} + +func (c *Client) Witness(roles ...data.RoleName) ([]data.RoleName, error) { + return nil, ErrNotImplemented +} + +func (c *Client) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error { + return ErrNotImplemented +} + +func (c *Client) SetLegacyVersions(n int) { + // do nothing. New client API based repos only support new format root key rotation +} + +func (c *Client) CryptoService() signed.CryptoService { + return c.cs +} + +type CryptoService struct { + client NotaryClient +} + +// Create issues a new key pair and is responsible for loading +// the private key into the appropriate signing service. +func (cs *CryptoService) Create(role data.RoleName, gun data.GUN, algorithm string) (data.PublicKey, error) { + return nil, ErrNotImplemented +} + +// AddKey adds a private key to the specified role and gun +func (cs *CryptoService) AddKey(role data.RoleName, gun data.GUN, key data.PrivateKey) error { + return ErrNotImplemented +} + +// GetKey retrieves the public key if present, otherwise it returns nil +func (cs *CryptoService) GetKey(keyID string) data.PublicKey { + return nil +} + +// GetPrivateKey retrieves the private key and role if present and retrievable, +// otherwise it returns nil and an error +func (cs *CryptoService) GetPrivateKey(keyID string) (data.PrivateKey, data.RoleName, error) { + return nil, "", ErrNotImplemented +} + +// RemoveKey deletes the specified key, and returns an error only if the key +// removal fails. If the key doesn't exist, no error should be returned. +func (cs *CryptoService) RemoveKey(keyID string) error { + return ErrNotImplemented +} + +// ListKeys returns a list of key IDs for the role, or an empty list or +// nil if there are no keys. +func (cs *CryptoService) ListKeys(role data.RoleName) []string { + return nil +} - return NewNotaryClient(conn), nil +// ListAllKeys returns a map of all available signing key IDs to role, or +// an empty map or nil if there are no keys. +func (cs *CryptoService) ListAllKeys() map[string]data.RoleName { + return nil } diff --git a/client_api/api/errors.go b/client_api/api/errors.go index 976611216..ef6d1f750 100644 --- a/client_api/api/errors.go +++ b/client_api/api/errors.go @@ -1,5 +1,9 @@ package api +import "errors" + +var ErrNotImplemented = errors.New("not implemented") + type ErrUnknown struct { msg string } @@ -13,8 +17,8 @@ func (err ErrUnknown) Error() string { } func translateAPIError(t string, msg string) error { - switch t{ + switch t { default: return NewErrorUnknown(msg) } -} \ No newline at end of file +} diff --git a/client_api/api/server.go b/client_api/api/server.go index 7bff82dc9..5cbb2715d 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -1,13 +1,18 @@ package api import ( + "github.com/docker/notary" "github.com/docker/notary/client" + "github.com/docker/notary/client/changelist" + "github.com/docker/notary/cryptoservice" "github.com/docker/notary/storage" + "github.com/docker/notary/trustmanager" "github.com/docker/notary/trustpinning" "github.com/docker/notary/tuf/data" "github.com/docker/notary/utils" "golang.org/x/net/context" "google.golang.org/grpc" + "path/filepath" ) // NewServer creates a new instance of a Client API server with a configured @@ -81,10 +86,10 @@ func publishRepo(r *client.NotaryRepository) error { } func initializeRepo(r *client.NotaryRepository) error { - rootKeyList := r.CryptoService.ListKeys(data.CanonicalRootRole) + rootKeyList := r.CryptoService().ListKeys(data.CanonicalRootRole) var rootKeyID string if len(rootKeyList) < 1 { - rootPublicKey, err := r.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey) + rootPublicKey, err := r.CryptoService().Create(data.CanonicalRootRole, "", data.ECDSAKey) if err != nil { return err } @@ -98,6 +103,7 @@ func initializeRepo(r *client.NotaryRepository) error { } func (srv *Server) initRepo(gun data.GUN) (*client.NotaryRepository, error) { + baseDir := "var/lib/clientapi" rt, err := utils.GetReadOnlyAuthTransport( srv.upstream, []string{gun.String()}, @@ -108,14 +114,31 @@ func (srv *Server) initRepo(gun data.GUN) (*client.NotaryRepository, error) { if err != nil { return nil, err } + + keyStore, err := trustmanager.NewKeyFileStore(filepath.Join(baseDir, notary.PrivDir), retriever) + if err != nil { + return nil, err + } + + cryptoService := cryptoservice.NewCryptoService(keyStore) + + remoteStore, err := storage.NewHTTPStore( + srv.upstream+"/v2/"+gun.String()+"/_trust/tuf/", + "", + "json", + "key", + rt, + ) + return client.NewNotaryRepository( - "/var/lib/clientapi", + baseDir, gun, srv.upstream, - rt, + remoteStore, // remote store storage.NewMemoryStore(nil), - retriever, trustpinning.TrustPinConfig{}, + cryptoService, + changelist.NewMemChangelist(), ) } diff --git a/cmd/notary/delegations.go b/cmd/notary/delegations.go index 6b96304be..f25647708 100644 --- a/cmd/notary/delegations.go +++ b/cmd/notary/delegations.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/docker/notary" - notaryclient "github.com/docker/notary/client" "github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/utils" "github.com/spf13/cobra" @@ -98,19 +97,8 @@ func (d *delegationCommander) delegationPurgeKeys(cmd *cobra.Command, args []str return err } - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), - gun, - getRemoteTrustServer(config), - nil, - d.retriever, - trustPin, - ) + fact := ConfigureRepo(config, d.retriever, false) + nRepo, err := fact(gun) if err != nil { return err } @@ -142,19 +130,8 @@ func (d *delegationCommander) delegationsList(cmd *cobra.Command, args []string) gun := data.GUN(args[0]) - rt, err := getTransport(config, gun, readOnly) - if err != nil { - return err - } - - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - // initialize repo with transport to get latest state of the world before listing delegations - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, d.retriever, trustPin) + fact := ConfigureRepo(config, d.retriever, true) + nRepo, err := fact(gun) if err != nil { return err } @@ -177,15 +154,8 @@ func (d *delegationCommander) delegationRemove(cmd *cobra.Command, args []string return err } - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - // no online operations are performed by add so the transport argument - // should be nil - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, d.retriever, trustPin) + fact := ConfigureRepo(config, d.retriever, false) + nRepo, err := fact(gun) if err != nil { return err } @@ -307,15 +277,8 @@ func (d *delegationCommander) delegationAdd(cmd *cobra.Command, args []string) e checkAllPaths(d) - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - // no online operations are performed by add so the transport argument - // should be nil - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, d.retriever, trustPin) + fact := ConfigureRepo(config, d.retriever, false) + nRepo, err := fact(gun) if err != nil { return err } diff --git a/cmd/notary/keys.go b/cmd/notary/keys.go index 44a5dc935..5e70b6dd7 100644 --- a/cmd/notary/keys.go +++ b/cmd/notary/keys.go @@ -9,7 +9,6 @@ import ( "strings" "github.com/docker/notary" - notaryclient "github.com/docker/notary/client" "github.com/docker/notary/cryptoservice" store "github.com/docker/notary/storage" "github.com/docker/notary/trustmanager" @@ -218,19 +217,8 @@ func (k *keyCommander) keysRotate(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) rotateKeyRole := data.RoleName(args[1]) - rt, err := getTransport(config, gun, admin) - if err != nil { - return err - } - - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), - rt, k.getRetriever(), trustPin) + fact := ConfigureRepo(config, k.getRetriever(), true) + nRepo, err := fact(gun) if err != nil { return err } @@ -242,7 +230,7 @@ func (k *keyCommander) keysRotate(cmd *cobra.Command, args []string) error { if err != nil { return err } - err = nRepo.CryptoService.AddKey(rotateKeyRole, gun, privKey) + err = nRepo.CryptoService().AddKey(rotateKeyRole, gun, privKey) if err != nil { return fmt.Errorf("Error importing key: %v", err) } @@ -259,7 +247,7 @@ func (k *keyCommander) keysRotate(cmd *cobra.Command, args []string) error { return nil } } - nRepo.LegacyVersions = k.legacyVersions + nRepo.SetLegacyVersions(k.legacyVersions) if err := nRepo.RotateKey(rotateKeyRole, k.rotateKeyServerManaged, keyList); err != nil { return err } diff --git a/cmd/notary/keys_test.go b/cmd/notary/keys_test.go index f45ba33eb..da3573c32 100644 --- a/cmd/notary/keys_test.go +++ b/cmd/notary/keys_test.go @@ -336,13 +336,13 @@ func setUpRepo(t *testing.T, tempBaseDir string, gun data.GUN, ret notary.PassRe tempBaseDir, gun, ts.URL, http.DefaultTransport, ret, trustpinning.TrustPinConfig{}) require.NoError(t, err, "error creating repo: %s", err) - rootPubKey, err := repo.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey) + rootPubKey, err := repo.CryptoService().Create(data.CanonicalRootRole, "", data.ECDSAKey) require.NoError(t, err, "error generating root key: %s", err) err = repo.Initialize([]string{rootPubKey.ID()}) require.NoError(t, err) - return ts, repo.CryptoService.ListAllKeys() + return ts, repo.CryptoService().ListAllKeys() } // The command line uses NotaryRepository's RotateKey - this is just testing @@ -382,7 +382,7 @@ func TestRotateKeyRemoteServerManagesKey(t *testing.T) { require.NoError(t, err, "unable to get changelist: %v", err) require.Len(t, cl.List(), 0, "expected the changes to have been published") - finalKeys := repo.CryptoService.ListAllKeys() + finalKeys := repo.CryptoService().ListAllKeys() // no keys have been created, since a remote key was specified if role == data.CanonicalSnapshotRole.String() { require.Len(t, finalKeys, 2) @@ -437,7 +437,7 @@ func TestRotateKeyBothKeys(t *testing.T) { require.Len(t, cl.List(), 0) // two new keys have been created, and the old keys should still be gone - newKeys := repo.CryptoService.ListAllKeys() + newKeys := repo.CryptoService().ListAllKeys() // there should be 3 keys - snapshot, targets, and root require.Len(t, newKeys, 3) @@ -498,7 +498,7 @@ func TestRotateKeyRootIsInteractive(t *testing.T) { require.NoError(t, err, "error creating repo: %s", err) // There should still just be one root key (and one targets and one snapshot) - allKeys := repo.CryptoService.ListAllKeys() + allKeys := repo.CryptoService().ListAllKeys() require.Len(t, allKeys, 3) } diff --git a/cmd/notary/repo_factory.go b/cmd/notary/repo_factory.go new file mode 100644 index 000000000..648b990ad --- /dev/null +++ b/cmd/notary/repo_factory.go @@ -0,0 +1,44 @@ +package main + +import ( + "github.com/spf13/viper" + + "github.com/docker/notary" + "github.com/docker/notary/client" + "github.com/docker/notary/client_api/api" + "github.com/docker/notary/tuf/data" + "net/http" +) + +type repoFactory func(gun data.GUN) (client.Repository, error) + +func ConfigureRepo(v *viper.Viper, retriever notary.PassRetriever, onlineOperation bool) repoFactory { + localRepo := func(gun data.GUN) (client.Repository, error) { + var rt http.RoundTripper + trustPin, err := getTrustPinning(v) + if err != nil { + return nil, err + } + if onlineOperation { + rt, err = getTransport(v, gun, admin) + if err != nil { + return nil, err + } + } + return client.NewFileCachedNotaryRepository( + v.GetString("trust_dir"), + gun, + getRemoteTrustServer(v), + rt, + retriever, + trustPin, + ) + } + remoteRepo := func(gun data.GUN) (client.Repository, error) { + return api.NewClient(nil), nil + } + if v.GetBool("remote") { + return remoteRepo + } + return localRepo +} diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index c6dcf88b6..06ab4c804 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -193,17 +193,12 @@ func (t *tufCommander) tufWitness(cmd *cobra.Command, args []string) error { if err != nil { return err } - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } + gun := data.GUN(args[0]) roles := data.NewRoleList(args[1:]) - // no online operations are performed by add so the transport argument - // should be nil - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, false) + nRepo, err := fact(gun) if err != nil { return err } @@ -268,15 +263,8 @@ func (t *tufCommander) tufAddByHash(cmd *cobra.Command, args []string) error { return err } - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - // no online operations are performed by add so the transport argument - // should be nil - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, false) + nRepo, err := fact(gun) if err != nil { return err } @@ -322,15 +310,8 @@ func (t *tufCommander) tufAdd(cmd *cobra.Command, args []string) error { targetName := args[1] targetPath := args[2] - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - // no online operations are performed by add so the transport argument - // should be nil - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, false) + nRepo, err := fact(gun) if err != nil { return err } @@ -362,16 +343,16 @@ func (t *tufCommander) tufDeleteGUN(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) // Only initialize a roundtripper if we get the remote flag - var rt http.RoundTripper var remoteDeleteInfo string if t.deleteRemote { - rt, err = getTransport(config, gun, admin) - if err != nil { - return err - } remoteDeleteInfo = " and remote" } + rt, err := getTransport(config, gun, admin) + if err != nil { + return err + } + cmd.Printf("Deleting trust data for repository %s\n", gun) if err := notaryclient.DeleteTrustData( @@ -387,7 +368,7 @@ func (t *tufCommander) tufDeleteGUN(cmd *cobra.Command, args []string) error { return nil } -func importRootKey(cmd *cobra.Command, rootKey string, nRepo *notaryclient.NotaryRepository, retriever notary.PassRetriever) ([]string, error) { +func importRootKey(cmd *cobra.Command, rootKey string, nRepo notaryclient.Repository, retriever notary.PassRetriever) ([]string, error) { var rootKeyList []string if rootKey != "" { @@ -395,13 +376,13 @@ func importRootKey(cmd *cobra.Command, rootKey string, nRepo *notaryclient.Notar if err != nil { return nil, err } - err = nRepo.CryptoService.AddKey(data.CanonicalRootRole, "", privKey) + err = nRepo.CryptoService().AddKey(data.CanonicalRootRole, "", privKey) if err != nil { return nil, fmt.Errorf("Error importing key: %v", err) } rootKeyList = []string{privKey.ID()} } else { - rootKeyList = nRepo.CryptoService.ListKeys(data.CanonicalRootRole) + rootKeyList = nRepo.CryptoService().ListKeys(data.CanonicalRootRole) } if len(rootKeyList) > 0 { @@ -428,18 +409,8 @@ func (t *tufCommander) tufInit(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) - rt, err := getTransport(config, gun, readWrite) - if err != nil { - return err - } - - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, true) + nRepo, err := fact(gun) if err != nil { return err } @@ -500,18 +471,8 @@ func (t *tufCommander) tufList(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) - rt, err := getTransport(config, gun, readOnly) - if err != nil { - return err - } - - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, true) + nRepo, err := fact(gun) if err != nil { return err } @@ -539,18 +500,8 @@ func (t *tufCommander) tufLookup(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) targetName := args[1] - rt, err := getTransport(config, gun, readOnly) - if err != nil { - return err - } - - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, true) + nRepo, err := fact(gun) if err != nil { return err } @@ -576,13 +527,8 @@ func (t *tufCommander) tufStatus(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, false) + nRepo, err := fact(gun) if err != nil { return err } @@ -633,13 +579,8 @@ func (t *tufCommander) tufReset(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, false) + nRepo, err := fact(gun) if err != nil { return err } @@ -675,18 +616,8 @@ func (t *tufCommander) tufPublish(cmd *cobra.Command, args []string) error { cmd.Println("Pushing changes to", gun) - rt, err := getTransport(config, gun, readWrite) - if err != nil { - return err - } - - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, true) + nRepo, err := fact(gun) if err != nil { return err } @@ -706,15 +637,8 @@ func (t *tufCommander) tufRemove(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) targetName := args[1] - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - // no online operation are performed by remove so the transport argument - // should be nil. - repo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, false) + repo, err := fact(gun) if err != nil { return err } @@ -748,18 +672,8 @@ func (t *tufCommander) tufVerify(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) targetName := args[1] - rt, err := getTransport(config, gun, readOnly) - if err != nil { - return err - } - - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) + fact := ConfigureRepo(config, t.retriever, true) + nRepo, err := fact(gun) if err != nil { return err } @@ -1019,19 +933,8 @@ func maybeAutoPublish(cmd *cobra.Command, doPublish bool, gun data.GUN, config * return nil } - // We need to set up a http RoundTripper when publishing - rt, err := getTransport(config, gun, readWrite) - if err != nil { - return err - } - - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, passRetriever, trustPin) + fact := ConfigureRepo(config, passRetriever, true) + nRepo, err := fact(gun) if err != nil { return err } @@ -1040,7 +943,7 @@ func maybeAutoPublish(cmd *cobra.Command, doPublish bool, gun data.GUN, config * return publishAndPrintToCLI(cmd, nRepo) } -func publishAndPrintToCLI(cmd *cobra.Command, nRepo *notaryclient.NotaryRepository) error { +func publishAndPrintToCLI(cmd *cobra.Command, nRepo notaryclient.Repository) error { if err := nRepo.Publish(); err != nil { return err } From b024930beb83ddee86ca3627d571e602d78796a4 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Fri, 24 Feb 2017 14:44:49 -0800 Subject: [PATCH 04/62] clientapi works with cli Signed-off-by: David Lawrence (github: endophage) --- client_api/api/client.go | 21 ++++- client_api/api/server.go | 20 +++-- clientapi.Dockerfile | 16 ++++ cmd/{client_api => clientapi}/.gitignore | 0 cmd/{client_api => clientapi}/config.toml | 1 + cmd/{client_api => clientapi}/main.go | 6 +- cmd/{client_api => clientapi}/setup/config.go | 16 +--- cmd/notary/config.json | 6 +- cmd/notary/repo_factory.go | 13 ++- docker-compose.clientapi.yml | 72 ++++++++++++++++ fixtures/clientapi-server-config.toml | 11 +++ fixtures/clientapi-server.crt | 63 ++++++++++++++ fixtures/clientapi-server.key | 27 ++++++ fixtures/intermediate-ca.crt | 56 ++++++------- fixtures/notary-server.crt | 84 +++++++++---------- fixtures/notary-signer.crt | 84 +++++++++---------- fixtures/regenerateTestingCerts.sh | 50 +++++------ fixtures/root-ca.crt | 50 +++++------ fixtures/secure.example.com.crt | 28 +++---- fixtures/self-signed_docker.com-notary.crt | 18 ++-- fixtures/self-signed_secure.example.com.crt | 14 ++-- utils/grpc.go | 81 ++++++++++++++++++ 22 files changed, 518 insertions(+), 219 deletions(-) create mode 100644 clientapi.Dockerfile rename cmd/{client_api => clientapi}/.gitignore (100%) rename cmd/{client_api => clientapi}/config.toml (99%) rename cmd/{client_api => clientapi}/main.go (86%) rename cmd/{client_api => clientapi}/setup/config.go (82%) create mode 100644 docker-compose.clientapi.yml create mode 100644 fixtures/clientapi-server-config.toml create mode 100644 fixtures/clientapi-server.crt create mode 100644 fixtures/clientapi-server.key create mode 100644 utils/grpc.go diff --git a/client_api/api/client.go b/client_api/api/client.go index 6d15fabbf..e2dc398ba 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -7,16 +7,19 @@ import ( "github.com/docker/notary/client/changelist" "github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/signed" + "golang.org/x/net/context" ) type Client struct { client NotaryClient cs signed.CryptoService + gun data.GUN } -func NewClient(conn *grpc.ClientConn) *Client { +func NewClient(conn *grpc.ClientConn, gun data.GUN) *Client { return &Client{ client: NewNotaryClient(conn), + gun: gun, } } @@ -33,11 +36,23 @@ func (c *Client) DeleteTrustData(deleteRemote bool) error { } func (c *Client) AddTarget(target *client.Target, roles ...data.RoleName) error { - return ErrNotImplemented + t := &TargetAction{ + Gun: c.gun.String(), + Name: target.Name, + Length: target.Length, + Hashes: target.Hashes, + } + _, err := c.client.AddTarget(context.Background(), t) + return err } func (c *Client) RemoveTarget(targetName string, roles ...data.RoleName) error { - return ErrNotImplemented + t := &TargetAction{ + Gun: c.gun.String(), + Name: targetName, + } + _, err := c.client.RemoveTarget(context.Background(), t) + return err } func (c *Client) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) { diff --git a/client_api/api/server.go b/client_api/api/server.go index 5cbb2715d..480f21e11 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -1,6 +1,12 @@ package api import ( + "path/filepath" + + "github.com/Sirupsen/logrus" + "golang.org/x/net/context" + "google.golang.org/grpc" + "github.com/docker/notary" "github.com/docker/notary/client" "github.com/docker/notary/client/changelist" @@ -10,24 +16,23 @@ import ( "github.com/docker/notary/trustpinning" "github.com/docker/notary/tuf/data" "github.com/docker/notary/utils" - "golang.org/x/net/context" - "google.golang.org/grpc" - "path/filepath" ) // NewServer creates a new instance of a Client API server with a configured // upstream Notary Server. -func NewServer(upstream string, serverOpts []grpc.ServerOption) (*grpc.Server, error) { +func NewServer(upstream string, upstreamCAPath string, serverOpts []grpc.ServerOption) (*grpc.Server, error) { grpcSrv := grpc.NewServer(serverOpts...) srv := &Server{ - upstream: upstream, + upstream: upstream, + upstreamCAPath: upstreamCAPath, } RegisterNotaryServer(grpcSrv, srv) return grpcSrv, nil } type Server struct { - upstream string + upstream string + upstreamCAPath string } func (srv *Server) AddTarget(ctx context.Context, t *TargetAction) (*BasicResponse, error) { @@ -103,13 +108,14 @@ func initializeRepo(r *client.NotaryRepository) error { } func (srv *Server) initRepo(gun data.GUN) (*client.NotaryRepository, error) { + logrus.Errorf("initializing with upstream ca file %s", srv.upstreamCAPath) baseDir := "var/lib/clientapi" rt, err := utils.GetReadOnlyAuthTransport( srv.upstream, []string{gun.String()}, "", "", - "/fixtures/root-ca.crt", + srv.upstreamCAPath, ) if err != nil { return nil, err diff --git a/clientapi.Dockerfile b/clientapi.Dockerfile new file mode 100644 index 000000000..04528fa1a --- /dev/null +++ b/clientapi.Dockerfile @@ -0,0 +1,16 @@ +FROM golang:1.7.5-alpine + +RUN apk add --update git gcc libc-dev && rm -rf /var/cache/apk/* + +ENV NOTARY_PKG github.com/docker/notary + +COPY . /go/src/$NOTARY_PKG + +WORKDIR /go/src/$NOTARY_PKG +RUN go install \ + $NOTARY_PKG/cmd/clientapi + +EXPOSE 4449 + +ENTRYPOINT [ "clientapi" ] +CMD [ "-config", "fixtures/clientapi-server-config.toml" ] diff --git a/cmd/client_api/.gitignore b/cmd/clientapi/.gitignore similarity index 100% rename from cmd/client_api/.gitignore rename to cmd/clientapi/.gitignore diff --git a/cmd/client_api/config.toml b/cmd/clientapi/config.toml similarity index 99% rename from cmd/client_api/config.toml rename to cmd/clientapi/config.toml index 80b5df278..6ac8cb023 100644 --- a/cmd/client_api/config.toml +++ b/cmd/clientapi/config.toml @@ -8,3 +8,4 @@ level = "debug" [upstream] addr = "https://notaryserver:4443" + diff --git a/cmd/client_api/main.go b/cmd/clientapi/main.go similarity index 86% rename from cmd/client_api/main.go rename to cmd/clientapi/main.go index 2baca5514..1a0bfcf8e 100644 --- a/cmd/client_api/main.go +++ b/cmd/clientapi/main.go @@ -4,7 +4,8 @@ import ( "flag" "github.com/Sirupsen/logrus" "github.com/docker/notary/client_api/api" - "github.com/docker/notary/cmd/client_api/setup" + "github.com/docker/notary/cmd/clientapi/setup" + "github.com/docker/notary/utils" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "net" @@ -42,6 +43,7 @@ func main() { serverConfig := setup.Config{GRPCAddr: grpcAddr, TLSConfig: tlsConfig} upstreamAddr := vc.GetString("upstream.addr") + upstreamCAPath := utils.GetPathRelativeToConfig(vc, "upstream.tls_ca_file") lis, err := net.Listen("tcp", serverConfig.GRPCAddr) if err != nil { @@ -51,7 +53,7 @@ func main() { creds := credentials.NewTLS(serverConfig.TLSConfig) opts := []grpc.ServerOption{grpc.Creds(creds)} - s, err := api.NewServer(upstreamAddr, opts) + s, err := api.NewServer(upstreamAddr, upstreamCAPath, opts) if err != nil { logrus.Fatal(err) } diff --git a/cmd/client_api/setup/config.go b/cmd/clientapi/setup/config.go similarity index 82% rename from cmd/client_api/setup/config.go rename to cmd/clientapi/setup/config.go index 4d9a16832..08029dccd 100644 --- a/cmd/client_api/setup/config.go +++ b/cmd/clientapi/setup/config.go @@ -1,11 +1,11 @@ package setup import ( - "github.com/spf13/viper" - "github.com/Sirupsen/logrus" - "github.com/docker/notary/utils" "crypto/tls" "fmt" + "github.com/Sirupsen/logrus" + "github.com/docker/notary/utils" + "github.com/spf13/viper" "net" "google.golang.org/grpc" @@ -15,13 +15,12 @@ import ( ) type Config struct { - GRPCAddr string + GRPCAddr string TLSConfig *tls.Config } func ViperConfig(path string) (*viper.Viper, error) { vc := viper.New() - setDefaults(vc) vc.SetConfigFile(path) err := vc.ReadInConfig() if err != nil { @@ -31,13 +30,6 @@ func ViperConfig(path string) (*viper.Viper, error) { return vc, nil } -// SetDefaults is responsible for setting defaults on the Viper struct -// These should be overridden by a subsequent call to -func setDefaults(vc *viper.Viper) { - vc.SetDefault("upstream.addr", "https://localhost:4443") - vc.SetDefault("server", map[string]string{"addr":":4445"}) -} - func SetupGRPCServer(serverConfig Config) (*grpc.Server, net.Listener, error) { //RPC server setup diff --git a/cmd/notary/config.json b/cmd/notary/config.json index 6b9f1bf0c..2ae55d235 100644 --- a/cmd/notary/config.json +++ b/cmd/notary/config.json @@ -1,7 +1,11 @@ { "remote_server": { "url": "https://notary-server:4443", - "root_ca": "root-ca.crt" + "root_ca": "../../root-ca.crt" + }, + "api": { + "addr": "clientapi-server:4449", + "tls_ca_file": "/Users/david/go/src/github.com/docker/notary/fixtures/root-ca.crt" } } diff --git a/cmd/notary/repo_factory.go b/cmd/notary/repo_factory.go index 648b990ad..e0fd0d013 100644 --- a/cmd/notary/repo_factory.go +++ b/cmd/notary/repo_factory.go @@ -7,9 +7,12 @@ import ( "github.com/docker/notary/client" "github.com/docker/notary/client_api/api" "github.com/docker/notary/tuf/data" + "github.com/docker/notary/utils" "net/http" ) +const remoteConfigField = "api" + type repoFactory func(gun data.GUN) (client.Repository, error) func ConfigureRepo(v *viper.Viper, retriever notary.PassRetriever, onlineOperation bool) repoFactory { @@ -34,10 +37,16 @@ func ConfigureRepo(v *viper.Viper, retriever notary.PassRetriever, onlineOperati trustPin, ) } + remoteRepo := func(gun data.GUN) (client.Repository, error) { - return api.NewClient(nil), nil + conn, err := utils.GetGRPCClient(v, remoteConfigField) + if err != nil { + return nil, err + } + return api.NewClient(conn, gun), nil } - if v.GetBool("remote") { + + if v.IsSet(remoteConfigField) { return remoteRepo } return localRepo diff --git a/docker-compose.clientapi.yml b/docker-compose.clientapi.yml new file mode 100644 index 000000000..3604af88b --- /dev/null +++ b/docker-compose.clientapi.yml @@ -0,0 +1,72 @@ +version: "2" +services: + clientapi: + build: + context: . + dockerfile: clientapi.Dockerfile + depends_on: + - server + ports: + - "4449:4449" + volumes: + - clientapi_data:/var/lib/clientapi + networks: + api: + entrypoint: clientapi + command: -config=./fixtures/clientapi-server-config.toml + server: + build: + context: . + dockerfile: server.Dockerfile + networks: + mdb: + sig: + api: + aliases: + - notaryserver + ports: + - "8080" + - "4443:4443" + entrypoint: /usr/bin/env sh + command: -c "./migrations/migrate.sh && notary-server -config=./fixtures/server-config.json" + depends_on: + - mysql + - signer + signer: + build: + context: . + dockerfile: signer.Dockerfile + networks: + mdb: + sig: + aliases: + - notarysigner + ports: + - "7899:7899" + entrypoint: /usr/bin/env sh + command: -c "./migrations/migrate.sh && notary-signer -config=./fixtures/signer-config.json" + depends_on: + - mysql + mysql: + networks: + - mdb + volumes: + - ./notarysql/mysql-initdb.d:/docker-entrypoint-initdb.d + - notary_data:/var/lib/mysql + image: mariadb:10.1.10 + environment: + - TERM=dumb + - MYSQL_ALLOW_EMPTY_PASSWORD="true" + command: mysqld --innodb_file_per_table +volumes: + notary_data: + external: false + clientapi_data: + external: false +networks: + mdb: + external: false + sig: + external: false + api: + external: false diff --git a/fixtures/clientapi-server-config.toml b/fixtures/clientapi-server-config.toml new file mode 100644 index 000000000..c8c78c263 --- /dev/null +++ b/fixtures/clientapi-server-config.toml @@ -0,0 +1,11 @@ +[server] +grpc_addr = ":4449" +tls_cert_file = "./clientapi-server.crt" +tls_key_file = "./clientapi-server.key" + +[logging] +level = "debug" + +[upstream] +addr = "https://notaryserver:4443" +tls_ca_file = "./root-ca.crt" diff --git a/fixtures/clientapi-server.crt b/fixtures/clientapi-server.crt new file mode 100644 index 000000000..212144d69 --- /dev/null +++ b/fixtures/clientapi-server.crt @@ -0,0 +1,63 @@ +-----BEGIN CERTIFICATE----- +MIIFCjCCAvKgAwIBAgIJAM3wbUCyULKSMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G +A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp +bmcgQ0EwHhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjBeMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV +BAoTBkRvY2tlcjEZMBcGA1UEAxMQY2xpZW50YXBpLXNlcnZlcjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBALlrIUZNfqnIkEpcs2ItUMgMLtn9zP2fd77t +LyJy1NHDwOsVu2B43hQ3C+0clANaLv/lc3GLio2kxfEQ6xho1kT/miE34x/a4j54 +N3/H5fogqum2etNY7CvJIPN4c5Tvusp3oMfPL79ZuT19JgbhQFnNLMZu8Y+CI5by +Uqw4g2lXYVGfYqF1zV3cnRU3C8ShhnDdh+e0P5yYYogL736G3Wn/v/ESm4TuR6Us +F7DoHAXerr7N9gSwf0c+MmCBY5CW1JqkUk2KqbyYaBswLQc9h1AA41pFRwVuNCPk +RyUoXijbaLLCg5kAIMkUfXtev5O/DdKXSIObwLhhzF1FL7Ub8nUCAwEAAaOBvDCB +uTAfBgNVHSMEGDAWgBROUsIBGs5SfcR4cQDIf3vfcKBfMTAMBgNVHRMBAf8EAjAA +MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAw +OgYDVR0RBDMwMYIQY2xpZW50YXBpLXNlcnZlcoIMbm90YXJ5c2lnbmVygglsb2Nh +bGhvc3SHBH8AAAEwHQYDVR0OBBYEFN4D0cwp92DpFJmyvdT4gmipvk3uMA0GCSqG +SIb3DQEBCwUAA4ICAQBf2q05/+H32tAc8SZxGlA/M/Y7M8uwFAhS++KKKvff0RXl +HWtiltSgAdOMdvOMjEyKS0r3CzyfmoF1QFKsCdOrlo997W9SC99VS62b4fLujQHC +48Hk3aIbEMiopgdDrns99BCu+3004KJe1npxuudTF1LjGPErCz1ehomKTktTbfqr +Wi7PG8NIF3yjkyS1He8HC60cbNMmZ54cqMXB0Rwv+2WufAyxSotncWspixFTykXQ +HYYU2pE44llFydxeKiP4V327D1YHa06qL5p04rakHGQBe6dh/mMgRJGdivbrvCL9 +TD/8/JR+5UQw80XhFliGZc4oerWkuroFNLueJxyJqN0mHlOrLx5ehcQBn3JVGU1N +IcdxQncmfv+xCSVXFR9u8u94lzPtskE/B+nhwTUew3zN27ZJGMmAwGlZhTMlX3ue ++GZIFKi0YRbZMaH+Cf4B3Mibo10lRdFySJ2rV8MnAE0MhFBoPoyv6sYvjIW0U9Bf +iiJkdgOCWQ5fagTFQVoTEx8Mu61rbHCB3lDxWHYa1DFaGfqSQ1qDdFli+aQyYoDI +F8FhLjGTs17fGmpPDvyO82VRHyXFsHMX5f24Y02ekENMI/Rs403Zrk5wdX1xyScx +t+D6MC//38A0h2gw6zA0MV7u94EPs4eGRm1ZkfqpwerrNAxUNB7d840PmeKJug== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +Pl9leAX0LJ7l +-----END CERTIFICATE----- diff --git a/fixtures/clientapi-server.key b/fixtures/clientapi-server.key new file mode 100644 index 000000000..0f65cc77d --- /dev/null +++ b/fixtures/clientapi-server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuWshRk1+qciQSlyzYi1QyAwu2f3M/Z93vu0vInLU0cPA6xW7 +YHjeFDcL7RyUA1ou/+VzcYuKjaTF8RDrGGjWRP+aITfjH9riPng3f8fl+iCq6bZ6 +01jsK8kg83hzlO+6ynegx88vv1m5PX0mBuFAWc0sxm7xj4IjlvJSrDiDaVdhUZ9i +oXXNXdydFTcLxKGGcN2H57Q/nJhiiAvvfobdaf+/8RKbhO5HpSwXsOgcBd6uvs32 +BLB/Rz4yYIFjkJbUmqRSTYqpvJhoGzAtBz2HUADjWkVHBW40I+RHJSheKNtossKD +mQAgyRR9e16/k78N0pdIg5vAuGHMXUUvtRvydQIDAQABAoIBAQCGxRJbeipNmAUg +t75+5rcnoItRUUN1OTqdYOJ4pISBr0oC1Tnrxg6NHPGjN7lxslQlFY7Sgf2ENLbX +IFfw1wqe/jX2XRvN5Je7lj+othA3vRTdaRBfm+uVa8xyiyNfptvbHBaWBMcMy1d0 +FQnVyFWwsAwSc0NK7umVZq6mlTEXF/pTNp8F7IyPIKRpkuAjucJXBCuuYPwoQO6m +kaVBns7P/EXX7yBiulSPsmZIneAZGenVA6AamOB8KzZ2o53yuv75q9tvJcGIjuAN +v9tcTXXpB8hlpo+AD7jPplLGQarxQzIcwhwGLEQkZJWMlputo/qN2FRY+5RdWS3x +QL+UsOFhAoGBAN4Iov4gcFs+OqZogNueFzE/nGzdN3eZ/tlU1pziy3ukLumQPriR +w96NjTc5yuzzdg2y4P6TnuIKcdtfbkSQtNcflVDi5vY+vsMlQ8j9Xev4TEzHdh2z +RUYGjdjjp4X9XSCd/iv/UZJUGDF5v4C9bSnZbxFNi/iglgiJ6NUUEEFdAoGBANXI +jbcN3B74ZmHeBhZ9qtzKP+oH2xnaQVGnrSWTlDZh7jE02ywWj8mxgBJvPAyn2VkQ +oChqYibKNg1mY3/1gAfkbnNkfufcipeMdIjnm8iD9q7jr49wKbBG7YYm3cul/Jbg +vPbu3eKmqSXIutyudLbbmYC1AYnCDDSVsugJvOv5AoGALSP8X0YhEavZKLPeXsgJ +Vw3js45WFI7ObUj+SO8jB4QdtYaJ+eRIuhp1N2EcjIgC3E4dyCQjDTmqZDtGo9H3 +sjTNmqBG7JFdHzeYTGiWi77zZDi5HtivoMj8VbgS+v7DzDnSzwcdgm5ubMCf2oCo +jPWTyyTE7EtZtWq0V324wFECgYA1XrkKTvp5/NdKbWwlpz/FmPQ1z7pCDPurj+mo +7Nvea7pULHbe3c8NsjNf5scd/bVEB+OD03MnbenqlHoYkshgsAVm51rLNYKf7N+W +4gNBHrix1oOYko7FxB8+E2vhkFGrtPVXzDA2ihbGKQOFXkQi9lWvDQESTBBR/GFK +jkvMuQKBgQCMngxw2gZqSENSTtlO8SDTTyIKUis1td/kCsXBurARTvUKHdcReqra +TFeafWMYaa6Gk+B1jzhiNl0fpXy3dysQSwsLZ2BXXkxOaf/U14qbOuXfNFqhzUdv +TwP073OqEAf62IUm5FIqLrwDLAfIo4ZvWMVMZAOxW1i8xrlsmPGAtw== +-----END RSA PRIVATE KEY----- diff --git a/fixtures/intermediate-ca.crt b/fixtures/intermediate-ca.crt index 690300597..aab910827 100644 --- a/fixtures/intermediate-ca.crt +++ b/fixtures/intermediate-ca.crt @@ -1,34 +1,34 @@ -----BEGIN CERTIFICATE----- -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 -ALNmRewqFkXD +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDiHv1wniM1L4dpAHMYDj8PxrHbjeBtim/T +KU57m1PXqA2Uby7nGHiLE4c1ie8mVYkHXz0nQ0VjcuTUsIUa7xQj3yJ2z5ATnsgq +urE28xTRmHZmthbyddIsfmOVGrZPpAmJfJ4/LX3KJJZjqqUEPO1mkNFsG/fLkVOm +AEhzZO/g9txqbB/s2KYtMy4QxsRaepfcECGotnt+vYdk7+rJvli5PeMuKoWBLzjz +gUTzvea7VId/0ff4DO4XG9u8KjhYMHSINUsIcT8amZbl5CjQAsCRyU6lDfOl2hH3 +F1erbTFMEFtRSFh7CSpjKFCvJkyqcRAW8zIwhX+Yl1MMnEItxnBkc+rbe29oGZoD +uGjHAhzCV46IfgFQxmRrMQydUp4BRvAHTlhnXPnDjSuczYzt66p71C/UPzEH7tUe +ubHbqxVv1y6BGpI7cEALQ2o3FJ/3T8YaLbXKSYQ/uO9GpIMTgTWLwhoqwq+lgpxu +ApPJ5EY3LrLChvIZViHkxrCwjsGX31q/l17s3R9rJcGEzEIkVPxHJrvi07KelUYO +xmv1u1o/5FGfWafs0wcj0whswnU9w7LI7+o47t5ZCvNYseP7JPIMti+9KgBCUyEC +uB+YwHFcXwRDEA3GaCYePetTq+gg93iE7VoiwVo8JI8AxjwfGH17o09PjmeyNOHU +dbPcJRBJQwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFJdjQCkJsHhLo1GM3d7OxJ/R +YVTIMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUTlLCARrOUn3EeHEAyH97 +33CgXzEwDQYJKoZIhvcNAQELBQADggIBAJFoIVlB6PFPz+9ukOcH0hlrl7VPKbb+ +FO8tGizASgDsM32oeSqAaasKQw9pWhtPia/u7rIYI+mnqUi9WlgUYzy1yZmGkcWj +2Us7i9Lrq4VSMblhCOFYVJZe6SkF1TtgRQrP7NLxFLQ+oyl85inEpbcNRI82t+c3 +KIxbq8Fb9qHGAGPr9v1W+KoVo+NSrL/38FfGWAygAfTwUJJf1SNJjxUuklOsl3RS +qdkMhjmHaJF6OJm2Y0Y5aKoEGqP0vYXyTkmbgtCeFnDyc16KQV+saQ/UAFTpcyE2 +kWTri3M1uNL3tEjNBZaEHifJlv6jVA+AGK9dBfyysMTLtZXbmGxdlPAfoIkrxF3k +VxhY8kTMqSim5TRk0MzV5DZIUT5rY4yITeRicass9sAkScSKIlqEplqk/U7ZqbVY +c1q3H9zafhxjZ5rrpB8amo6brWRXzenJQ/x4wo1n/Zgf7fL3vQStxA3AVTWD3TmA +FeRlb/el+7nHziajPYmA6uxpSyRjNdyXqxP45u4nkGt7xPIvVcLTULPf2Y2NOVr0 +F0glAC5OLIrejaDGTFlMTupU9CjgkNbEiqJLnaByK3LWOu26GynVcF3eogRYYKjs +J0ETQvK+/GhRttp1QhiPVkBJrQF7fSIZAz919gD21cQAZSgNg13XTXhNNRuIw0eT +Pl9leAX0LJ7l -----END CERTIFICATE----- diff --git a/fixtures/notary-server.crt b/fixtures/notary-server.crt index 2573d0021..0b98a14d1 100644 --- a/fixtures/notary-server.crt +++ b/fixtures/notary-server.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFBDCCAuygAwIBAgIJAPlHYZzp1daGMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIFBDCCAuygAwIBAgIJAM3wbUCyULKOMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMjE3MDA0MzE3WhcNMTkwMzA5MDA0MzE3WjBbMQswCQYDVQQG +bmcgQ0EwHhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjBbMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEWMBQGA1UEAxMNbm90YXJ5LXNlcnZlcjCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAKjbeflOtVrOv0IOeJGKfi5LHH3Di0O2nlZu8AIT @@ -11,53 +11,53 @@ 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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -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 -ALNmRewqFkXD +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDiHv1wniM1L4dpAHMYDj8PxrHbjeBtim/T +KU57m1PXqA2Uby7nGHiLE4c1ie8mVYkHXz0nQ0VjcuTUsIUa7xQj3yJ2z5ATnsgq +urE28xTRmHZmthbyddIsfmOVGrZPpAmJfJ4/LX3KJJZjqqUEPO1mkNFsG/fLkVOm +AEhzZO/g9txqbB/s2KYtMy4QxsRaepfcECGotnt+vYdk7+rJvli5PeMuKoWBLzjz +gUTzvea7VId/0ff4DO4XG9u8KjhYMHSINUsIcT8amZbl5CjQAsCRyU6lDfOl2hH3 +F1erbTFMEFtRSFh7CSpjKFCvJkyqcRAW8zIwhX+Yl1MMnEItxnBkc+rbe29oGZoD +uGjHAhzCV46IfgFQxmRrMQydUp4BRvAHTlhnXPnDjSuczYzt66p71C/UPzEH7tUe +ubHbqxVv1y6BGpI7cEALQ2o3FJ/3T8YaLbXKSYQ/uO9GpIMTgTWLwhoqwq+lgpxu +ApPJ5EY3LrLChvIZViHkxrCwjsGX31q/l17s3R9rJcGEzEIkVPxHJrvi07KelUYO +xmv1u1o/5FGfWafs0wcj0whswnU9w7LI7+o47t5ZCvNYseP7JPIMti+9KgBCUyEC +uB+YwHFcXwRDEA3GaCYePetTq+gg93iE7VoiwVo8JI8AxjwfGH17o09PjmeyNOHU +dbPcJRBJQwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFJdjQCkJsHhLo1GM3d7OxJ/R +YVTIMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUTlLCARrOUn3EeHEAyH97 +33CgXzEwDQYJKoZIhvcNAQELBQADggIBAJFoIVlB6PFPz+9ukOcH0hlrl7VPKbb+ +FO8tGizASgDsM32oeSqAaasKQw9pWhtPia/u7rIYI+mnqUi9WlgUYzy1yZmGkcWj +2Us7i9Lrq4VSMblhCOFYVJZe6SkF1TtgRQrP7NLxFLQ+oyl85inEpbcNRI82t+c3 +KIxbq8Fb9qHGAGPr9v1W+KoVo+NSrL/38FfGWAygAfTwUJJf1SNJjxUuklOsl3RS +qdkMhjmHaJF6OJm2Y0Y5aKoEGqP0vYXyTkmbgtCeFnDyc16KQV+saQ/UAFTpcyE2 +kWTri3M1uNL3tEjNBZaEHifJlv6jVA+AGK9dBfyysMTLtZXbmGxdlPAfoIkrxF3k +VxhY8kTMqSim5TRk0MzV5DZIUT5rY4yITeRicass9sAkScSKIlqEplqk/U7ZqbVY +c1q3H9zafhxjZ5rrpB8amo6brWRXzenJQ/x4wo1n/Zgf7fL3vQStxA3AVTWD3TmA +FeRlb/el+7nHziajPYmA6uxpSyRjNdyXqxP45u4nkGt7xPIvVcLTULPf2Y2NOVr0 +F0glAC5OLIrejaDGTFlMTupU9CjgkNbEiqJLnaByK3LWOu26GynVcF3eogRYYKjs +J0ETQvK+/GhRttp1QhiPVkBJrQF7fSIZAz919gD21cQAZSgNg13XTXhNNRuIw0eT +Pl9leAX0LJ7l -----END CERTIFICATE----- diff --git a/fixtures/notary-signer.crt b/fixtures/notary-signer.crt index e766c45ba..5b368b2b2 100644 --- a/fixtures/notary-signer.crt +++ b/fixtures/notary-signer.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFBDCCAuygAwIBAgIJAPlHYZzp1daHMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIFBDCCAuygAwIBAgIJAM3wbUCyULKPMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMjE3MDA0MzE3WhcNMTkwMzA5MDA0MzE3WjBbMQswCQYDVQQG +bmcgQ0EwHhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjBbMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEWMBQGA1UEAxMNbm90YXJ5LXNpZ25lcjCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBANhO8+K9xT6M9dQC90Hxs6bmTXWQzE5oV2kLeVKq @@ -11,53 +11,53 @@ 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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -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 -ALNmRewqFkXD +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDiHv1wniM1L4dpAHMYDj8PxrHbjeBtim/T +KU57m1PXqA2Uby7nGHiLE4c1ie8mVYkHXz0nQ0VjcuTUsIUa7xQj3yJ2z5ATnsgq +urE28xTRmHZmthbyddIsfmOVGrZPpAmJfJ4/LX3KJJZjqqUEPO1mkNFsG/fLkVOm +AEhzZO/g9txqbB/s2KYtMy4QxsRaepfcECGotnt+vYdk7+rJvli5PeMuKoWBLzjz +gUTzvea7VId/0ff4DO4XG9u8KjhYMHSINUsIcT8amZbl5CjQAsCRyU6lDfOl2hH3 +F1erbTFMEFtRSFh7CSpjKFCvJkyqcRAW8zIwhX+Yl1MMnEItxnBkc+rbe29oGZoD +uGjHAhzCV46IfgFQxmRrMQydUp4BRvAHTlhnXPnDjSuczYzt66p71C/UPzEH7tUe +ubHbqxVv1y6BGpI7cEALQ2o3FJ/3T8YaLbXKSYQ/uO9GpIMTgTWLwhoqwq+lgpxu +ApPJ5EY3LrLChvIZViHkxrCwjsGX31q/l17s3R9rJcGEzEIkVPxHJrvi07KelUYO +xmv1u1o/5FGfWafs0wcj0whswnU9w7LI7+o47t5ZCvNYseP7JPIMti+9KgBCUyEC +uB+YwHFcXwRDEA3GaCYePetTq+gg93iE7VoiwVo8JI8AxjwfGH17o09PjmeyNOHU +dbPcJRBJQwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFJdjQCkJsHhLo1GM3d7OxJ/R +YVTIMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUTlLCARrOUn3EeHEAyH97 +33CgXzEwDQYJKoZIhvcNAQELBQADggIBAJFoIVlB6PFPz+9ukOcH0hlrl7VPKbb+ +FO8tGizASgDsM32oeSqAaasKQw9pWhtPia/u7rIYI+mnqUi9WlgUYzy1yZmGkcWj +2Us7i9Lrq4VSMblhCOFYVJZe6SkF1TtgRQrP7NLxFLQ+oyl85inEpbcNRI82t+c3 +KIxbq8Fb9qHGAGPr9v1W+KoVo+NSrL/38FfGWAygAfTwUJJf1SNJjxUuklOsl3RS +qdkMhjmHaJF6OJm2Y0Y5aKoEGqP0vYXyTkmbgtCeFnDyc16KQV+saQ/UAFTpcyE2 +kWTri3M1uNL3tEjNBZaEHifJlv6jVA+AGK9dBfyysMTLtZXbmGxdlPAfoIkrxF3k +VxhY8kTMqSim5TRk0MzV5DZIUT5rY4yITeRicass9sAkScSKIlqEplqk/U7ZqbVY +c1q3H9zafhxjZ5rrpB8amo6brWRXzenJQ/x4wo1n/Zgf7fL3vQStxA3AVTWD3TmA +FeRlb/el+7nHziajPYmA6uxpSyRjNdyXqxP45u4nkGt7xPIvVcLTULPf2Y2NOVr0 +F0glAC5OLIrejaDGTFlMTupU9CjgkNbEiqJLnaByK3LWOu26GynVcF3eogRYYKjs +J0ETQvK+/GhRttp1QhiPVkBJrQF7fSIZAz919gD21cQAZSgNg13XTXhNNRuIw0eT +Pl9leAX0LJ7l -----END CERTIFICATE----- diff --git a/fixtures/regenerateTestingCerts.sh b/fixtures/regenerateTestingCerts.sh index 192ed06d0..33c61ac2d 100755 --- a/fixtures/regenerateTestingCerts.sh +++ b/fixtures/regenerateTestingCerts.sh @@ -99,30 +99,6 @@ cat "intermediate-ca.crt" >> "notary-signer.crt" rm "notary-signer.cnf" "notary-signer.csr" -# Then generate notary-escrow -# Use the existing notary-escrow key -openssl req -new -key "notary-escrow.key" -out "notary-escrow.csr" -sha256 \ - -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=notary-escrow' - -cat > "notary-escrow.cnf" <> "notary-escrow.crt" - -rm "notary-escrow.cnf" "notary-escrow.csr" - - # Then generate secure.example.com # Use the existing secure.example.com key openssl req -new -key "secure.example.com.key" -out "secure.example.com.csr" -sha256 \ @@ -142,7 +118,6 @@ openssl x509 -req -days 750 -in "secure.example.com.csr" -sha256 \ -CA "intermediate-ca.crt" -CAkey "intermediate-ca.key" -CAcreateserial \ -out "secure.example.com.crt" -extfile "secure.example.com.cnf" -extensions secure.example.com rm "secure.example.com.cnf" "secure.example.com.csr" -rm "intermediate-ca.key" "intermediate-ca.srl" # generate self-signed_docker.com-notary.crt and self-signed_secure.example.com @@ -167,3 +142,28 @@ EOL rm "${selfsigned}.cnf" "${selfsigned}.csr" "${selfsigned}.key" done + +# Then generate clientapi-server +# Use the existing clientapi-server key +openssl req -new -key "clientapi-server.key" -out "clientapi-server.csr" -sha256 \ + -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=clientapi-server' + +cat > "clientapi-server.cnf" <> "clientapi-server.crt" + +rm "clientapi-server.cnf" "clientapi-server.csr" + +rm "intermediate-ca.key" "intermediate-ca.srl" diff --git a/fixtures/root-ca.crt b/fixtures/root-ca.crt index 2f5b58bbe..5265c5409 100644 --- a/fixtures/root-ca.crt +++ b/fixtures/root-ca.crt @@ -1,32 +1,32 @@ -----BEGIN CERTIFICATE----- -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 -rba7O3YGSuScQakjt9mw2Q5ISwImkRHF3qE= +BBSXY0ApCbB4S6NRjN3ezsSf0WFUyDANBgkqhkiG9w0BAQsFAAOCAgEAu0F2fZnk +Do/mGcROgn16VvaqdPw6SDsXpuxHnmUcqRewYAIF3AWleYWtNWtjmdoLMusE4Acx +fnocy8B/wRXS37I9REL+KZXaZ8713fqkcglXOPr1GPRylzmsV79QNQcxc0zNbfTc +f1Twwl963fe8QWOgCBTT0NsQLF4L0LxP25A4jd51WcmmGWsngAz+IKxbFf4dKOkX ++kHQCasw8IQHnUwSQlLnBn7K28VHNdduX5FIaNVgX/t1il4GtTvaJuIEVtBOXm5m +h/EqYze4Z6Dfrthu2dmtP8Z8292aLxv56hU6hENpIxt/BWwgVlJZRlnrUlu/qmbn +sxuY3qtB1BWor8qd7u4KdRVnljvzfwSlk5/eEAkNJ6nGAJFInGcpZTOcFLVZnBAA +m3SMx1nw0H1OD9U5GC/ke2Z8cq2o5veUIxUQE35eNLhdSpkEXWzKVgeMUXvENfH3 +iEgXpCPmqehhAd5/Di5z3eyptXYnJy49hVqGAYqDwM90ereeMmvNnQcRGIA0gXLz +YKKX6lH1t4Cxc7ZVgxC6gtx6tpJRb61cLc5QvcKuehriyq+ru7ywL2Jxl6i3QtE1 +090XLqpavnxmJ/wNh5dMk0PYutSnaQ5+WcxTrMwPqDkW+ZO+CnWhiQMwu87uGqQ9 +YstYjBovWExc0Fai6Sud3LBRnzlThs7LU74= -----END CERTIFICATE----- diff --git a/fixtures/secure.example.com.crt b/fixtures/secure.example.com.crt index fa8e5162f..7f41a1ede 100644 --- a/fixtures/secure.example.com.crt +++ b/fixtures/secure.example.com.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFADCCAuigAwIBAgIJAPlHYZzp1daJMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIFADCCAuigAwIBAgIJAM3wbUCyULKQMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMjE3MDA0MzE3WhcNMTkwMzA5MDA0MzE3WjBgMQswCQYDVQQG +bmcgQ0EwHhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjBgMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEbMBkGA1UEAxMSc2VjdXJlLmV4YW1wbGUuY29tMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmLYiYCTAWJBWAuxZLqVmV4FiUdGgEqoQ @@ -11,19 +11,19 @@ IsSlHGvVtXDv93oR3ydmfZO+ULRU8xHloqcLr1KrOP1daLfdMRbactd75UQgvw9X TsdeMVX5AlicSENVKV+AQXvVpv8PT10MSvlBFam4reXuY/SkeMbIaW5pFu6AQv3Z mftt2ta0CB9kb1mYd+OKru8Hnnq5aJw6R3GhP0TBd25P1PkiSxM2KGYZZk0W/NZq LK9/LTFKTNCv7VjCbysVo7HxCY0bQe/bDP82v7SnLtb3aZogfva4HQIDAQABo4Gw -MIGtMB8GA1UdIwQYMBaAFLqXQxvNV+//052AnZXa39/eg4ndMAwGA1UdEwEB/wQC +MIGtMB8GA1UdIwQYMBaAFE5SwgEazlJ9xHhxAMh/e99woF8xMAwGA1UdEwEB/wQC MAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIF oDAuBgNVHREEJzAlghJzZWN1cmUuZXhhbXBsZS5jb22CCWxvY2FsaG9zdIcEfwAA ATAdBgNVHQ4EFgQUDPD4CaXRbu5QBb5e8y8odvTqW4IwDQYJKoZIhvcNAQELBQAD -ggIBAFUC3GDxayLiHZoq6uqENrmS/4KcoWXtvoJ0J7jusxAGw8DpIGAXTKjByXnL -L64dsOUKUNXigd0lLw9nWq6oAK4alIgbvMeAr5984SHcPjL2VOetkN8spn4nn/2h -WTe7MJqCyDJB/6FBokYcybkprsKgi8fV/MXciLwZCfylzh55ennDufeDXV2WyXVl -pAWnR8FV4+t6Ue6OVec9637yxWmhne4l8MVSZjkzDOMzNUM/+tzkiCSMW7VP0MpE -yHihO8p4+g/hKWdVJldCh6QnnNqz2E+iQGrBY3kO72UF+aaOfA77UzantHE2gkNi -ZuFPgTHwUpjTShQxLRkvt1+sRg2xm3oN5cVzEfFyYKAdyH8IhiNTBniKXI2XKuPj -+HuIWUu1t5MRVs30Iod9+DR6T6UU6IuAznlWIhMUkoPcpqTGQI8p+WYF+bp3addt -i5uBXVWrZ/BLv7E2n1Ly4ZbUt06EzBaOcoRv2Gl5KR/FuYBX03mr5/XY4THANAqP -C9HMtN7pZpDKNKBYC+l5u+V7JuFEiz7Tq62oZKvbUILs2GWBCb7pe8KoDJscjP/4 -Q2uIkOZaEi/58WIvqIATFvqt12OLpY1uavkU7+DwVwsDjIF3CT11iYsnKisdXEtj -AJkMIFHWe+nwBIKldfd7RYT5SBdWPii27sW9IUtAb817Z31p +ggIBAFSErJ+ir635pWkqB48XEYz2TvqHenld5W+wkWjO7BLq2vhTsNIonpbNV6zm +pujI6flQKHfgXqssrbf2bzfyZvIja5rgo314eOKmu/iyLr8j8bjYiTTS+s/UvDKA +k5j5rOQaOkfTMRSJSJiT/dcFPaL4Xbm1mSKNX9grIQfj7ekDUzNh9Ov3+ivALkDv +GY85oTwjS4rjh1/TPyb7JZ657VM5S39+LOnusD4Ay+ztRXaLAFlE2UphU00sJMuS +/uicPaBu3PVFnNCCZOGYWT4jZStOC4vw6x9hHGp0dGSmI0HaW+Un68+2M7B3792G +Hsd8EvEoqclQFNt3Sp0mE0C863duMQCOe5R8zVczBL8QzTn1fuIlQSpkZswj+bWb +VWODuzJGbnwQl2/qvi998uFUPyWL//8eyjuyePiluQIkruZrf3bD0I4sfYFcx2Hi +1QtTMl4zmItglXlPLv6LcT9e4scdjD4APDe7f277yI92BE28SmyszsULHZQzN9RJ +FU93yJ39sSpInglv6awys9kiZ5VsdiMC6slWVoGWApxb4VHxHUrzX1OnLKCCaY4h +tcZ6VlqJjeMrvuu4UOYWprvitZcNUNboWIzmkrZOjwEPY4EHCwSN5YbqNs4jU+sA +47RVtDsJHaLD5ymsCu+vPRcXddigk8jaIwMpIZ7DR06ZBN0G -----END CERTIFICATE----- diff --git a/fixtures/self-signed_docker.com-notary.crt b/fixtures/self-signed_docker.com-notary.crt index 37d966eef..25f2c2798 100644 --- a/fixtures/self-signed_docker.com-notary.crt +++ b/fixtures/self-signed_docker.com-notary.crt @@ -1,11 +1,11 @@ -----BEGIN CERTIFICATE----- -MIIBpDCCAUqgAwIBAgIJAKMU61pdVikDMAkGByqGSM49BAEwLTEPMA0GA1UEChMG -RG9ja2VyMRowGAYDVQQDExFkb2NrZXIuY29tL25vdGFyeTAeFw0xNzAyMTcwMDQz -MTdaFw0xOTAzMDkwMDQzMTdaMC0xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UEAxMR -ZG9ja2VyLmNvbS9ub3RhcnkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASg0Cmh -SHFK/18+NIUaBkgVcWJSCgc6KInu+mTMpSVuWHLXSvVF53oKNjWeA9W2Wk9FDVTz -/xEHbdAGSVDVn34Xo1QwUjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAT -BgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUC25FC+NAuXIFTB62LHa6GtL2 -ARcwCQYHKoZIzj0EAQNJADBGAiEA7Z4+BKZMbxtkT8WxZ1dSgj0s/zAQXaOyb7Wh -wo6nAtgCIQDdyb/8QinrwsaZLeCiCE8LdGfE/+L2qiI3KMlEU0ktEw== +MIIBozCCAUqgAwIBAgIJAPoMYEzgRhkvMAkGByqGSM49BAEwLTEPMA0GA1UEChMG +RG9ja2VyMRowGAYDVQQDExFkb2NrZXIuY29tL25vdGFyeTAeFw0xNzAyMjAxODE3 +MTFaFw0xOTAzMTIxODE3MTFaMC0xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UEAxMR +ZG9ja2VyLmNvbS9ub3RhcnkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQm/eal +Hsu+ay26ckTxZ7ZjV0L7pSDvE6fnMub4MNV4BdBKXzd7ZxKFPT720oN4l1NH2l3k +bCVXMoEptZLdAjVTo1QwUjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAT +BgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUv+NPAjQlwPkcOGX/aOb6Tj/+ +7wMwCQYHKoZIzj0EAQNIADBFAiBkvZ6ELX8BelmsC1ueG3kh+s7QeD+wkhUevE9r +RV0NXQIhAJpcvV4nlreK3irCLatSirqGxzq+XdrIwE8V1ZVQIHab -----END CERTIFICATE----- diff --git a/fixtures/self-signed_secure.example.com.crt b/fixtures/self-signed_secure.example.com.crt index a062e57b7..1e65265b0 100755 --- a/fixtures/self-signed_secure.example.com.crt +++ b/fixtures/self-signed_secure.example.com.crt @@ -1,12 +1,12 @@ -----BEGIN CERTIFICATE----- -MIIBvjCCAWSgAwIBAgIJAI4W1iagD9wJMAkGByqGSM49BAEwOjEbMBkGA1UEChMS +MIIBvTCCAWSgAwIBAgIJAP+Cqherm0u2MAkGByqGSM49BAEwOjEbMBkGA1UEChMS c2VjdXJlLmV4YW1wbGUuY29tMRswGQYDVQQDExJzZWN1cmUuZXhhbXBsZS5jb20w -HhcNMTcwMjE3MDA0MzE3WhcNMTkwMzA5MDA0MzE3WjA6MRswGQYDVQQKExJzZWN1 +HhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjA6MRswGQYDVQQKExJzZWN1 cmUuZXhhbXBsZS5jb20xGzAZBgNVBAMTEnNlY3VyZS5leGFtcGxlLmNvbTBZMBMG -ByqGSM49AgEGCCqGSM49AwEHA0IABKdTvQvZJoZAQ+9qluOMtwjvxLvg9rVJMMhd -0oSjFWD7/mCqxCq0Nvy6jcHLaOflu4/+xPWoXSkHGDJVbc3tXDqjVDBSMAwGA1Ud +ByqGSM49AgEGCCqGSM49AwEHA0IABMzSsSlxwt8J6PZIW1cmcmsnS96tEXggayGx +QZR8bGTcslZ6clyG4vt4mExRcBUsvnR4eWRseKHnNRPKFz/WmM2jVDBSMAwGA1Ud EwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0G -A1UdDgQWBBSB6K6DihEBUuioQ00YAG55gST2ITAJBgcqhkjOPQQBA0kAMEYCIQCG -+Sk2UhufFp19BxuKO6mlXHz4fGblS6WxSsISesZ3aQIhAMZMXg9CkfNwFUXOxIwW -fspZc4rX0tz9Rg9kxts+YZk1 +A1UdDgQWBBTeojZoNb/5aFKmw7yUnurWHny2szAJBgcqhkjOPQQBA0gAMEUCIQDi +ZXq9PaRvRON32Z8xQD8WgnmxszeNwuK+MaiOHih2MgIgUlemw6UL8yv0ecNsYc/A +KeyHdoYj+rFIudRu46lkAgU= -----END CERTIFICATE----- diff --git a/utils/grpc.go b/utils/grpc.go new file mode 100644 index 000000000..397a520dc --- /dev/null +++ b/utils/grpc.go @@ -0,0 +1,81 @@ +package utils + +import ( + "crypto/tls" + "fmt" + "github.com/Sirupsen/logrus" + "github.com/docker/go-connections/tlsconfig" + "github.com/spf13/viper" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "strings" +) + +// sets up TLS for the GRPC connection to notary-signer +func grpcTLS(configuration *viper.Viper, prefix string) (*tls.Config, error) { + rootCA := GetPathRelativeToConfig( + configuration, + strings.Join([]string{prefix, "tls_ca_file"}, "."), + ) + clientCert := GetPathRelativeToConfig( + configuration, + strings.Join([]string{prefix, "tls_client_cert"}, "."), + ) + clientKey := GetPathRelativeToConfig( + configuration, + strings.Join([]string{prefix, "tls_client_key"}, "."), + ) + + if clientCert == "" && clientKey != "" || clientCert != "" && clientKey == "" { + return nil, fmt.Errorf("either pass both client key and cert, or neither") + } + + tlsConfig, err := tlsconfig.Client(tlsconfig.Options{ + CAFile: rootCA, + CertFile: clientCert, + KeyFile: clientKey, + }) + if err != nil { + return nil, fmt.Errorf( + "Unable to configure TLS to the client API gRPC service: %s", err.Error()) + } + + return tlsConfig, nil +} + +func GetGRPCClient(vc *viper.Viper, prefix string) (*grpc.ClientConn, error) { + var ( + dialOpts = []grpc.DialOption{ + grpc.WithBlock(), + } + tlsConfig *tls.Config + err error + ) + addr := vc.GetString( + strings.Join( + []string{prefix, "addr"}, + ".", + ), + ) + + if vc.GetBool( + strings.Join( + []string{prefix, "insecure"}, + ".", + ), + ) { + logrus.Warn("setting insecure connection") + dialOpts = append(dialOpts, grpc.WithInsecure()) + } else { + tlsConfig, err = grpcTLS(vc, prefix) + if err != nil { + logrus.Warn(err) + dialOpts = append(dialOpts, grpc.WithInsecure()) + } else { + creds := credentials.NewTLS(tlsConfig) + dialOpts = append(dialOpts, grpc.WithTransportCredentials(creds)) + } + } + + return grpc.Dial(addr, dialOpts...) +} From f2f3118ccd52d998c0ebaf546e3a3bfe1394f8c4 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Sun, 5 Mar 2017 22:08:17 -0800 Subject: [PATCH 05/62] grpc interceptors are working, need to get proper token auth in place Signed-off-by: David Lawrence (github: endophage) --- client_api/api/api.proto | 2 +- client_api/api/server.go | 10 ++- cmd/clientapi/main.go | 22 ++++--- cmd/clientapi/setup/config.go | 27 ++++---- utils/grpcauth/auth.go | 118 ++++++++++++++++++++++++++++++++++ utils/grpcauth/auth_test.go | 36 +++++++++++ 6 files changed, 188 insertions(+), 27 deletions(-) create mode 100644 utils/grpcauth/auth.go create mode 100644 utils/grpcauth/auth_test.go diff --git a/client_api/api/api.proto b/client_api/api/api.proto index fe31e648f..36d88c90f 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -1,4 +1,4 @@ -syntax = "proto3"; + syntax = "proto3"; package api; diff --git a/client_api/api/server.go b/client_api/api/server.go index 480f21e11..11ddfd95f 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -20,8 +20,7 @@ import ( // NewServer creates a new instance of a Client API server with a configured // upstream Notary Server. -func NewServer(upstream string, upstreamCAPath string, serverOpts []grpc.ServerOption) (*grpc.Server, error) { - grpcSrv := grpc.NewServer(serverOpts...) +func NewServer(upstream string, upstreamCAPath string, grpcSrv *grpc.Server) (*grpc.Server, error) { srv := &Server{ upstream: upstream, upstreamCAPath: upstreamCAPath, @@ -151,3 +150,10 @@ func (srv *Server) initRepo(gun data.GUN) (*client.NotaryRepository, error) { func retriever(keyName, alias string, createNew bool, attempts int) (string, bool, error) { return "password", false, nil } + +func DefaultPermissions() map[string][]string { + return map[string][]string{ + "/api.Notary/AddTarget": {"push", "pull"}, + "/api.Notary/RemoveTarget": {"push", "pull"}, + } +} \ No newline at end of file diff --git a/cmd/clientapi/main.go b/cmd/clientapi/main.go index 1a0bfcf8e..f34d654b4 100644 --- a/cmd/clientapi/main.go +++ b/cmd/clientapi/main.go @@ -40,20 +40,26 @@ func main() { logrus.Fatal("unable to set up TLS: %s", err.Error()) } - serverConfig := setup.Config{GRPCAddr: grpcAddr, TLSConfig: tlsConfig} - upstreamAddr := vc.GetString("upstream.addr") upstreamCAPath := utils.GetPathRelativeToConfig(vc, "upstream.tls_ca_file") - lis, err := net.Listen("tcp", serverConfig.GRPCAddr) + creds := credentials.NewTLS(tlsConfig) + auth, err := setup.Authorization(vc) if err != nil { - logrus.Fatal("grpc server failed to listen on %s: %v", - serverConfig.GRPCAddr, err) + logrus.Fatal("unable to configure authorization: %s", err.Error()) + } + + opts := []grpc.ServerOption{ + grpc.Creds(creds), + grpc.UnaryInterceptor(auth), } - creds := credentials.NewTLS(serverConfig.TLSConfig) - opts := []grpc.ServerOption{grpc.Creds(creds)} - s, err := api.NewServer(upstreamAddr, upstreamCAPath, opts) + srv, lis, err := setup.NewGRPCServer(grpcAddr, opts) + if err != nil { + logrus.Fatal("grpc server failed to start on %s: %v", + grpcAddr, err) + } + s, err := api.NewServer(upstreamAddr, upstreamCAPath, srv) if err != nil { logrus.Fatal(err) } diff --git a/cmd/clientapi/setup/config.go b/cmd/clientapi/setup/config.go index 08029dccd..3755c18c7 100644 --- a/cmd/clientapi/setup/config.go +++ b/cmd/clientapi/setup/config.go @@ -9,16 +9,11 @@ import ( "net" "google.golang.org/grpc" - "google.golang.org/grpc/credentials" ghealth "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" + "github.com/docker/notary/utils/grpcauth" ) -type Config struct { - GRPCAddr string - TLSConfig *tls.Config -} - func ViperConfig(path string) (*viper.Viper, error) { vc := viper.New() vc.SetConfigFile(path) @@ -30,19 +25,15 @@ func ViperConfig(path string) (*viper.Viper, error) { return vc, nil } -func SetupGRPCServer(serverConfig Config) (*grpc.Server, net.Listener, error) { - +func NewGRPCServer(addr string, opts []grpc.ServerOption) (*grpc.Server, net.Listener, error) { //RPC server setup hs := ghealth.NewServer() - lis, err := net.Listen("tcp", serverConfig.GRPCAddr) + lis, err := net.Listen("tcp", addr) if err != nil { - return nil, nil, fmt.Errorf("grpc server failed to listen on %s: %v", - serverConfig.GRPCAddr, err) + return nil, nil, fmt.Errorf("grpc server failed to listen on %s: %v", addr, err) } - creds := credentials.NewTLS(serverConfig.TLSConfig) - opts := []grpc.ServerOption{grpc.Creds(creds)} grpcServer := grpc.NewServer(opts...) healthpb.RegisterHealthServer(grpcServer, hs) @@ -50,16 +41,20 @@ func SetupGRPCServer(serverConfig Config) (*grpc.Server, net.Listener, error) { return grpcServer, lis, nil } -func GetAddrAndTLSConfig(configuration *viper.Viper) (string, *tls.Config, error) { - tlsConfig, err := utils.ParseServerTLS(configuration, true) +func GetAddrAndTLSConfig(vc *viper.Viper) (string, *tls.Config, error) { + tlsConfig, err := utils.ParseServerTLS(vc, true) if err != nil { return "", nil, fmt.Errorf("unable to set up TLS: %s", err.Error()) } - grpcAddr := configuration.GetString("server.grpc_addr") + grpcAddr := vc.GetString("server.grpc_addr") if grpcAddr == "" { return "", nil, fmt.Errorf("grpc listen address required for server") } return grpcAddr, tlsConfig, nil } + +func Authorization(vc *viper.Viper) (grpc.UnaryServerInterceptor, error) { + return grpcauth.NewServerAuthorizer("", nil) +} diff --git a/utils/grpcauth/auth.go b/utils/grpcauth/auth.go new file mode 100644 index 000000000..536f0d018 --- /dev/null +++ b/utils/grpcauth/auth.go @@ -0,0 +1,118 @@ +package grpcauth + +import ( + "fmt" + + "golang.org/x/net/context" + + "github.com/docker/distribution/registry/auth" + google_protobuf "github.com/golang/protobuf/ptypes/empty" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "github.com/Sirupsen/logrus" +) + +type guner interface { + GetGun() string +} + +// ServerAuthorizer performs server checks for the correct authorization tokens +type ServerAuthorizer struct { + permissions map[string][]string + realm string + service string +} + +// NewServerAuthorizer instantiates a ServerAuthorizer and returns the Interceptor +// attached to it. +func NewServerAuthorizer(tokenCAPath string, permissions map[string][]string) (grpc.UnaryServerInterceptor, error) { + s := ServerAuthorizer{ + permissions: permissions, + } + return s.Interceptor, nil +} + +// Interceptor checks the provided tokens and either returns an error that includes the required +// token scope and actions, or allows the request to proceed +// TODO: are the error responses the ones we want to use +func (s ServerAuthorizer) Interceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + gnr, ok := req.(guner) + if !ok { + if !ok { + return &google_protobuf.Empty{}, grpc.Errorf( + codes.Unauthenticated, + "no authorization credentials provided", + ) + } + } + md, ok := metadata.FromContext(ctx) + if !ok || !s.authorized(md) { + md, ok := s.buildAuthChallenge(gnr.GetGun(), info.FullMethod) + if !ok { + return &google_protobuf.Empty{}, grpc.Errorf( + codes.Unauthenticated, + "no authorization credentials provided", + ) + } + grpc.SendHeader(ctx, md) + return &google_protobuf.Empty{}, grpc.Errorf( + codes.Unauthenticated, + "no authorization credentials provided", + ) + } + return handler(ctx, req) +} + +func (s ServerAuthorizer) buildAuthChallenge(gun, method string) (metadata.MD, bool) { + str := fmt.Sprintf("Bearer realm=%q,service=%q", s.realm, s.service) + + perms, ok := s.permissions[method] + if !ok { + return nil, ok + } + requiredAccess := make([]auth.Access, 0, len(perms)) + for _, perm := range perms { + requiredAccess = append(requiredAccess, auth.Access{ + Resource: auth.Resource{ + Type: "repository", + Name: gun, + }, + Action: perm, + }) + } + + str = fmt.Sprintf("%s,scope=%q", str, ) + return metadata.MD{ + "WWW-Authenticate": []string{str}, + }, true +} + +func (s ServerAuthorizer) authorized(md metadata.MD) bool { + _, ok := md["Authorization"] + return ok +} + +// ClientAuthorizer deals with satisfying tokens required by the server. If it receives an +// error response, it will attempt to retrieve a token the server will accept +type ClientAuthorizer struct{} + +func NewClientAuthorizer() grpc.UnaryClientInterceptor { + c := ClientAuthorizer{} + return c.Interceptor +} + +// Interceptor attempts to retrieve and attach the appropriate tokens for the request +// being made +func (c *ClientAuthorizer) Interceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + err := invoker(ctx, method, req, reply, cc, opts...) + if err != nil { + logrus.Error(err) + //return err + } + + md := metadata.New(map[string]string{"Authorization": "foo"}) + ctx = metadata.NewContext(ctx, md) + err = invoker(ctx, method, req, reply, cc, opts...) + return err +} diff --git a/utils/grpcauth/auth_test.go b/utils/grpcauth/auth_test.go new file mode 100644 index 000000000..326fd1d8f --- /dev/null +++ b/utils/grpcauth/auth_test.go @@ -0,0 +1,36 @@ +package grpcauth + +import ( + "testing" + "google.golang.org/grpc" + "net" + "github.com/stretchr/testify/require" + "github.com/docker/notary/client_api/api" + "github.com/docker/notary/client" +) + +func TestServerAuthorizer(t *testing.T) { + auth, err := NewServerAuthorizer("", nil) + require.NoError(t, err) + srv := grpc.NewServer( + grpc.UnaryInterceptor(auth), + ) + lis, err := net.Listen("tcp", "localhost:6789") + require.NoError(t, err) + + api.NewServer("", "", srv) + go srv.Serve(lis) + + conn, err := grpc.Dial( + "localhost:6789", + grpc.WithInsecure(), + grpc.WithUnaryInterceptor(NewClientAuthorizer()), + ) + require.NoError(t, err) + c := api.NewClient(conn, "testRepo") + err = c.AddTarget( + &client.Target{}, + "targets", + ) + require.NoError(t, err) +} \ No newline at end of file From 7760a7797e8fdedeab6994c4d2cd635e6b5bf150 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 8 Mar 2017 13:14:22 -0800 Subject: [PATCH 06/62] regenerated certs for all the services and server side of tokens should be working Signed-off-by: David Lawrence (github: endophage) --- cmd/clientapi/config.toml | 11 -- cmd/escrow/config.toml | 9 -- cmd/notary/root-ca.crt | 52 ++++----- fixtures/cert_config.cnf | 57 ++++++++++ fixtures/clientapi-server-config.toml | 5 + fixtures/clientapi-server.crt | 92 +++++++-------- fixtures/escrow-config-local.toml | 9 ++ fixtures/intermediate-ca.crt | 58 +++++----- fixtures/notary-escrow.crt | 64 +++-------- fixtures/notary-server.crt | 120 +++++++++++++------- fixtures/notary-signer.crt | 86 +++++++------- fixtures/regenerateTestingCerts.sh | 120 +++++++------------- fixtures/root-ca.crt | 52 ++++----- fixtures/secure.example.com.crt | 28 ++--- fixtures/self-signed_docker.com-notary.crt | 18 +-- fixtures/self-signed_secure.example.com.crt | 14 +-- utils/grpcauth/auth.go | 36 ++++-- 17 files changed, 430 insertions(+), 401 deletions(-) delete mode 100644 cmd/clientapi/config.toml delete mode 100644 cmd/escrow/config.toml create mode 100644 fixtures/cert_config.cnf create mode 100644 fixtures/escrow-config-local.toml diff --git a/cmd/clientapi/config.toml b/cmd/clientapi/config.toml deleted file mode 100644 index 6ac8cb023..000000000 --- a/cmd/clientapi/config.toml +++ /dev/null @@ -1,11 +0,0 @@ -[server] -grpc_addr = ":4449" -tls_cert_file = "/fixtures/clientapi-server.crt" -tls_key_file = "/fixtures/clientapi-server.key" - -[logging] -level = "debug" - -[upstream] -addr = "https://notaryserver:4443" - diff --git a/cmd/escrow/config.toml b/cmd/escrow/config.toml deleted file mode 100644 index 3b13ea068..000000000 --- a/cmd/escrow/config.toml +++ /dev/null @@ -1,9 +0,0 @@ -[storage] -backend = "file" -path = "/tmp/keys" - -[server] -addr = "0.0.0.0:4450" -tls_key_file = "../../fixtures/notary-escrow.key" -tls_cert_file = "../../fixtures/notary-escrow.crt" -client_ca_file = "" diff --git a/cmd/notary/root-ca.crt b/cmd/notary/root-ca.crt index 2f5b58bbe..8210c3480 100644 --- a/cmd/notary/root-ca.crt +++ b/cmd/notary/root-ca.crt @@ -1,32 +1,32 @@ -----BEGIN CERTIFICATE----- -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 -rba7O3YGSuScQakjt9mw2Q5ISwImkRHF3qE= +BBS/zToT4cEMf7VMKx1ODSePll28ADANBgkqhkiG9w0BAQsFAAOCAgEAcKJSgy6t +MqjEG+r008jzic7lNciX+sHp6j6kfLau9d0oYjBXQDfeBXNlqdGSvZeT157bhtrT +V64ouh5os9l+t67nbYrg1e2G/XdtA7rK0DGFW+6+M3f2KJzDtqaEBRnt+b/o3pG8 +MnTGWKt7Dqok9wmP+QMo4rAXM2dgB40CNhJae8EQGlmNHKM+O13CZfaGWRzw0aZr +ivDYNYblxKc6hTSYU01ZlYaHSF/D/kzeObbtPurWsg2wtcmXo8s4kbVdJcMXK3+R +oHzYhj7G67Ol0bVHdJXzj5xVYqVz5g473U5cmKXCNS7EtSCgO/kU7Zt/hrKY81rs +/Auv4zZ3gooaTcpDSvhHh0ZkXDOrUS3JtkSkUcU4OYV+Z7p/+CU7pHcJXUwHBLoC +tTl3SBTjrOzFvH54qf8TZ7cSVSmM3jSzS54a8K9+2eqFRW3/zwxzKZRPJimwuMUt +3YcHPH/Tk+yARvvlPiBwZqYlnLadi/Kew5Enur3eqCWeH5UcYUdC6lTA4bNHnywZ +rjQqIvQuA2MnkJDOU5DC23svXjsxIKDqIbvkh5CS/2veJ0y1ALfMNRmkmXwjP2Y2 +7/bGHP6HWYaxOCjfsOomcGwuc1DCDCu4jBFtLNXllqrsCp3dGIsEMGNbERhPfUvJ +mSU+sXjNtnlrP4jBgWMl074YdvqQ4Tj6xeg= -----END CERTIFICATE----- diff --git a/fixtures/cert_config.cnf b/fixtures/cert_config.cnf new file mode 100644 index 000000000..94096387f --- /dev/null +++ b/fixtures/cert_config.cnf @@ -0,0 +1,57 @@ +[clientapi_server] +authorityKeyIdentifier=keyid,issuer +basicConstraints = critical,CA:FALSE +extendedKeyUsage=serverAuth,clientAuth +keyUsage = critical, digitalSignature, keyEncipherment +subjectAltName = DNS:clientapi-server, DNS:localhost, IP:127.0.0.1 +subjectKeyIdentifier=hash + +[selfsigned] +basicConstraints = critical,CA:FALSE +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage=codeSigning +subjectKeyIdentifier=hash + +[secure.example.com] +authorityKeyIdentifier=keyid,issuer +basicConstraints = critical,CA:FALSE +extendedKeyUsage=serverAuth,clientAuth +keyUsage = critical, digitalSignature, keyEncipherment +subjectAltName = DNS:secure.example.com, DNS:localhost, IP:127.0.0.1 +subjectKeyIdentifier=hash + +[notary_signer] +authorityKeyIdentifier=keyid,issuer +basicConstraints = critical,CA:FALSE +extendedKeyUsage=serverAuth,clientAuth +keyUsage = critical, digitalSignature, keyEncipherment +subjectAltName = DNS:notary-signer, DNS:notarysigner, DNS:localhost, IP:127.0.0.1 +subjectKeyIdentifier=hash + +[notary_escrow] +authorityKeyIdentifier=keyid,issuer +basicConstraints = critical,CA:FALSE +extendedKeyUsage=serverAuth,clientAuth +keyUsage = critical, digitalSignature, keyEncipherment +subjectAltName = DNS:notary-escrow, DNS:notaryescrow, DNS:localhost, IP:127.0.0.1 +subjectKeyIdentifier=hash + +[notary_server] +authorityKeyIdentifier=keyid,issuer +basicConstraints = critical,CA:FALSE +extendedKeyUsage=serverAuth,clientAuth +keyUsage = critical, digitalSignature, keyEncipherment +subjectAltName = DNS:notary-server, DNS:notaryserver, DNS:localhost, IP:127.0.0.1 +subjectKeyIdentifier=hash + +[intermediate_ca] +authorityKeyIdentifier=keyid,issuer +basicConstraints = critical,CA:TRUE,pathlen:0 +extendedKeyUsage=serverAuth,clientAuth +keyUsage = critical, nonRepudiation, cRLSign, keyCertSign +subjectKeyIdentifier=hash + +[root_ca] +basicConstraints = critical,CA:TRUE,pathlen:1 +keyUsage = critical, nonRepudiation, cRLSign, keyCertSign +subjectKeyIdentifier=hash diff --git a/fixtures/clientapi-server-config.toml b/fixtures/clientapi-server-config.toml index c8c78c263..87948555c 100644 --- a/fixtures/clientapi-server-config.toml +++ b/fixtures/clientapi-server-config.toml @@ -9,3 +9,8 @@ level = "debug" [upstream] addr = "https://notaryserver:4443" tls_ca_file = "./root-ca.crt" + +[key_storage] +method = "remote" +addr = "https://escrow:4450" +tls_ca_file = "./root-ca.crt" \ No newline at end of file diff --git a/fixtures/clientapi-server.crt b/fixtures/clientapi-server.crt index 212144d69..faba655f3 100644 --- a/fixtures/clientapi-server.crt +++ b/fixtures/clientapi-server.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFCjCCAvKgAwIBAgIJAM3wbUCyULKSMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIE/DCCAuSgAwIBAgIJAMzwtUOFSlr2MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjBeMQswCQYDVQQG +bmcgQ0EwHhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjBeMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEZMBcGA1UEAxMQY2xpZW50YXBpLXNlcnZlcjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBALlrIUZNfqnIkEpcs2ItUMgMLtn9zP2fd77t @@ -10,54 +10,54 @@ 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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIF1TCCA72gAwIBAgIJAOPfcGEXu4wMMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV +MIIF1TCCA72gAwIBAgIJAMELzHI4DbdfMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G -A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAy -MjAxODE3MTFaFw0yNzAyMTgxODE3MTFaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI +A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAz +MDExOTM2MjhaFw0yNzAyMjcxOTM2MjhaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI EwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0GA1UEChMGRG9ja2VyMScw JQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3RpbmcgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQDiHv1wniM1L4dpAHMYDj8PxrHbjeBtim/T -KU57m1PXqA2Uby7nGHiLE4c1ie8mVYkHXz0nQ0VjcuTUsIUa7xQj3yJ2z5ATnsgq -urE28xTRmHZmthbyddIsfmOVGrZPpAmJfJ4/LX3KJJZjqqUEPO1mkNFsG/fLkVOm -AEhzZO/g9txqbB/s2KYtMy4QxsRaepfcECGotnt+vYdk7+rJvli5PeMuKoWBLzjz -gUTzvea7VId/0ff4DO4XG9u8KjhYMHSINUsIcT8amZbl5CjQAsCRyU6lDfOl2hH3 -F1erbTFMEFtRSFh7CSpjKFCvJkyqcRAW8zIwhX+Yl1MMnEItxnBkc+rbe29oGZoD -uGjHAhzCV46IfgFQxmRrMQydUp4BRvAHTlhnXPnDjSuczYzt66p71C/UPzEH7tUe -ubHbqxVv1y6BGpI7cEALQ2o3FJ/3T8YaLbXKSYQ/uO9GpIMTgTWLwhoqwq+lgpxu -ApPJ5EY3LrLChvIZViHkxrCwjsGX31q/l17s3R9rJcGEzEIkVPxHJrvi07KelUYO -xmv1u1o/5FGfWafs0wcj0whswnU9w7LI7+o47t5ZCvNYseP7JPIMti+9KgBCUyEC -uB+YwHFcXwRDEA3GaCYePetTq+gg93iE7VoiwVo8JI8AxjwfGH17o09PjmeyNOHU -dbPcJRBJQwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFJdjQCkJsHhLo1GM3d7OxJ/R -YVTIMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG -AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUTlLCARrOUn3EeHEAyH97 -33CgXzEwDQYJKoZIhvcNAQELBQADggIBAJFoIVlB6PFPz+9ukOcH0hlrl7VPKbb+ -FO8tGizASgDsM32oeSqAaasKQw9pWhtPia/u7rIYI+mnqUi9WlgUYzy1yZmGkcWj -2Us7i9Lrq4VSMblhCOFYVJZe6SkF1TtgRQrP7NLxFLQ+oyl85inEpbcNRI82t+c3 -KIxbq8Fb9qHGAGPr9v1W+KoVo+NSrL/38FfGWAygAfTwUJJf1SNJjxUuklOsl3RS -qdkMhjmHaJF6OJm2Y0Y5aKoEGqP0vYXyTkmbgtCeFnDyc16KQV+saQ/UAFTpcyE2 -kWTri3M1uNL3tEjNBZaEHifJlv6jVA+AGK9dBfyysMTLtZXbmGxdlPAfoIkrxF3k -VxhY8kTMqSim5TRk0MzV5DZIUT5rY4yITeRicass9sAkScSKIlqEplqk/U7ZqbVY -c1q3H9zafhxjZ5rrpB8amo6brWRXzenJQ/x4wo1n/Zgf7fL3vQStxA3AVTWD3TmA -FeRlb/el+7nHziajPYmA6uxpSyRjNdyXqxP45u4nkGt7xPIvVcLTULPf2Y2NOVr0 -F0glAC5OLIrejaDGTFlMTupU9CjgkNbEiqJLnaByK3LWOu26GynVcF3eogRYYKjs -J0ETQvK+/GhRttp1QhiPVkBJrQF7fSIZAz919gD21cQAZSgNg13XTXhNNRuIw0eT -Pl9leAX0LJ7l +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC5gi0twJAtlvL9XwzeXpu6zAUGUkPIU3Wp +GA3zYqqFcYKBxPuQ8AfexGCRJZ6MDteQMUKbtQFbbPj3x7OcXx0OAwlirvZAajec +9o7jmmhGJ0jZWFlMtTs9ZvqR5nkRESWdVcegzX+/zVVDgbNkHRd0iQCPvcfBZskg +G6t1LksQwKunhssaaDSk1vbS/QaxCE5/ywBqMocvxarkg+sklPC+/iBUN8/KUa2j +oqaOkcSUiKsqXskAyYLDTdqGpVee5nmg1WMUUpfmuBXYSxuxEmqu+9pjzFfBQDu9 +Fn+LY0UviccascCYT6h/RNU/hVqaLc9NnMsF388HXXo7T7OChzWkr+7qJvAxUctn +y94eUBzLkS4LmYlUvpE6YYLDSab8AUNJYLHFXIbn93A0wukfboCqucERiMz1qtSg +ZYyx5Vy8RcmVC8bB5LfCFoZLTZ+WT6+NyumVbCFebHARMGyaJPlUlcaNwHWlwMlv +fUJQM454alIfLartvdXVpAhibCB7HLk3GDCs5jec9pKtwpQqXVfv07/FeRl67QfR +EQYhXxs2iUK4L1IJZRoroVg2NdG9+z5kF7SxZHmZKagQIUQYcnSXT63QaCC6KsmH +SjMxEH81OSYbJoV3Jrj4sgp4uKG7tkEgYnmjvFpyvay6ymZioff6+QPZi02RKjag +jeut/4XjIQIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFL/NOhPhwQx/tUwrHU4NJ4+W +XbwAMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUvd13yFS117Joo/nPZOTz +GzVqFRIwDQYJKoZIhvcNAQELBQADggIBAE0jLDhm8Cn6N+TvGqbdtOKwCo5JPY1Z +eUxz1O5lDbcLAOG8AGPCRdT+TEdnsm9fG8nnv0d7X5GciSIqd5zv0Zi5oSItUUwm +qjAgbJMAFMTQTA0KbzNf0QaWvfeUPSIHTr8S19QctoDYXtvO5afkuT1V30uYY9u7 +IJHJHAM/IaWDaQcJw1f4TUPb5wFmvVof6vl19KcU4NtO3CLJpcL4w4OzSEWWepJ7 +3kz4PEibhHnY3zDotbVXSK5R6RceOwF9Jzw0IzTrfL5WGKcm4vq369/BfHSWZ5IP +RazsSK/aFfQI1C1uJPogPmpP2bMRWEWp/RrWkonMQLM2etRRi6Nq4G+H5SSIIjzB +vr/FzqsFQS0H9JsT6B7Br+3OCjjeLk0G17okrVihVQ8N95wxGMWRbuUVAWdrJsAQ +Ep3leFQdlR0tJnw4Jh8vPT8BwzQQXR4DqCNFxWFZnbDUr5eSpfuaoC9JLUP7vm9t +231i3h8r6cZontwXcAuVZsMnwqwtrYNb/L9yb0Uz+kR1SnBfrY5Yd9sV6gWbhDol +RcB4Cv2EHTOrQCz06VsA91lFprKP+aqA5qA63tHlmVe5jTfJDJsIQVJS31bT6DES +877VDtKsXNWZ/gq91q3dAXLopDtW9OvO13E0tBhUgOSC8Sc3r4N4Gv8SObAFuawQ +YKGxswAOLRmF -----END CERTIFICATE----- diff --git a/fixtures/escrow-config-local.toml b/fixtures/escrow-config-local.toml new file mode 100644 index 000000000..e03e19a09 --- /dev/null +++ b/fixtures/escrow-config-local.toml @@ -0,0 +1,9 @@ +[storage] +backend = "file" +path = "/tmp/keys" + +[server] +addr = "0.0.0.0:4450" +tls_key_file = "notary-escrow.key" +tls_cert_file = "notary-escrow.crt" +client_ca_file = "" diff --git a/fixtures/intermediate-ca.crt b/fixtures/intermediate-ca.crt index aab910827..c6263aff3 100644 --- a/fixtures/intermediate-ca.crt +++ b/fixtures/intermediate-ca.crt @@ -1,34 +1,34 @@ -----BEGIN CERTIFICATE----- -MIIF1TCCA72gAwIBAgIJAOPfcGEXu4wMMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV +MIIF1TCCA72gAwIBAgIJAMELzHI4DbdfMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G -A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAy -MjAxODE3MTFaFw0yNzAyMTgxODE3MTFaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI +A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAz +MDExOTM2MjhaFw0yNzAyMjcxOTM2MjhaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI EwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0GA1UEChMGRG9ja2VyMScw JQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3RpbmcgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQDiHv1wniM1L4dpAHMYDj8PxrHbjeBtim/T -KU57m1PXqA2Uby7nGHiLE4c1ie8mVYkHXz0nQ0VjcuTUsIUa7xQj3yJ2z5ATnsgq -urE28xTRmHZmthbyddIsfmOVGrZPpAmJfJ4/LX3KJJZjqqUEPO1mkNFsG/fLkVOm -AEhzZO/g9txqbB/s2KYtMy4QxsRaepfcECGotnt+vYdk7+rJvli5PeMuKoWBLzjz -gUTzvea7VId/0ff4DO4XG9u8KjhYMHSINUsIcT8amZbl5CjQAsCRyU6lDfOl2hH3 -F1erbTFMEFtRSFh7CSpjKFCvJkyqcRAW8zIwhX+Yl1MMnEItxnBkc+rbe29oGZoD -uGjHAhzCV46IfgFQxmRrMQydUp4BRvAHTlhnXPnDjSuczYzt66p71C/UPzEH7tUe -ubHbqxVv1y6BGpI7cEALQ2o3FJ/3T8YaLbXKSYQ/uO9GpIMTgTWLwhoqwq+lgpxu -ApPJ5EY3LrLChvIZViHkxrCwjsGX31q/l17s3R9rJcGEzEIkVPxHJrvi07KelUYO -xmv1u1o/5FGfWafs0wcj0whswnU9w7LI7+o47t5ZCvNYseP7JPIMti+9KgBCUyEC -uB+YwHFcXwRDEA3GaCYePetTq+gg93iE7VoiwVo8JI8AxjwfGH17o09PjmeyNOHU -dbPcJRBJQwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFJdjQCkJsHhLo1GM3d7OxJ/R -YVTIMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG -AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUTlLCARrOUn3EeHEAyH97 -33CgXzEwDQYJKoZIhvcNAQELBQADggIBAJFoIVlB6PFPz+9ukOcH0hlrl7VPKbb+ -FO8tGizASgDsM32oeSqAaasKQw9pWhtPia/u7rIYI+mnqUi9WlgUYzy1yZmGkcWj -2Us7i9Lrq4VSMblhCOFYVJZe6SkF1TtgRQrP7NLxFLQ+oyl85inEpbcNRI82t+c3 -KIxbq8Fb9qHGAGPr9v1W+KoVo+NSrL/38FfGWAygAfTwUJJf1SNJjxUuklOsl3RS -qdkMhjmHaJF6OJm2Y0Y5aKoEGqP0vYXyTkmbgtCeFnDyc16KQV+saQ/UAFTpcyE2 -kWTri3M1uNL3tEjNBZaEHifJlv6jVA+AGK9dBfyysMTLtZXbmGxdlPAfoIkrxF3k -VxhY8kTMqSim5TRk0MzV5DZIUT5rY4yITeRicass9sAkScSKIlqEplqk/U7ZqbVY -c1q3H9zafhxjZ5rrpB8amo6brWRXzenJQ/x4wo1n/Zgf7fL3vQStxA3AVTWD3TmA -FeRlb/el+7nHziajPYmA6uxpSyRjNdyXqxP45u4nkGt7xPIvVcLTULPf2Y2NOVr0 -F0glAC5OLIrejaDGTFlMTupU9CjgkNbEiqJLnaByK3LWOu26GynVcF3eogRYYKjs -J0ETQvK+/GhRttp1QhiPVkBJrQF7fSIZAz919gD21cQAZSgNg13XTXhNNRuIw0eT -Pl9leAX0LJ7l +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC5gi0twJAtlvL9XwzeXpu6zAUGUkPIU3Wp +GA3zYqqFcYKBxPuQ8AfexGCRJZ6MDteQMUKbtQFbbPj3x7OcXx0OAwlirvZAajec +9o7jmmhGJ0jZWFlMtTs9ZvqR5nkRESWdVcegzX+/zVVDgbNkHRd0iQCPvcfBZskg +G6t1LksQwKunhssaaDSk1vbS/QaxCE5/ywBqMocvxarkg+sklPC+/iBUN8/KUa2j +oqaOkcSUiKsqXskAyYLDTdqGpVee5nmg1WMUUpfmuBXYSxuxEmqu+9pjzFfBQDu9 +Fn+LY0UviccascCYT6h/RNU/hVqaLc9NnMsF388HXXo7T7OChzWkr+7qJvAxUctn +y94eUBzLkS4LmYlUvpE6YYLDSab8AUNJYLHFXIbn93A0wukfboCqucERiMz1qtSg +ZYyx5Vy8RcmVC8bB5LfCFoZLTZ+WT6+NyumVbCFebHARMGyaJPlUlcaNwHWlwMlv +fUJQM454alIfLartvdXVpAhibCB7HLk3GDCs5jec9pKtwpQqXVfv07/FeRl67QfR +EQYhXxs2iUK4L1IJZRoroVg2NdG9+z5kF7SxZHmZKagQIUQYcnSXT63QaCC6KsmH +SjMxEH81OSYbJoV3Jrj4sgp4uKG7tkEgYnmjvFpyvay6ymZioff6+QPZi02RKjag +jeut/4XjIQIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFL/NOhPhwQx/tUwrHU4NJ4+W +XbwAMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUvd13yFS117Joo/nPZOTz +GzVqFRIwDQYJKoZIhvcNAQELBQADggIBAE0jLDhm8Cn6N+TvGqbdtOKwCo5JPY1Z +eUxz1O5lDbcLAOG8AGPCRdT+TEdnsm9fG8nnv0d7X5GciSIqd5zv0Zi5oSItUUwm +qjAgbJMAFMTQTA0KbzNf0QaWvfeUPSIHTr8S19QctoDYXtvO5afkuT1V30uYY9u7 +IJHJHAM/IaWDaQcJw1f4TUPb5wFmvVof6vl19KcU4NtO3CLJpcL4w4OzSEWWepJ7 +3kz4PEibhHnY3zDotbVXSK5R6RceOwF9Jzw0IzTrfL5WGKcm4vq369/BfHSWZ5IP +RazsSK/aFfQI1C1uJPogPmpP2bMRWEWp/RrWkonMQLM2etRRi6Nq4G+H5SSIIjzB +vr/FzqsFQS0H9JsT6B7Br+3OCjjeLk0G17okrVihVQ8N95wxGMWRbuUVAWdrJsAQ +Ep3leFQdlR0tJnw4Jh8vPT8BwzQQXR4DqCNFxWFZnbDUr5eSpfuaoC9JLUP7vm9t +231i3h8r6cZontwXcAuVZsMnwqwtrYNb/L9yb0Uz+kR1SnBfrY5Yd9sV6gWbhDol +RcB4Cv2EHTOrQCz06VsA91lFprKP+aqA5qA63tHlmVe5jTfJDJsIQVJS31bT6DES +877VDtKsXNWZ/gq91q3dAXLopDtW9OvO13E0tBhUgOSC8Sc3r4N4Gv8SObAFuawQ +YKGxswAOLRmF -----END CERTIFICATE----- diff --git a/fixtures/notary-escrow.crt b/fixtures/notary-escrow.crt index c84d08016..6d4db1057 100644 --- a/fixtures/notary-escrow.crt +++ b/fixtures/notary-escrow.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIGBDCCA+ygAwIBAgIJAPlHYZzp1daIMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIGBDCCA+ygAwIBAgIJAMzwtUOFSlrzMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMjE3MDA0MzE3WhcNMTkwMzA5MDA0MzE3WjBbMQswCQYDVQQG +bmcgQ0EwHhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjBbMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEWMBQGA1UEAxMNbm90YXJ5LWVzY3JvdzCCAiIwDQYJKoZIhvcN AQEBBQADggIPADCCAgoCggIBAMFzgrRu1r3leMdD19sSgfqW85Bi4FCv6LCDbnAO @@ -16,54 +16,20 @@ voL/5206/Npd0bCodXGX62ARUdEuTayG5a7fJ6NCZa+C7W6hhAs9Mvw6LC8Webuw +wuzFE1v/Ktt2dLkwtvYC2N+J3nmxbBN4y0Uud0MqnO+SFV+Ib2nzlLKtZoNAG9x kcMQzuubdsj0HHq0ywYCCkjDaz+ltcUqF7NNhRJL47ccNfOumJD5LY9KbRPeZ19X f63g0iniyBFxcAmwwCql2PX07i8X4FcteH5J2ehiLuAJ8inz7uwMPEVFSr8n3AqS -y079AgMBAAGjgbkwgbYwHwYDVR0jBBgwFoAUupdDG81X7//TnYCdldrf396Did0w +y079AgMBAAGjgbkwgbYwHwYDVR0jBBgwFoAUvd13yFS117Joo/nPZOTzGzVqFRIw DAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYD VR0PAQH/BAQDAgWgMDcGA1UdEQQwMC6CDW5vdGFyeS1lc2Nyb3eCDG5vdGFyeWVz Y3Jvd4IJbG9jYWxob3N0hwR/AAABMB0GA1UdDgQWBBQdk/HK+26ISl+VOgKh5vtV -WRmqWzANBgkqhkiG9w0BAQsFAAOCAgEAFOxSPTgsFvF7lP/PPRr5faJGypEafRVk -YuyrSu/45O2L1BZLsiE4TjLVgiNGHq0ECL8GCMgHgfFeWrbqlFpvHc3F8xiwzKZq -GA0ig2ql9JGxGyancgHbkA5xkfGLY139Q8ORmCn6QCUF05uSiosckGuJ4ke/Xz6v -MH2OCcW+tRn+KsA+eurDueFjjqLAOE04d1PQ3sHIkeTlMgFVhj19oPp6lcr0VoN4 -rUPC1wzBNwp+odenl/84/9UiDTIUfmW7k+jxVEsEDMRh5xyM9yrNMkiuvOXOVc89 -IkaJPZBX+wynjPgStsfZNRHJWSY2NlIyQI1/Y/tjjygSIjR6HmOFaKp5y+2TNZfA -r1yNwI1nRN4HrkA+zxhoIgidL/mEwL1NGiLgS4fZc3V71VSqGomGZKfqbQotPCBP -qTH875io9wQWPLCMaNiTocrLiTLQREdW0OmVxkn8PEwImRb7lLhvVA2I1tVB4cXd -EQME2qvp2Lx6lGJJHx0X/kwK6f9aOn5I9VNAPcpmgzk4wvlylFJSII78TSg8LBlE -xYMr5G5Y5D6Z/WS53pj+qRxtRMTjZXHBUFuKicWHZnM9MtIAXS2m0G16gYMRkCqJ -VUdLIBaY8FC8efdPXP/7yd9STdnCKAaJ8d80ZbSSJSAPDK3r0DKWw3Nj1gioIEx+ -vXLaxnuP4Nc= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF1TCCA72gAwIBAgIJAKfYxoqVGl7nMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G -A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAy -MTcwMDQzMTdaFw0yNzAyMTUwMDQzMTdaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI -EwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0GA1UEChMGRG9ja2VyMScw -JQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3RpbmcgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/VjDUa9JQLhfnHvonnF+yxsbwJSkFWbad -ci5boMGakJGsjgjDK+IfzzkRNbA3aYSd27UX5Vz+nPyt3BLJHIhlxOW9iDA6nqWb -q/eJn5eV42eXoR+6ttrNzFWLZOTT+v5ZGQJYOKmk4vmZT/xoHTgHlsRshpj3EFRd -PxgolcKMSsZpSD8I2sgUYwh+rmI/nbesZGmb7mjQxMb2jtZPhxlHpSwL79RlFw4f -cS0x7qts0WsZtY8pa3HWxSG0x4uWuNkwivojq0vpsFvynpLY6t7jdb0Vu7iUgMAA -t8AsbCt+uTv4KhyJw5rD7kg+Ad55QqVuTqtwoz0+SBREHm67q8gn/skTQT3ro4pB -nQdlAQDNPBa3JnZvXmLDkgHdVCKZtaarm92L0P5byIUo+UtDA4j+FkkRXLyVC1FU -O3awwbAOIK2/VznRpaKoxEV7p2sp7pkqFIFAX1ALUXQRjuxd2EPuTn4HgMdIta6e -xnZjTxcehUzpSxMBEnlfSNmYvSWD6enMDr0ZuRU1L5ZnLU6RibBtMREqfTaHAygf -kPBRO6AHB+K5OPK5yVwzp4G8yve5FAUo0YnNTnaIYs7ZYL14eOzPH3RIkRE+F8hB -A8YB5vFEAbjto/ZxeikvCVk6jNuuvw5mbHN9yHIfD7qI1pPY54EIEGgxVZGwaJTj -mRKvTbf6JQIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFMXa5XX+ba5Jf0YRuL6UqjtU -QS5ZMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG -AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUupdDG81X7//TnYCdldrf -396Did0wDQYJKoZIhvcNAQELBQADggIBAEKzd2/OInjHpFNmqJnuAvrFJPQHhwAQ -CUv4HwLqMdRbKLhAF2Xc687K0rJaW6ZpvvCWP/bsgzDi7bcti+sbpRtutL98ollq -NtqEBW7pW3ljvQteBHiXCPzHmSdKBG5B972mFvIi1k9NpeHcEz4y9q5s9BBW5hIu -6UwKIQSZ/dQGsukgQXe3lXJ/MjRg/QK0U1Xn/ABknm75vMbdc7L+WLvmrEY11NAy -3vso6qm7k2elDLUVmqIwMU+r9pfGZFi0nQCxfiRhW1hZyDxzpngBZFnRppiO+2CX -u16yiJfipD5wHZc1NjZ1WQ+XuoUhDgV1yzGpgRGtUdX4fByEUqNZb1GbY6UdIjmx -LvwT2SJnEcv9irGlQU2D4mm5oXgeZXJhxP3gMxEtw9bZS3tUDMWkMD5GCdo8T+FB -tjlGIe8Uh8R4wn33EYDMq+qFeUe+NiMDsVcFIlKWSwCRvmsTB3gvTYYkssuyS65Y -8Ngdsy5GIBhMEsLnZNdwmP7NJ41CECqlojK9tQeu8KAhB7xsKibbwPUbec7whQFl -82vOLgag7Fn3V1eVonqxk7uBt0nriV39/hXifPwBRo3WLoVLUTs+IAOiLapLAb6o -LCQV7ymBRptOyj9bPPYV+NJrfr/5IlkNamioWlbzH3SJdvyp5ldZH/2vciItlO3s -ALNmRewqFkXD +WRmqWzANBgkqhkiG9w0BAQsFAAOCAgEAEQMQTzu/BikIWXXvptGUAVl5XJ4bbz1P +anwlcJjxOOjAPEGz6/K3frLnZSoHH9dUtQW6D/CjdfFKGzkdJ+2f908AOdiTOuFL +VcWdp+zcW4ee7yr7PbZxlPYkVNFONF4fILJO2U2JNFt7I0bTljOWZzpChePmKaD5 +77mjv71YpiH+sj7w7m6no4lrc19fkDFtMl6blskdjZlHehFLmekRhq9gaRpe7Igz ++QDiOLL/8M8xBOvycs4x5B0qs59rIr2uZtsUDXGuvSz0z9JWCLMnlbmtAzClmcCv +sj3ClDxJEQdyqE1Y0La4EwMHJjV55gqzl/Q4ypgwxqOdb8/8xrM6E6rnb2uhlqlj +7pAa0/IYXZYds6V/DtcUQGkGBK18ky3f5d8jfxVGnFwldK5Ug3RmwbatjqZrtBGX +t0ETaV2YW+29TGUl9ikNqFqcoRPbK/77ljSnCvxoX1SdBJY095zkM9OLBVnGwk0W +R2HJwds2qIT8WYTV1t23SEyEPT0BqBZESTEeoIJqlT1lgXXElwDS0ddXJjCCVXOI +LJBOrBFcckJy7JAyYF+ZYAOesjP7GVNUnsYKJ1CvyD3LVXQhGV7fElHUNujvl3MU +q0iMGgCNYpAiw7oG7rRXV4nHB4Jmsfw6gIATUCgUjXTwjOxxsgu65WF7BR2smYs4 +d0v/58k1s6I= -----END CERTIFICATE----- diff --git a/fixtures/notary-server.crt b/fixtures/notary-server.crt index 0b98a14d1..a3171e949 100644 --- a/fixtures/notary-server.crt +++ b/fixtures/notary-server.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFBDCCAuygAwIBAgIJAM3wbUCyULKOMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIFBDCCAuygAwIBAgIJAMzwtUOFSlryMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjBbMQswCQYDVQQG +bmcgQ0EwHhcNMTcwMzAxMTkzNjI4WhcNMTkwMzIxMTkzNjI4WjBbMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEWMBQGA1UEAxMNbm90YXJ5LXNlcnZlcjCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAKjbeflOtVrOv0IOeJGKfi5LHH3Di0O2nlZu8AIT @@ -11,53 +11,87 @@ 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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIF1TCCA72gAwIBAgIJAOPfcGEXu4wMMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV +MIIF1TCCA72gAwIBAgIJAMELzHI4DbdfMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G -A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAy -MjAxODE3MTFaFw0yNzAyMTgxODE3MTFaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI +A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAz +MDExOTM2MjhaFw0yNzAyMjcxOTM2MjhaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI EwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0GA1UEChMGRG9ja2VyMScw JQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3RpbmcgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQDiHv1wniM1L4dpAHMYDj8PxrHbjeBtim/T -KU57m1PXqA2Uby7nGHiLE4c1ie8mVYkHXz0nQ0VjcuTUsIUa7xQj3yJ2z5ATnsgq -urE28xTRmHZmthbyddIsfmOVGrZPpAmJfJ4/LX3KJJZjqqUEPO1mkNFsG/fLkVOm -AEhzZO/g9txqbB/s2KYtMy4QxsRaepfcECGotnt+vYdk7+rJvli5PeMuKoWBLzjz -gUTzvea7VId/0ff4DO4XG9u8KjhYMHSINUsIcT8amZbl5CjQAsCRyU6lDfOl2hH3 -F1erbTFMEFtRSFh7CSpjKFCvJkyqcRAW8zIwhX+Yl1MMnEItxnBkc+rbe29oGZoD -uGjHAhzCV46IfgFQxmRrMQydUp4BRvAHTlhnXPnDjSuczYzt66p71C/UPzEH7tUe -ubHbqxVv1y6BGpI7cEALQ2o3FJ/3T8YaLbXKSYQ/uO9GpIMTgTWLwhoqwq+lgpxu -ApPJ5EY3LrLChvIZViHkxrCwjsGX31q/l17s3R9rJcGEzEIkVPxHJrvi07KelUYO -xmv1u1o/5FGfWafs0wcj0whswnU9w7LI7+o47t5ZCvNYseP7JPIMti+9KgBCUyEC -uB+YwHFcXwRDEA3GaCYePetTq+gg93iE7VoiwVo8JI8AxjwfGH17o09PjmeyNOHU -dbPcJRBJQwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFJdjQCkJsHhLo1GM3d7OxJ/R -YVTIMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG -AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUTlLCARrOUn3EeHEAyH97 -33CgXzEwDQYJKoZIhvcNAQELBQADggIBAJFoIVlB6PFPz+9ukOcH0hlrl7VPKbb+ -FO8tGizASgDsM32oeSqAaasKQw9pWhtPia/u7rIYI+mnqUi9WlgUYzy1yZmGkcWj -2Us7i9Lrq4VSMblhCOFYVJZe6SkF1TtgRQrP7NLxFLQ+oyl85inEpbcNRI82t+c3 -KIxbq8Fb9qHGAGPr9v1W+KoVo+NSrL/38FfGWAygAfTwUJJf1SNJjxUuklOsl3RS -qdkMhjmHaJF6OJm2Y0Y5aKoEGqP0vYXyTkmbgtCeFnDyc16KQV+saQ/UAFTpcyE2 -kWTri3M1uNL3tEjNBZaEHifJlv6jVA+AGK9dBfyysMTLtZXbmGxdlPAfoIkrxF3k -VxhY8kTMqSim5TRk0MzV5DZIUT5rY4yITeRicass9sAkScSKIlqEplqk/U7ZqbVY -c1q3H9zafhxjZ5rrpB8amo6brWRXzenJQ/x4wo1n/Zgf7fL3vQStxA3AVTWD3TmA -FeRlb/el+7nHziajPYmA6uxpSyRjNdyXqxP45u4nkGt7xPIvVcLTULPf2Y2NOVr0 -F0glAC5OLIrejaDGTFlMTupU9CjgkNbEiqJLnaByK3LWOu26GynVcF3eogRYYKjs -J0ETQvK+/GhRttp1QhiPVkBJrQF7fSIZAz919gD21cQAZSgNg13XTXhNNRuIw0eT -Pl9leAX0LJ7l +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC5gi0twJAtlvL9XwzeXpu6zAUGUkPIU3Wp +GA3zYqqFcYKBxPuQ8AfexGCRJZ6MDteQMUKbtQFbbPj3x7OcXx0OAwlirvZAajec +9o7jmmhGJ0jZWFlMtTs9ZvqR5nkRESWdVcegzX+/zVVDgbNkHRd0iQCPvcfBZskg +G6t1LksQwKunhssaaDSk1vbS/QaxCE5/ywBqMocvxarkg+sklPC+/iBUN8/KUa2j +oqaOkcSUiKsqXskAyYLDTdqGpVee5nmg1WMUUpfmuBXYSxuxEmqu+9pjzFfBQDu9 +Fn+LY0UviccascCYT6h/RNU/hVqaLc9NnMsF388HXXo7T7OChzWkr+7qJvAxUctn +y94eUBzLkS4LmYlUvpE6YYLDSab8AUNJYLHFXIbn93A0wukfboCqucERiMz1qtSg +ZYyx5Vy8RcmVC8bB5LfCFoZLTZ+WT6+NyumVbCFebHARMGyaJPlUlcaNwHWlwMlv +fUJQM454alIfLartvdXVpAhibCB7HLk3GDCs5jec9pKtwpQqXVfv07/FeRl67QfR +EQYhXxs2iUK4L1IJZRoroVg2NdG9+z5kF7SxZHmZKagQIUQYcnSXT63QaCC6KsmH +SjMxEH81OSYbJoV3Jrj4sgp4uKG7tkEgYnmjvFpyvay6ymZioff6+QPZi02RKjag +jeut/4XjIQIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFL/NOhPhwQx/tUwrHU4NJ4+W +XbwAMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUvd13yFS117Joo/nPZOTz +GzVqFRIwDQYJKoZIhvcNAQELBQADggIBAE0jLDhm8Cn6N+TvGqbdtOKwCo5JPY1Z +eUxz1O5lDbcLAOG8AGPCRdT+TEdnsm9fG8nnv0d7X5GciSIqd5zv0Zi5oSItUUwm +qjAgbJMAFMTQTA0KbzNf0QaWvfeUPSIHTr8S19QctoDYXtvO5afkuT1V30uYY9u7 +IJHJHAM/IaWDaQcJw1f4TUPb5wFmvVof6vl19KcU4NtO3CLJpcL4w4OzSEWWepJ7 +3kz4PEibhHnY3zDotbVXSK5R6RceOwF9Jzw0IzTrfL5WGKcm4vq369/BfHSWZ5IP +RazsSK/aFfQI1C1uJPogPmpP2bMRWEWp/RrWkonMQLM2etRRi6Nq4G+H5SSIIjzB +vr/FzqsFQS0H9JsT6B7Br+3OCjjeLk0G17okrVihVQ8N95wxGMWRbuUVAWdrJsAQ +Ep3leFQdlR0tJnw4Jh8vPT8BwzQQXR4DqCNFxWFZnbDUr5eSpfuaoC9JLUP7vm9t +231i3h8r6cZontwXcAuVZsMnwqwtrYNb/L9yb0Uz+kR1SnBfrY5Yd9sV6gWbhDol +RcB4Cv2EHTOrQCz06VsA91lFprKP+aqA5qA63tHlmVe5jTfJDJsIQVJS31bT6DES +877VDtKsXNWZ/gq91q3dAXLopDtW9OvO13E0tBhUgOSC8Sc3r4N4Gv8SObAFuawQ +YKGxswAOLRmF +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +YKGxswAOLRmF -----END CERTIFICATE----- diff --git a/fixtures/notary-signer.crt b/fixtures/notary-signer.crt index 5b368b2b2..1eb32c937 100644 --- a/fixtures/notary-signer.crt +++ b/fixtures/notary-signer.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFBDCCAuygAwIBAgIJAM3wbUCyULKPMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIFBDCCAuygAwIBAgIJAMzwtUOFSlr0MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjBbMQswCQYDVQQG +bmcgQ0EwHhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjBbMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEWMBQGA1UEAxMNbm90YXJ5LXNpZ25lcjCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBANhO8+K9xT6M9dQC90Hxs6bmTXWQzE5oV2kLeVKq @@ -11,53 +11,53 @@ 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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIF1TCCA72gAwIBAgIJAOPfcGEXu4wMMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV +MIIF1TCCA72gAwIBAgIJAMELzHI4DbdfMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G -A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAy -MjAxODE3MTFaFw0yNzAyMTgxODE3MTFaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI +A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAz +MDExOTM2MjhaFw0yNzAyMjcxOTM2MjhaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI EwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0GA1UEChMGRG9ja2VyMScw JQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3RpbmcgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQDiHv1wniM1L4dpAHMYDj8PxrHbjeBtim/T -KU57m1PXqA2Uby7nGHiLE4c1ie8mVYkHXz0nQ0VjcuTUsIUa7xQj3yJ2z5ATnsgq -urE28xTRmHZmthbyddIsfmOVGrZPpAmJfJ4/LX3KJJZjqqUEPO1mkNFsG/fLkVOm -AEhzZO/g9txqbB/s2KYtMy4QxsRaepfcECGotnt+vYdk7+rJvli5PeMuKoWBLzjz -gUTzvea7VId/0ff4DO4XG9u8KjhYMHSINUsIcT8amZbl5CjQAsCRyU6lDfOl2hH3 -F1erbTFMEFtRSFh7CSpjKFCvJkyqcRAW8zIwhX+Yl1MMnEItxnBkc+rbe29oGZoD -uGjHAhzCV46IfgFQxmRrMQydUp4BRvAHTlhnXPnDjSuczYzt66p71C/UPzEH7tUe -ubHbqxVv1y6BGpI7cEALQ2o3FJ/3T8YaLbXKSYQ/uO9GpIMTgTWLwhoqwq+lgpxu -ApPJ5EY3LrLChvIZViHkxrCwjsGX31q/l17s3R9rJcGEzEIkVPxHJrvi07KelUYO -xmv1u1o/5FGfWafs0wcj0whswnU9w7LI7+o47t5ZCvNYseP7JPIMti+9KgBCUyEC -uB+YwHFcXwRDEA3GaCYePetTq+gg93iE7VoiwVo8JI8AxjwfGH17o09PjmeyNOHU -dbPcJRBJQwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFJdjQCkJsHhLo1GM3d7OxJ/R -YVTIMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG -AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUTlLCARrOUn3EeHEAyH97 -33CgXzEwDQYJKoZIhvcNAQELBQADggIBAJFoIVlB6PFPz+9ukOcH0hlrl7VPKbb+ -FO8tGizASgDsM32oeSqAaasKQw9pWhtPia/u7rIYI+mnqUi9WlgUYzy1yZmGkcWj -2Us7i9Lrq4VSMblhCOFYVJZe6SkF1TtgRQrP7NLxFLQ+oyl85inEpbcNRI82t+c3 -KIxbq8Fb9qHGAGPr9v1W+KoVo+NSrL/38FfGWAygAfTwUJJf1SNJjxUuklOsl3RS -qdkMhjmHaJF6OJm2Y0Y5aKoEGqP0vYXyTkmbgtCeFnDyc16KQV+saQ/UAFTpcyE2 -kWTri3M1uNL3tEjNBZaEHifJlv6jVA+AGK9dBfyysMTLtZXbmGxdlPAfoIkrxF3k -VxhY8kTMqSim5TRk0MzV5DZIUT5rY4yITeRicass9sAkScSKIlqEplqk/U7ZqbVY -c1q3H9zafhxjZ5rrpB8amo6brWRXzenJQ/x4wo1n/Zgf7fL3vQStxA3AVTWD3TmA -FeRlb/el+7nHziajPYmA6uxpSyRjNdyXqxP45u4nkGt7xPIvVcLTULPf2Y2NOVr0 -F0glAC5OLIrejaDGTFlMTupU9CjgkNbEiqJLnaByK3LWOu26GynVcF3eogRYYKjs -J0ETQvK+/GhRttp1QhiPVkBJrQF7fSIZAz919gD21cQAZSgNg13XTXhNNRuIw0eT -Pl9leAX0LJ7l +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC5gi0twJAtlvL9XwzeXpu6zAUGUkPIU3Wp +GA3zYqqFcYKBxPuQ8AfexGCRJZ6MDteQMUKbtQFbbPj3x7OcXx0OAwlirvZAajec +9o7jmmhGJ0jZWFlMtTs9ZvqR5nkRESWdVcegzX+/zVVDgbNkHRd0iQCPvcfBZskg +G6t1LksQwKunhssaaDSk1vbS/QaxCE5/ywBqMocvxarkg+sklPC+/iBUN8/KUa2j +oqaOkcSUiKsqXskAyYLDTdqGpVee5nmg1WMUUpfmuBXYSxuxEmqu+9pjzFfBQDu9 +Fn+LY0UviccascCYT6h/RNU/hVqaLc9NnMsF388HXXo7T7OChzWkr+7qJvAxUctn +y94eUBzLkS4LmYlUvpE6YYLDSab8AUNJYLHFXIbn93A0wukfboCqucERiMz1qtSg +ZYyx5Vy8RcmVC8bB5LfCFoZLTZ+WT6+NyumVbCFebHARMGyaJPlUlcaNwHWlwMlv +fUJQM454alIfLartvdXVpAhibCB7HLk3GDCs5jec9pKtwpQqXVfv07/FeRl67QfR +EQYhXxs2iUK4L1IJZRoroVg2NdG9+z5kF7SxZHmZKagQIUQYcnSXT63QaCC6KsmH +SjMxEH81OSYbJoV3Jrj4sgp4uKG7tkEgYnmjvFpyvay6ymZioff6+QPZi02RKjag +jeut/4XjIQIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFL/NOhPhwQx/tUwrHU4NJ4+W +XbwAMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUvd13yFS117Joo/nPZOTz +GzVqFRIwDQYJKoZIhvcNAQELBQADggIBAE0jLDhm8Cn6N+TvGqbdtOKwCo5JPY1Z +eUxz1O5lDbcLAOG8AGPCRdT+TEdnsm9fG8nnv0d7X5GciSIqd5zv0Zi5oSItUUwm +qjAgbJMAFMTQTA0KbzNf0QaWvfeUPSIHTr8S19QctoDYXtvO5afkuT1V30uYY9u7 +IJHJHAM/IaWDaQcJw1f4TUPb5wFmvVof6vl19KcU4NtO3CLJpcL4w4OzSEWWepJ7 +3kz4PEibhHnY3zDotbVXSK5R6RceOwF9Jzw0IzTrfL5WGKcm4vq369/BfHSWZ5IP +RazsSK/aFfQI1C1uJPogPmpP2bMRWEWp/RrWkonMQLM2etRRi6Nq4G+H5SSIIjzB +vr/FzqsFQS0H9JsT6B7Br+3OCjjeLk0G17okrVihVQ8N95wxGMWRbuUVAWdrJsAQ +Ep3leFQdlR0tJnw4Jh8vPT8BwzQQXR4DqCNFxWFZnbDUr5eSpfuaoC9JLUP7vm9t +231i3h8r6cZontwXcAuVZsMnwqwtrYNb/L9yb0Uz+kR1SnBfrY5Yd9sV6gWbhDol +RcB4Cv2EHTOrQCz06VsA91lFprKP+aqA5qA63tHlmVe5jTfJDJsIQVJS31bT6DES +877VDtKsXNWZ/gq91q3dAXLopDtW9OvO13E0tBhUgOSC8Sc3r4N4Gv8SObAFuawQ +YKGxswAOLRmF -----END CERTIFICATE----- diff --git a/fixtures/regenerateTestingCerts.sh b/fixtures/regenerateTestingCerts.sh index 33c61ac2d..645cb7269 100755 --- a/fixtures/regenerateTestingCerts.sh +++ b/fixtures/regenerateTestingCerts.sh @@ -19,106 +19,82 @@ openssl genrsa -out "root-ca.key" 4096 openssl req -new -key "root-ca.key" -out "root-ca.csr" -sha256 \ -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=Notary Testing CA' -cat > "root-ca.cnf" < "intermediate-ca.cnf" < "notary-server.cnf" <> "notary-server.crt" + +rm "notary-server.csr" + +############################################################################### + +# Then generate notary-escrow +# Use the existing notary-escrow key +openssl req -new -key "notary-escrow.key" -out "notary-escrow.csr" -sha256 \ + -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=notary-escrow' + +openssl x509 -req -days 750 -in "notary-escrow.csr" -sha256 \ + -CA "intermediate-ca.crt" -CAkey "intermediate-ca.key" -CAcreateserial \ + -out "notary-escrow.crt" -extfile "cert_config.cnf" -extensions notary_escrow # append the intermediate cert to this one to make it a proper bundle cat "intermediate-ca.crt" >> "notary-server.crt" -rm "notary-server.cnf" "notary-server.csr" +rm "notary-escrow.csr" + +############################################################################### # Then generate notary-signer # Use the existing notary-signer key openssl req -new -key "notary-signer.key" -out "notary-signer.csr" -sha256 \ -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=notary-signer' -cat > "notary-signer.cnf" <> "notary-signer.crt" -rm "notary-signer.cnf" "notary-signer.csr" +rm "notary-signer.csr" + +############################################################################### # Then generate secure.example.com # Use the existing secure.example.com key openssl req -new -key "secure.example.com.key" -out "secure.example.com.csr" -sha256 \ -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=secure.example.com' -cat > "secure.example.com.cnf" < "${selfsigned}.cnf" < "clientapi-server.cnf" <> "clientapi-server.crt" -rm "clientapi-server.cnf" "clientapi-server.csr" +rm "clientapi-server.csr" + +############################################################################### +# Cleanup rm "intermediate-ca.key" "intermediate-ca.srl" diff --git a/fixtures/root-ca.crt b/fixtures/root-ca.crt index 5265c5409..8210c3480 100644 --- a/fixtures/root-ca.crt +++ b/fixtures/root-ca.crt @@ -1,32 +1,32 @@ -----BEGIN CERTIFICATE----- -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 -YstYjBovWExc0Fai6Sud3LBRnzlThs7LU74= +BBS/zToT4cEMf7VMKx1ODSePll28ADANBgkqhkiG9w0BAQsFAAOCAgEAcKJSgy6t +MqjEG+r008jzic7lNciX+sHp6j6kfLau9d0oYjBXQDfeBXNlqdGSvZeT157bhtrT +V64ouh5os9l+t67nbYrg1e2G/XdtA7rK0DGFW+6+M3f2KJzDtqaEBRnt+b/o3pG8 +MnTGWKt7Dqok9wmP+QMo4rAXM2dgB40CNhJae8EQGlmNHKM+O13CZfaGWRzw0aZr +ivDYNYblxKc6hTSYU01ZlYaHSF/D/kzeObbtPurWsg2wtcmXo8s4kbVdJcMXK3+R +oHzYhj7G67Ol0bVHdJXzj5xVYqVz5g473U5cmKXCNS7EtSCgO/kU7Zt/hrKY81rs +/Auv4zZ3gooaTcpDSvhHh0ZkXDOrUS3JtkSkUcU4OYV+Z7p/+CU7pHcJXUwHBLoC +tTl3SBTjrOzFvH54qf8TZ7cSVSmM3jSzS54a8K9+2eqFRW3/zwxzKZRPJimwuMUt +3YcHPH/Tk+yARvvlPiBwZqYlnLadi/Kew5Enur3eqCWeH5UcYUdC6lTA4bNHnywZ +rjQqIvQuA2MnkJDOU5DC23svXjsxIKDqIbvkh5CS/2veJ0y1ALfMNRmkmXwjP2Y2 +7/bGHP6HWYaxOCjfsOomcGwuc1DCDCu4jBFtLNXllqrsCp3dGIsEMGNbERhPfUvJ +mSU+sXjNtnlrP4jBgWMl074YdvqQ4Tj6xeg= -----END CERTIFICATE----- diff --git a/fixtures/secure.example.com.crt b/fixtures/secure.example.com.crt index 7f41a1ede..4a668d231 100644 --- a/fixtures/secure.example.com.crt +++ b/fixtures/secure.example.com.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFADCCAuigAwIBAgIJAM3wbUCyULKQMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIFADCCAuigAwIBAgIJAMzwtUOFSlr1MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjBgMQswCQYDVQQG +bmcgQ0EwHhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjBgMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEbMBkGA1UEAxMSc2VjdXJlLmV4YW1wbGUuY29tMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmLYiYCTAWJBWAuxZLqVmV4FiUdGgEqoQ @@ -11,19 +11,19 @@ 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 -----END CERTIFICATE----- diff --git a/fixtures/self-signed_docker.com-notary.crt b/fixtures/self-signed_docker.com-notary.crt index 25f2c2798..25b0c9a88 100644 --- a/fixtures/self-signed_docker.com-notary.crt +++ b/fixtures/self-signed_docker.com-notary.crt @@ -1,11 +1,11 @@ -----BEGIN CERTIFICATE----- -MIIBozCCAUqgAwIBAgIJAPoMYEzgRhkvMAkGByqGSM49BAEwLTEPMA0GA1UEChMG -RG9ja2VyMRowGAYDVQQDExFkb2NrZXIuY29tL25vdGFyeTAeFw0xNzAyMjAxODE3 -MTFaFw0xOTAzMTIxODE3MTFaMC0xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UEAxMR -ZG9ja2VyLmNvbS9ub3RhcnkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQm/eal -Hsu+ay26ckTxZ7ZjV0L7pSDvE6fnMub4MNV4BdBKXzd7ZxKFPT720oN4l1NH2l3k -bCVXMoEptZLdAjVTo1QwUjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAT -BgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUv+NPAjQlwPkcOGX/aOb6Tj/+ -7wMwCQYHKoZIzj0EAQNIADBFAiBkvZ6ELX8BelmsC1ueG3kh+s7QeD+wkhUevE9r -RV0NXQIhAJpcvV4nlreK3irCLatSirqGxzq+XdrIwE8V1ZVQIHab +MIIBojCCAUqgAwIBAgIJAJ/QvR7begAjMAkGByqGSM49BAEwLTEPMA0GA1UEChMG +RG9ja2VyMRowGAYDVQQDExFkb2NrZXIuY29tL25vdGFyeTAeFw0xNzAzMDExOTM2 +MjlaFw0xOTAzMjExOTM2MjlaMC0xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UEAxMR +ZG9ja2VyLmNvbS9ub3RhcnkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARhDFJB +B0yw20CDHoOWUU/bDKykjGy78yo1P608zugjy3cfiGFXXuuzcBsd/qV/btceqYrS +Eih1ygc06ql0UzsZo1QwUjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAT +BgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUH7glsL3UQMQFdJpbmZN3GE9u +nsEwCQYHKoZIzj0EAQNHADBEAiAjIdQW0DyQT1Kj5MvrohJ+PIAp6/z4Gy7gEKv0 +IWQJNAIgM1lndnPUo+pyGVBRdhqqwi2ilEW1IFfYkeuj2qjo37o= -----END CERTIFICATE----- diff --git a/fixtures/self-signed_secure.example.com.crt b/fixtures/self-signed_secure.example.com.crt index 1e65265b0..198746694 100755 --- a/fixtures/self-signed_secure.example.com.crt +++ b/fixtures/self-signed_secure.example.com.crt @@ -1,12 +1,12 @@ -----BEGIN CERTIFICATE----- -MIIBvTCCAWSgAwIBAgIJAP+Cqherm0u2MAkGByqGSM49BAEwOjEbMBkGA1UEChMS +MIIBvTCCAWSgAwIBAgIJANDdYEto/G43MAkGByqGSM49BAEwOjEbMBkGA1UEChMS c2VjdXJlLmV4YW1wbGUuY29tMRswGQYDVQQDExJzZWN1cmUuZXhhbXBsZS5jb20w -HhcNMTcwMjIwMTgxNzExWhcNMTkwMzEyMTgxNzExWjA6MRswGQYDVQQKExJzZWN1 +HhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjA6MRswGQYDVQQKExJzZWN1 cmUuZXhhbXBsZS5jb20xGzAZBgNVBAMTEnNlY3VyZS5leGFtcGxlLmNvbTBZMBMG -ByqGSM49AgEGCCqGSM49AwEHA0IABMzSsSlxwt8J6PZIW1cmcmsnS96tEXggayGx -QZR8bGTcslZ6clyG4vt4mExRcBUsvnR4eWRseKHnNRPKFz/WmM2jVDBSMAwGA1Ud +ByqGSM49AgEGCCqGSM49AwEHA0IABEfv3eYe/i6sM+Z0paRbiXGeCJ8puGcOHnGG +j5zgmcYgbP3LQ8V7EXVR9d1c4/UkiP/h8hngf7jIpN7c4cv02f6jVDBSMAwGA1Ud EwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0G -A1UdDgQWBBTeojZoNb/5aFKmw7yUnurWHny2szAJBgcqhkjOPQQBA0gAMEUCIQDi -ZXq9PaRvRON32Z8xQD8WgnmxszeNwuK+MaiOHih2MgIgUlemw6UL8yv0ecNsYc/A -KeyHdoYj+rFIudRu46lkAgU= +A1UdDgQWBBR8BdSOsCrM6DW8JEPY+eQIsdfJbTAJBgcqhkjOPQQBA0gAMEUCIQD1 +gCl7JkpOoh82V+B1wfIorq75c0dDUjf9wC/Rc6wlqAIgebuKMb8/kIyplETYeKyo +Eg0uVIQTi6aZA62T0/W1Umw= -----END CERTIFICATE----- diff --git a/utils/grpcauth/auth.go b/utils/grpcauth/auth.go index 536f0d018..e23788b5d 100644 --- a/utils/grpcauth/auth.go +++ b/utils/grpcauth/auth.go @@ -5,12 +5,13 @@ import ( "golang.org/x/net/context" + "github.com/Sirupsen/logrus" "github.com/docker/distribution/registry/auth" google_protobuf "github.com/golang/protobuf/ptypes/empty" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" - "github.com/Sirupsen/logrus" + "strings" ) type guner interface { @@ -71,18 +72,22 @@ func (s ServerAuthorizer) buildAuthChallenge(gun, method string) (metadata.MD, b if !ok { return nil, ok } - requiredAccess := make([]auth.Access, 0, len(perms)) - for _, perm := range perms { - requiredAccess = append(requiredAccess, auth.Access{ - Resource: auth.Resource{ - Type: "repository", - Name: gun, - }, - Action: perm, - }) + access := buildAccessRecords(gun, perms...) + + scopes := make([]string, 0, len(access)) + + for resource, actions := range access { + scopes = append(scopes, fmt.Sprintf( + "%s:%s:%s", + resource.Type, + resource.Name, + strings.Join(actions, ",")), + ) } - str = fmt.Sprintf("%s,scope=%q", str, ) + scope := strings.Join(scopes, " ") + + str = fmt.Sprintf("%s,scope=%q", str, scope) return metadata.MD{ "WWW-Authenticate": []string{str}, }, true @@ -116,3 +121,12 @@ func (c *ClientAuthorizer) Interceptor(ctx context.Context, method string, req, err = invoker(ctx, method, req, reply, cc, opts...) return err } + +func buildAccessRecords(repo string, actions ...string) map[auth.Resource][]string { + return map[auth.Resource][]string{ + auth.Resource{ + Type: "repository", + Name: repo, + }: actions, + } +} From 44656cc6a48c8c3279eff963954a7c3234b8401f Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 8 Mar 2017 13:20:52 -0800 Subject: [PATCH 07/62] grpc client needed GetGUN method to meet Repository interface Signed-off-by: David Lawrence (github: endophage) --- client_api/api/client.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client_api/api/client.go b/client_api/api/client.go index e2dc398ba..4d0777b00 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -127,6 +127,10 @@ func (c *Client) CryptoService() signed.CryptoService { return c.cs } +func (c *Client) GetGUN() string { + return c.gun.String() +} + type CryptoService struct { client NotaryClient } From bc29fa6be7f19fbb88409b800ce5694780429c9e Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 8 Mar 2017 13:25:47 -0800 Subject: [PATCH 08/62] fixing some interfaces Signed-off-by: David Lawrence (github: endophage) --- client/interface.go | 2 +- client_api/api/client.go | 4 ++-- cmd/clientapi/main.go | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/client/interface.go b/client/interface.go index 782c66713..f0058b40a 100644 --- a/client/interface.go +++ b/client/interface.go @@ -42,5 +42,5 @@ type Repository interface { CryptoService() signed.CryptoService SetLegacyVersions(int) - GetGUN() string + GetGUN() data.GUN } diff --git a/client_api/api/client.go b/client_api/api/client.go index 4d0777b00..afc91dbe8 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -127,8 +127,8 @@ func (c *Client) CryptoService() signed.CryptoService { return c.cs } -func (c *Client) GetGUN() string { - return c.gun.String() +func (c *Client) GetGUN() data.GUN { + return c.gun } type CryptoService struct { diff --git a/cmd/clientapi/main.go b/cmd/clientapi/main.go index f34d654b4..950aaa70f 100644 --- a/cmd/clientapi/main.go +++ b/cmd/clientapi/main.go @@ -8,7 +8,6 @@ import ( "github.com/docker/notary/utils" "google.golang.org/grpc" "google.golang.org/grpc/credentials" - "net" ) var ( From 2386ae0e294f98877198906988a63353fe08b656 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 8 Mar 2017 18:08:48 -0800 Subject: [PATCH 09/62] server side of producing a token is working Signed-off-by: David Lawrence (github: endophage) --- utils/grpcauth/auth.go | 89 +++----- utils/grpcauth/auth_test.go | 22 +- utils/token/accesscontroller.go | 215 ++++++++++++++++++ utils/token/stringset.go | 35 +++ utils/token/token.go | 378 ++++++++++++++++++++++++++++++++ utils/token/util.go | 73 ++++++ 6 files changed, 742 insertions(+), 70 deletions(-) create mode 100644 utils/token/accesscontroller.go create mode 100644 utils/token/stringset.go create mode 100644 utils/token/token.go create mode 100644 utils/token/util.go diff --git a/utils/grpcauth/auth.go b/utils/grpcauth/auth.go index e23788b5d..c89f64a94 100644 --- a/utils/grpcauth/auth.go +++ b/utils/grpcauth/auth.go @@ -1,17 +1,13 @@ package grpcauth import ( - "fmt" - - "golang.org/x/net/context" - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/registry/auth" + "github.com/docker/notary/utils/token" google_protobuf "github.com/golang/protobuf/ptypes/empty" + "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" - "strings" ) type guner interface { @@ -21,15 +17,15 @@ type guner interface { // ServerAuthorizer performs server checks for the correct authorization tokens type ServerAuthorizer struct { permissions map[string][]string - realm string - service string + auth *token.Auth } // NewServerAuthorizer instantiates a ServerAuthorizer and returns the Interceptor // attached to it. -func NewServerAuthorizer(tokenCAPath string, permissions map[string][]string) (grpc.UnaryServerInterceptor, error) { +func NewServerAuthorizer(auth *token.Auth, permissions map[string][]string) (grpc.UnaryServerInterceptor, error) { s := ServerAuthorizer{ permissions: permissions, + auth: auth, } return s.Interceptor, nil } @@ -38,66 +34,40 @@ func NewServerAuthorizer(tokenCAPath string, permissions map[string][]string) (g // token scope and actions, or allows the request to proceed // TODO: are the error responses the ones we want to use func (s ServerAuthorizer) Interceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { - gnr, ok := req.(guner) - if !ok { + if s.auth != nil { + gnr, ok := req.(guner) if !ok { return &google_protobuf.Empty{}, grpc.Errorf( codes.Unauthenticated, "no authorization credentials provided", ) } - } - md, ok := metadata.FromContext(ctx) - if !ok || !s.authorized(md) { - md, ok := s.buildAuthChallenge(gnr.GetGun(), info.FullMethod) - if !ok { + md, ok := metadata.FromContext(ctx) + var rawToken string + if ok { + ts := md["Authorization"] + if len(ts) > 0 { + rawToken = ts[0] + } + } + if _, err := s.auth.Authorize(rawToken); !ok || err != nil { + md := s.auth.ChallengeHeaders( + err, + token.BuildAccessRecords( + gnr.GetGun(), + s.permissions[info.FullMethod]..., + )..., + ) + grpc.SendHeader(ctx, md) return &google_protobuf.Empty{}, grpc.Errorf( codes.Unauthenticated, "no authorization credentials provided", ) } - grpc.SendHeader(ctx, md) - return &google_protobuf.Empty{}, grpc.Errorf( - codes.Unauthenticated, - "no authorization credentials provided", - ) } return handler(ctx, req) } -func (s ServerAuthorizer) buildAuthChallenge(gun, method string) (metadata.MD, bool) { - str := fmt.Sprintf("Bearer realm=%q,service=%q", s.realm, s.service) - - perms, ok := s.permissions[method] - if !ok { - return nil, ok - } - access := buildAccessRecords(gun, perms...) - - scopes := make([]string, 0, len(access)) - - for resource, actions := range access { - scopes = append(scopes, fmt.Sprintf( - "%s:%s:%s", - resource.Type, - resource.Name, - strings.Join(actions, ",")), - ) - } - - scope := strings.Join(scopes, " ") - - str = fmt.Sprintf("%s,scope=%q", str, scope) - return metadata.MD{ - "WWW-Authenticate": []string{str}, - }, true -} - -func (s ServerAuthorizer) authorized(md metadata.MD) bool { - _, ok := md["Authorization"] - return ok -} - // ClientAuthorizer deals with satisfying tokens required by the server. If it receives an // error response, it will attempt to retrieve a token the server will accept type ClientAuthorizer struct{} @@ -110,6 +80,8 @@ func NewClientAuthorizer() grpc.UnaryClientInterceptor { // Interceptor attempts to retrieve and attach the appropriate tokens for the request // being made func (c *ClientAuthorizer) Interceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + headers := metadata.MD{} + opts = append(opts, grpc.Header(&headers)) err := invoker(ctx, method, req, reply, cc, opts...) if err != nil { logrus.Error(err) @@ -121,12 +93,3 @@ func (c *ClientAuthorizer) Interceptor(ctx context.Context, method string, req, err = invoker(ctx, method, req, reply, cc, opts...) return err } - -func buildAccessRecords(repo string, actions ...string) map[auth.Resource][]string { - return map[auth.Resource][]string{ - auth.Resource{ - Type: "repository", - Name: repo, - }: actions, - } -} diff --git a/utils/grpcauth/auth_test.go b/utils/grpcauth/auth_test.go index 326fd1d8f..db20b74e2 100644 --- a/utils/grpcauth/auth_test.go +++ b/utils/grpcauth/auth_test.go @@ -1,16 +1,24 @@ package grpcauth import ( - "testing" + "github.com/docker/notary/client" + "github.com/docker/notary/client_api/api" + "github.com/docker/notary/utils/token" + "github.com/stretchr/testify/require" "google.golang.org/grpc" "net" - "github.com/stretchr/testify/require" - "github.com/docker/notary/client_api/api" - "github.com/docker/notary/client" + "testing" ) func TestServerAuthorizer(t *testing.T) { - auth, err := NewServerAuthorizer("", nil) + tok, err := token.NewAuth("testRealm", "testIssuer", "service", "../../fixtures/root-ca.crt") + require.NoError(t, err) + auth, err := NewServerAuthorizer( + tok, + map[string][]string{ + "/api.Notary/AddTarget": {"push", "pull"}, + }, + ) require.NoError(t, err) srv := grpc.NewServer( grpc.UnaryInterceptor(auth), @@ -21,7 +29,7 @@ func TestServerAuthorizer(t *testing.T) { api.NewServer("", "", srv) go srv.Serve(lis) - conn, err := grpc.Dial( + conn, err := grpc.Dial( "localhost:6789", grpc.WithInsecure(), grpc.WithUnaryInterceptor(NewClientAuthorizer()), @@ -33,4 +41,4 @@ func TestServerAuthorizer(t *testing.T) { "targets", ) require.NoError(t, err) -} \ No newline at end of file +} diff --git a/utils/token/accesscontroller.go b/utils/token/accesscontroller.go new file mode 100644 index 000000000..350138e80 --- /dev/null +++ b/utils/token/accesscontroller.go @@ -0,0 +1,215 @@ +package token + +import ( + "crypto" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "io/ioutil" + "net/http" + "os" + "strings" + + "github.com/docker/distribution/registry/auth" + "github.com/docker/libtrust" +) + +// accessSet maps a typed, named resource to +// a set of actions requested or authorized. +type accessSet map[auth.Resource]actionSet + +// newAccessSet constructs an accessSet from +// a variable number of auth.Access items. +func newAccessSet(accessItems ...auth.Access) accessSet { + accessSet := make(accessSet, len(accessItems)) + + for _, access := range accessItems { + resource := auth.Resource{ + Type: access.Type, + Name: access.Name, + } + + set, exists := accessSet[resource] + if !exists { + set = newActionSet() + accessSet[resource] = set + } + + set.add(access.Action) + } + + return accessSet +} + +// contains returns whether or not the given access is in this accessSet. +func (s accessSet) contains(access auth.Access) bool { + actionSet, ok := s[access.Resource] + if ok { + return actionSet.contains(access.Action) + } + + return false +} + +// scopeParam returns a collection of scopes which can +// be used for a WWW-Authenticate challenge parameter. +// See https://tools.ietf.org/html/rfc6750#section-3 +func (s accessSet) scopeParam() string { + scopes := make([]string, 0, len(s)) + + for resource, actionSet := range s { + actions := strings.Join(actionSet.keys(), ",") + scopes = append(scopes, fmt.Sprintf("%s:%s:%s", resource.Type, resource.Name, actions)) + } + + return strings.Join(scopes, " ") +} + +// Errors used and exported by this package. +var ( + ErrInsufficientScope = errors.New("insufficient scope") + ErrTokenRequired = errors.New("authorization token required") +) + +type authChallenge struct { + err error + realm string + service string + accessSet accessSet +} + +// Error returns the internal error string for this authChallenge. +func (ac authChallenge) Error() string { + return ac.err.Error() +} + +// Status returns the HTTP Response Status Code for this authChallenge. +func (ac authChallenge) Status() int { + return http.StatusUnauthorized +} + +// challengeParams constructs the value to be used in +// the WWW-Authenticate response challenge header. +// See https://tools.ietf.org/html/rfc6750#section-3 +func (ac authChallenge) challengeParams() string { + str := fmt.Sprintf("Bearer realm=%q,service=%q", ac.realm, ac.service) + + if scope := ac.accessSet.scopeParam(); scope != "" { + str = fmt.Sprintf("%s,scope=%q", str, scope) + } + + if ac.err == ErrInvalidToken || ac.err == ErrMalformedToken { + str = fmt.Sprintf("%s,error=%q", str, "invalid_token") + } else if ac.err == ErrInsufficientScope { + str = fmt.Sprintf("%s,error=%q", str, "insufficient_scope") + } + + return str +} + +// SetChallenge sets the WWW-Authenticate value for the response. +func (ac authChallenge) Headers() map[string][]string { + return map[string][]string{ + "authenticate": {ac.challengeParams()}, + } +} + +// Auth implements the auth.Auth interface. +type Auth struct { + realm string + issuer string + service string + rootCerts *x509.CertPool + trustedKeys map[string]libtrust.PublicKey + verifyOpts VerifyOptions +} + +// NewAuth creates an accessController using the given options. +func NewAuth(realm, issuer, service, rootCertBundle string) (*Auth, error) { + + fp, err := os.Open(rootCertBundle) + if err != nil { + return nil, fmt.Errorf("unable to open token auth root certificate bundle file %q: %s", rootCertBundle, err) + } + defer fp.Close() + + rawCertBundle, err := ioutil.ReadAll(fp) + if err != nil { + return nil, fmt.Errorf("unable to read token auth root certificate bundle file %q: %s", rootCertBundle, err) + } + + var rootCerts []*x509.Certificate + pemBlock, rawCertBundle := pem.Decode(rawCertBundle) + for pemBlock != nil { + if pemBlock.Type == "CERTIFICATE" { + cert, err := x509.ParseCertificate(pemBlock.Bytes) + if err != nil { + return nil, fmt.Errorf("unable to parse token auth root certificate: %s", err) + } + + rootCerts = append(rootCerts, cert) + } + + pemBlock, rawCertBundle = pem.Decode(rawCertBundle) + } + + if len(rootCerts) == 0 { + return nil, errors.New("token auth requires at least one token signing root certificate") + } + + rootPool := x509.NewCertPool() + trustedKeys := make(map[string]libtrust.PublicKey, len(rootCerts)) + for _, rootCert := range rootCerts { + rootPool.AddCert(rootCert) + pubKey, err := libtrust.FromCryptoPublicKey(crypto.PublicKey(rootCert.PublicKey)) + if err != nil { + return nil, fmt.Errorf("unable to get public key from token auth root certificate: %s", err) + } + trustedKeys[pubKey.KeyID()] = pubKey + } + + return &Auth{ + realm: realm, + issuer: issuer, + service: service, + verifyOpts: VerifyOptions{ + TrustedIssuers: []string{issuer}, + AcceptedAudiences: []string{service}, + Roots: rootPool, + TrustedKeys: trustedKeys, + }, + }, nil +} + +func (ac *Auth) Authorize(rawToken string, accessItems ...auth.Access) (*auth.UserInfo, error) { + if rawToken == "" { + return nil, ErrTokenRequired + } + token, err := NewToken(rawToken) + if err != nil { + return nil, err + } + + accessSet := token.accessSet() + for _, access := range accessItems { + if !accessSet.contains(access) { + return nil, ErrInsufficientScope + } + } + + return &auth.UserInfo{Name: token.Claims.Subject}, nil +} + +// ChallengeHeaders produces the necessary keys and values to provide a challenge +// response to a client. If an err is provided, its string is included in the +// challenge values. +func (ac *Auth) ChallengeHeaders(err error, accessItems ...auth.Access) map[string][]string { + challenge := &authChallenge{ + realm: ac.realm, + service: ac.service, + accessSet: newAccessSet(accessItems...), + err: err, + } + return challenge.Headers() +} diff --git a/utils/token/stringset.go b/utils/token/stringset.go new file mode 100644 index 000000000..1d04f104c --- /dev/null +++ b/utils/token/stringset.go @@ -0,0 +1,35 @@ +package token + +// StringSet is a useful type for looking up strings. +type stringSet map[string]struct{} + +// NewStringSet creates a new StringSet with the given strings. +func newStringSet(keys ...string) stringSet { + ss := make(stringSet, len(keys)) + ss.add(keys...) + return ss +} + +// Add inserts the given keys into this StringSet. +func (ss stringSet) add(keys ...string) { + for _, key := range keys { + ss[key] = struct{}{} + } +} + +// Contains returns whether the given key is in this StringSet. +func (ss stringSet) contains(key string) bool { + _, ok := ss[key] + return ok +} + +// Keys returns a slice of all keys in this StringSet. +func (ss stringSet) keys() []string { + keys := make([]string, 0, len(ss)) + + for key := range ss { + keys = append(keys, key) + } + + return keys +} diff --git a/utils/token/token.go b/utils/token/token.go new file mode 100644 index 000000000..850f5813f --- /dev/null +++ b/utils/token/token.go @@ -0,0 +1,378 @@ +package token + +import ( + "crypto" + "crypto/x509" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + log "github.com/Sirupsen/logrus" + "github.com/docker/libtrust" + + "github.com/docker/distribution/registry/auth" +) + +const ( + // TokenSeparator is the value which separates the header, claims, and + // signature in the compact serialization of a JSON Web Token. + TokenSeparator = "." + // Leeway is the Duration that will be added to NBF and EXP claim + // checks to account for clock skew as per https://tools.ietf.org/html/rfc7519#section-4.1.5 + Leeway = 60 * time.Second +) + +// Errors used by token parsing and verification. +var ( + ErrMalformedToken = errors.New("malformed token") + ErrInvalidToken = errors.New("invalid token") +) + +// ResourceActions stores allowed actions on a named and typed resource. +type ResourceActions struct { + Type string `json:"type"` + Class string `json:"class,omitempty"` + Name string `json:"name"` + Actions []string `json:"actions"` +} + +// ClaimSet describes the main section of a JSON Web Token. +type ClaimSet struct { + // Public claims + Issuer string `json:"iss"` + Subject string `json:"sub"` + Audience string `json:"aud"` + Expiration int64 `json:"exp"` + NotBefore int64 `json:"nbf"` + IssuedAt int64 `json:"iat"` + JWTID string `json:"jti"` + + // Private claims + Access []*ResourceActions `json:"access"` +} + +// Header describes the header section of a JSON Web Token. +type Header struct { + Type string `json:"typ"` + SigningAlg string `json:"alg"` + KeyID string `json:"kid,omitempty"` + X5c []string `json:"x5c,omitempty"` + RawJWK *json.RawMessage `json:"jwk,omitempty"` +} + +// Token describes a JSON Web Token. +type Token struct { + Raw string + Header *Header + Claims *ClaimSet + Signature []byte +} + +// VerifyOptions is used to specify +// options when verifying a JSON Web Token. +type VerifyOptions struct { + TrustedIssuers []string + AcceptedAudiences []string + Roots *x509.CertPool + TrustedKeys map[string]libtrust.PublicKey +} + +// NewToken parses the given raw token string +// and constructs an unverified JSON Web Token. +func NewToken(rawToken string) (*Token, error) { + parts := strings.Split(rawToken, TokenSeparator) + if len(parts) != 3 { + return nil, ErrMalformedToken + } + + var ( + rawHeader, rawClaims = parts[0], parts[1] + headerJSON, claimsJSON []byte + err error + ) + + defer func() { + if err != nil { + log.Infof("error while unmarshalling raw token: %s", err) + } + }() + + if headerJSON, err = joseBase64UrlDecode(rawHeader); err != nil { + err = fmt.Errorf("unable to decode header: %s", err) + return nil, ErrMalformedToken + } + + if claimsJSON, err = joseBase64UrlDecode(rawClaims); err != nil { + err = fmt.Errorf("unable to decode claims: %s", err) + return nil, ErrMalformedToken + } + + token := new(Token) + token.Header = new(Header) + token.Claims = new(ClaimSet) + + token.Raw = strings.Join(parts[:2], TokenSeparator) + if token.Signature, err = joseBase64UrlDecode(parts[2]); err != nil { + err = fmt.Errorf("unable to decode signature: %s", err) + return nil, ErrMalformedToken + } + + if err = json.Unmarshal(headerJSON, token.Header); err != nil { + return nil, ErrMalformedToken + } + + if err = json.Unmarshal(claimsJSON, token.Claims); err != nil { + return nil, ErrMalformedToken + } + + return token, nil +} + +// Verify attempts to verify this token using the given options. +// Returns a nil error if the token is valid. +func (t *Token) Verify(verifyOpts VerifyOptions) error { + // Verify that the Issuer claim is a trusted authority. + if !contains(verifyOpts.TrustedIssuers, t.Claims.Issuer) { + log.Infof("token from untrusted issuer: %q", t.Claims.Issuer) + return ErrInvalidToken + } + + // Verify that the Audience claim is allowed. + if !contains(verifyOpts.AcceptedAudiences, t.Claims.Audience) { + log.Infof("token intended for another audience: %q", t.Claims.Audience) + return ErrInvalidToken + } + + // Verify that the token is currently usable and not expired. + currentTime := time.Now() + + ExpWithLeeway := time.Unix(t.Claims.Expiration, 0).Add(Leeway) + if currentTime.After(ExpWithLeeway) { + log.Infof("token not to be used after %s - currently %s", ExpWithLeeway, currentTime) + return ErrInvalidToken + } + + NotBeforeWithLeeway := time.Unix(t.Claims.NotBefore, 0).Add(-Leeway) + if currentTime.Before(NotBeforeWithLeeway) { + log.Infof("token not to be used before %s - currently %s", NotBeforeWithLeeway, currentTime) + return ErrInvalidToken + } + + // Verify the token signature. + if len(t.Signature) == 0 { + log.Info("token has no signature") + return ErrInvalidToken + } + + // Verify that the signing key is trusted. + signingKey, err := t.VerifySigningKey(verifyOpts) + if err != nil { + log.Info(err) + return ErrInvalidToken + } + + // Finally, verify the signature of the token using the key which signed it. + if err := signingKey.Verify(strings.NewReader(t.Raw), t.Header.SigningAlg, t.Signature); err != nil { + log.Infof("unable to verify token signature: %s", err) + return ErrInvalidToken + } + + return nil +} + +// VerifySigningKey attempts to get the key which was used to sign this token. +// The token header should contain either of these 3 fields: +// `x5c` - The x509 certificate chain for the signing key. Needs to be +// verified. +// `jwk` - The JSON Web Key representation of the signing key. +// May contain its own `x5c` field which needs to be verified. +// `kid` - The unique identifier for the key. This library interprets it +// as a libtrust fingerprint. The key itself can be looked up in +// the trustedKeys field of the given verify options. +// Each of these methods are tried in that order of preference until the +// signing key is found or an error is returned. +func (t *Token) VerifySigningKey(verifyOpts VerifyOptions) (signingKey libtrust.PublicKey, err error) { + // First attempt to get an x509 certificate chain from the header. + var ( + x5c = t.Header.X5c + rawJWK = t.Header.RawJWK + keyID = t.Header.KeyID + ) + + switch { + case len(x5c) > 0: + signingKey, err = parseAndVerifyCertChain(x5c, verifyOpts.Roots) + case rawJWK != nil: + signingKey, err = parseAndVerifyRawJWK(rawJWK, verifyOpts) + case len(keyID) > 0: + signingKey = verifyOpts.TrustedKeys[keyID] + if signingKey == nil { + err = fmt.Errorf("token signed by untrusted key with ID: %q", keyID) + } + default: + err = errors.New("unable to get token signing key") + } + + return +} + +func parseAndVerifyCertChain(x5c []string, roots *x509.CertPool) (leafKey libtrust.PublicKey, err error) { + if len(x5c) == 0 { + return nil, errors.New("empty x509 certificate chain") + } + + // Ensure the first element is encoded correctly. + leafCertDer, err := base64.StdEncoding.DecodeString(x5c[0]) + if err != nil { + return nil, fmt.Errorf("unable to decode leaf certificate: %s", err) + } + + // And that it is a valid x509 certificate. + leafCert, err := x509.ParseCertificate(leafCertDer) + if err != nil { + return nil, fmt.Errorf("unable to parse leaf certificate: %s", err) + } + + // The rest of the certificate chain are intermediate certificates. + intermediates := x509.NewCertPool() + for i := 1; i < len(x5c); i++ { + intermediateCertDer, err := base64.StdEncoding.DecodeString(x5c[i]) + if err != nil { + return nil, fmt.Errorf("unable to decode intermediate certificate: %s", err) + } + + intermediateCert, err := x509.ParseCertificate(intermediateCertDer) + if err != nil { + return nil, fmt.Errorf("unable to parse intermediate certificate: %s", err) + } + + intermediates.AddCert(intermediateCert) + } + + verifyOpts := x509.VerifyOptions{ + Intermediates: intermediates, + Roots: roots, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, + } + + // TODO: this call returns certificate chains which we ignore for now, but + // we should check them for revocations if we have the ability later. + if _, err = leafCert.Verify(verifyOpts); err != nil { + return nil, fmt.Errorf("unable to verify certificate chain: %s", err) + } + + // Get the public key from the leaf certificate. + leafCryptoKey, ok := leafCert.PublicKey.(crypto.PublicKey) + if !ok { + return nil, errors.New("unable to get leaf cert public key value") + } + + leafKey, err = libtrust.FromCryptoPublicKey(leafCryptoKey) + if err != nil { + return nil, fmt.Errorf("unable to make libtrust public key from leaf certificate: %s", err) + } + + return +} + +func parseAndVerifyRawJWK(rawJWK *json.RawMessage, verifyOpts VerifyOptions) (pubKey libtrust.PublicKey, err error) { + pubKey, err = libtrust.UnmarshalPublicKeyJWK([]byte(*rawJWK)) + if err != nil { + return nil, fmt.Errorf("unable to decode raw JWK value: %s", err) + } + + // Check to see if the key includes a certificate chain. + x5cVal, ok := pubKey.GetExtendedField("x5c").([]interface{}) + if !ok { + // The JWK should be one of the trusted root keys. + if _, trusted := verifyOpts.TrustedKeys[pubKey.KeyID()]; !trusted { + return nil, errors.New("untrusted JWK with no certificate chain") + } + + // The JWK is one of the trusted keys. + return + } + + // Ensure each item in the chain is of the correct type. + x5c := make([]string, len(x5cVal)) + for i, val := range x5cVal { + certString, ok := val.(string) + if !ok || len(certString) == 0 { + return nil, errors.New("malformed certificate chain") + } + x5c[i] = certString + } + + // Ensure that the x509 certificate chain can + // be verified up to one of our trusted roots. + leafKey, err := parseAndVerifyCertChain(x5c, verifyOpts.Roots) + if err != nil { + return nil, fmt.Errorf("could not verify JWK certificate chain: %s", err) + } + + // Verify that the public key in the leaf cert *is* the signing key. + if pubKey.KeyID() != leafKey.KeyID() { + return nil, errors.New("leaf certificate public key ID does not match JWK key ID") + } + + return +} + +// accessSet returns a set of actions available for the resource +// actions listed in the `access` section of this token. +func (t *Token) accessSet() accessSet { + if t.Claims == nil { + return nil + } + + accessSet := make(accessSet, len(t.Claims.Access)) + + for _, resourceActions := range t.Claims.Access { + resource := auth.Resource{ + Type: resourceActions.Type, + Name: resourceActions.Name, + } + + set, exists := accessSet[resource] + if !exists { + set = newActionSet() + accessSet[resource] = set + } + + for _, action := range resourceActions.Actions { + set.add(action) + } + } + + return accessSet +} + +func (t *Token) resources() []auth.Resource { + if t.Claims == nil { + return nil + } + + resourceSet := map[auth.Resource]struct{}{} + for _, resourceActions := range t.Claims.Access { + resource := auth.Resource{ + Type: resourceActions.Type, + Class: resourceActions.Class, + Name: resourceActions.Name, + } + resourceSet[resource] = struct{}{} + } + + resources := make([]auth.Resource, 0, len(resourceSet)) + for resource := range resourceSet { + resources = append(resources, resource) + } + + return resources +} + +func (t *Token) compactRaw() string { + return fmt.Sprintf("%s.%s", t.Raw, joseBase64UrlEncode(t.Signature)) +} diff --git a/utils/token/util.go b/utils/token/util.go new file mode 100644 index 000000000..0b283ad8b --- /dev/null +++ b/utils/token/util.go @@ -0,0 +1,73 @@ +package token + +import ( + "encoding/base64" + "errors" + "github.com/docker/distribution/registry/auth" + "strings" +) + +// joseBase64UrlEncode encodes the given data using the standard base64 url +// encoding format but with all trailing '=' characters omitted in accordance +// with the jose specification. +// http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-2 +func joseBase64UrlEncode(b []byte) string { + return strings.TrimRight(base64.URLEncoding.EncodeToString(b), "=") +} + +// joseBase64UrlDecode decodes the given string using the standard base64 url +// decoder but first adds the appropriate number of trailing '=' characters in +// accordance with the jose specification. +// http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-2 +func joseBase64UrlDecode(s string) ([]byte, error) { + switch len(s) % 4 { + case 0: + case 2: + s += "==" + case 3: + s += "=" + default: + return nil, errors.New("illegal base64url string") + } + return base64.URLEncoding.DecodeString(s) +} + +// actionSet is a special type of stringSet. +type actionSet struct { + stringSet +} + +func newActionSet(actions ...string) actionSet { + return actionSet{newStringSet(actions...)} +} + +// Contains calls StringSet.Contains() for +// either "*" or the given action string. +func (s actionSet) contains(action string) bool { + return s.stringSet.contains("*") || s.stringSet.contains(action) +} + +// contains returns true if q is found in ss. +func contains(ss []string, q string) bool { + for _, s := range ss { + if s == q { + return true + } + } + + return false +} + +func BuildAccessRecords(repo string, actions ...string) []auth.Access { + requiredAccess := make([]auth.Access, 0, len(actions)) + for _, action := range actions { + requiredAccess = append(requiredAccess, auth.Access{ + Resource: auth.Resource{ + Type: "repository", + Name: repo, + }, + Action: action, + }) + } + return requiredAccess +} From cc73b50da539264644f6224ecc23be92dc4419be Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Tue, 14 Mar 2017 10:18:07 -0700 Subject: [PATCH 10/62] working token auth end to end Signed-off-by: David Lawrence (github: endophage) --- client/auth/challenge/authchallenge.go | 222 ++++++++++++++++ client/auth/session.go | 337 +++++++++++++++++++++++++ utils/grpcauth/auth.go | 103 +++++++- utils/grpcauth/auth_test.go | 6 +- utils/token/accesscontroller.go | 2 +- 5 files changed, 652 insertions(+), 18 deletions(-) create mode 100644 client/auth/challenge/authchallenge.go create mode 100644 client/auth/session.go diff --git a/client/auth/challenge/authchallenge.go b/client/auth/challenge/authchallenge.go new file mode 100644 index 000000000..38b9b7994 --- /dev/null +++ b/client/auth/challenge/authchallenge.go @@ -0,0 +1,222 @@ +package challenge + +import ( + "net/http" + "net/url" + "strings" +) + +// Challenge carries information from a WWW-Authenticate response header. +// See RFC 2617. +type Challenge struct { + // Scheme is the auth-scheme according to RFC 2617 + Scheme string + + // Parameters are the auth-params according to RFC 2617 + Parameters map[string]string +} + +// Manager manages the challenges for endpoints. +// The challenges are pulled out of HTTP responses. Only +// responses which expect challenges should be added to +// the manager, since a non-unauthorized request will be +// viewed as not requiring challenges. +type Manager interface { + // GetChallenges returns the challenges for the given + // endpoint URL. + GetChallenges(endpoint url.URL) ([]Challenge, error) + + // AddResponse adds the response to the challenge + // manager. The challenges will be parsed out of + // the WWW-Authenicate headers and added to the + // URL which was produced the response. If the + // response was authorized, any challenges for the + // endpoint will be cleared. + AddResponse(resp *http.Response) error +} + +// NewSimpleManager returns an instance of +// Manger which only maps endpoints to challenges +// based on the responses which have been added the +// manager. The simple manager will make no attempt to +// perform requests on the endpoints or cache the responses +// to a backend. +//func NewSimpleManager() Manager { +// return &simpleManager{ +// Challanges: make(map[string][]Challenge), +// } +//} +// +//type simpleManager struct { +// sync.RWMutex +// Challanges map[string][]Challenge +//} +// +//func normalizeURL(endpoint *url.URL) { +// endpoint.Host = strings.ToLower(endpoint.Host) +// endpoint.Host = canonicalAddr(endpoint) +//} +// +//func (m *simpleManager) GetChallenges(endpoint url.URL) ([]Challenge, error) { +// normalizeURL(&endpoint) +// +// m.RLock() +// defer m.RUnlock() +// challenges := m.Challanges[endpoint.String()] +// return challenges, nil +//} +// +//func (m *simpleManager) AddResponse(resp *http.Response) error { +// challenges := ResponseChallenges(resp) +// if resp.Request == nil { +// return fmt.Errorf("missing request reference") +// } +// urlCopy := url.URL{ +// Path: resp.Request.URL.Path, +// Host: resp.Request.URL.Host, +// Scheme: resp.Request.URL.Scheme, +// } +// normalizeURL(&urlCopy) +// +// m.Lock() +// defer m.Unlock() +// m.Challanges[urlCopy.String()] = challenges +// return nil +//} + +// Octet types from RFC 2616. +type octetType byte + +var octetTypes [256]octetType + +const ( + isToken octetType = 1 << iota + isSpace +) + +func init() { + // OCTET = + // CHAR = + // CTL = + // CR = + // LF = + // SP = + // HT = + // <"> = + // CRLF = CR LF + // LWS = [CRLF] 1*( SP | HT ) + // TEXT = + // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> + // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT + // token = 1* + // qdtext = > + + for c := 0; c < 256; c++ { + var t octetType + isCtl := c <= 31 || c == 127 + isChar := 0 <= c && c <= 127 + isSeparator := strings.IndexRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) >= 0 + if strings.IndexRune(" \t\r\n", rune(c)) >= 0 { + t |= isSpace + } + if isChar && !isCtl && !isSeparator { + t |= isToken + } + octetTypes[c] = t + } +} + +func ParseAuthHeader(header []string) []Challenge { + challenges := []Challenge{} + for _, h := range header { + v, p := parseValueAndParams(h) + if v != "" { + challenges = append(challenges, Challenge{Scheme: v, Parameters: p}) + } + } + return challenges +} + +func parseValueAndParams(header string) (value string, params map[string]string) { + params = make(map[string]string) + value, s := expectToken(header) + if value == "" { + return + } + value = strings.ToLower(value) + s = "," + skipSpace(s) + for strings.HasPrefix(s, ",") { + var pkey string + pkey, s = expectToken(skipSpace(s[1:])) + if pkey == "" { + return + } + if !strings.HasPrefix(s, "=") { + return + } + var pvalue string + pvalue, s = expectTokenOrQuoted(s[1:]) + if pvalue == "" { + return + } + pkey = strings.ToLower(pkey) + params[pkey] = pvalue + s = skipSpace(s) + } + return +} + +func skipSpace(s string) (rest string) { + i := 0 + for ; i < len(s); i++ { + if octetTypes[s[i]]&isSpace == 0 { + break + } + } + return s[i:] +} + +func expectToken(s string) (token, rest string) { + i := 0 + for ; i < len(s); i++ { + if octetTypes[s[i]]&isToken == 0 { + break + } + } + return s[:i], s[i:] +} + +func expectTokenOrQuoted(s string) (value string, rest string) { + if !strings.HasPrefix(s, "\"") { + return expectToken(s) + } + s = s[1:] + for i := 0; i < len(s); i++ { + switch s[i] { + case '"': + return s[:i], s[i+1:] + case '\\': + p := make([]byte, len(s)-1) + j := copy(p, s[:i]) + escape := true + for i = i + 1; i < len(s); i++ { + b := s[i] + switch { + case escape: + escape = false + p[j] = b + j++ + case b == '\\': + escape = true + case b == '"': + return string(p[:j]), s[i+1:] + default: + p[j] = b + j++ + } + } + return "", "" + } + } + return "", "" +} diff --git a/client/auth/session.go b/client/auth/session.go new file mode 100644 index 000000000..248cceb80 --- /dev/null +++ b/client/auth/session.go @@ -0,0 +1,337 @@ +package auth + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + "net/url" + "strings" + "sync" + "time" + + "github.com/Sirupsen/logrus" + "github.com/docker/distribution/registry/client" +) + +var ( + // ErrNoBasicAuthCredentials is returned if a request can't be authorized with + // basic auth due to lack of credentials. + ErrNoBasicAuthCredentials = errors.New("no basic auth credentials") + + // ErrNoToken is returned if a request is successful but the body does not + // contain an authorization token. + ErrNoToken = errors.New("authorization server did not include a token in the response") +) + +// CredentialStore is an interface for getting credentials for +// a given URL +type CredentialStore interface { + // Basic returns basic auth for the given URL + Basic(*url.URL) (string, string) + + // RefreshToken returns a refresh token for the + // given URL and service + RefreshToken(*url.URL, string) string + + // SetRefreshToken sets the refresh token if none + // is provided for the given url and service + SetRefreshToken(realm *url.URL, service, token string) +} + +// This is the minimum duration a token can last (in seconds). +// A token must not live less than 60 seconds because older versions +// of the Docker client didn't read their expiration from the token +// response and assumed 60 seconds. So to remain compatible with +// those implementations, a token must live at least this long. +const minimumTokenLifetimeSeconds = 60 + +type TokenHandler struct { + creds CredentialStore + transport http.RoundTripper + + offlineAccess bool + forceOAuth bool + clientID string + scopes []Scope + + tokenLock sync.Mutex + tokenCache string + tokenExpiration time.Time +} + +// Scope is a type which is serializable to a string +// using the allow scope grammar. +type Scope interface { + String() string +} + +// RepositoryScope represents a token scope for access +// to a repository. +type RepositoryScope struct { + Repository string + Class string + Actions []string +} + +// String returns the string representation of the repository +// using the scope grammar +func (rs RepositoryScope) String() string { + repoType := "repository" + if rs.Class != "" { + repoType = fmt.Sprintf("%s(%s)", repoType, rs.Class) + } + return fmt.Sprintf("%s:%s:%s", repoType, rs.Repository, strings.Join(rs.Actions, ",")) +} + +//// RegistryScope represents a token scope for access +//// to resources in the registry. +//type RegistryScope struct { +// Name string +// Actions []string +//} +// +//// String returns the string representation of the user +//// using the scope grammar +//func (rs RegistryScope) String() string { +// return fmt.Sprintf("registry:%s:%s", rs.Name, strings.Join(rs.Actions, ",")) +//} + +// TokenHandlerOptions is used to configure a new token handler +type TokenHandlerOptions struct { + Transport http.RoundTripper + Credentials CredentialStore + + OfflineAccess bool + ForceOAuth bool + ClientID string + Scopes []Scope +} + +// NewTokenHandler creates a new AuthenicationHandler which supports +// fetching tokens from a remote token server. +func NewTokenHandler(transport http.RoundTripper, creds CredentialStore, clientID, scope string, actions ...string) *TokenHandler { + return &TokenHandler{ + transport: transport, + creds: creds, + offlineAccess: false, + forceOAuth: false, + clientID: clientID, + //scopes: []Scope{ + // RepositoryScope{ + // Repository: scope, + // Actions: actions, + // }, + //}, + } +} + +func (th *TokenHandler) client() *http.Client { + return &http.Client{ + Transport: th.transport, + Timeout: 15 * time.Second, + } +} + +func (th *TokenHandler) Scheme() string { + return "bearer" +} + +func (th *TokenHandler) AuthorizeRequest(params map[string]string, scopes ...string) (string, error) { + //th.tokenLock.Lock() + //defer th.tokenLock.Unlock() + + rawToken, _, err := th.fetchToken(params, scopes) + return rawToken, err +} + +type postTokenResponse struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + ExpiresIn int `json:"expires_in"` + IssuedAt time.Time `json:"issued_at"` + Scope string `json:"scope"` +} + +func (th *TokenHandler) fetchTokenWithOAuth(realm *url.URL, refreshToken, service string, scopes []string) (token string, expiration time.Time, err error) { + form := url.Values{} + form.Set("scope", strings.Join(scopes, " ")) + form.Set("service", service) + + clientID := th.clientID + if clientID == "" { + // Use default client, this is a required field + return "", time.Time{}, errors.New("no client ID configured") + } + form.Set("client_id", clientID) + + if refreshToken != "" { + form.Set("grant_type", "refresh_token") + form.Set("refresh_token", refreshToken) + } else if th.creds != nil { + form.Set("grant_type", "password") + username, password := th.creds.Basic(realm) + form.Set("username", username) + form.Set("password", password) + + // attempt to get a refresh token + form.Set("access_type", "offline") + } else { + // refuse to do oauth without a grant type + return "", time.Time{}, fmt.Errorf("no supported grant type") + } + + resp, err := th.client().PostForm(realm.String(), form) + if err != nil { + return "", time.Time{}, err + } + defer resp.Body.Close() + + if !client.SuccessStatus(resp.StatusCode) { + err := client.HandleErrorResponse(resp) + return "", time.Time{}, err + } + + decoder := json.NewDecoder(resp.Body) + + var tr postTokenResponse + if err = decoder.Decode(&tr); err != nil { + return "", time.Time{}, fmt.Errorf("unable to decode token response: %s", err) + } + + if tr.RefreshToken != "" && tr.RefreshToken != refreshToken { + th.creds.SetRefreshToken(realm, service, tr.RefreshToken) + } + + if tr.ExpiresIn < minimumTokenLifetimeSeconds { + // The default/minimum lifetime. + tr.ExpiresIn = minimumTokenLifetimeSeconds + logrus.Debugf("Increasing token expiration to: %d seconds", tr.ExpiresIn) + } + + if tr.IssuedAt.IsZero() { + // issued_at is optional in the token response. + tr.IssuedAt = time.Now().UTC() + } + + return tr.AccessToken, tr.IssuedAt.Add(time.Duration(tr.ExpiresIn) * time.Second), nil +} + +type getTokenResponse struct { + Token string `json:"token"` + AccessToken string `json:"access_token"` + ExpiresIn int `json:"expires_in"` + IssuedAt time.Time `json:"issued_at"` + RefreshToken string `json:"refresh_token"` +} + +func (th *TokenHandler) fetchTokenWithBasicAuth(realm *url.URL, service string, scopes []string) (token string, expiration time.Time, err error) { + + req, err := http.NewRequest("GET", realm.String(), nil) + if err != nil { + return "", time.Time{}, err + } + + reqParams := req.URL.Query() + + if service != "" { + reqParams.Add("service", service) + } + + for _, scope := range scopes { + reqParams.Add("scope", scope) + } + + if th.offlineAccess { + reqParams.Add("offline_token", "true") + clientID := th.clientID + if clientID == "" { + return "", time.Time{}, errors.New("no client ID configured") + } + reqParams.Add("client_id", clientID) + } + + if th.creds != nil { + username, password := th.creds.Basic(realm) + if username != "" && password != "" { + reqParams.Add("account", username) + req.SetBasicAuth(username, password) + } + } + + req.URL.RawQuery = reqParams.Encode() + logrus.Infof("requesting token for following permissions: %s", req.URL.RawQuery) + + resp, err := th.client().Do(req) + if err != nil { + return "", time.Time{}, err + } + defer resp.Body.Close() + + if !client.SuccessStatus(resp.StatusCode) { + err := client.HandleErrorResponse(resp) + return "", time.Time{}, err + } + + decoder := json.NewDecoder(resp.Body) + + var tr getTokenResponse + if err = decoder.Decode(&tr); err != nil { + return "", time.Time{}, fmt.Errorf("unable to decode token response: %s", err) + } + + if tr.RefreshToken != "" && th.creds != nil { + th.creds.SetRefreshToken(realm, service, tr.RefreshToken) + } + + // `access_token` is equivalent to `token` and if both are specified + // the choice is undefined. Canonicalize `access_token` by sticking + // things in `token`. + if tr.AccessToken != "" { + tr.Token = tr.AccessToken + } + + if tr.Token == "" { + return "", time.Time{}, ErrNoToken + } + + if tr.ExpiresIn < minimumTokenLifetimeSeconds { + // The default/minimum lifetime. + tr.ExpiresIn = minimumTokenLifetimeSeconds + logrus.Debugf("Increasing token expiration to: %d seconds", tr.ExpiresIn) + } + + if tr.IssuedAt.IsZero() { + // issued_at is optional in the token response. + tr.IssuedAt = time.Now().UTC() + } + + return tr.Token, tr.IssuedAt.Add(time.Duration(tr.ExpiresIn) * time.Second), nil +} + +func (th *TokenHandler) fetchToken(params map[string]string, scopes []string) (token string, expiration time.Time, err error) { + realm, ok := params["realm"] + if !ok { + return "", time.Time{}, errors.New("no realm specified for token auth challenge") + } + + // TODO(dmcgowan): Handle empty scheme and relative realm + realmURL, err := url.Parse(realm) + if err != nil { + return "", time.Time{}, fmt.Errorf("invalid token auth challenge realm: %s", err) + } + + service := params["service"] + + var refreshToken string + + if th.creds != nil { + refreshToken = th.creds.RefreshToken(realmURL, service) + } + + if refreshToken != "" || th.forceOAuth { + return th.fetchTokenWithOAuth(realmURL, refreshToken, service, scopes) + } + + return th.fetchTokenWithBasicAuth(realmURL, service, scopes) +} diff --git a/utils/grpcauth/auth.go b/utils/grpcauth/auth.go index c89f64a94..e1201a658 100644 --- a/utils/grpcauth/auth.go +++ b/utils/grpcauth/auth.go @@ -1,13 +1,18 @@ package grpcauth import ( + "fmt" "github.com/Sirupsen/logrus" + "github.com/docker/notary/client/auth" + "github.com/docker/notary/client/auth/challenge" "github.com/docker/notary/utils/token" google_protobuf "github.com/golang/protobuf/ptypes/empty" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" + "net/http" + "net/url" ) type guner interface { @@ -16,16 +21,16 @@ type guner interface { // ServerAuthorizer performs server checks for the correct authorization tokens type ServerAuthorizer struct { - permissions map[string][]string - auth *token.Auth + permissions map[string][]string + authVerifier *token.Auth } // NewServerAuthorizer instantiates a ServerAuthorizer and returns the Interceptor // attached to it. -func NewServerAuthorizer(auth *token.Auth, permissions map[string][]string) (grpc.UnaryServerInterceptor, error) { +func NewServerAuthorizer(authVerifier *token.Auth, permissions map[string][]string) (grpc.UnaryServerInterceptor, error) { s := ServerAuthorizer{ - permissions: permissions, - auth: auth, + permissions: permissions, + authVerifier: authVerifier, } return s.Interceptor, nil } @@ -34,7 +39,7 @@ func NewServerAuthorizer(auth *token.Auth, permissions map[string][]string) (grp // token scope and actions, or allows the request to proceed // TODO: are the error responses the ones we want to use func (s ServerAuthorizer) Interceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { - if s.auth != nil { + if s.authVerifier != nil { gnr, ok := req.(guner) if !ok { return &google_protobuf.Empty{}, grpc.Errorf( @@ -45,13 +50,13 @@ func (s ServerAuthorizer) Interceptor(ctx context.Context, req interface{}, info md, ok := metadata.FromContext(ctx) var rawToken string if ok { - ts := md["Authorization"] + ts := md["authorization"] if len(ts) > 0 { rawToken = ts[0] } } - if _, err := s.auth.Authorize(rawToken); !ok || err != nil { - md := s.auth.ChallengeHeaders( + if _, err := s.authVerifier.Authorize(rawToken); !ok || err != nil { + md := s.authVerifier.ChallengeHeaders( err, token.BuildAccessRecords( gnr.GetGun(), @@ -70,10 +75,19 @@ func (s ServerAuthorizer) Interceptor(ctx context.Context, req interface{}, info // ClientAuthorizer deals with satisfying tokens required by the server. If it receives an // error response, it will attempt to retrieve a token the server will accept -type ClientAuthorizer struct{} +type ClientAuthorizer struct { + authHandler *auth.TokenHandler +} func NewClientAuthorizer() grpc.UnaryClientInterceptor { - c := ClientAuthorizer{} + c := ClientAuthorizer{ + authHandler: auth.NewTokenHandler( + http.DefaultTransport, + credStore{}, + "registry-client", + "", + ), + } return c.Interceptor } @@ -83,13 +97,74 @@ func (c *ClientAuthorizer) Interceptor(ctx context.Context, method string, req, headers := metadata.MD{} opts = append(opts, grpc.Header(&headers)) err := invoker(ctx, method, req, reply, cc, opts...) - if err != nil { + if err == nil { + // no error, we can immediately return + return nil + } + + logrus.Error(err) + code := grpc.Code(err) + if code != codes.Unauthenticated { + // an error other than unauthenticated, there's nothing we can do further to try + // and make this request succeed. + return err + } + + tok, errToken := c.getToken(headers["www-authenticate"]) + if errToken != nil { + // couldn't get a token, log the error and return the original Unauthenticated error + // (the caller of the GRPC method may be relying on a grpc type error) logrus.Error(err) - //return err + return err + } + logrus.Info("token") + logrus.Info(tok) + + md, ok := metadata.FromContext(ctx) + if !ok { + md = metadata.New(nil) + } + md["authorization"] = []string{ + fmt.Sprintf("Bearer %s", tok), } - md := metadata.New(map[string]string{"Authorization": "foo"}) ctx = metadata.NewContext(ctx, md) err = invoker(ctx, method, req, reply, cc, opts...) return err } + +func (c *ClientAuthorizer) getToken(challengeHeader []string) (string, error) { + challenges := challenge.ParseAuthHeader(challengeHeader) + logrus.Infof("received challenge for following token: %s", challenges[0]) + return c.authHandler.AuthorizeRequest(challenges[0].Parameters, challenges[0].Parameters["scope"]) +} + +func NewCredStore(username, password string, refreshTokens, accessTokens map[string]string) auth.CredentialStore { + if refreshTokens == nil { + refreshTokens = make(map[string]string) + } + if accessTokens == nil { + accessTokens = make(map[string]string) + } + return &credStore{ + username: username, + password: password, + refreshTokens: refreshTokens, + accessTokens: accessTokens, + } +} + +type credStore struct { + username, password string + refreshTokens, accessTokens map[string]string +} + +func (cs credStore) Basic(*url.URL) (string, string) { + return cs.username, cs.password +} + +func (cs credStore) RefreshToken(*url.URL, string) string { + return "" +} + +func (cs credStore) SetRefreshToken(realm *url.URL, service, token string) {} diff --git a/utils/grpcauth/auth_test.go b/utils/grpcauth/auth_test.go index db20b74e2..186acf074 100644 --- a/utils/grpcauth/auth_test.go +++ b/utils/grpcauth/auth_test.go @@ -11,12 +11,12 @@ import ( ) func TestServerAuthorizer(t *testing.T) { - tok, err := token.NewAuth("testRealm", "testIssuer", "service", "../../fixtures/root-ca.crt") + tok, err := token.NewAuth("https://auth.docker.io/token", "auth.docker.io", "registry.docker.io", "../../fixtures/root-ca.crt") require.NoError(t, err) auth, err := NewServerAuthorizer( tok, map[string][]string{ - "/api.Notary/AddTarget": {"push", "pull"}, + "/api.Notary/AddTarget": {"push"}, }, ) require.NoError(t, err) @@ -35,7 +35,7 @@ func TestServerAuthorizer(t *testing.T) { grpc.WithUnaryInterceptor(NewClientAuthorizer()), ) require.NoError(t, err) - c := api.NewClient(conn, "testRepo") + c := api.NewClient(conn, "endophage/carrot") err = c.AddTarget( &client.Target{}, "targets", diff --git a/utils/token/accesscontroller.go b/utils/token/accesscontroller.go index 350138e80..9dba869a4 100644 --- a/utils/token/accesscontroller.go +++ b/utils/token/accesscontroller.go @@ -111,7 +111,7 @@ func (ac authChallenge) challengeParams() string { // SetChallenge sets the WWW-Authenticate value for the response. func (ac authChallenge) Headers() map[string][]string { return map[string][]string{ - "authenticate": {ac.challengeParams()}, + "www-authenticate": {ac.challengeParams()}, } } From 02415dba6ae57087f06941b344ba4db7bcf228de Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 7 Mar 2017 01:11:08 +0100 Subject: [PATCH 11/62] Add Target operations to client API protobuf definitions and generated code Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 467 +++++++++++++++++++++++++++++++++++---- client_api/api/api.proto | 74 ++++++- 2 files changed, 494 insertions(+), 47 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index 5456bf7c9..797c8434d 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -9,7 +9,17 @@ It is generated from these files: api.proto It has these top-level messages: - TargetAction + RoleList + TargetName + Target + TargetWithRole + TargetWithRoleList + TargetByNameAction + Signature + PublicKey + DelegationRole + TargetSigned + TargetSignedList BasicResponse */ package api @@ -34,8 +44,41 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +// RoleList message holds a list of TUF role names +type RoleList struct { + Roles []string `protobuf:"bytes,1,rep,name=roles" json:"roles,omitempty"` +} + +func (m *RoleList) Reset() { *m = RoleList{} } +func (m *RoleList) String() string { return proto.CompactTextString(m) } +func (*RoleList) ProtoMessage() {} +func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *RoleList) GetRoles() []string { + if m != nil { + return m.Roles + } + return nil +} + +type TargetName struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *TargetName) Reset() { *m = TargetName{} } +func (m *TargetName) String() string { return proto.CompactTextString(m) } +func (*TargetName) ProtoMessage() {} +func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *TargetName) GetName() string { + if m != nil { + return m.Name + } + return "" +} + // Target message describes a TUF target -type TargetAction struct { +type Target struct { Gun string `protobuf:"bytes,1,opt,name=gun" json:"gun,omitempty"` Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` Length int64 `protobuf:"varint,3,opt,name=length" json:"length,omitempty"` @@ -43,46 +86,247 @@ type TargetAction struct { Custom []byte `protobuf:"bytes,5,opt,name=custom,proto3" json:"custom,omitempty"` } -func (m *TargetAction) Reset() { *m = TargetAction{} } -func (m *TargetAction) String() string { return proto.CompactTextString(m) } -func (*TargetAction) ProtoMessage() {} -func (*TargetAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *Target) Reset() { *m = Target{} } +func (m *Target) String() string { return proto.CompactTextString(m) } +func (*Target) ProtoMessage() {} +func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } -func (m *TargetAction) GetGun() string { +func (m *Target) GetGun() string { if m != nil { return m.Gun } return "" } -func (m *TargetAction) GetName() string { +func (m *Target) GetName() string { if m != nil { return m.Name } return "" } -func (m *TargetAction) GetLength() int64 { +func (m *Target) GetLength() int64 { if m != nil { return m.Length } return 0 } -func (m *TargetAction) GetHashes() map[string][]byte { +func (m *Target) GetHashes() map[string][]byte { if m != nil { return m.Hashes } return nil } -func (m *TargetAction) GetCustom() []byte { +func (m *Target) GetCustom() []byte { if m != nil { return m.Custom } return nil } +// TargetWithRole represents a Target that exists in a particular role +type TargetWithRole struct { + Target *Target `protobuf:"bytes,1,opt,name=target" json:"target,omitempty"` + Role string `protobuf:"bytes,2,opt,name=role" json:"role,omitempty"` +} + +func (m *TargetWithRole) Reset() { *m = TargetWithRole{} } +func (m *TargetWithRole) String() string { return proto.CompactTextString(m) } +func (*TargetWithRole) ProtoMessage() {} +func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *TargetWithRole) GetTarget() *Target { + if m != nil { + return m.Target + } + return nil +} + +func (m *TargetWithRole) GetRole() string { + if m != nil { + return m.Role + } + return "" +} + +type TargetWithRoleList struct { + Targets []*TargetWithRole `protobuf:"bytes,1,rep,name=targets" json:"targets,omitempty"` +} + +func (m *TargetWithRoleList) Reset() { *m = TargetWithRoleList{} } +func (m *TargetWithRoleList) String() string { return proto.CompactTextString(m) } +func (*TargetWithRoleList) ProtoMessage() {} +func (*TargetWithRoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *TargetWithRoleList) GetTargets() []*TargetWithRole { + if m != nil { + return m.Targets + } + return nil +} + +type TargetByNameAction struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Roles *RoleList `protobuf:"bytes,2,opt,name=roles" json:"roles,omitempty"` +} + +func (m *TargetByNameAction) Reset() { *m = TargetByNameAction{} } +func (m *TargetByNameAction) String() string { return proto.CompactTextString(m) } +func (*TargetByNameAction) ProtoMessage() {} +func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *TargetByNameAction) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *TargetByNameAction) GetRoles() *RoleList { + if m != nil { + return m.Roles + } + return nil +} + +type Signature struct { + KeyID string `protobuf:"bytes,1,opt,name=keyID" json:"keyID,omitempty"` + Method string `protobuf:"bytes,2,opt,name=method" json:"method,omitempty"` + Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` + IsValid bool `protobuf:"varint,4,opt,name=isValid" json:"isValid,omitempty"` +} + +func (m *Signature) Reset() { *m = Signature{} } +func (m *Signature) String() string { return proto.CompactTextString(m) } +func (*Signature) ProtoMessage() {} +func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *Signature) GetKeyID() string { + if m != nil { + return m.KeyID + } + return "" +} + +func (m *Signature) GetMethod() string { + if m != nil { + return m.Method + } + return "" +} + +func (m *Signature) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *Signature) GetIsValid() bool { + if m != nil { + return m.IsValid + } + return false +} + +type PublicKey struct { +} + +func (m *PublicKey) Reset() { *m = PublicKey{} } +func (m *PublicKey) String() string { return proto.CompactTextString(m) } +func (*PublicKey) ProtoMessage() {} +func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +type DelegationRole struct { + Keys map[string]*PublicKey `protobuf:"bytes,1,rep,name=keys" json:"keys,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` + Threshold int32 `protobuf:"varint,3,opt,name=threshold" json:"threshold,omitempty"` + Paths []string `protobuf:"bytes,4,rep,name=paths" json:"paths,omitempty"` +} + +func (m *DelegationRole) Reset() { *m = DelegationRole{} } +func (m *DelegationRole) String() string { return proto.CompactTextString(m) } +func (*DelegationRole) ProtoMessage() {} +func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *DelegationRole) GetKeys() map[string]*PublicKey { + if m != nil { + return m.Keys + } + return nil +} + +func (m *DelegationRole) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *DelegationRole) GetThreshold() int32 { + if m != nil { + return m.Threshold + } + return 0 +} + +func (m *DelegationRole) GetPaths() []string { + if m != nil { + return m.Paths + } + return nil +} + +type TargetSigned struct { + Role *DelegationRole `protobuf:"bytes,1,opt,name=role" json:"role,omitempty"` + Target *Target `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"` + Signatures []*Signature `protobuf:"bytes,3,rep,name=signatures" json:"signatures,omitempty"` +} + +func (m *TargetSigned) Reset() { *m = TargetSigned{} } +func (m *TargetSigned) String() string { return proto.CompactTextString(m) } +func (*TargetSigned) ProtoMessage() {} +func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +func (m *TargetSigned) GetRole() *DelegationRole { + if m != nil { + return m.Role + } + return nil +} + +func (m *TargetSigned) GetTarget() *Target { + if m != nil { + return m.Target + } + return nil +} + +func (m *TargetSigned) GetSignatures() []*Signature { + if m != nil { + return m.Signatures + } + return nil +} + +type TargetSignedList struct { + Targets []*TargetSigned `protobuf:"bytes,1,rep,name=targets" json:"targets,omitempty"` +} + +func (m *TargetSignedList) Reset() { *m = TargetSignedList{} } +func (m *TargetSignedList) String() string { return proto.CompactTextString(m) } +func (*TargetSignedList) ProtoMessage() {} +func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +func (m *TargetSignedList) GetTargets() []*TargetSigned { + if m != nil { + return m.Targets + } + return nil +} + // BasicResponse describes a response with a true/false success indicator, // and if false, an error type and message. See the errors.go file in this // package for the possible errors and a translation function between the @@ -95,7 +339,7 @@ type BasicResponse struct { func (m *BasicResponse) Reset() { *m = BasicResponse{} } func (m *BasicResponse) String() string { return proto.CompactTextString(m) } func (*BasicResponse) ProtoMessage() {} -func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *BasicResponse) GetSuccess() bool { if m != nil { @@ -112,7 +356,17 @@ func (m *BasicResponse) GetMessage() string { } func init() { - proto.RegisterType((*TargetAction)(nil), "api.TargetAction") + proto.RegisterType((*RoleList)(nil), "api.RoleList") + proto.RegisterType((*TargetName)(nil), "api.TargetName") + proto.RegisterType((*Target)(nil), "api.Target") + proto.RegisterType((*TargetWithRole)(nil), "api.TargetWithRole") + proto.RegisterType((*TargetWithRoleList)(nil), "api.TargetWithRoleList") + proto.RegisterType((*TargetByNameAction)(nil), "api.TargetByNameAction") + proto.RegisterType((*Signature)(nil), "api.Signature") + proto.RegisterType((*PublicKey)(nil), "api.PublicKey") + proto.RegisterType((*DelegationRole)(nil), "api.DelegationRole") + proto.RegisterType((*TargetSigned)(nil), "api.TargetSigned") + proto.RegisterType((*TargetSignedList)(nil), "api.TargetSignedList") proto.RegisterType((*BasicResponse)(nil), "api.BasicResponse") } @@ -128,10 +382,16 @@ const _ = grpc.SupportPackageIsVersion4 type NotaryClient interface { // AddTarget adds a target to the TUF repository and re-signs. - AddTarget(ctx context.Context, in *TargetAction, opts ...grpc.CallOption) (*BasicResponse, error) + AddTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) // RemoveTarget deletes a target from the TUF repository and re-signs. It only // uses the `name` field from the Target object, ignoring all other fields - RemoveTarget(ctx context.Context, in *TargetAction, opts ...grpc.CallOption) (*BasicResponse, error) + RemoveTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) + // ListTargets list the targets for the specified roles in the TUF repository + ListTargets(ctx context.Context, in *RoleList, opts ...grpc.CallOption) (*TargetWithRoleList, error) + // GetTargetByName returns a target by the given name. + GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRole, error) + // GetAllTargetMetadataByName + GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedList, error) } type notaryClient struct { @@ -142,7 +402,7 @@ func NewNotaryClient(cc *grpc.ClientConn) NotaryClient { return ¬aryClient{cc} } -func (c *notaryClient) AddTarget(ctx context.Context, in *TargetAction, opts ...grpc.CallOption) (*BasicResponse, error) { +func (c *notaryClient) AddTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) { out := new(BasicResponse) err := grpc.Invoke(ctx, "/api.Notary/AddTarget", in, out, c.cc, opts...) if err != nil { @@ -151,7 +411,7 @@ func (c *notaryClient) AddTarget(ctx context.Context, in *TargetAction, opts ... return out, nil } -func (c *notaryClient) RemoveTarget(ctx context.Context, in *TargetAction, opts ...grpc.CallOption) (*BasicResponse, error) { +func (c *notaryClient) RemoveTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) { out := new(BasicResponse) err := grpc.Invoke(ctx, "/api.Notary/RemoveTarget", in, out, c.cc, opts...) if err != nil { @@ -160,14 +420,47 @@ func (c *notaryClient) RemoveTarget(ctx context.Context, in *TargetAction, opts return out, nil } +func (c *notaryClient) ListTargets(ctx context.Context, in *RoleList, opts ...grpc.CallOption) (*TargetWithRoleList, error) { + out := new(TargetWithRoleList) + err := grpc.Invoke(ctx, "/api.Notary/ListTargets", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRole, error) { + out := new(TargetWithRole) + err := grpc.Invoke(ctx, "/api.Notary/GetTargetByName", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedList, error) { + out := new(TargetSignedList) + err := grpc.Invoke(ctx, "/api.Notary/GetAllTargetMetadataByName", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Notary service type NotaryServer interface { // AddTarget adds a target to the TUF repository and re-signs. - AddTarget(context.Context, *TargetAction) (*BasicResponse, error) + AddTarget(context.Context, *Target) (*BasicResponse, error) // RemoveTarget deletes a target from the TUF repository and re-signs. It only // uses the `name` field from the Target object, ignoring all other fields - RemoveTarget(context.Context, *TargetAction) (*BasicResponse, error) + RemoveTarget(context.Context, *Target) (*BasicResponse, error) + // ListTargets list the targets for the specified roles in the TUF repository + ListTargets(context.Context, *RoleList) (*TargetWithRoleList, error) + // GetTargetByName returns a target by the given name. + GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRole, error) + // GetAllTargetMetadataByName + GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedList, error) } func RegisterNotaryServer(s *grpc.Server, srv NotaryServer) { @@ -175,7 +468,7 @@ func RegisterNotaryServer(s *grpc.Server, srv NotaryServer) { } func _Notary_AddTarget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(TargetAction) + in := new(Target) if err := dec(in); err != nil { return nil, err } @@ -187,13 +480,13 @@ func _Notary_AddTarget_Handler(srv interface{}, ctx context.Context, dec func(in FullMethod: "/api.Notary/AddTarget", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).AddTarget(ctx, req.(*TargetAction)) + return srv.(NotaryServer).AddTarget(ctx, req.(*Target)) } return interceptor(ctx, in, info, handler) } func _Notary_RemoveTarget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(TargetAction) + in := new(Target) if err := dec(in); err != nil { return nil, err } @@ -205,7 +498,61 @@ func _Notary_RemoveTarget_Handler(srv interface{}, ctx context.Context, dec func FullMethod: "/api.Notary/RemoveTarget", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).RemoveTarget(ctx, req.(*TargetAction)) + return srv.(NotaryServer).RemoveTarget(ctx, req.(*Target)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_ListTargets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RoleList) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).ListTargets(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/ListTargets", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).ListTargets(ctx, req.(*RoleList)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_GetTargetByName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TargetByNameAction) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).GetTargetByName(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/GetTargetByName", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).GetTargetByName(ctx, req.(*TargetByNameAction)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_GetAllTargetMetadataByName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TargetName) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).GetAllTargetMetadataByName(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/GetAllTargetMetadataByName", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).GetAllTargetMetadataByName(ctx, req.(*TargetName)) } return interceptor(ctx, in, info, handler) } @@ -222,6 +569,18 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "RemoveTarget", Handler: _Notary_RemoveTarget_Handler, }, + { + MethodName: "ListTargets", + Handler: _Notary_ListTargets_Handler, + }, + { + MethodName: "GetTargetByName", + Handler: _Notary_GetTargetByName_Handler, + }, + { + MethodName: "GetAllTargetMetadataByName", + Handler: _Notary_GetAllTargetMetadataByName_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "api.proto", @@ -230,23 +589,47 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 278 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x91, 0x4f, 0x4b, 0xf3, 0x40, - 0x10, 0xc6, 0xdf, 0x6d, 0xda, 0xbc, 0x66, 0x1a, 0x41, 0x07, 0x91, 0xa5, 0x20, 0x84, 0x9c, 0x72, - 0xca, 0xa1, 0x2a, 0xfe, 0xb9, 0x55, 0x11, 0x3c, 0x79, 0x58, 0xfc, 0x02, 0x6b, 0x3a, 0x24, 0xa1, - 0xcd, 0x6e, 0xc8, 0x6e, 0x2a, 0xf9, 0xa2, 0x7e, 0x1e, 0xc9, 0x26, 0x81, 0x8a, 0x27, 0x6f, 0xf3, - 0x9b, 0x99, 0x9d, 0xe7, 0x79, 0x58, 0x08, 0x64, 0x5d, 0xa6, 0x75, 0xa3, 0xad, 0x46, 0x4f, 0xd6, - 0x65, 0xfc, 0xc5, 0x20, 0x7c, 0x97, 0x4d, 0x4e, 0x76, 0x93, 0xd9, 0x52, 0x2b, 0x3c, 0x03, 0x2f, - 0x6f, 0x15, 0x67, 0x11, 0x4b, 0x02, 0xd1, 0x97, 0x88, 0x30, 0x57, 0xb2, 0x22, 0x3e, 0x73, 0x2d, - 0x57, 0xe3, 0x25, 0xf8, 0x7b, 0x52, 0xb9, 0x2d, 0xb8, 0x17, 0xb1, 0xc4, 0x13, 0x23, 0xe1, 0x2d, - 0xf8, 0x85, 0x34, 0x05, 0x19, 0x3e, 0x8f, 0xbc, 0x64, 0xb9, 0xbe, 0x4a, 0x7b, 0xbd, 0x63, 0x81, - 0xf4, 0xd5, 0xcd, 0x5f, 0x94, 0x6d, 0x3a, 0x31, 0x2e, 0xf7, 0xe7, 0xb2, 0xd6, 0x58, 0x5d, 0xf1, - 0x45, 0xc4, 0x92, 0x50, 0x8c, 0xb4, 0x7a, 0x80, 0xe5, 0xd1, 0x7a, 0xef, 0x6d, 0x47, 0xdd, 0xe4, - 0x6d, 0x47, 0x1d, 0x5e, 0xc0, 0xe2, 0x20, 0xf7, 0xed, 0x60, 0x2e, 0x14, 0x03, 0x3c, 0xce, 0xee, - 0x59, 0xfc, 0x0c, 0xa7, 0x4f, 0xd2, 0x94, 0x99, 0x20, 0x53, 0x6b, 0x65, 0x08, 0x39, 0xfc, 0x37, - 0x6d, 0x96, 0x91, 0x31, 0xee, 0xc0, 0x89, 0x98, 0xb0, 0x9f, 0x54, 0x64, 0x8c, 0xcc, 0xa7, 0x8c, - 0x13, 0xae, 0x3f, 0xc1, 0x7f, 0xd3, 0x56, 0x36, 0x1d, 0xde, 0x40, 0xb0, 0xd9, 0x6e, 0x87, 0x20, - 0x78, 0xfe, 0x2b, 0xd5, 0x0a, 0x5d, 0xeb, 0x87, 0x62, 0xfc, 0x0f, 0xef, 0x20, 0x14, 0x54, 0xe9, - 0x03, 0xfd, 0xf1, 0xe1, 0x87, 0xef, 0xbe, 0xe8, 0xfa, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x4d, 0x9e, - 0x39, 0x36, 0xaf, 0x01, 0x00, 0x00, + // 662 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x54, 0x5d, 0x6f, 0xd3, 0x3c, + 0x14, 0x5e, 0x9a, 0xae, 0x5b, 0x4e, 0xba, 0x8f, 0xd7, 0x7b, 0x61, 0x51, 0x34, 0xa4, 0x28, 0x43, + 0xa2, 0x12, 0xa2, 0x68, 0xe5, 0x82, 0x8f, 0x1b, 0xd4, 0x6d, 0x30, 0xa6, 0xb1, 0x09, 0x19, 0x04, + 0xd7, 0x5e, 0x73, 0xd4, 0x44, 0x4d, 0x93, 0x12, 0xbb, 0x93, 0xf2, 0x1f, 0xf8, 0x2f, 0xfc, 0x0f, + 0xae, 0xf9, 0x41, 0xc8, 0x76, 0xdc, 0xba, 0x50, 0x24, 0xee, 0x72, 0x7c, 0x3e, 0xfc, 0x3c, 0xcf, + 0x79, 0x1c, 0xf0, 0xd8, 0x2c, 0xeb, 0xcf, 0xaa, 0x52, 0x94, 0xc4, 0x65, 0xb3, 0x2c, 0x8e, 0x60, + 0x9b, 0x96, 0x39, 0xbe, 0xcf, 0xb8, 0x20, 0xff, 0xc3, 0x66, 0x55, 0xe6, 0xc8, 0x03, 0x27, 0x72, + 0x7b, 0x1e, 0xd5, 0x41, 0x1c, 0x01, 0x7c, 0x62, 0xd5, 0x18, 0xc5, 0x0d, 0x9b, 0x22, 0x21, 0xd0, + 0x2e, 0xd8, 0x14, 0x03, 0x27, 0x72, 0x7a, 0x1e, 0x55, 0xdf, 0xf1, 0x0f, 0x07, 0x3a, 0xba, 0x84, + 0xec, 0x83, 0x3b, 0x9e, 0x17, 0x4d, 0x56, 0x7e, 0x2e, 0x1a, 0x5a, 0xcb, 0x06, 0x72, 0x1f, 0x3a, + 0x39, 0x16, 0x63, 0x91, 0x06, 0x6e, 0xe4, 0xf4, 0x5c, 0xda, 0x44, 0xe4, 0x29, 0x74, 0x52, 0xc6, + 0x53, 0xe4, 0x41, 0x3b, 0x72, 0x7b, 0xfe, 0xe0, 0xb0, 0x2f, 0xd1, 0xea, 0xd1, 0xfd, 0x77, 0x2a, + 0xf3, 0xa6, 0x10, 0x55, 0x4d, 0x9b, 0x32, 0x39, 0x68, 0x34, 0xe7, 0xa2, 0x9c, 0x06, 0x9b, 0x91, + 0xd3, 0xeb, 0xd2, 0x26, 0x0a, 0x5f, 0x82, 0x6f, 0x95, 0x4b, 0x54, 0x13, 0xac, 0x0d, 0xaa, 0x09, + 0xd6, 0x92, 0xea, 0x1d, 0xcb, 0xe7, 0x1a, 0x56, 0x97, 0xea, 0xe0, 0x55, 0xeb, 0x85, 0x13, 0x5f, + 0xc2, 0xae, 0xbe, 0xf0, 0x4b, 0x26, 0x52, 0x29, 0x0d, 0x39, 0x86, 0x8e, 0x50, 0x27, 0x6a, 0x80, + 0x3f, 0xf0, 0x2d, 0x54, 0xb4, 0x49, 0x49, 0x9a, 0x52, 0x2e, 0x43, 0x53, 0x7e, 0xc7, 0x67, 0x40, + 0x56, 0x47, 0x29, 0x95, 0x9f, 0xc0, 0x96, 0xee, 0xd1, 0x3a, 0xfb, 0x83, 0x03, 0x6b, 0x9e, 0xa9, + 0xa4, 0xa6, 0x26, 0xbe, 0x36, 0x43, 0x4e, 0x6b, 0xb9, 0x80, 0xe1, 0x48, 0x64, 0x65, 0xb1, 0x6e, + 0x0d, 0xe4, 0xd8, 0xac, 0xaf, 0xa5, 0x60, 0xee, 0xa8, 0xb1, 0xe6, 0x5a, 0xb3, 0xcd, 0xaf, 0xe0, + 0x7d, 0xcc, 0xc6, 0x05, 0x13, 0xf3, 0x0a, 0xa5, 0x0a, 0x13, 0xac, 0x2f, 0xcf, 0x9b, 0x31, 0x3a, + 0x90, 0xa2, 0x4e, 0x51, 0xa4, 0x65, 0xd2, 0x90, 0x69, 0x22, 0x72, 0x04, 0x1e, 0x37, 0xad, 0x6a, + 0x71, 0x5d, 0xba, 0x3c, 0x20, 0x01, 0x6c, 0x65, 0xfc, 0x33, 0xcb, 0xb3, 0x24, 0x68, 0x47, 0x4e, + 0x6f, 0x9b, 0x9a, 0x30, 0xf6, 0xc1, 0xfb, 0x30, 0xbf, 0xcd, 0xb3, 0xd1, 0x15, 0xd6, 0xf1, 0x4f, + 0x07, 0x76, 0xcf, 0x31, 0xc7, 0x31, 0x93, 0x3c, 0x94, 0xbe, 0x27, 0xd0, 0x9e, 0x60, 0x6d, 0xd4, + 0x78, 0xa0, 0x60, 0xaf, 0x96, 0xf4, 0xaf, 0xb0, 0x6e, 0x36, 0xaf, 0x4a, 0xd7, 0x9a, 0xea, 0x08, + 0x3c, 0x91, 0x56, 0xc8, 0xd3, 0x32, 0x4f, 0x14, 0xbc, 0x4d, 0xba, 0x3c, 0x90, 0x54, 0x67, 0x4c, + 0xa4, 0xda, 0x59, 0x1e, 0xd5, 0x41, 0x78, 0x01, 0xde, 0x62, 0xf4, 0x1a, 0x97, 0x3c, 0xb4, 0x5d, + 0xe2, 0x0f, 0x76, 0x15, 0xb4, 0x05, 0x17, 0xdb, 0x35, 0xdf, 0x1c, 0xe8, 0xea, 0x35, 0x49, 0x75, + 0x31, 0x21, 0x8f, 0x1a, 0x3f, 0x68, 0xcb, 0x1c, 0xac, 0x21, 0xa5, 0x4d, 0x62, 0xb9, 0xab, 0xf5, + 0x77, 0x77, 0xf5, 0x01, 0x16, 0x4a, 0xf3, 0xc0, 0x55, 0x42, 0x69, 0x34, 0x8b, 0x65, 0x52, 0xab, + 0x22, 0x7e, 0x0d, 0xfb, 0x36, 0x1a, 0xe5, 0xbb, 0xc7, 0xbf, 0xfb, 0xee, 0x3f, 0xeb, 0x26, 0x5d, + 0xb7, 0x74, 0xdd, 0x19, 0xec, 0x9c, 0x32, 0x9e, 0x8d, 0x28, 0xf2, 0x59, 0x59, 0x70, 0xb5, 0x5e, + 0x3e, 0x1f, 0x8d, 0x90, 0x73, 0x45, 0x69, 0x9b, 0x9a, 0x50, 0x66, 0xa6, 0xc8, 0x39, 0x1b, 0x9b, + 0x75, 0x98, 0x70, 0xf0, 0xbd, 0x05, 0x9d, 0x9b, 0x52, 0xb0, 0xaa, 0x26, 0x7d, 0xf0, 0x86, 0x49, + 0xd2, 0xfc, 0x24, 0x6c, 0x8a, 0x21, 0x51, 0xc1, 0xca, 0x65, 0xf1, 0x06, 0x39, 0x81, 0x2e, 0xc5, + 0x69, 0x79, 0x87, 0xff, 0xde, 0xf2, 0x1c, 0x7c, 0xc9, 0x53, 0xd7, 0x70, 0xb2, 0x6a, 0xff, 0xf0, + 0x70, 0xcd, 0x23, 0x93, 0x89, 0x78, 0x83, 0x0c, 0x61, 0xef, 0x02, 0x85, 0xfd, 0xc8, 0x88, 0x5d, + 0x6d, 0xbf, 0xbb, 0x70, 0xdd, 0x5b, 0x8d, 0x37, 0xc8, 0x5b, 0x08, 0x2f, 0x50, 0x0c, 0xf3, 0x5c, + 0x67, 0xae, 0x51, 0xb0, 0x84, 0x09, 0xd6, 0x4c, 0xdb, 0xb3, 0x9a, 0xe4, 0x41, 0x78, 0xef, 0x0f, + 0xe5, 0x35, 0x94, 0xdb, 0x8e, 0xfa, 0x33, 0x3f, 0xfb, 0x15, 0x00, 0x00, 0xff, 0xff, 0x81, 0xf5, + 0x43, 0xd6, 0xa6, 0x05, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index 36d88c90f..f3e337371 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -1,19 +1,38 @@ - syntax = "proto3"; +syntax = "proto3"; package api; // Notary Interface service Notary { + // AddTarget adds a target to the TUF repository and re-signs. - rpc AddTarget(TargetAction) returns (BasicResponse) {} + rpc AddTarget(Target) returns (BasicResponse) {} // RemoveTarget deletes a target from the TUF repository and re-signs. It only // uses the `name` field from the Target object, ignoring all other fields - rpc RemoveTarget(TargetAction) returns (BasicResponse) {} + rpc RemoveTarget(Target) returns (BasicResponse) {} + + // ListTargets list the targets for the specified roles in the TUF repository + rpc ListTargets(RoleList) returns (TargetWithRoleList) {} + + // GetTargetByName returns a target by the given name. + rpc GetTargetByName(TargetByNameAction) returns (TargetWithRole) {} + + // GetAllTargetMetadataByName + rpc GetAllTargetMetadataByName(TargetName) returns (TargetSignedList) {} +} + +// RoleList message holds a list of TUF role names +message RoleList { + repeated string roles = 1; +} + +message TargetName { + string name = 1; } -// Target message describes a TUF target. -message TargetAction { +// Target message describes a TUF target +message Target { string gun = 1; string name = 2; int64 length = 3; @@ -21,6 +40,49 @@ message TargetAction { bytes custom = 5; } +// TargetWithRole represents a Target that exists in a particular role +message TargetWithRole { + Target target = 1; + string role = 2; +} + +message TargetWithRoleList { + repeated TargetWithRole targets = 1; +} + +message TargetByNameAction { + string name = 1; + RoleList roles = 2; +} + +message Signature { + string keyID = 1; + string method = 2; + bytes signature = 3; + bool isValid = 4; +} + +message PublicKey { + +} + +message DelegationRole { + map keys = 1; + string name = 2; + int32 threshold = 3; + repeated string paths = 4; +} + +message TargetSigned { + DelegationRole role = 1; + Target target = 2; + repeated Signature signatures = 3; +} + +message TargetSignedList { + repeated TargetSigned targets = 1; +} + // BasicResponse describes a response with a true/false success indicator, // and if false, an error type and message. See the errors.go file in this // package for the possible errors and a translation function between the @@ -31,3 +93,5 @@ message BasicResponse { } + + From a0095e8ce6685522d0db0cd622a4147eb15c5f14 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 7 Mar 2017 01:38:02 +0100 Subject: [PATCH 12/62] Add ChangeList operations to client API protobuf definitions Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.proto | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/client_api/api/api.proto b/client_api/api/api.proto index f3e337371..34ec7ab99 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -20,6 +20,13 @@ service Notary { // GetAllTargetMetadataByName rpc GetAllTargetMetadataByName(TargetName) returns (TargetSignedList) {} + + // GetChangelist returns the list of the repository's unpublished changes + rpc GetChangelist(Empty) returns (ChangeList) {} +} + +message Empty { + } // RoleList message holds a list of TUF role names @@ -92,6 +99,19 @@ message BasicResponse { string message = 2; } +// Change describes a repository's change +message Change { + string action = 1; + string scope = 2; + string type = 3; + string path = 4; + bytes content = 5; +} + +// ChangeList describes a list of a repository's changes +message ChangeList { + repeated Change changes = 1; +} From 904cf353edce4c1ff6cf1052e14eb7681110d996 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 7 Mar 2017 01:39:29 +0100 Subject: [PATCH 13/62] Add generated code for ChangeList grpc interface Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 231 +++++++++++++++++++++++++++++---------- 1 file changed, 176 insertions(+), 55 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index 797c8434d..fbcce87e6 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -9,6 +9,7 @@ It is generated from these files: api.proto It has these top-level messages: + Empty RoleList TargetName Target @@ -21,6 +22,8 @@ It has these top-level messages: TargetSigned TargetSignedList BasicResponse + Change + ChangeList */ package api @@ -44,6 +47,14 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +type Empty struct { +} + +func (m *Empty) Reset() { *m = Empty{} } +func (m *Empty) String() string { return proto.CompactTextString(m) } +func (*Empty) ProtoMessage() {} +func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + // RoleList message holds a list of TUF role names type RoleList struct { Roles []string `protobuf:"bytes,1,rep,name=roles" json:"roles,omitempty"` @@ -52,7 +63,7 @@ type RoleList struct { func (m *RoleList) Reset() { *m = RoleList{} } func (m *RoleList) String() string { return proto.CompactTextString(m) } func (*RoleList) ProtoMessage() {} -func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *RoleList) GetRoles() []string { if m != nil { @@ -68,7 +79,7 @@ type TargetName struct { func (m *TargetName) Reset() { *m = TargetName{} } func (m *TargetName) String() string { return proto.CompactTextString(m) } func (*TargetName) ProtoMessage() {} -func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *TargetName) GetName() string { if m != nil { @@ -89,7 +100,7 @@ type Target struct { func (m *Target) Reset() { *m = Target{} } func (m *Target) String() string { return proto.CompactTextString(m) } func (*Target) ProtoMessage() {} -func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *Target) GetGun() string { if m != nil { @@ -135,7 +146,7 @@ type TargetWithRole struct { func (m *TargetWithRole) Reset() { *m = TargetWithRole{} } func (m *TargetWithRole) String() string { return proto.CompactTextString(m) } func (*TargetWithRole) ProtoMessage() {} -func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *TargetWithRole) GetTarget() *Target { if m != nil { @@ -158,7 +169,7 @@ type TargetWithRoleList struct { func (m *TargetWithRoleList) Reset() { *m = TargetWithRoleList{} } func (m *TargetWithRoleList) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleList) ProtoMessage() {} -func (*TargetWithRoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*TargetWithRoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *TargetWithRoleList) GetTargets() []*TargetWithRole { if m != nil { @@ -175,7 +186,7 @@ type TargetByNameAction struct { func (m *TargetByNameAction) Reset() { *m = TargetByNameAction{} } func (m *TargetByNameAction) String() string { return proto.CompactTextString(m) } func (*TargetByNameAction) ProtoMessage() {} -func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (m *TargetByNameAction) GetName() string { if m != nil { @@ -201,7 +212,7 @@ type Signature struct { func (m *Signature) Reset() { *m = Signature{} } func (m *Signature) String() string { return proto.CompactTextString(m) } func (*Signature) ProtoMessage() {} -func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *Signature) GetKeyID() string { if m != nil { @@ -237,7 +248,7 @@ type PublicKey struct { func (m *PublicKey) Reset() { *m = PublicKey{} } func (m *PublicKey) String() string { return proto.CompactTextString(m) } func (*PublicKey) ProtoMessage() {} -func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } type DelegationRole struct { Keys map[string]*PublicKey `protobuf:"bytes,1,rep,name=keys" json:"keys,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` @@ -249,7 +260,7 @@ type DelegationRole struct { func (m *DelegationRole) Reset() { *m = DelegationRole{} } func (m *DelegationRole) String() string { return proto.CompactTextString(m) } func (*DelegationRole) ProtoMessage() {} -func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (m *DelegationRole) GetKeys() map[string]*PublicKey { if m != nil { @@ -288,7 +299,7 @@ type TargetSigned struct { func (m *TargetSigned) Reset() { *m = TargetSigned{} } func (m *TargetSigned) String() string { return proto.CompactTextString(m) } func (*TargetSigned) ProtoMessage() {} -func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *TargetSigned) GetRole() *DelegationRole { if m != nil { @@ -318,7 +329,7 @@ type TargetSignedList struct { func (m *TargetSignedList) Reset() { *m = TargetSignedList{} } func (m *TargetSignedList) String() string { return proto.CompactTextString(m) } func (*TargetSignedList) ProtoMessage() {} -func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *TargetSignedList) GetTargets() []*TargetSigned { if m != nil { @@ -339,7 +350,7 @@ type BasicResponse struct { func (m *BasicResponse) Reset() { *m = BasicResponse{} } func (m *BasicResponse) String() string { return proto.CompactTextString(m) } func (*BasicResponse) ProtoMessage() {} -func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } func (m *BasicResponse) GetSuccess() bool { if m != nil { @@ -355,7 +366,74 @@ func (m *BasicResponse) GetMessage() string { return "" } +// Change describes a repository's change +type Change struct { + Action string `protobuf:"bytes,1,opt,name=action" json:"action,omitempty"` + Scope string `protobuf:"bytes,2,opt,name=scope" json:"scope,omitempty"` + Type string `protobuf:"bytes,3,opt,name=type" json:"type,omitempty"` + Path string `protobuf:"bytes,4,opt,name=path" json:"path,omitempty"` + Content []byte `protobuf:"bytes,5,opt,name=content,proto3" json:"content,omitempty"` +} + +func (m *Change) Reset() { *m = Change{} } +func (m *Change) String() string { return proto.CompactTextString(m) } +func (*Change) ProtoMessage() {} +func (*Change) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } + +func (m *Change) GetAction() string { + if m != nil { + return m.Action + } + return "" +} + +func (m *Change) GetScope() string { + if m != nil { + return m.Scope + } + return "" +} + +func (m *Change) GetType() string { + if m != nil { + return m.Type + } + return "" +} + +func (m *Change) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *Change) GetContent() []byte { + if m != nil { + return m.Content + } + return nil +} + +// ChangeList describes a list of a repository's changes +type ChangeList struct { + Changes []*Change `protobuf:"bytes,1,rep,name=changes" json:"changes,omitempty"` +} + +func (m *ChangeList) Reset() { *m = ChangeList{} } +func (m *ChangeList) String() string { return proto.CompactTextString(m) } +func (*ChangeList) ProtoMessage() {} +func (*ChangeList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } + +func (m *ChangeList) GetChanges() []*Change { + if m != nil { + return m.Changes + } + return nil +} + func init() { + proto.RegisterType((*Empty)(nil), "api.Empty") proto.RegisterType((*RoleList)(nil), "api.RoleList") proto.RegisterType((*TargetName)(nil), "api.TargetName") proto.RegisterType((*Target)(nil), "api.Target") @@ -368,6 +446,8 @@ func init() { proto.RegisterType((*TargetSigned)(nil), "api.TargetSigned") proto.RegisterType((*TargetSignedList)(nil), "api.TargetSignedList") proto.RegisterType((*BasicResponse)(nil), "api.BasicResponse") + proto.RegisterType((*Change)(nil), "api.Change") + proto.RegisterType((*ChangeList)(nil), "api.ChangeList") } // Reference imports to suppress errors if they are not otherwise used. @@ -392,6 +472,8 @@ type NotaryClient interface { GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRole, error) // GetAllTargetMetadataByName GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedList, error) + // GetChangelist returns the list of the repository's unpublished changes + GetChangelist(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ChangeList, error) } type notaryClient struct { @@ -447,6 +529,15 @@ func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *Targe return out, nil } +func (c *notaryClient) GetChangelist(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ChangeList, error) { + out := new(ChangeList) + err := grpc.Invoke(ctx, "/api.Notary/GetChangelist", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Notary service type NotaryServer interface { @@ -461,6 +552,8 @@ type NotaryServer interface { GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRole, error) // GetAllTargetMetadataByName GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedList, error) + // GetChangelist returns the list of the repository's unpublished changes + GetChangelist(context.Context, *Empty) (*ChangeList, error) } func RegisterNotaryServer(s *grpc.Server, srv NotaryServer) { @@ -557,6 +650,24 @@ func _Notary_GetAllTargetMetadataByName_Handler(srv interface{}, ctx context.Con return interceptor(ctx, in, info, handler) } +func _Notary_GetChangelist_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).GetChangelist(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/GetChangelist", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).GetChangelist(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + var _Notary_serviceDesc = grpc.ServiceDesc{ ServiceName: "api.Notary", HandlerType: (*NotaryServer)(nil), @@ -581,6 +692,10 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "GetAllTargetMetadataByName", Handler: _Notary_GetAllTargetMetadataByName_Handler, }, + { + MethodName: "GetChangelist", + Handler: _Notary_GetChangelist_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "api.proto", @@ -589,47 +704,53 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 662 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x54, 0x5d, 0x6f, 0xd3, 0x3c, - 0x14, 0x5e, 0x9a, 0xae, 0x5b, 0x4e, 0xba, 0x8f, 0xd7, 0x7b, 0x61, 0x51, 0x34, 0xa4, 0x28, 0x43, - 0xa2, 0x12, 0xa2, 0x68, 0xe5, 0x82, 0x8f, 0x1b, 0xd4, 0x6d, 0x30, 0xa6, 0xb1, 0x09, 0x19, 0x04, - 0xd7, 0x5e, 0x73, 0xd4, 0x44, 0x4d, 0x93, 0x12, 0xbb, 0x93, 0xf2, 0x1f, 0xf8, 0x2f, 0xfc, 0x0f, - 0xae, 0xf9, 0x41, 0xc8, 0x76, 0xdc, 0xba, 0x50, 0x24, 0xee, 0x72, 0x7c, 0x3e, 0xfc, 0x3c, 0xcf, - 0x79, 0x1c, 0xf0, 0xd8, 0x2c, 0xeb, 0xcf, 0xaa, 0x52, 0x94, 0xc4, 0x65, 0xb3, 0x2c, 0x8e, 0x60, - 0x9b, 0x96, 0x39, 0xbe, 0xcf, 0xb8, 0x20, 0xff, 0xc3, 0x66, 0x55, 0xe6, 0xc8, 0x03, 0x27, 0x72, - 0x7b, 0x1e, 0xd5, 0x41, 0x1c, 0x01, 0x7c, 0x62, 0xd5, 0x18, 0xc5, 0x0d, 0x9b, 0x22, 0x21, 0xd0, - 0x2e, 0xd8, 0x14, 0x03, 0x27, 0x72, 0x7a, 0x1e, 0x55, 0xdf, 0xf1, 0x0f, 0x07, 0x3a, 0xba, 0x84, - 0xec, 0x83, 0x3b, 0x9e, 0x17, 0x4d, 0x56, 0x7e, 0x2e, 0x1a, 0x5a, 0xcb, 0x06, 0x72, 0x1f, 0x3a, - 0x39, 0x16, 0x63, 0x91, 0x06, 0x6e, 0xe4, 0xf4, 0x5c, 0xda, 0x44, 0xe4, 0x29, 0x74, 0x52, 0xc6, - 0x53, 0xe4, 0x41, 0x3b, 0x72, 0x7b, 0xfe, 0xe0, 0xb0, 0x2f, 0xd1, 0xea, 0xd1, 0xfd, 0x77, 0x2a, - 0xf3, 0xa6, 0x10, 0x55, 0x4d, 0x9b, 0x32, 0x39, 0x68, 0x34, 0xe7, 0xa2, 0x9c, 0x06, 0x9b, 0x91, - 0xd3, 0xeb, 0xd2, 0x26, 0x0a, 0x5f, 0x82, 0x6f, 0x95, 0x4b, 0x54, 0x13, 0xac, 0x0d, 0xaa, 0x09, - 0xd6, 0x92, 0xea, 0x1d, 0xcb, 0xe7, 0x1a, 0x56, 0x97, 0xea, 0xe0, 0x55, 0xeb, 0x85, 0x13, 0x5f, - 0xc2, 0xae, 0xbe, 0xf0, 0x4b, 0x26, 0x52, 0x29, 0x0d, 0x39, 0x86, 0x8e, 0x50, 0x27, 0x6a, 0x80, - 0x3f, 0xf0, 0x2d, 0x54, 0xb4, 0x49, 0x49, 0x9a, 0x52, 0x2e, 0x43, 0x53, 0x7e, 0xc7, 0x67, 0x40, - 0x56, 0x47, 0x29, 0x95, 0x9f, 0xc0, 0x96, 0xee, 0xd1, 0x3a, 0xfb, 0x83, 0x03, 0x6b, 0x9e, 0xa9, - 0xa4, 0xa6, 0x26, 0xbe, 0x36, 0x43, 0x4e, 0x6b, 0xb9, 0x80, 0xe1, 0x48, 0x64, 0x65, 0xb1, 0x6e, - 0x0d, 0xe4, 0xd8, 0xac, 0xaf, 0xa5, 0x60, 0xee, 0xa8, 0xb1, 0xe6, 0x5a, 0xb3, 0xcd, 0xaf, 0xe0, - 0x7d, 0xcc, 0xc6, 0x05, 0x13, 0xf3, 0x0a, 0xa5, 0x0a, 0x13, 0xac, 0x2f, 0xcf, 0x9b, 0x31, 0x3a, - 0x90, 0xa2, 0x4e, 0x51, 0xa4, 0x65, 0xd2, 0x90, 0x69, 0x22, 0x72, 0x04, 0x1e, 0x37, 0xad, 0x6a, - 0x71, 0x5d, 0xba, 0x3c, 0x20, 0x01, 0x6c, 0x65, 0xfc, 0x33, 0xcb, 0xb3, 0x24, 0x68, 0x47, 0x4e, - 0x6f, 0x9b, 0x9a, 0x30, 0xf6, 0xc1, 0xfb, 0x30, 0xbf, 0xcd, 0xb3, 0xd1, 0x15, 0xd6, 0xf1, 0x4f, - 0x07, 0x76, 0xcf, 0x31, 0xc7, 0x31, 0x93, 0x3c, 0x94, 0xbe, 0x27, 0xd0, 0x9e, 0x60, 0x6d, 0xd4, - 0x78, 0xa0, 0x60, 0xaf, 0x96, 0xf4, 0xaf, 0xb0, 0x6e, 0x36, 0xaf, 0x4a, 0xd7, 0x9a, 0xea, 0x08, - 0x3c, 0x91, 0x56, 0xc8, 0xd3, 0x32, 0x4f, 0x14, 0xbc, 0x4d, 0xba, 0x3c, 0x90, 0x54, 0x67, 0x4c, - 0xa4, 0xda, 0x59, 0x1e, 0xd5, 0x41, 0x78, 0x01, 0xde, 0x62, 0xf4, 0x1a, 0x97, 0x3c, 0xb4, 0x5d, - 0xe2, 0x0f, 0x76, 0x15, 0xb4, 0x05, 0x17, 0xdb, 0x35, 0xdf, 0x1c, 0xe8, 0xea, 0x35, 0x49, 0x75, - 0x31, 0x21, 0x8f, 0x1a, 0x3f, 0x68, 0xcb, 0x1c, 0xac, 0x21, 0xa5, 0x4d, 0x62, 0xb9, 0xab, 0xf5, - 0x77, 0x77, 0xf5, 0x01, 0x16, 0x4a, 0xf3, 0xc0, 0x55, 0x42, 0x69, 0x34, 0x8b, 0x65, 0x52, 0xab, - 0x22, 0x7e, 0x0d, 0xfb, 0x36, 0x1a, 0xe5, 0xbb, 0xc7, 0xbf, 0xfb, 0xee, 0x3f, 0xeb, 0x26, 0x5d, - 0xb7, 0x74, 0xdd, 0x19, 0xec, 0x9c, 0x32, 0x9e, 0x8d, 0x28, 0xf2, 0x59, 0x59, 0x70, 0xb5, 0x5e, - 0x3e, 0x1f, 0x8d, 0x90, 0x73, 0x45, 0x69, 0x9b, 0x9a, 0x50, 0x66, 0xa6, 0xc8, 0x39, 0x1b, 0x9b, - 0x75, 0x98, 0x70, 0xf0, 0xbd, 0x05, 0x9d, 0x9b, 0x52, 0xb0, 0xaa, 0x26, 0x7d, 0xf0, 0x86, 0x49, - 0xd2, 0xfc, 0x24, 0x6c, 0x8a, 0x21, 0x51, 0xc1, 0xca, 0x65, 0xf1, 0x06, 0x39, 0x81, 0x2e, 0xc5, - 0x69, 0x79, 0x87, 0xff, 0xde, 0xf2, 0x1c, 0x7c, 0xc9, 0x53, 0xd7, 0x70, 0xb2, 0x6a, 0xff, 0xf0, - 0x70, 0xcd, 0x23, 0x93, 0x89, 0x78, 0x83, 0x0c, 0x61, 0xef, 0x02, 0x85, 0xfd, 0xc8, 0x88, 0x5d, - 0x6d, 0xbf, 0xbb, 0x70, 0xdd, 0x5b, 0x8d, 0x37, 0xc8, 0x5b, 0x08, 0x2f, 0x50, 0x0c, 0xf3, 0x5c, - 0x67, 0xae, 0x51, 0xb0, 0x84, 0x09, 0xd6, 0x4c, 0xdb, 0xb3, 0x9a, 0xe4, 0x41, 0x78, 0xef, 0x0f, - 0xe5, 0x35, 0x94, 0xdb, 0x8e, 0xfa, 0x33, 0x3f, 0xfb, 0x15, 0x00, 0x00, 0xff, 0xff, 0x81, 0xf5, - 0x43, 0xd6, 0xa6, 0x05, 0x00, 0x00, + // 762 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x55, 0x5b, 0x6f, 0xdb, 0x36, + 0x14, 0x8e, 0x7c, 0x8d, 0x8e, 0x9c, 0xcb, 0x98, 0x6d, 0x11, 0x84, 0x0c, 0x10, 0x98, 0x0d, 0x33, + 0x30, 0xcc, 0x43, 0x9c, 0x87, 0x6d, 0x7d, 0x29, 0x9c, 0x4b, 0xdd, 0x20, 0x4d, 0x50, 0xb0, 0x45, + 0xfb, 0xcc, 0xc8, 0x84, 0x25, 0x58, 0x96, 0x54, 0x93, 0x0e, 0xaa, 0xff, 0xd0, 0x5f, 0xd6, 0xe7, + 0xbe, 0xf7, 0xaf, 0x14, 0xbc, 0xd9, 0x74, 0xeb, 0x02, 0x7d, 0xe3, 0x47, 0x9e, 0x73, 0x78, 0xce, + 0xf7, 0x7d, 0xa2, 0xc0, 0xa7, 0x55, 0x36, 0xa8, 0x16, 0xa5, 0x28, 0x51, 0x93, 0x56, 0x19, 0xee, + 0x42, 0xfb, 0x7a, 0x5e, 0x89, 0x1a, 0xc7, 0xb0, 0x4b, 0xca, 0x9c, 0xbd, 0xc8, 0xb8, 0x40, 0x3f, + 0x43, 0x7b, 0x51, 0xe6, 0x8c, 0x87, 0x5e, 0xdc, 0xec, 0xfb, 0x44, 0x03, 0x1c, 0x03, 0xbc, 0xa6, + 0x8b, 0x29, 0x13, 0xf7, 0x74, 0xce, 0x10, 0x82, 0x56, 0x41, 0xe7, 0x2c, 0xf4, 0x62, 0xaf, 0xef, + 0x13, 0xb5, 0xc6, 0x1f, 0x3d, 0xe8, 0xe8, 0x10, 0x74, 0x08, 0xcd, 0xe9, 0xb2, 0x30, 0xa7, 0x72, + 0xb9, 0x4a, 0x68, 0xac, 0x13, 0xd0, 0xaf, 0xd0, 0xc9, 0x59, 0x31, 0x15, 0x69, 0xd8, 0x8c, 0xbd, + 0x7e, 0x93, 0x18, 0x84, 0xfe, 0x81, 0x4e, 0x4a, 0x79, 0xca, 0x78, 0xd8, 0x8a, 0x9b, 0xfd, 0x60, + 0x78, 0x3c, 0x90, 0x6d, 0xeb, 0xd2, 0x83, 0xe7, 0xea, 0xe4, 0xba, 0x10, 0x8b, 0x9a, 0x98, 0x30, + 0x59, 0x28, 0x59, 0x72, 0x51, 0xce, 0xc3, 0x76, 0xec, 0xf5, 0x7b, 0xc4, 0xa0, 0xe8, 0x7f, 0x08, + 0x9c, 0x70, 0xd9, 0xd5, 0x8c, 0xd5, 0xb6, 0xab, 0x19, 0xab, 0xe5, 0xa8, 0x8f, 0x34, 0x5f, 0xea, + 0xb6, 0x7a, 0x44, 0x83, 0x27, 0x8d, 0xff, 0x3c, 0x7c, 0x03, 0xfb, 0xfa, 0xc2, 0xb7, 0x99, 0x48, + 0x25, 0x35, 0xe8, 0x14, 0x3a, 0x42, 0xed, 0xa8, 0x02, 0xc1, 0x30, 0x70, 0xba, 0x22, 0xe6, 0x48, + 0x8e, 0x29, 0xe9, 0xb2, 0x63, 0xca, 0x35, 0xbe, 0x04, 0xb4, 0x59, 0x4a, 0xb1, 0xfc, 0x37, 0x74, + 0x75, 0x8e, 0xe6, 0x39, 0x18, 0x1e, 0x39, 0xf5, 0x6c, 0x24, 0xb1, 0x31, 0xf8, 0xce, 0x16, 0xb9, + 0xa8, 0xa5, 0x00, 0xa3, 0x44, 0x64, 0x65, 0xb1, 0x4d, 0x06, 0x74, 0x6a, 0xe5, 0x6b, 0xa8, 0x36, + 0xf7, 0x54, 0x59, 0x7b, 0xad, 0x55, 0xf3, 0x1d, 0xf8, 0xaf, 0xb2, 0x69, 0x41, 0xc5, 0x72, 0xc1, + 0x24, 0x0b, 0x33, 0x56, 0xdf, 0x5c, 0x99, 0x32, 0x1a, 0x48, 0x52, 0xe7, 0x4c, 0xa4, 0xe5, 0xc4, + 0x0c, 0x63, 0x10, 0x3a, 0x01, 0x9f, 0xdb, 0x54, 0x25, 0x5c, 0x8f, 0xac, 0x37, 0x50, 0x08, 0xdd, + 0x8c, 0xbf, 0xa1, 0x79, 0x36, 0x09, 0x5b, 0xb1, 0xd7, 0xdf, 0x25, 0x16, 0xe2, 0x00, 0xfc, 0x97, + 0xcb, 0x87, 0x3c, 0x4b, 0x6e, 0x59, 0x8d, 0x3f, 0x79, 0xb0, 0x7f, 0xc5, 0x72, 0x36, 0xa5, 0x72, + 0x0e, 0xc5, 0xef, 0x19, 0xb4, 0x66, 0xac, 0xb6, 0x6c, 0xfc, 0xa6, 0xda, 0xde, 0x0c, 0x19, 0xdc, + 0xb2, 0xda, 0x28, 0xaf, 0x42, 0xb7, 0x9a, 0xea, 0x04, 0x7c, 0x91, 0x2e, 0x18, 0x4f, 0xcb, 0x7c, + 0xa2, 0xda, 0x6b, 0x93, 0xf5, 0x86, 0x1c, 0xb5, 0xa2, 0x22, 0xd5, 0xce, 0xf2, 0x89, 0x06, 0xd1, + 0x18, 0xfc, 0x55, 0xe9, 0x2d, 0x2e, 0xf9, 0xdd, 0x75, 0x49, 0x30, 0xdc, 0x57, 0xad, 0xad, 0x66, + 0x71, 0x5d, 0xf3, 0xc1, 0x83, 0x9e, 0x96, 0x49, 0xb2, 0xcb, 0x26, 0xe8, 0x4f, 0xe3, 0x07, 0x6d, + 0x99, 0xa3, 0x2d, 0x43, 0x69, 0x93, 0x38, 0xee, 0x6a, 0x7c, 0xdf, 0x5d, 0x03, 0x80, 0x15, 0xd3, + 0x3c, 0x6c, 0x2a, 0xa2, 0x74, 0x37, 0x2b, 0x31, 0x89, 0x13, 0x81, 0x9f, 0xc2, 0xa1, 0xdb, 0x8d, + 0xf2, 0xdd, 0x5f, 0x5f, 0xfb, 0xee, 0x27, 0xe7, 0x26, 0x1d, 0xb7, 0x76, 0xdd, 0x25, 0xec, 0x5d, + 0x50, 0x9e, 0x25, 0x84, 0xf1, 0xaa, 0x2c, 0xb8, 0x92, 0x97, 0x2f, 0x93, 0x84, 0x71, 0xae, 0x46, + 0xda, 0x25, 0x16, 0xca, 0x93, 0x39, 0xe3, 0x9c, 0x4e, 0xad, 0x1c, 0x16, 0xe2, 0xf7, 0xd0, 0xb9, + 0x4c, 0x69, 0x31, 0x55, 0x1f, 0x3c, 0x55, 0xc6, 0x35, 0xec, 0x1a, 0x24, 0x55, 0xe1, 0x49, 0x59, + 0xd9, 0x4c, 0x0d, 0xa4, 0xba, 0xa2, 0xae, 0xb4, 0xc7, 0x7c, 0xa2, 0xd6, 0x72, 0x4f, 0x4a, 0xa6, + 0xbc, 0xe5, 0x13, 0xb5, 0x96, 0x37, 0x27, 0x65, 0x21, 0x58, 0x21, 0xcc, 0xe7, 0x6f, 0x21, 0x3e, + 0x07, 0xd0, 0x37, 0xab, 0xc9, 0xff, 0x80, 0x6e, 0xa2, 0x90, 0x9d, 0x5c, 0x73, 0xac, 0x23, 0x88, + 0x3d, 0x1b, 0x7e, 0x6e, 0x40, 0xe7, 0xbe, 0x14, 0x74, 0x51, 0xa3, 0x01, 0xf8, 0xa3, 0xc9, 0xc4, + 0xbc, 0x69, 0xae, 0x22, 0x11, 0x52, 0x60, 0x83, 0x1b, 0xbc, 0x83, 0xce, 0xa0, 0x47, 0xd8, 0xbc, + 0x7c, 0x64, 0x3f, 0x9e, 0xf2, 0x2f, 0x04, 0xb2, 0x39, 0x1d, 0xc3, 0xd1, 0xe6, 0xd7, 0x1a, 0x1d, + 0x6f, 0x79, 0x13, 0xe4, 0x01, 0xde, 0x41, 0x23, 0x38, 0x18, 0x33, 0xe1, 0xbe, 0x09, 0xc8, 0x8d, + 0x76, 0x9f, 0x89, 0x68, 0xdb, 0xd3, 0x82, 0x77, 0xd0, 0x33, 0x88, 0xc6, 0x4c, 0x8c, 0xf2, 0x5c, + 0x9f, 0xdc, 0x31, 0x41, 0x27, 0x54, 0x50, 0x53, 0xed, 0xc0, 0x49, 0x92, 0x1b, 0xd1, 0x2f, 0xdf, + 0x18, 0xc5, 0xb4, 0x32, 0x80, 0xbd, 0x31, 0x13, 0x9a, 0xc7, 0x5c, 0x32, 0x0d, 0x2a, 0x52, 0xfd, + 0x59, 0xa2, 0x03, 0x87, 0x64, 0x1d, 0xff, 0xd0, 0x51, 0x7f, 0xa0, 0xf3, 0x2f, 0x01, 0x00, 0x00, + 0xff, 0xff, 0xc2, 0x4b, 0x49, 0x92, 0x8e, 0x06, 0x00, 0x00, } From 7bba7ecc266428f6f0bd7f0fa6aa8e28a731bff4 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 7 Mar 2017 02:06:49 +0100 Subject: [PATCH 14/62] Add Init, Publish and returned Errors to client API gRPC interface Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 400 +++++++++++++++++++++++++++++++-------- client_api/api/api.proto | 43 ++++- 2 files changed, 359 insertions(+), 84 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index fbcce87e6..58eda8e1e 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -10,20 +10,25 @@ It is generated from these files: It has these top-level messages: Empty + InitMessage RoleList TargetName Target TargetWithRole + TargetWithRoleResponse TargetWithRoleList + TargetWithRoleListResponse TargetByNameAction Signature PublicKey DelegationRole TargetSigned TargetSignedList + TargetSignedListResponse BasicResponse Change ChangeList + ChangeListResponse */ package api @@ -55,6 +60,32 @@ func (m *Empty) String() string { return proto.CompactTextString(m) } func (*Empty) ProtoMessage() {} func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +// InitMessage holds a list of root key IDs and a list of roles for which +// the server automatically should manage the keys +type InitMessage struct { + RootKeyIDs []string `protobuf:"bytes,1,rep,name=rootKeyIDs" json:"rootKeyIDs,omitempty"` + ServerManagedRoles *RoleList `protobuf:"bytes,2,opt,name=serverManagedRoles" json:"serverManagedRoles,omitempty"` +} + +func (m *InitMessage) Reset() { *m = InitMessage{} } +func (m *InitMessage) String() string { return proto.CompactTextString(m) } +func (*InitMessage) ProtoMessage() {} +func (*InitMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *InitMessage) GetRootKeyIDs() []string { + if m != nil { + return m.RootKeyIDs + } + return nil +} + +func (m *InitMessage) GetServerManagedRoles() *RoleList { + if m != nil { + return m.ServerManagedRoles + } + return nil +} + // RoleList message holds a list of TUF role names type RoleList struct { Roles []string `protobuf:"bytes,1,rep,name=roles" json:"roles,omitempty"` @@ -63,7 +94,7 @@ type RoleList struct { func (m *RoleList) Reset() { *m = RoleList{} } func (m *RoleList) String() string { return proto.CompactTextString(m) } func (*RoleList) ProtoMessage() {} -func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *RoleList) GetRoles() []string { if m != nil { @@ -79,7 +110,7 @@ type TargetName struct { func (m *TargetName) Reset() { *m = TargetName{} } func (m *TargetName) String() string { return proto.CompactTextString(m) } func (*TargetName) ProtoMessage() {} -func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *TargetName) GetName() string { if m != nil { @@ -100,7 +131,7 @@ type Target struct { func (m *Target) Reset() { *m = Target{} } func (m *Target) String() string { return proto.CompactTextString(m) } func (*Target) ProtoMessage() {} -func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *Target) GetGun() string { if m != nil { @@ -146,7 +177,7 @@ type TargetWithRole struct { func (m *TargetWithRole) Reset() { *m = TargetWithRole{} } func (m *TargetWithRole) String() string { return proto.CompactTextString(m) } func (*TargetWithRole) ProtoMessage() {} -func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *TargetWithRole) GetTarget() *Target { if m != nil { @@ -162,6 +193,38 @@ func (m *TargetWithRole) GetRole() string { return "" } +type TargetWithRoleResponse struct { + TargetWithRole *TargetWithRole `protobuf:"bytes,1,opt,name=targetWithRole" json:"targetWithRole,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *TargetWithRoleResponse) Reset() { *m = TargetWithRoleResponse{} } +func (m *TargetWithRoleResponse) String() string { return proto.CompactTextString(m) } +func (*TargetWithRoleResponse) ProtoMessage() {} +func (*TargetWithRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *TargetWithRoleResponse) GetTargetWithRole() *TargetWithRole { + if m != nil { + return m.TargetWithRole + } + return nil +} + +func (m *TargetWithRoleResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *TargetWithRoleResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + type TargetWithRoleList struct { Targets []*TargetWithRole `protobuf:"bytes,1,rep,name=targets" json:"targets,omitempty"` } @@ -169,7 +232,7 @@ type TargetWithRoleList struct { func (m *TargetWithRoleList) Reset() { *m = TargetWithRoleList{} } func (m *TargetWithRoleList) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleList) ProtoMessage() {} -func (*TargetWithRoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*TargetWithRoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *TargetWithRoleList) GetTargets() []*TargetWithRole { if m != nil { @@ -178,6 +241,38 @@ func (m *TargetWithRoleList) GetTargets() []*TargetWithRole { return nil } +type TargetWithRoleListResponse struct { + TargetWithRoleList *TargetWithRoleList `protobuf:"bytes,1,opt,name=targetWithRoleList" json:"targetWithRoleList,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *TargetWithRoleListResponse) Reset() { *m = TargetWithRoleListResponse{} } +func (m *TargetWithRoleListResponse) String() string { return proto.CompactTextString(m) } +func (*TargetWithRoleListResponse) ProtoMessage() {} +func (*TargetWithRoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *TargetWithRoleListResponse) GetTargetWithRoleList() *TargetWithRoleList { + if m != nil { + return m.TargetWithRoleList + } + return nil +} + +func (m *TargetWithRoleListResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *TargetWithRoleListResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + type TargetByNameAction struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Roles *RoleList `protobuf:"bytes,2,opt,name=roles" json:"roles,omitempty"` @@ -186,7 +281,7 @@ type TargetByNameAction struct { func (m *TargetByNameAction) Reset() { *m = TargetByNameAction{} } func (m *TargetByNameAction) String() string { return proto.CompactTextString(m) } func (*TargetByNameAction) ProtoMessage() {} -func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (m *TargetByNameAction) GetName() string { if m != nil { @@ -212,7 +307,7 @@ type Signature struct { func (m *Signature) Reset() { *m = Signature{} } func (m *Signature) String() string { return proto.CompactTextString(m) } func (*Signature) ProtoMessage() {} -func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *Signature) GetKeyID() string { if m != nil { @@ -242,13 +337,14 @@ func (m *Signature) GetIsValid() bool { return false } +// FIXME: implement type PublicKey struct { } func (m *PublicKey) Reset() { *m = PublicKey{} } func (m *PublicKey) String() string { return proto.CompactTextString(m) } func (*PublicKey) ProtoMessage() {} -func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } type DelegationRole struct { Keys map[string]*PublicKey `protobuf:"bytes,1,rep,name=keys" json:"keys,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` @@ -260,7 +356,7 @@ type DelegationRole struct { func (m *DelegationRole) Reset() { *m = DelegationRole{} } func (m *DelegationRole) String() string { return proto.CompactTextString(m) } func (*DelegationRole) ProtoMessage() {} -func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } func (m *DelegationRole) GetKeys() map[string]*PublicKey { if m != nil { @@ -299,7 +395,7 @@ type TargetSigned struct { func (m *TargetSigned) Reset() { *m = TargetSigned{} } func (m *TargetSigned) String() string { return proto.CompactTextString(m) } func (*TargetSigned) ProtoMessage() {} -func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *TargetSigned) GetRole() *DelegationRole { if m != nil { @@ -329,7 +425,7 @@ type TargetSignedList struct { func (m *TargetSignedList) Reset() { *m = TargetSignedList{} } func (m *TargetSignedList) String() string { return proto.CompactTextString(m) } func (*TargetSignedList) ProtoMessage() {} -func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *TargetSignedList) GetTargets() []*TargetSigned { if m != nil { @@ -338,6 +434,38 @@ func (m *TargetSignedList) GetTargets() []*TargetSigned { return nil } +type TargetSignedListResponse struct { + TargetSignedList *TargetSignedList `protobuf:"bytes,1,opt,name=targetSignedList" json:"targetSignedList,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *TargetSignedListResponse) Reset() { *m = TargetSignedListResponse{} } +func (m *TargetSignedListResponse) String() string { return proto.CompactTextString(m) } +func (*TargetSignedListResponse) ProtoMessage() {} +func (*TargetSignedListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } + +func (m *TargetSignedListResponse) GetTargetSignedList() *TargetSignedList { + if m != nil { + return m.TargetSignedList + } + return nil +} + +func (m *TargetSignedListResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *TargetSignedListResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + // BasicResponse describes a response with a true/false success indicator, // and if false, an error type and message. See the errors.go file in this // package for the possible errors and a translation function between the @@ -350,7 +478,7 @@ type BasicResponse struct { func (m *BasicResponse) Reset() { *m = BasicResponse{} } func (m *BasicResponse) String() string { return proto.CompactTextString(m) } func (*BasicResponse) ProtoMessage() {} -func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *BasicResponse) GetSuccess() bool { if m != nil { @@ -378,7 +506,7 @@ type Change struct { func (m *Change) Reset() { *m = Change{} } func (m *Change) String() string { return proto.CompactTextString(m) } func (*Change) ProtoMessage() {} -func (*Change) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*Change) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *Change) GetAction() string { if m != nil { @@ -423,7 +551,7 @@ type ChangeList struct { func (m *ChangeList) Reset() { *m = ChangeList{} } func (m *ChangeList) String() string { return proto.CompactTextString(m) } func (*ChangeList) ProtoMessage() {} -func (*ChangeList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*ChangeList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *ChangeList) GetChanges() []*Change { if m != nil { @@ -432,22 +560,59 @@ func (m *ChangeList) GetChanges() []*Change { return nil } +type ChangeListResponse struct { + Changelist *ChangeList `protobuf:"bytes,1,opt,name=changelist" json:"changelist,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *ChangeListResponse) Reset() { *m = ChangeListResponse{} } +func (m *ChangeListResponse) String() string { return proto.CompactTextString(m) } +func (*ChangeListResponse) ProtoMessage() {} +func (*ChangeListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } + +func (m *ChangeListResponse) GetChangelist() *ChangeList { + if m != nil { + return m.Changelist + } + return nil +} + +func (m *ChangeListResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *ChangeListResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + func init() { proto.RegisterType((*Empty)(nil), "api.Empty") + proto.RegisterType((*InitMessage)(nil), "api.InitMessage") proto.RegisterType((*RoleList)(nil), "api.RoleList") proto.RegisterType((*TargetName)(nil), "api.TargetName") proto.RegisterType((*Target)(nil), "api.Target") proto.RegisterType((*TargetWithRole)(nil), "api.TargetWithRole") + proto.RegisterType((*TargetWithRoleResponse)(nil), "api.TargetWithRoleResponse") proto.RegisterType((*TargetWithRoleList)(nil), "api.TargetWithRoleList") + proto.RegisterType((*TargetWithRoleListResponse)(nil), "api.TargetWithRoleListResponse") proto.RegisterType((*TargetByNameAction)(nil), "api.TargetByNameAction") proto.RegisterType((*Signature)(nil), "api.Signature") proto.RegisterType((*PublicKey)(nil), "api.PublicKey") proto.RegisterType((*DelegationRole)(nil), "api.DelegationRole") proto.RegisterType((*TargetSigned)(nil), "api.TargetSigned") proto.RegisterType((*TargetSignedList)(nil), "api.TargetSignedList") + proto.RegisterType((*TargetSignedListResponse)(nil), "api.TargetSignedListResponse") proto.RegisterType((*BasicResponse)(nil), "api.BasicResponse") proto.RegisterType((*Change)(nil), "api.Change") proto.RegisterType((*ChangeList)(nil), "api.ChangeList") + proto.RegisterType((*ChangeListResponse)(nil), "api.ChangeListResponse") } // Reference imports to suppress errors if they are not otherwise used. @@ -461,19 +626,21 @@ const _ = grpc.SupportPackageIsVersion4 // Client API for Notary service type NotaryClient interface { + Initialize(ctx context.Context, in *InitMessage, opts ...grpc.CallOption) (*BasicResponse, error) + Publish(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BasicResponse, error) // AddTarget adds a target to the TUF repository and re-signs. AddTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) // RemoveTarget deletes a target from the TUF repository and re-signs. It only // uses the `name` field from the Target object, ignoring all other fields RemoveTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) // ListTargets list the targets for the specified roles in the TUF repository - ListTargets(ctx context.Context, in *RoleList, opts ...grpc.CallOption) (*TargetWithRoleList, error) + ListTargets(ctx context.Context, in *RoleList, opts ...grpc.CallOption) (*TargetWithRoleListResponse, error) // GetTargetByName returns a target by the given name. - GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRole, error) + GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName - GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedList, error) + GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes - GetChangelist(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ChangeList, error) + GetChangelist(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ChangeListResponse, error) } type notaryClient struct { @@ -484,6 +651,24 @@ func NewNotaryClient(cc *grpc.ClientConn) NotaryClient { return ¬aryClient{cc} } +func (c *notaryClient) Initialize(ctx context.Context, in *InitMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/Initialize", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) Publish(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/Publish", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *notaryClient) AddTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) { out := new(BasicResponse) err := grpc.Invoke(ctx, "/api.Notary/AddTarget", in, out, c.cc, opts...) @@ -502,8 +687,8 @@ func (c *notaryClient) RemoveTarget(ctx context.Context, in *Target, opts ...grp return out, nil } -func (c *notaryClient) ListTargets(ctx context.Context, in *RoleList, opts ...grpc.CallOption) (*TargetWithRoleList, error) { - out := new(TargetWithRoleList) +func (c *notaryClient) ListTargets(ctx context.Context, in *RoleList, opts ...grpc.CallOption) (*TargetWithRoleListResponse, error) { + out := new(TargetWithRoleListResponse) err := grpc.Invoke(ctx, "/api.Notary/ListTargets", in, out, c.cc, opts...) if err != nil { return nil, err @@ -511,8 +696,8 @@ func (c *notaryClient) ListTargets(ctx context.Context, in *RoleList, opts ...gr return out, nil } -func (c *notaryClient) GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRole, error) { - out := new(TargetWithRole) +func (c *notaryClient) GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRoleResponse, error) { + out := new(TargetWithRoleResponse) err := grpc.Invoke(ctx, "/api.Notary/GetTargetByName", in, out, c.cc, opts...) if err != nil { return nil, err @@ -520,8 +705,8 @@ func (c *notaryClient) GetTargetByName(ctx context.Context, in *TargetByNameActi return out, nil } -func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedList, error) { - out := new(TargetSignedList) +func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedListResponse, error) { + out := new(TargetSignedListResponse) err := grpc.Invoke(ctx, "/api.Notary/GetAllTargetMetadataByName", in, out, c.cc, opts...) if err != nil { return nil, err @@ -529,8 +714,8 @@ func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *Targe return out, nil } -func (c *notaryClient) GetChangelist(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ChangeList, error) { - out := new(ChangeList) +func (c *notaryClient) GetChangelist(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ChangeListResponse, error) { + out := new(ChangeListResponse) err := grpc.Invoke(ctx, "/api.Notary/GetChangelist", in, out, c.cc, opts...) if err != nil { return nil, err @@ -541,25 +726,63 @@ func (c *notaryClient) GetChangelist(ctx context.Context, in *Empty, opts ...grp // Server API for Notary service type NotaryServer interface { + Initialize(context.Context, *InitMessage) (*BasicResponse, error) + Publish(context.Context, *Empty) (*BasicResponse, error) // AddTarget adds a target to the TUF repository and re-signs. AddTarget(context.Context, *Target) (*BasicResponse, error) // RemoveTarget deletes a target from the TUF repository and re-signs. It only // uses the `name` field from the Target object, ignoring all other fields RemoveTarget(context.Context, *Target) (*BasicResponse, error) // ListTargets list the targets for the specified roles in the TUF repository - ListTargets(context.Context, *RoleList) (*TargetWithRoleList, error) + ListTargets(context.Context, *RoleList) (*TargetWithRoleListResponse, error) // GetTargetByName returns a target by the given name. - GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRole, error) + GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName - GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedList, error) + GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes - GetChangelist(context.Context, *Empty) (*ChangeList, error) + GetChangelist(context.Context, *Empty) (*ChangeListResponse, error) } func RegisterNotaryServer(s *grpc.Server, srv NotaryServer) { s.RegisterService(&_Notary_serviceDesc, srv) } +func _Notary_Initialize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InitMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).Initialize(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/Initialize", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).Initialize(ctx, req.(*InitMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).Publish(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/Publish", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).Publish(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + func _Notary_AddTarget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(Target) if err := dec(in); err != nil { @@ -672,6 +895,14 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ ServiceName: "api.Notary", HandlerType: (*NotaryServer)(nil), Methods: []grpc.MethodDesc{ + { + MethodName: "Initialize", + Handler: _Notary_Initialize_Handler, + }, + { + MethodName: "Publish", + Handler: _Notary_Publish_Handler, + }, { MethodName: "AddTarget", Handler: _Notary_AddTarget_Handler, @@ -704,53 +935,64 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 762 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x55, 0x5b, 0x6f, 0xdb, 0x36, - 0x14, 0x8e, 0x7c, 0x8d, 0x8e, 0x9c, 0xcb, 0x98, 0x6d, 0x11, 0x84, 0x0c, 0x10, 0x98, 0x0d, 0x33, - 0x30, 0xcc, 0x43, 0x9c, 0x87, 0x6d, 0x7d, 0x29, 0x9c, 0x4b, 0xdd, 0x20, 0x4d, 0x50, 0xb0, 0x45, - 0xfb, 0xcc, 0xc8, 0x84, 0x25, 0x58, 0x96, 0x54, 0x93, 0x0e, 0xaa, 0xff, 0xd0, 0x5f, 0xd6, 0xe7, - 0xbe, 0xf7, 0xaf, 0x14, 0xbc, 0xd9, 0x74, 0xeb, 0x02, 0x7d, 0xe3, 0x47, 0x9e, 0x73, 0x78, 0xce, - 0xf7, 0x7d, 0xa2, 0xc0, 0xa7, 0x55, 0x36, 0xa8, 0x16, 0xa5, 0x28, 0x51, 0x93, 0x56, 0x19, 0xee, - 0x42, 0xfb, 0x7a, 0x5e, 0x89, 0x1a, 0xc7, 0xb0, 0x4b, 0xca, 0x9c, 0xbd, 0xc8, 0xb8, 0x40, 0x3f, - 0x43, 0x7b, 0x51, 0xe6, 0x8c, 0x87, 0x5e, 0xdc, 0xec, 0xfb, 0x44, 0x03, 0x1c, 0x03, 0xbc, 0xa6, - 0x8b, 0x29, 0x13, 0xf7, 0x74, 0xce, 0x10, 0x82, 0x56, 0x41, 0xe7, 0x2c, 0xf4, 0x62, 0xaf, 0xef, - 0x13, 0xb5, 0xc6, 0x1f, 0x3d, 0xe8, 0xe8, 0x10, 0x74, 0x08, 0xcd, 0xe9, 0xb2, 0x30, 0xa7, 0x72, - 0xb9, 0x4a, 0x68, 0xac, 0x13, 0xd0, 0xaf, 0xd0, 0xc9, 0x59, 0x31, 0x15, 0x69, 0xd8, 0x8c, 0xbd, - 0x7e, 0x93, 0x18, 0x84, 0xfe, 0x81, 0x4e, 0x4a, 0x79, 0xca, 0x78, 0xd8, 0x8a, 0x9b, 0xfd, 0x60, - 0x78, 0x3c, 0x90, 0x6d, 0xeb, 0xd2, 0x83, 0xe7, 0xea, 0xe4, 0xba, 0x10, 0x8b, 0x9a, 0x98, 0x30, - 0x59, 0x28, 0x59, 0x72, 0x51, 0xce, 0xc3, 0x76, 0xec, 0xf5, 0x7b, 0xc4, 0xa0, 0xe8, 0x7f, 0x08, - 0x9c, 0x70, 0xd9, 0xd5, 0x8c, 0xd5, 0xb6, 0xab, 0x19, 0xab, 0xe5, 0xa8, 0x8f, 0x34, 0x5f, 0xea, - 0xb6, 0x7a, 0x44, 0x83, 0x27, 0x8d, 0xff, 0x3c, 0x7c, 0x03, 0xfb, 0xfa, 0xc2, 0xb7, 0x99, 0x48, - 0x25, 0x35, 0xe8, 0x14, 0x3a, 0x42, 0xed, 0xa8, 0x02, 0xc1, 0x30, 0x70, 0xba, 0x22, 0xe6, 0x48, - 0x8e, 0x29, 0xe9, 0xb2, 0x63, 0xca, 0x35, 0xbe, 0x04, 0xb4, 0x59, 0x4a, 0xb1, 0xfc, 0x37, 0x74, - 0x75, 0x8e, 0xe6, 0x39, 0x18, 0x1e, 0x39, 0xf5, 0x6c, 0x24, 0xb1, 0x31, 0xf8, 0xce, 0x16, 0xb9, - 0xa8, 0xa5, 0x00, 0xa3, 0x44, 0x64, 0x65, 0xb1, 0x4d, 0x06, 0x74, 0x6a, 0xe5, 0x6b, 0xa8, 0x36, - 0xf7, 0x54, 0x59, 0x7b, 0xad, 0x55, 0xf3, 0x1d, 0xf8, 0xaf, 0xb2, 0x69, 0x41, 0xc5, 0x72, 0xc1, - 0x24, 0x0b, 0x33, 0x56, 0xdf, 0x5c, 0x99, 0x32, 0x1a, 0x48, 0x52, 0xe7, 0x4c, 0xa4, 0xe5, 0xc4, - 0x0c, 0x63, 0x10, 0x3a, 0x01, 0x9f, 0xdb, 0x54, 0x25, 0x5c, 0x8f, 0xac, 0x37, 0x50, 0x08, 0xdd, - 0x8c, 0xbf, 0xa1, 0x79, 0x36, 0x09, 0x5b, 0xb1, 0xd7, 0xdf, 0x25, 0x16, 0xe2, 0x00, 0xfc, 0x97, - 0xcb, 0x87, 0x3c, 0x4b, 0x6e, 0x59, 0x8d, 0x3f, 0x79, 0xb0, 0x7f, 0xc5, 0x72, 0x36, 0xa5, 0x72, - 0x0e, 0xc5, 0xef, 0x19, 0xb4, 0x66, 0xac, 0xb6, 0x6c, 0xfc, 0xa6, 0xda, 0xde, 0x0c, 0x19, 0xdc, - 0xb2, 0xda, 0x28, 0xaf, 0x42, 0xb7, 0x9a, 0xea, 0x04, 0x7c, 0x91, 0x2e, 0x18, 0x4f, 0xcb, 0x7c, - 0xa2, 0xda, 0x6b, 0x93, 0xf5, 0x86, 0x1c, 0xb5, 0xa2, 0x22, 0xd5, 0xce, 0xf2, 0x89, 0x06, 0xd1, - 0x18, 0xfc, 0x55, 0xe9, 0x2d, 0x2e, 0xf9, 0xdd, 0x75, 0x49, 0x30, 0xdc, 0x57, 0xad, 0xad, 0x66, - 0x71, 0x5d, 0xf3, 0xc1, 0x83, 0x9e, 0x96, 0x49, 0xb2, 0xcb, 0x26, 0xe8, 0x4f, 0xe3, 0x07, 0x6d, - 0x99, 0xa3, 0x2d, 0x43, 0x69, 0x93, 0x38, 0xee, 0x6a, 0x7c, 0xdf, 0x5d, 0x03, 0x80, 0x15, 0xd3, - 0x3c, 0x6c, 0x2a, 0xa2, 0x74, 0x37, 0x2b, 0x31, 0x89, 0x13, 0x81, 0x9f, 0xc2, 0xa1, 0xdb, 0x8d, - 0xf2, 0xdd, 0x5f, 0x5f, 0xfb, 0xee, 0x27, 0xe7, 0x26, 0x1d, 0xb7, 0x76, 0xdd, 0x25, 0xec, 0x5d, - 0x50, 0x9e, 0x25, 0x84, 0xf1, 0xaa, 0x2c, 0xb8, 0x92, 0x97, 0x2f, 0x93, 0x84, 0x71, 0xae, 0x46, - 0xda, 0x25, 0x16, 0xca, 0x93, 0x39, 0xe3, 0x9c, 0x4e, 0xad, 0x1c, 0x16, 0xe2, 0xf7, 0xd0, 0xb9, - 0x4c, 0x69, 0x31, 0x55, 0x1f, 0x3c, 0x55, 0xc6, 0x35, 0xec, 0x1a, 0x24, 0x55, 0xe1, 0x49, 0x59, - 0xd9, 0x4c, 0x0d, 0xa4, 0xba, 0xa2, 0xae, 0xb4, 0xc7, 0x7c, 0xa2, 0xd6, 0x72, 0x4f, 0x4a, 0xa6, - 0xbc, 0xe5, 0x13, 0xb5, 0x96, 0x37, 0x27, 0x65, 0x21, 0x58, 0x21, 0xcc, 0xe7, 0x6f, 0x21, 0x3e, - 0x07, 0xd0, 0x37, 0xab, 0xc9, 0xff, 0x80, 0x6e, 0xa2, 0x90, 0x9d, 0x5c, 0x73, 0xac, 0x23, 0x88, - 0x3d, 0x1b, 0x7e, 0x6e, 0x40, 0xe7, 0xbe, 0x14, 0x74, 0x51, 0xa3, 0x01, 0xf8, 0xa3, 0xc9, 0xc4, - 0xbc, 0x69, 0xae, 0x22, 0x11, 0x52, 0x60, 0x83, 0x1b, 0xbc, 0x83, 0xce, 0xa0, 0x47, 0xd8, 0xbc, - 0x7c, 0x64, 0x3f, 0x9e, 0xf2, 0x2f, 0x04, 0xb2, 0x39, 0x1d, 0xc3, 0xd1, 0xe6, 0xd7, 0x1a, 0x1d, - 0x6f, 0x79, 0x13, 0xe4, 0x01, 0xde, 0x41, 0x23, 0x38, 0x18, 0x33, 0xe1, 0xbe, 0x09, 0xc8, 0x8d, - 0x76, 0x9f, 0x89, 0x68, 0xdb, 0xd3, 0x82, 0x77, 0xd0, 0x33, 0x88, 0xc6, 0x4c, 0x8c, 0xf2, 0x5c, - 0x9f, 0xdc, 0x31, 0x41, 0x27, 0x54, 0x50, 0x53, 0xed, 0xc0, 0x49, 0x92, 0x1b, 0xd1, 0x2f, 0xdf, - 0x18, 0xc5, 0xb4, 0x32, 0x80, 0xbd, 0x31, 0x13, 0x9a, 0xc7, 0x5c, 0x32, 0x0d, 0x2a, 0x52, 0xfd, - 0x59, 0xa2, 0x03, 0x87, 0x64, 0x1d, 0xff, 0xd0, 0x51, 0x7f, 0xa0, 0xf3, 0x2f, 0x01, 0x00, 0x00, - 0xff, 0xff, 0xc2, 0x4b, 0x49, 0x92, 0x8e, 0x06, 0x00, 0x00, + // 935 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x56, 0xdd, 0x6e, 0xe3, 0x44, + 0x14, 0xc6, 0x49, 0x9b, 0xae, 0x8f, 0xd3, 0x1f, 0x06, 0xd8, 0x5a, 0x61, 0x17, 0x22, 0x2f, 0x88, + 0x48, 0x88, 0xac, 0x36, 0x8b, 0x10, 0x3f, 0x42, 0xab, 0x6e, 0x77, 0x15, 0xaa, 0xd2, 0x0a, 0x0d, + 0x08, 0xae, 0xa7, 0xce, 0x51, 0x6c, 0xd5, 0xb1, 0x8d, 0x67, 0x52, 0x61, 0xde, 0x00, 0x89, 0x1b, + 0x2e, 0x79, 0x25, 0xae, 0x79, 0x02, 0x9e, 0x04, 0xcd, 0x8f, 0xed, 0x71, 0xe2, 0x48, 0xab, 0xde, + 0xcd, 0x99, 0xf9, 0xce, 0x37, 0xe7, 0xef, 0x1b, 0x1b, 0x5c, 0x96, 0xc7, 0xd3, 0xbc, 0xc8, 0x44, + 0x46, 0xfa, 0x2c, 0x8f, 0x83, 0x03, 0xd8, 0x7f, 0xbd, 0xca, 0x45, 0x19, 0x24, 0xe0, 0x5d, 0xa4, + 0xb1, 0xb8, 0x42, 0xce, 0xd9, 0x12, 0xc9, 0x07, 0x00, 0x45, 0x96, 0x89, 0x4b, 0x2c, 0x2f, 0x5e, + 0x71, 0xdf, 0x19, 0xf7, 0x27, 0x2e, 0xb5, 0x76, 0xc8, 0xb7, 0x40, 0x38, 0x16, 0x77, 0x58, 0x5c, + 0xb1, 0x94, 0x2d, 0x71, 0x41, 0xb3, 0x04, 0xb9, 0xdf, 0x1b, 0x3b, 0x13, 0x6f, 0x76, 0x38, 0x95, + 0x97, 0xc8, 0x9d, 0xef, 0x63, 0x2e, 0x68, 0x07, 0x30, 0x18, 0xc3, 0x83, 0xea, 0x9c, 0xbc, 0x0b, + 0xfb, 0x85, 0xf2, 0xd6, 0xb7, 0x68, 0x23, 0x18, 0x03, 0xfc, 0xc4, 0x8a, 0x25, 0x8a, 0x6b, 0xb6, + 0x42, 0x42, 0x60, 0x2f, 0x65, 0x2b, 0xf4, 0x9d, 0xb1, 0x33, 0x71, 0xa9, 0x5a, 0x07, 0xff, 0x38, + 0x30, 0xd0, 0x10, 0x72, 0x02, 0xfd, 0xe5, 0x3a, 0x35, 0xa7, 0x72, 0x59, 0x3b, 0xf4, 0x1a, 0x07, + 0xf2, 0x10, 0x06, 0x09, 0xa6, 0x4b, 0x11, 0xf9, 0xfd, 0xb1, 0x33, 0xe9, 0x53, 0x63, 0x91, 0xa7, + 0x30, 0x88, 0x18, 0x8f, 0x90, 0xfb, 0x7b, 0xe3, 0xfe, 0xc4, 0x9b, 0x9d, 0xaa, 0xf8, 0x35, 0xf5, + 0xf4, 0x3b, 0x75, 0xf2, 0x3a, 0x15, 0x45, 0x49, 0x0d, 0x4c, 0x12, 0x85, 0x6b, 0x2e, 0xb2, 0x95, + 0xbf, 0x3f, 0x76, 0x26, 0x43, 0x6a, 0xac, 0xd1, 0x57, 0xe0, 0x59, 0x70, 0x19, 0xd5, 0x2d, 0x96, + 0x55, 0x54, 0xb7, 0x58, 0xca, 0x54, 0xef, 0x58, 0xb2, 0xd6, 0x61, 0x0d, 0xa9, 0x36, 0xbe, 0xee, + 0x7d, 0xe9, 0x04, 0x17, 0x70, 0xa4, 0x2f, 0xfc, 0x25, 0x16, 0x91, 0x2c, 0x0d, 0x79, 0x02, 0x03, + 0xa1, 0x76, 0x14, 0x81, 0x37, 0xf3, 0xac, 0xa8, 0xa8, 0x39, 0x92, 0x69, 0xca, 0x72, 0x55, 0x69, + 0xca, 0x75, 0xf0, 0x87, 0x03, 0x0f, 0xdb, 0x5c, 0x14, 0x79, 0x9e, 0xa5, 0x1c, 0xc9, 0x37, 0x70, + 0x24, 0x5a, 0x27, 0x86, 0xfb, 0x1d, 0x8b, 0xbb, 0x76, 0xda, 0x80, 0x12, 0x1f, 0x0e, 0xf8, 0x3a, + 0x0c, 0x91, 0xeb, 0x3e, 0x3f, 0xa0, 0x95, 0x29, 0x4f, 0x56, 0x7a, 0x6e, 0x54, 0x65, 0x5d, 0x5a, + 0x99, 0xc1, 0x39, 0x90, 0x36, 0xab, 0xea, 0xf8, 0x67, 0x70, 0xa0, 0xb9, 0x75, 0xcf, 0x77, 0xdc, + 0x5f, 0x61, 0x82, 0xbf, 0x1d, 0x18, 0x6d, 0xb3, 0xd4, 0x49, 0xcd, 0x81, 0x88, 0xad, 0x53, 0x93, + 0xd8, 0x69, 0x07, 0xb1, 0x1e, 0xca, 0x6d, 0x97, 0x7b, 0x25, 0x78, 0x55, 0x25, 0xf8, 0xb2, 0x94, + 0x83, 0x7a, 0x16, 0x8a, 0x38, 0x4b, 0xbb, 0xc6, 0x95, 0x3c, 0xa9, 0xc6, 0xbc, 0x53, 0x24, 0x66, + 0xea, 0x7f, 0x05, 0xf7, 0xc7, 0x78, 0x99, 0x32, 0xb1, 0x2e, 0x50, 0x4e, 0xcb, 0xad, 0x54, 0x9b, + 0xa1, 0xd1, 0x86, 0x1c, 0xbe, 0x15, 0x8a, 0x28, 0x5b, 0x98, 0xa6, 0x1b, 0x8b, 0x3c, 0x02, 0x97, + 0x57, 0xae, 0x2a, 0xca, 0x21, 0x6d, 0x36, 0x64, 0x06, 0x31, 0xff, 0x99, 0x25, 0xf1, 0xc2, 0xdf, + 0xd3, 0xb9, 0x19, 0x33, 0xf0, 0xc0, 0xfd, 0x61, 0x7d, 0x93, 0xc4, 0xe1, 0x25, 0x96, 0xc1, 0xbf, + 0x0e, 0x1c, 0xbd, 0xc2, 0x04, 0x97, 0x4c, 0xe6, 0xa1, 0xda, 0xfe, 0x0c, 0xf6, 0x6e, 0xb1, 0xac, + 0x3a, 0xf5, 0x58, 0x85, 0xdd, 0x86, 0x4c, 0x2f, 0xb1, 0x34, 0x0a, 0x51, 0xd0, 0x4e, 0xf1, 0x3d, + 0x02, 0x57, 0x44, 0x05, 0xf2, 0x28, 0x4b, 0x16, 0x2a, 0xbc, 0x7d, 0xda, 0x6c, 0xc8, 0x54, 0x73, + 0x26, 0x22, 0xad, 0x40, 0x97, 0x6a, 0x63, 0x34, 0x07, 0xb7, 0xa6, 0xee, 0x50, 0xd3, 0x47, 0xb6, + 0x9a, 0xbc, 0xd9, 0x91, 0x0a, 0xad, 0xce, 0xc5, 0x56, 0xd7, 0x9f, 0x0e, 0x0c, 0x75, 0x9b, 0x64, + 0x75, 0x71, 0x41, 0x3e, 0x31, 0xba, 0xb1, 0xc7, 0xbf, 0x9d, 0x94, 0x16, 0x93, 0xa5, 0xc2, 0xde, + 0x6e, 0x15, 0x4e, 0x01, 0xea, 0x4a, 0x73, 0xbf, 0xaf, 0x0a, 0xa5, 0xa3, 0xa9, 0x9b, 0x49, 0x2d, + 0x44, 0xf0, 0x02, 0x4e, 0xec, 0x68, 0xd4, 0xf0, 0x7d, 0xba, 0xa9, 0x89, 0xb7, 0xad, 0x9b, 0x34, + 0xae, 0x51, 0xc4, 0x5f, 0x0e, 0xf8, 0x9b, 0x0c, 0xb5, 0x1e, 0xce, 0xe0, 0x44, 0x6c, 0x9c, 0x99, + 0x3c, 0xdf, 0xdb, 0xa2, 0x54, 0x8e, 0x5b, 0xf0, 0x7b, 0x4a, 0xfd, 0xf0, 0x25, 0xe3, 0x71, 0x58, + 0xc7, 0x61, 0x91, 0x38, 0x3b, 0x49, 0x7a, 0x6d, 0x92, 0xdf, 0x60, 0x70, 0x1e, 0xb1, 0x74, 0xa9, + 0x1e, 0x6b, 0xa6, 0xc4, 0x64, 0x3a, 0x6e, 0x2c, 0x39, 0x29, 0x3c, 0xcc, 0xf2, 0xca, 0x53, 0x1b, + 0x72, 0xe2, 0x44, 0x99, 0x57, 0x31, 0xa9, 0xb5, 0xdc, 0x93, 0x63, 0xa4, 0xe6, 0xdd, 0xa5, 0x6a, + 0x2d, 0x6f, 0x0e, 0xb3, 0x54, 0x60, 0x2a, 0xcc, 0xd3, 0x5d, 0x99, 0xc1, 0x73, 0x00, 0x7d, 0xb3, + 0x2a, 0xc0, 0xc7, 0x70, 0x10, 0x2a, 0xab, 0xea, 0x86, 0xee, 0xbb, 0x46, 0xd0, 0xea, 0x2c, 0x28, + 0x81, 0x34, 0x4e, 0x75, 0xe2, 0x4f, 0x01, 0x34, 0x20, 0x69, 0x4a, 0x7f, 0x6c, 0xf9, 0x2b, 0xb0, + 0x05, 0xb9, 0x4f, 0xb9, 0x67, 0xff, 0xf5, 0x61, 0x70, 0x9d, 0x09, 0x56, 0x94, 0xe4, 0x73, 0x00, + 0xf9, 0xe9, 0x8e, 0x59, 0x12, 0xff, 0x8e, 0xe4, 0x44, 0xdd, 0x64, 0x7d, 0xcb, 0x47, 0x44, 0xed, + 0xb4, 0x9a, 0x13, 0xbc, 0x25, 0x07, 0x4e, 0x69, 0x85, 0x47, 0x04, 0x14, 0x40, 0xfd, 0x07, 0xec, + 0x00, 0x4f, 0xc1, 0x3d, 0x5b, 0x2c, 0xcc, 0xd7, 0xd6, 0xd6, 0xc0, 0x0e, 0xfc, 0x33, 0x18, 0x52, + 0x5c, 0x65, 0x77, 0xf8, 0xe6, 0x2e, 0x2f, 0xc0, 0x93, 0x85, 0xd1, 0x18, 0x4e, 0xda, 0xef, 0xe3, + 0xe8, 0xc3, 0x5d, 0x0f, 0x79, 0x43, 0x70, 0x01, 0xc7, 0x73, 0x14, 0xf6, 0x6b, 0x4c, 0xec, 0xe7, + 0xdf, 0x7e, 0xa0, 0x47, 0xef, 0x77, 0x7d, 0x70, 0x1a, 0xaa, 0x6b, 0x18, 0xcd, 0x51, 0x9c, 0x25, + 0x89, 0x46, 0x5c, 0xa1, 0x60, 0x0b, 0x26, 0x98, 0x61, 0x3d, 0xb6, 0x9c, 0xe5, 0xc6, 0xe8, 0x71, + 0xb7, 0xae, 0x1a, 0xbe, 0x2f, 0xe0, 0x70, 0x8e, 0xe2, 0xbc, 0xe9, 0xb8, 0x5d, 0xf1, 0xd3, 0xcd, + 0xd1, 0xa8, 0xfd, 0x6e, 0x06, 0xea, 0x4f, 0xed, 0xf9, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xea, + 0x85, 0x57, 0x39, 0xb6, 0x09, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index 34ec7ab99..41d5ec838 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -4,6 +4,9 @@ package api; // Notary Interface service Notary { + rpc Initialize(InitMessage) returns (BasicResponse) {} + + rpc Publish(Empty) returns (BasicResponse) {} // AddTarget adds a target to the TUF repository and re-signs. rpc AddTarget(Target) returns (BasicResponse) {} @@ -13,22 +16,29 @@ service Notary { rpc RemoveTarget(Target) returns (BasicResponse) {} // ListTargets list the targets for the specified roles in the TUF repository - rpc ListTargets(RoleList) returns (TargetWithRoleList) {} + rpc ListTargets(RoleList) returns (TargetWithRoleListResponse) {} // GetTargetByName returns a target by the given name. - rpc GetTargetByName(TargetByNameAction) returns (TargetWithRole) {} + rpc GetTargetByName(TargetByNameAction) returns (TargetWithRoleResponse) {} // GetAllTargetMetadataByName - rpc GetAllTargetMetadataByName(TargetName) returns (TargetSignedList) {} + rpc GetAllTargetMetadataByName(TargetName) returns (TargetSignedListResponse) {} // GetChangelist returns the list of the repository's unpublished changes - rpc GetChangelist(Empty) returns (ChangeList) {} + rpc GetChangelist(Empty) returns (ChangeListResponse) {} } message Empty { } +// InitMessage holds a list of root key IDs and a list of roles for which +// the server automatically should manage the keys +message InitMessage { + repeated string rootKeyIDs = 1; + RoleList serverManagedRoles = 2; +} + // RoleList message holds a list of TUF role names message RoleList { repeated string roles = 1; @@ -53,10 +63,22 @@ message TargetWithRole { string role = 2; } +message TargetWithRoleResponse { + TargetWithRole targetWithRole = 1; + bool success = 2; + string message = 3; +} + message TargetWithRoleList { repeated TargetWithRole targets = 1; } +message TargetWithRoleListResponse { + TargetWithRoleList targetWithRoleList = 1; + bool success = 2; + string message = 3; +} + message TargetByNameAction { string name = 1; RoleList roles = 2; @@ -69,8 +91,8 @@ message Signature { bool isValid = 4; } +// FIXME: implement message PublicKey { - } message DelegationRole { @@ -90,6 +112,12 @@ message TargetSignedList { repeated TargetSigned targets = 1; } +message TargetSignedListResponse { + TargetSignedList targetSignedList = 1; + bool success = 2; + string message = 3; +} + // BasicResponse describes a response with a true/false success indicator, // and if false, an error type and message. See the errors.go file in this // package for the possible errors and a translation function between the @@ -113,5 +141,10 @@ message ChangeList { repeated Change changes = 1; } +message ChangeListResponse { + ChangeList changelist = 1; + bool success = 2; + string message = 3; +} From 9066aa34c5bab65c3d6db72ada9fe8e541807ece Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 7 Mar 2017 02:48:44 +0100 Subject: [PATCH 15/62] Add Role operations to client API gRPC interface with generated code Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 1020 +++++++++++++++++++++++++++++++++----- client_api/api/api.proto | 112 ++++- 2 files changed, 998 insertions(+), 134 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index 58eda8e1e..8a5794673 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -10,14 +10,22 @@ It is generated from these files: It has these top-level messages: Empty + AddDelegationMessage + AddDelegationRoleAndKeysMessage + AddDelegationPathsMessage + RemoveDelegationKeysAndPathsMessage + RemoveDelegationRoleMessage + RemoveDelegationPathsMessage + RemoveDelegationKeysMessage + ClearDelegationPathsMessage InitMessage - RoleList + RoleNameList TargetName Target TargetWithRole TargetWithRoleResponse - TargetWithRoleList - TargetWithRoleListResponse + TargetWithRoleNameList + TargetWithRoleNameListResponse TargetByNameAction Signature PublicKey @@ -29,6 +37,13 @@ It has these top-level messages: Change ChangeList ChangeListResponse + RootRole + Role + RoleList + RoleListResponse + RoleWithSignatures + RoleWithSignaturesList + RoleWithSignaturesListResponse */ package api @@ -60,17 +75,211 @@ func (m *Empty) String() string { return proto.CompactTextString(m) } func (*Empty) ProtoMessage() {} func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +type AddDelegationMessage struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + DelegationKeys []*PublicKey `protobuf:"bytes,2,rep,name=delegationKeys" json:"delegationKeys,omitempty"` + Paths []string `protobuf:"bytes,3,rep,name=paths" json:"paths,omitempty"` +} + +func (m *AddDelegationMessage) Reset() { *m = AddDelegationMessage{} } +func (m *AddDelegationMessage) String() string { return proto.CompactTextString(m) } +func (*AddDelegationMessage) ProtoMessage() {} +func (*AddDelegationMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *AddDelegationMessage) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *AddDelegationMessage) GetDelegationKeys() []*PublicKey { + if m != nil { + return m.DelegationKeys + } + return nil +} + +func (m *AddDelegationMessage) GetPaths() []string { + if m != nil { + return m.Paths + } + return nil +} + +type AddDelegationRoleAndKeysMessage struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + DelegationKeys []*PublicKey `protobuf:"bytes,2,rep,name=delegationKeys" json:"delegationKeys,omitempty"` +} + +func (m *AddDelegationRoleAndKeysMessage) Reset() { *m = AddDelegationRoleAndKeysMessage{} } +func (m *AddDelegationRoleAndKeysMessage) String() string { return proto.CompactTextString(m) } +func (*AddDelegationRoleAndKeysMessage) ProtoMessage() {} +func (*AddDelegationRoleAndKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *AddDelegationRoleAndKeysMessage) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *AddDelegationRoleAndKeysMessage) GetDelegationKeys() []*PublicKey { + if m != nil { + return m.DelegationKeys + } + return nil +} + +type AddDelegationPathsMessage struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Paths []string `protobuf:"bytes,2,rep,name=paths" json:"paths,omitempty"` +} + +func (m *AddDelegationPathsMessage) Reset() { *m = AddDelegationPathsMessage{} } +func (m *AddDelegationPathsMessage) String() string { return proto.CompactTextString(m) } +func (*AddDelegationPathsMessage) ProtoMessage() {} +func (*AddDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *AddDelegationPathsMessage) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *AddDelegationPathsMessage) GetPaths() []string { + if m != nil { + return m.Paths + } + return nil +} + +type RemoveDelegationKeysAndPathsMessage struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + KeyIDs []string `protobuf:"bytes,2,rep,name=keyIDs" json:"keyIDs,omitempty"` + Paths []string `protobuf:"bytes,3,rep,name=paths" json:"paths,omitempty"` +} + +func (m *RemoveDelegationKeysAndPathsMessage) Reset() { *m = RemoveDelegationKeysAndPathsMessage{} } +func (m *RemoveDelegationKeysAndPathsMessage) String() string { return proto.CompactTextString(m) } +func (*RemoveDelegationKeysAndPathsMessage) ProtoMessage() {} +func (*RemoveDelegationKeysAndPathsMessage) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{4} +} + +func (m *RemoveDelegationKeysAndPathsMessage) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *RemoveDelegationKeysAndPathsMessage) GetKeyIDs() []string { + if m != nil { + return m.KeyIDs + } + return nil +} + +func (m *RemoveDelegationKeysAndPathsMessage) GetPaths() []string { + if m != nil { + return m.Paths + } + return nil +} + +type RemoveDelegationRoleMessage struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` +} + +func (m *RemoveDelegationRoleMessage) Reset() { *m = RemoveDelegationRoleMessage{} } +func (m *RemoveDelegationRoleMessage) String() string { return proto.CompactTextString(m) } +func (*RemoveDelegationRoleMessage) ProtoMessage() {} +func (*RemoveDelegationRoleMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *RemoveDelegationRoleMessage) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +type RemoveDelegationPathsMessage struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Paths []string `protobuf:"bytes,2,rep,name=paths" json:"paths,omitempty"` +} + +func (m *RemoveDelegationPathsMessage) Reset() { *m = RemoveDelegationPathsMessage{} } +func (m *RemoveDelegationPathsMessage) String() string { return proto.CompactTextString(m) } +func (*RemoveDelegationPathsMessage) ProtoMessage() {} +func (*RemoveDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *RemoveDelegationPathsMessage) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *RemoveDelegationPathsMessage) GetPaths() []string { + if m != nil { + return m.Paths + } + return nil +} + +type RemoveDelegationKeysMessage struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + KeyIDs []string `protobuf:"bytes,2,rep,name=keyIDs" json:"keyIDs,omitempty"` +} + +func (m *RemoveDelegationKeysMessage) Reset() { *m = RemoveDelegationKeysMessage{} } +func (m *RemoveDelegationKeysMessage) String() string { return proto.CompactTextString(m) } +func (*RemoveDelegationKeysMessage) ProtoMessage() {} +func (*RemoveDelegationKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *RemoveDelegationKeysMessage) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *RemoveDelegationKeysMessage) GetKeyIDs() []string { + if m != nil { + return m.KeyIDs + } + return nil +} + +type ClearDelegationPathsMessage struct { + Role string `protobuf:"bytes,1,opt,name=role" json:"role,omitempty"` +} + +func (m *ClearDelegationPathsMessage) Reset() { *m = ClearDelegationPathsMessage{} } +func (m *ClearDelegationPathsMessage) String() string { return proto.CompactTextString(m) } +func (*ClearDelegationPathsMessage) ProtoMessage() {} +func (*ClearDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *ClearDelegationPathsMessage) GetRole() string { + if m != nil { + return m.Role + } + return "" +} + // InitMessage holds a list of root key IDs and a list of roles for which // the server automatically should manage the keys type InitMessage struct { - RootKeyIDs []string `protobuf:"bytes,1,rep,name=rootKeyIDs" json:"rootKeyIDs,omitempty"` - ServerManagedRoles *RoleList `protobuf:"bytes,2,opt,name=serverManagedRoles" json:"serverManagedRoles,omitempty"` + RootKeyIDs []string `protobuf:"bytes,1,rep,name=rootKeyIDs" json:"rootKeyIDs,omitempty"` + ServerManagedRoles *RoleNameList `protobuf:"bytes,2,opt,name=serverManagedRoles" json:"serverManagedRoles,omitempty"` } func (m *InitMessage) Reset() { *m = InitMessage{} } func (m *InitMessage) String() string { return proto.CompactTextString(m) } func (*InitMessage) ProtoMessage() {} -func (*InitMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*InitMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (m *InitMessage) GetRootKeyIDs() []string { if m != nil { @@ -79,24 +288,24 @@ func (m *InitMessage) GetRootKeyIDs() []string { return nil } -func (m *InitMessage) GetServerManagedRoles() *RoleList { +func (m *InitMessage) GetServerManagedRoles() *RoleNameList { if m != nil { return m.ServerManagedRoles } return nil } -// RoleList message holds a list of TUF role names -type RoleList struct { +// RoleNameList message holds a list of TUF role names +type RoleNameList struct { Roles []string `protobuf:"bytes,1,rep,name=roles" json:"roles,omitempty"` } -func (m *RoleList) Reset() { *m = RoleList{} } -func (m *RoleList) String() string { return proto.CompactTextString(m) } -func (*RoleList) ProtoMessage() {} -func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (m *RoleNameList) Reset() { *m = RoleNameList{} } +func (m *RoleNameList) String() string { return proto.CompactTextString(m) } +func (*RoleNameList) ProtoMessage() {} +func (*RoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } -func (m *RoleList) GetRoles() []string { +func (m *RoleNameList) GetRoles() []string { if m != nil { return m.Roles } @@ -110,7 +319,7 @@ type TargetName struct { func (m *TargetName) Reset() { *m = TargetName{} } func (m *TargetName) String() string { return proto.CompactTextString(m) } func (*TargetName) ProtoMessage() {} -func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *TargetName) GetName() string { if m != nil { @@ -131,7 +340,7 @@ type Target struct { func (m *Target) Reset() { *m = Target{} } func (m *Target) String() string { return proto.CompactTextString(m) } func (*Target) ProtoMessage() {} -func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } func (m *Target) GetGun() string { if m != nil { @@ -177,7 +386,7 @@ type TargetWithRole struct { func (m *TargetWithRole) Reset() { *m = TargetWithRole{} } func (m *TargetWithRole) String() string { return proto.CompactTextString(m) } func (*TargetWithRole) ProtoMessage() {} -func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *TargetWithRole) GetTarget() *Target { if m != nil { @@ -202,7 +411,7 @@ type TargetWithRoleResponse struct { func (m *TargetWithRoleResponse) Reset() { *m = TargetWithRoleResponse{} } func (m *TargetWithRoleResponse) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleResponse) ProtoMessage() {} -func (*TargetWithRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*TargetWithRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *TargetWithRoleResponse) GetTargetWithRole() *TargetWithRole { if m != nil { @@ -225,48 +434,48 @@ func (m *TargetWithRoleResponse) GetMessage() string { return "" } -type TargetWithRoleList struct { +type TargetWithRoleNameList struct { Targets []*TargetWithRole `protobuf:"bytes,1,rep,name=targets" json:"targets,omitempty"` } -func (m *TargetWithRoleList) Reset() { *m = TargetWithRoleList{} } -func (m *TargetWithRoleList) String() string { return proto.CompactTextString(m) } -func (*TargetWithRoleList) ProtoMessage() {} -func (*TargetWithRoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (m *TargetWithRoleNameList) Reset() { *m = TargetWithRoleNameList{} } +func (m *TargetWithRoleNameList) String() string { return proto.CompactTextString(m) } +func (*TargetWithRoleNameList) ProtoMessage() {} +func (*TargetWithRoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } -func (m *TargetWithRoleList) GetTargets() []*TargetWithRole { +func (m *TargetWithRoleNameList) GetTargets() []*TargetWithRole { if m != nil { return m.Targets } return nil } -type TargetWithRoleListResponse struct { - TargetWithRoleList *TargetWithRoleList `protobuf:"bytes,1,opt,name=targetWithRoleList" json:"targetWithRoleList,omitempty"` - Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +type TargetWithRoleNameListResponse struct { + TargetWithRoleNameList *TargetWithRoleNameList `protobuf:"bytes,1,opt,name=targetWithRoleNameList" json:"targetWithRoleNameList,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` } -func (m *TargetWithRoleListResponse) Reset() { *m = TargetWithRoleListResponse{} } -func (m *TargetWithRoleListResponse) String() string { return proto.CompactTextString(m) } -func (*TargetWithRoleListResponse) ProtoMessage() {} -func (*TargetWithRoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (m *TargetWithRoleNameListResponse) Reset() { *m = TargetWithRoleNameListResponse{} } +func (m *TargetWithRoleNameListResponse) String() string { return proto.CompactTextString(m) } +func (*TargetWithRoleNameListResponse) ProtoMessage() {} +func (*TargetWithRoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } -func (m *TargetWithRoleListResponse) GetTargetWithRoleList() *TargetWithRoleList { +func (m *TargetWithRoleNameListResponse) GetTargetWithRoleNameList() *TargetWithRoleNameList { if m != nil { - return m.TargetWithRoleList + return m.TargetWithRoleNameList } return nil } -func (m *TargetWithRoleListResponse) GetSuccess() bool { +func (m *TargetWithRoleNameListResponse) GetSuccess() bool { if m != nil { return m.Success } return false } -func (m *TargetWithRoleListResponse) GetMessage() string { +func (m *TargetWithRoleNameListResponse) GetMessage() string { if m != nil { return m.Message } @@ -274,14 +483,14 @@ func (m *TargetWithRoleListResponse) GetMessage() string { } type TargetByNameAction struct { - Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Roles *RoleList `protobuf:"bytes,2,opt,name=roles" json:"roles,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Roles *RoleNameList `protobuf:"bytes,2,opt,name=roles" json:"roles,omitempty"` } func (m *TargetByNameAction) Reset() { *m = TargetByNameAction{} } func (m *TargetByNameAction) String() string { return proto.CompactTextString(m) } func (*TargetByNameAction) ProtoMessage() {} -func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *TargetByNameAction) GetName() string { if m != nil { @@ -290,7 +499,7 @@ func (m *TargetByNameAction) GetName() string { return "" } -func (m *TargetByNameAction) GetRoles() *RoleList { +func (m *TargetByNameAction) GetRoles() *RoleNameList { if m != nil { return m.Roles } @@ -307,7 +516,7 @@ type Signature struct { func (m *Signature) Reset() { *m = Signature{} } func (m *Signature) String() string { return proto.CompactTextString(m) } func (*Signature) ProtoMessage() {} -func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *Signature) GetKeyID() string { if m != nil { @@ -337,14 +546,37 @@ func (m *Signature) GetIsValid() bool { return false } -// FIXME: implement type PublicKey struct { + Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` + Algorithm string `protobuf:"bytes,2,opt,name=algorithm" json:"algorithm,omitempty"` + Public []byte `protobuf:"bytes,3,opt,name=public,proto3" json:"public,omitempty"` } func (m *PublicKey) Reset() { *m = PublicKey{} } func (m *PublicKey) String() string { return proto.CompactTextString(m) } func (*PublicKey) ProtoMessage() {} -func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } + +func (m *PublicKey) GetId() string { + if m != nil { + return m.Id + } + return "" +} + +func (m *PublicKey) GetAlgorithm() string { + if m != nil { + return m.Algorithm + } + return "" +} + +func (m *PublicKey) GetPublic() []byte { + if m != nil { + return m.Public + } + return nil +} type DelegationRole struct { Keys map[string]*PublicKey `protobuf:"bytes,1,rep,name=keys" json:"keys,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` @@ -356,7 +588,7 @@ type DelegationRole struct { func (m *DelegationRole) Reset() { *m = DelegationRole{} } func (m *DelegationRole) String() string { return proto.CompactTextString(m) } func (*DelegationRole) ProtoMessage() {} -func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *DelegationRole) GetKeys() map[string]*PublicKey { if m != nil { @@ -395,7 +627,7 @@ type TargetSigned struct { func (m *TargetSigned) Reset() { *m = TargetSigned{} } func (m *TargetSigned) String() string { return proto.CompactTextString(m) } func (*TargetSigned) ProtoMessage() {} -func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } func (m *TargetSigned) GetRole() *DelegationRole { if m != nil { @@ -425,7 +657,7 @@ type TargetSignedList struct { func (m *TargetSignedList) Reset() { *m = TargetSignedList{} } func (m *TargetSignedList) String() string { return proto.CompactTextString(m) } func (*TargetSignedList) ProtoMessage() {} -func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } func (m *TargetSignedList) GetTargets() []*TargetSigned { if m != nil { @@ -443,7 +675,7 @@ type TargetSignedListResponse struct { func (m *TargetSignedListResponse) Reset() { *m = TargetSignedListResponse{} } func (m *TargetSignedListResponse) String() string { return proto.CompactTextString(m) } func (*TargetSignedListResponse) ProtoMessage() {} -func (*TargetSignedListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*TargetSignedListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } func (m *TargetSignedListResponse) GetTargetSignedList() *TargetSignedList { if m != nil { @@ -478,7 +710,7 @@ type BasicResponse struct { func (m *BasicResponse) Reset() { *m = BasicResponse{} } func (m *BasicResponse) String() string { return proto.CompactTextString(m) } func (*BasicResponse) ProtoMessage() {} -func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } func (m *BasicResponse) GetSuccess() bool { if m != nil { @@ -506,7 +738,7 @@ type Change struct { func (m *Change) Reset() { *m = Change{} } func (m *Change) String() string { return proto.CompactTextString(m) } func (*Change) ProtoMessage() {} -func (*Change) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*Change) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } func (m *Change) GetAction() string { if m != nil { @@ -551,7 +783,7 @@ type ChangeList struct { func (m *ChangeList) Reset() { *m = ChangeList{} } func (m *ChangeList) String() string { return proto.CompactTextString(m) } func (*ChangeList) ProtoMessage() {} -func (*ChangeList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*ChangeList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } func (m *ChangeList) GetChanges() []*Change { if m != nil { @@ -569,7 +801,7 @@ type ChangeListResponse struct { func (m *ChangeListResponse) Reset() { *m = ChangeListResponse{} } func (m *ChangeListResponse) String() string { return proto.CompactTextString(m) } func (*ChangeListResponse) ProtoMessage() {} -func (*ChangeListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*ChangeListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } func (m *ChangeListResponse) GetChangelist() *ChangeList { if m != nil { @@ -592,16 +824,200 @@ func (m *ChangeListResponse) GetMessage() string { return "" } +type RootRole struct { + KeyIDs []string `protobuf:"bytes,1,rep,name=keyIDs" json:"keyIDs,omitempty"` + Threshold int32 `protobuf:"varint,2,opt,name=threshold" json:"threshold,omitempty"` +} + +func (m *RootRole) Reset() { *m = RootRole{} } +func (m *RootRole) String() string { return proto.CompactTextString(m) } +func (*RootRole) ProtoMessage() {} +func (*RootRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } + +func (m *RootRole) GetKeyIDs() []string { + if m != nil { + return m.KeyIDs + } + return nil +} + +func (m *RootRole) GetThreshold() int32 { + if m != nil { + return m.Threshold + } + return 0 +} + +type Role struct { + RootRole *RootRole `protobuf:"bytes,1,opt,name=rootRole" json:"rootRole,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` + Paths []string `protobuf:"bytes,3,rep,name=paths" json:"paths,omitempty"` +} + +func (m *Role) Reset() { *m = Role{} } +func (m *Role) String() string { return proto.CompactTextString(m) } +func (*Role) ProtoMessage() {} +func (*Role) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } + +func (m *Role) GetRootRole() *RootRole { + if m != nil { + return m.RootRole + } + return nil +} + +func (m *Role) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Role) GetPaths() []string { + if m != nil { + return m.Paths + } + return nil +} + +type RoleList struct { + Roles []*Role `protobuf:"bytes,1,rep,name=roles" json:"roles,omitempty"` +} + +func (m *RoleList) Reset() { *m = RoleList{} } +func (m *RoleList) String() string { return proto.CompactTextString(m) } +func (*RoleList) ProtoMessage() {} +func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } + +func (m *RoleList) GetRoles() []*Role { + if m != nil { + return m.Roles + } + return nil +} + +type RoleListResponse struct { + RoleList *RoleList `protobuf:"bytes,1,opt,name=roleList" json:"roleList,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *RoleListResponse) Reset() { *m = RoleListResponse{} } +func (m *RoleListResponse) String() string { return proto.CompactTextString(m) } +func (*RoleListResponse) ProtoMessage() {} +func (*RoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } + +func (m *RoleListResponse) GetRoleList() *RoleList { + if m != nil { + return m.RoleList + } + return nil +} + +func (m *RoleListResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *RoleListResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +type RoleWithSignatures struct { + Signatures []*Signature `protobuf:"bytes,1,rep,name=signatures" json:"signatures,omitempty"` + Role *Role `protobuf:"bytes,2,opt,name=role" json:"role,omitempty"` +} + +func (m *RoleWithSignatures) Reset() { *m = RoleWithSignatures{} } +func (m *RoleWithSignatures) String() string { return proto.CompactTextString(m) } +func (*RoleWithSignatures) ProtoMessage() {} +func (*RoleWithSignatures) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } + +func (m *RoleWithSignatures) GetSignatures() []*Signature { + if m != nil { + return m.Signatures + } + return nil +} + +func (m *RoleWithSignatures) GetRole() *Role { + if m != nil { + return m.Role + } + return nil +} + +type RoleWithSignaturesList struct { + RoleWithSignatures []*RoleWithSignatures `protobuf:"bytes,1,rep,name=roleWithSignatures" json:"roleWithSignatures,omitempty"` +} + +func (m *RoleWithSignaturesList) Reset() { *m = RoleWithSignaturesList{} } +func (m *RoleWithSignaturesList) String() string { return proto.CompactTextString(m) } +func (*RoleWithSignaturesList) ProtoMessage() {} +func (*RoleWithSignaturesList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } + +func (m *RoleWithSignaturesList) GetRoleWithSignatures() []*RoleWithSignatures { + if m != nil { + return m.RoleWithSignatures + } + return nil +} + +type RoleWithSignaturesListResponse struct { + RoleWithSignaturesList *RoleWithSignaturesList `protobuf:"bytes,1,opt,name=roleWithSignaturesList" json:"roleWithSignaturesList,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *RoleWithSignaturesListResponse) Reset() { *m = RoleWithSignaturesListResponse{} } +func (m *RoleWithSignaturesListResponse) String() string { return proto.CompactTextString(m) } +func (*RoleWithSignaturesListResponse) ProtoMessage() {} +func (*RoleWithSignaturesListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } + +func (m *RoleWithSignaturesListResponse) GetRoleWithSignaturesList() *RoleWithSignaturesList { + if m != nil { + return m.RoleWithSignaturesList + } + return nil +} + +func (m *RoleWithSignaturesListResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *RoleWithSignaturesListResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + func init() { proto.RegisterType((*Empty)(nil), "api.Empty") + proto.RegisterType((*AddDelegationMessage)(nil), "api.AddDelegationMessage") + proto.RegisterType((*AddDelegationRoleAndKeysMessage)(nil), "api.AddDelegationRoleAndKeysMessage") + proto.RegisterType((*AddDelegationPathsMessage)(nil), "api.AddDelegationPathsMessage") + proto.RegisterType((*RemoveDelegationKeysAndPathsMessage)(nil), "api.RemoveDelegationKeysAndPathsMessage") + proto.RegisterType((*RemoveDelegationRoleMessage)(nil), "api.RemoveDelegationRoleMessage") + proto.RegisterType((*RemoveDelegationPathsMessage)(nil), "api.RemoveDelegationPathsMessage") + proto.RegisterType((*RemoveDelegationKeysMessage)(nil), "api.RemoveDelegationKeysMessage") + proto.RegisterType((*ClearDelegationPathsMessage)(nil), "api.ClearDelegationPathsMessage") proto.RegisterType((*InitMessage)(nil), "api.InitMessage") - proto.RegisterType((*RoleList)(nil), "api.RoleList") + proto.RegisterType((*RoleNameList)(nil), "api.RoleNameList") proto.RegisterType((*TargetName)(nil), "api.TargetName") proto.RegisterType((*Target)(nil), "api.Target") proto.RegisterType((*TargetWithRole)(nil), "api.TargetWithRole") proto.RegisterType((*TargetWithRoleResponse)(nil), "api.TargetWithRoleResponse") - proto.RegisterType((*TargetWithRoleList)(nil), "api.TargetWithRoleList") - proto.RegisterType((*TargetWithRoleListResponse)(nil), "api.TargetWithRoleListResponse") + proto.RegisterType((*TargetWithRoleNameList)(nil), "api.TargetWithRoleNameList") + proto.RegisterType((*TargetWithRoleNameListResponse)(nil), "api.TargetWithRoleNameListResponse") proto.RegisterType((*TargetByNameAction)(nil), "api.TargetByNameAction") proto.RegisterType((*Signature)(nil), "api.Signature") proto.RegisterType((*PublicKey)(nil), "api.PublicKey") @@ -613,6 +1029,13 @@ func init() { proto.RegisterType((*Change)(nil), "api.Change") proto.RegisterType((*ChangeList)(nil), "api.ChangeList") proto.RegisterType((*ChangeListResponse)(nil), "api.ChangeListResponse") + proto.RegisterType((*RootRole)(nil), "api.RootRole") + proto.RegisterType((*Role)(nil), "api.Role") + proto.RegisterType((*RoleList)(nil), "api.RoleList") + proto.RegisterType((*RoleListResponse)(nil), "api.RoleListResponse") + proto.RegisterType((*RoleWithSignatures)(nil), "api.RoleWithSignatures") + proto.RegisterType((*RoleWithSignaturesList)(nil), "api.RoleWithSignaturesList") + proto.RegisterType((*RoleWithSignaturesListResponse)(nil), "api.RoleWithSignaturesListResponse") } // Reference imports to suppress errors if they are not otherwise used. @@ -634,13 +1057,23 @@ type NotaryClient interface { // uses the `name` field from the Target object, ignoring all other fields RemoveTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) // ListTargets list the targets for the specified roles in the TUF repository - ListTargets(ctx context.Context, in *RoleList, opts ...grpc.CallOption) (*TargetWithRoleListResponse, error) + ListTargets(ctx context.Context, in *RoleNameList, opts ...grpc.CallOption) (*TargetWithRoleNameListResponse, error) // GetTargetByName returns a target by the given name. GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes GetChangelist(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ChangeListResponse, error) + ListRoles(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) + GetDelegationRoles(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*RoleListResponse, error) + AddDelegation(ctx context.Context, in *AddDelegationMessage, opts ...grpc.CallOption) (*BasicResponse, error) + AddDelegationRoleAndKeys(ctx context.Context, in *AddDelegationRoleAndKeysMessage, opts ...grpc.CallOption) (*BasicResponse, error) + AddDelegationPaths(ctx context.Context, in *AddDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) + RemoveDelegationKeysAndPaths(ctx context.Context, in *RemoveDelegationKeysAndPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) + RemoveDelegationRole(ctx context.Context, in *RemoveDelegationRoleMessage, opts ...grpc.CallOption) (*BasicResponse, error) + RemoveDelegationPaths(ctx context.Context, in *RemoveDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) + RemoveDelegationKeys(ctx context.Context, in *RemoveDelegationKeysMessage, opts ...grpc.CallOption) (*BasicResponse, error) + ClearDelegationPaths(ctx context.Context, in *ClearDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) } type notaryClient struct { @@ -687,8 +1120,8 @@ func (c *notaryClient) RemoveTarget(ctx context.Context, in *Target, opts ...grp return out, nil } -func (c *notaryClient) ListTargets(ctx context.Context, in *RoleList, opts ...grpc.CallOption) (*TargetWithRoleListResponse, error) { - out := new(TargetWithRoleListResponse) +func (c *notaryClient) ListTargets(ctx context.Context, in *RoleNameList, opts ...grpc.CallOption) (*TargetWithRoleNameListResponse, error) { + out := new(TargetWithRoleNameListResponse) err := grpc.Invoke(ctx, "/api.Notary/ListTargets", in, out, c.cc, opts...) if err != nil { return nil, err @@ -723,6 +1156,96 @@ func (c *notaryClient) GetChangelist(ctx context.Context, in *Empty, opts ...grp return out, nil } +func (c *notaryClient) ListRoles(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) { + out := new(RoleWithSignaturesListResponse) + err := grpc.Invoke(ctx, "/api.Notary/ListRoles", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) GetDelegationRoles(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*RoleListResponse, error) { + out := new(RoleListResponse) + err := grpc.Invoke(ctx, "/api.Notary/GetDelegationRoles", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) AddDelegation(ctx context.Context, in *AddDelegationMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/AddDelegation", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) AddDelegationRoleAndKeys(ctx context.Context, in *AddDelegationRoleAndKeysMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/AddDelegationRoleAndKeys", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) AddDelegationPaths(ctx context.Context, in *AddDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/AddDelegationPaths", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) RemoveDelegationKeysAndPaths(ctx context.Context, in *RemoveDelegationKeysAndPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/RemoveDelegationKeysAndPaths", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) RemoveDelegationRole(ctx context.Context, in *RemoveDelegationRoleMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/RemoveDelegationRole", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) RemoveDelegationPaths(ctx context.Context, in *RemoveDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/RemoveDelegationPaths", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) RemoveDelegationKeys(ctx context.Context, in *RemoveDelegationKeysMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/RemoveDelegationKeys", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) ClearDelegationPaths(ctx context.Context, in *ClearDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/ClearDelegationPaths", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Notary service type NotaryServer interface { @@ -734,13 +1257,23 @@ type NotaryServer interface { // uses the `name` field from the Target object, ignoring all other fields RemoveTarget(context.Context, *Target) (*BasicResponse, error) // ListTargets list the targets for the specified roles in the TUF repository - ListTargets(context.Context, *RoleList) (*TargetWithRoleListResponse, error) + ListTargets(context.Context, *RoleNameList) (*TargetWithRoleNameListResponse, error) // GetTargetByName returns a target by the given name. GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes GetChangelist(context.Context, *Empty) (*ChangeListResponse, error) + ListRoles(context.Context, *Empty) (*RoleWithSignaturesListResponse, error) + GetDelegationRoles(context.Context, *Empty) (*RoleListResponse, error) + AddDelegation(context.Context, *AddDelegationMessage) (*BasicResponse, error) + AddDelegationRoleAndKeys(context.Context, *AddDelegationRoleAndKeysMessage) (*BasicResponse, error) + AddDelegationPaths(context.Context, *AddDelegationPathsMessage) (*BasicResponse, error) + RemoveDelegationKeysAndPaths(context.Context, *RemoveDelegationKeysAndPathsMessage) (*BasicResponse, error) + RemoveDelegationRole(context.Context, *RemoveDelegationRoleMessage) (*BasicResponse, error) + RemoveDelegationPaths(context.Context, *RemoveDelegationPathsMessage) (*BasicResponse, error) + RemoveDelegationKeys(context.Context, *RemoveDelegationKeysMessage) (*BasicResponse, error) + ClearDelegationPaths(context.Context, *ClearDelegationPathsMessage) (*BasicResponse, error) } func RegisterNotaryServer(s *grpc.Server, srv NotaryServer) { @@ -820,7 +1353,7 @@ func _Notary_RemoveTarget_Handler(srv interface{}, ctx context.Context, dec func } func _Notary_ListTargets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RoleList) + in := new(RoleNameList) if err := dec(in); err != nil { return nil, err } @@ -832,7 +1365,7 @@ func _Notary_ListTargets_Handler(srv interface{}, ctx context.Context, dec func( FullMethod: "/api.Notary/ListTargets", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).ListTargets(ctx, req.(*RoleList)) + return srv.(NotaryServer).ListTargets(ctx, req.(*RoleNameList)) } return interceptor(ctx, in, info, handler) } @@ -891,6 +1424,186 @@ func _Notary_GetChangelist_Handler(srv interface{}, ctx context.Context, dec fun return interceptor(ctx, in, info, handler) } +func _Notary_ListRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).ListRoles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/ListRoles", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).ListRoles(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_GetDelegationRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).GetDelegationRoles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/GetDelegationRoles", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).GetDelegationRoles(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_AddDelegation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddDelegationMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).AddDelegation(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/AddDelegation", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).AddDelegation(ctx, req.(*AddDelegationMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_AddDelegationRoleAndKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddDelegationRoleAndKeysMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).AddDelegationRoleAndKeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/AddDelegationRoleAndKeys", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).AddDelegationRoleAndKeys(ctx, req.(*AddDelegationRoleAndKeysMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_AddDelegationPaths_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddDelegationPathsMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).AddDelegationPaths(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/AddDelegationPaths", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).AddDelegationPaths(ctx, req.(*AddDelegationPathsMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_RemoveDelegationKeysAndPaths_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveDelegationKeysAndPathsMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).RemoveDelegationKeysAndPaths(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/RemoveDelegationKeysAndPaths", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).RemoveDelegationKeysAndPaths(ctx, req.(*RemoveDelegationKeysAndPathsMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_RemoveDelegationRole_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveDelegationRoleMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).RemoveDelegationRole(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/RemoveDelegationRole", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).RemoveDelegationRole(ctx, req.(*RemoveDelegationRoleMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_RemoveDelegationPaths_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveDelegationPathsMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).RemoveDelegationPaths(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/RemoveDelegationPaths", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).RemoveDelegationPaths(ctx, req.(*RemoveDelegationPathsMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_RemoveDelegationKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveDelegationKeysMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).RemoveDelegationKeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/RemoveDelegationKeys", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).RemoveDelegationKeys(ctx, req.(*RemoveDelegationKeysMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_ClearDelegationPaths_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ClearDelegationPathsMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).ClearDelegationPaths(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/ClearDelegationPaths", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).ClearDelegationPaths(ctx, req.(*ClearDelegationPathsMessage)) + } + return interceptor(ctx, in, info, handler) +} + var _Notary_serviceDesc = grpc.ServiceDesc{ ServiceName: "api.Notary", HandlerType: (*NotaryServer)(nil), @@ -927,6 +1640,46 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "GetChangelist", Handler: _Notary_GetChangelist_Handler, }, + { + MethodName: "ListRoles", + Handler: _Notary_ListRoles_Handler, + }, + { + MethodName: "GetDelegationRoles", + Handler: _Notary_GetDelegationRoles_Handler, + }, + { + MethodName: "AddDelegation", + Handler: _Notary_AddDelegation_Handler, + }, + { + MethodName: "AddDelegationRoleAndKeys", + Handler: _Notary_AddDelegationRoleAndKeys_Handler, + }, + { + MethodName: "AddDelegationPaths", + Handler: _Notary_AddDelegationPaths_Handler, + }, + { + MethodName: "RemoveDelegationKeysAndPaths", + Handler: _Notary_RemoveDelegationKeysAndPaths_Handler, + }, + { + MethodName: "RemoveDelegationRole", + Handler: _Notary_RemoveDelegationRole_Handler, + }, + { + MethodName: "RemoveDelegationPaths", + Handler: _Notary_RemoveDelegationPaths_Handler, + }, + { + MethodName: "RemoveDelegationKeys", + Handler: _Notary_RemoveDelegationKeys_Handler, + }, + { + MethodName: "ClearDelegationPaths", + Handler: _Notary_ClearDelegationPaths_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "api.proto", @@ -935,64 +1688,91 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 935 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x56, 0xdd, 0x6e, 0xe3, 0x44, - 0x14, 0xc6, 0x49, 0x9b, 0xae, 0x8f, 0xd3, 0x1f, 0x06, 0xd8, 0x5a, 0x61, 0x17, 0x22, 0x2f, 0x88, - 0x48, 0x88, 0xac, 0x36, 0x8b, 0x10, 0x3f, 0x42, 0xab, 0x6e, 0x77, 0x15, 0xaa, 0xd2, 0x0a, 0x0d, - 0x08, 0xae, 0xa7, 0xce, 0x51, 0x6c, 0xd5, 0xb1, 0x8d, 0x67, 0x52, 0x61, 0xde, 0x00, 0x89, 0x1b, - 0x2e, 0x79, 0x25, 0xae, 0x79, 0x02, 0x9e, 0x04, 0xcd, 0x8f, 0xed, 0x71, 0xe2, 0x48, 0xab, 0xde, - 0xcd, 0x99, 0xf9, 0xce, 0x37, 0xe7, 0xef, 0x1b, 0x1b, 0x5c, 0x96, 0xc7, 0xd3, 0xbc, 0xc8, 0x44, - 0x46, 0xfa, 0x2c, 0x8f, 0x83, 0x03, 0xd8, 0x7f, 0xbd, 0xca, 0x45, 0x19, 0x24, 0xe0, 0x5d, 0xa4, - 0xb1, 0xb8, 0x42, 0xce, 0xd9, 0x12, 0xc9, 0x07, 0x00, 0x45, 0x96, 0x89, 0x4b, 0x2c, 0x2f, 0x5e, - 0x71, 0xdf, 0x19, 0xf7, 0x27, 0x2e, 0xb5, 0x76, 0xc8, 0xb7, 0x40, 0x38, 0x16, 0x77, 0x58, 0x5c, - 0xb1, 0x94, 0x2d, 0x71, 0x41, 0xb3, 0x04, 0xb9, 0xdf, 0x1b, 0x3b, 0x13, 0x6f, 0x76, 0x38, 0x95, - 0x97, 0xc8, 0x9d, 0xef, 0x63, 0x2e, 0x68, 0x07, 0x30, 0x18, 0xc3, 0x83, 0xea, 0x9c, 0xbc, 0x0b, - 0xfb, 0x85, 0xf2, 0xd6, 0xb7, 0x68, 0x23, 0x18, 0x03, 0xfc, 0xc4, 0x8a, 0x25, 0x8a, 0x6b, 0xb6, - 0x42, 0x42, 0x60, 0x2f, 0x65, 0x2b, 0xf4, 0x9d, 0xb1, 0x33, 0x71, 0xa9, 0x5a, 0x07, 0xff, 0x38, - 0x30, 0xd0, 0x10, 0x72, 0x02, 0xfd, 0xe5, 0x3a, 0x35, 0xa7, 0x72, 0x59, 0x3b, 0xf4, 0x1a, 0x07, - 0xf2, 0x10, 0x06, 0x09, 0xa6, 0x4b, 0x11, 0xf9, 0xfd, 0xb1, 0x33, 0xe9, 0x53, 0x63, 0x91, 0xa7, - 0x30, 0x88, 0x18, 0x8f, 0x90, 0xfb, 0x7b, 0xe3, 0xfe, 0xc4, 0x9b, 0x9d, 0xaa, 0xf8, 0x35, 0xf5, - 0xf4, 0x3b, 0x75, 0xf2, 0x3a, 0x15, 0x45, 0x49, 0x0d, 0x4c, 0x12, 0x85, 0x6b, 0x2e, 0xb2, 0x95, - 0xbf, 0x3f, 0x76, 0x26, 0x43, 0x6a, 0xac, 0xd1, 0x57, 0xe0, 0x59, 0x70, 0x19, 0xd5, 0x2d, 0x96, - 0x55, 0x54, 0xb7, 0x58, 0xca, 0x54, 0xef, 0x58, 0xb2, 0xd6, 0x61, 0x0d, 0xa9, 0x36, 0xbe, 0xee, - 0x7d, 0xe9, 0x04, 0x17, 0x70, 0xa4, 0x2f, 0xfc, 0x25, 0x16, 0x91, 0x2c, 0x0d, 0x79, 0x02, 0x03, - 0xa1, 0x76, 0x14, 0x81, 0x37, 0xf3, 0xac, 0xa8, 0xa8, 0x39, 0x92, 0x69, 0xca, 0x72, 0x55, 0x69, - 0xca, 0x75, 0xf0, 0x87, 0x03, 0x0f, 0xdb, 0x5c, 0x14, 0x79, 0x9e, 0xa5, 0x1c, 0xc9, 0x37, 0x70, - 0x24, 0x5a, 0x27, 0x86, 0xfb, 0x1d, 0x8b, 0xbb, 0x76, 0xda, 0x80, 0x12, 0x1f, 0x0e, 0xf8, 0x3a, - 0x0c, 0x91, 0xeb, 0x3e, 0x3f, 0xa0, 0x95, 0x29, 0x4f, 0x56, 0x7a, 0x6e, 0x54, 0x65, 0x5d, 0x5a, - 0x99, 0xc1, 0x39, 0x90, 0x36, 0xab, 0xea, 0xf8, 0x67, 0x70, 0xa0, 0xb9, 0x75, 0xcf, 0x77, 0xdc, - 0x5f, 0x61, 0x82, 0xbf, 0x1d, 0x18, 0x6d, 0xb3, 0xd4, 0x49, 0xcd, 0x81, 0x88, 0xad, 0x53, 0x93, - 0xd8, 0x69, 0x07, 0xb1, 0x1e, 0xca, 0x6d, 0x97, 0x7b, 0x25, 0x78, 0x55, 0x25, 0xf8, 0xb2, 0x94, - 0x83, 0x7a, 0x16, 0x8a, 0x38, 0x4b, 0xbb, 0xc6, 0x95, 0x3c, 0xa9, 0xc6, 0xbc, 0x53, 0x24, 0x66, - 0xea, 0x7f, 0x05, 0xf7, 0xc7, 0x78, 0x99, 0x32, 0xb1, 0x2e, 0x50, 0x4e, 0xcb, 0xad, 0x54, 0x9b, - 0xa1, 0xd1, 0x86, 0x1c, 0xbe, 0x15, 0x8a, 0x28, 0x5b, 0x98, 0xa6, 0x1b, 0x8b, 0x3c, 0x02, 0x97, - 0x57, 0xae, 0x2a, 0xca, 0x21, 0x6d, 0x36, 0x64, 0x06, 0x31, 0xff, 0x99, 0x25, 0xf1, 0xc2, 0xdf, - 0xd3, 0xb9, 0x19, 0x33, 0xf0, 0xc0, 0xfd, 0x61, 0x7d, 0x93, 0xc4, 0xe1, 0x25, 0x96, 0xc1, 0xbf, - 0x0e, 0x1c, 0xbd, 0xc2, 0x04, 0x97, 0x4c, 0xe6, 0xa1, 0xda, 0xfe, 0x0c, 0xf6, 0x6e, 0xb1, 0xac, - 0x3a, 0xf5, 0x58, 0x85, 0xdd, 0x86, 0x4c, 0x2f, 0xb1, 0x34, 0x0a, 0x51, 0xd0, 0x4e, 0xf1, 0x3d, - 0x02, 0x57, 0x44, 0x05, 0xf2, 0x28, 0x4b, 0x16, 0x2a, 0xbc, 0x7d, 0xda, 0x6c, 0xc8, 0x54, 0x73, - 0x26, 0x22, 0xad, 0x40, 0x97, 0x6a, 0x63, 0x34, 0x07, 0xb7, 0xa6, 0xee, 0x50, 0xd3, 0x47, 0xb6, - 0x9a, 0xbc, 0xd9, 0x91, 0x0a, 0xad, 0xce, 0xc5, 0x56, 0xd7, 0x9f, 0x0e, 0x0c, 0x75, 0x9b, 0x64, - 0x75, 0x71, 0x41, 0x3e, 0x31, 0xba, 0xb1, 0xc7, 0xbf, 0x9d, 0x94, 0x16, 0x93, 0xa5, 0xc2, 0xde, - 0x6e, 0x15, 0x4e, 0x01, 0xea, 0x4a, 0x73, 0xbf, 0xaf, 0x0a, 0xa5, 0xa3, 0xa9, 0x9b, 0x49, 0x2d, - 0x44, 0xf0, 0x02, 0x4e, 0xec, 0x68, 0xd4, 0xf0, 0x7d, 0xba, 0xa9, 0x89, 0xb7, 0xad, 0x9b, 0x34, - 0xae, 0x51, 0xc4, 0x5f, 0x0e, 0xf8, 0x9b, 0x0c, 0xb5, 0x1e, 0xce, 0xe0, 0x44, 0x6c, 0x9c, 0x99, - 0x3c, 0xdf, 0xdb, 0xa2, 0x54, 0x8e, 0x5b, 0xf0, 0x7b, 0x4a, 0xfd, 0xf0, 0x25, 0xe3, 0x71, 0x58, - 0xc7, 0x61, 0x91, 0x38, 0x3b, 0x49, 0x7a, 0x6d, 0x92, 0xdf, 0x60, 0x70, 0x1e, 0xb1, 0x74, 0xa9, - 0x1e, 0x6b, 0xa6, 0xc4, 0x64, 0x3a, 0x6e, 0x2c, 0x39, 0x29, 0x3c, 0xcc, 0xf2, 0xca, 0x53, 0x1b, - 0x72, 0xe2, 0x44, 0x99, 0x57, 0x31, 0xa9, 0xb5, 0xdc, 0x93, 0x63, 0xa4, 0xe6, 0xdd, 0xa5, 0x6a, - 0x2d, 0x6f, 0x0e, 0xb3, 0x54, 0x60, 0x2a, 0xcc, 0xd3, 0x5d, 0x99, 0xc1, 0x73, 0x00, 0x7d, 0xb3, - 0x2a, 0xc0, 0xc7, 0x70, 0x10, 0x2a, 0xab, 0xea, 0x86, 0xee, 0xbb, 0x46, 0xd0, 0xea, 0x2c, 0x28, - 0x81, 0x34, 0x4e, 0x75, 0xe2, 0x4f, 0x01, 0x34, 0x20, 0x69, 0x4a, 0x7f, 0x6c, 0xf9, 0x2b, 0xb0, - 0x05, 0xb9, 0x4f, 0xb9, 0x67, 0xff, 0xf5, 0x61, 0x70, 0x9d, 0x09, 0x56, 0x94, 0xe4, 0x73, 0x00, - 0xf9, 0xe9, 0x8e, 0x59, 0x12, 0xff, 0x8e, 0xe4, 0x44, 0xdd, 0x64, 0x7d, 0xcb, 0x47, 0x44, 0xed, - 0xb4, 0x9a, 0x13, 0xbc, 0x25, 0x07, 0x4e, 0x69, 0x85, 0x47, 0x04, 0x14, 0x40, 0xfd, 0x07, 0xec, - 0x00, 0x4f, 0xc1, 0x3d, 0x5b, 0x2c, 0xcc, 0xd7, 0xd6, 0xd6, 0xc0, 0x0e, 0xfc, 0x33, 0x18, 0x52, - 0x5c, 0x65, 0x77, 0xf8, 0xe6, 0x2e, 0x2f, 0xc0, 0x93, 0x85, 0xd1, 0x18, 0x4e, 0xda, 0xef, 0xe3, - 0xe8, 0xc3, 0x5d, 0x0f, 0x79, 0x43, 0x70, 0x01, 0xc7, 0x73, 0x14, 0xf6, 0x6b, 0x4c, 0xec, 0xe7, - 0xdf, 0x7e, 0xa0, 0x47, 0xef, 0x77, 0x7d, 0x70, 0x1a, 0xaa, 0x6b, 0x18, 0xcd, 0x51, 0x9c, 0x25, - 0x89, 0x46, 0x5c, 0xa1, 0x60, 0x0b, 0x26, 0x98, 0x61, 0x3d, 0xb6, 0x9c, 0xe5, 0xc6, 0xe8, 0x71, - 0xb7, 0xae, 0x1a, 0xbe, 0x2f, 0xe0, 0x70, 0x8e, 0xe2, 0xbc, 0xe9, 0xb8, 0x5d, 0xf1, 0xd3, 0xcd, - 0xd1, 0xa8, 0xfd, 0x6e, 0x06, 0xea, 0x4f, 0xed, 0xf9, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xea, - 0x85, 0x57, 0x39, 0xb6, 0x09, 0x00, 0x00, + // 1364 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0xef, 0x6e, 0x1b, 0x45, + 0x10, 0xe7, 0x6c, 0xc7, 0xe9, 0x8d, 0x1d, 0x37, 0x5d, 0x9a, 0xc4, 0x75, 0x93, 0xd4, 0x5c, 0x82, + 0x6a, 0x54, 0xe1, 0x2a, 0x29, 0xaa, 0x28, 0x48, 0x50, 0x37, 0x89, 0xdc, 0x10, 0x12, 0xa5, 0x57, + 0x54, 0x3e, 0x20, 0x21, 0x6d, 0x7d, 0x2b, 0xfb, 0x94, 0xf3, 0x9d, 0xb9, 0x5b, 0x47, 0x35, 0x6f, + 0x80, 0xc4, 0x17, 0x1e, 0x83, 0x57, 0xe1, 0x33, 0xaf, 0xc1, 0x3b, 0xa0, 0xfd, 0x73, 0x7b, 0x7b, + 0xff, 0x12, 0x64, 0x89, 0x6f, 0x37, 0xbb, 0xbf, 0xf9, 0xcd, 0xec, 0xec, 0xce, 0xec, 0xce, 0x81, + 0x89, 0x67, 0x6e, 0x7f, 0x16, 0x06, 0x34, 0x40, 0x55, 0x3c, 0x73, 0xad, 0x55, 0x58, 0x39, 0x99, + 0xce, 0xe8, 0xc2, 0xfa, 0x00, 0xf7, 0x07, 0x8e, 0x73, 0x4c, 0x3c, 0x32, 0xc6, 0xd4, 0x0d, 0xfc, + 0x73, 0x12, 0x45, 0x78, 0x4c, 0x10, 0x82, 0x9a, 0x8f, 0xa7, 0xa4, 0x6d, 0x74, 0x8d, 0x9e, 0x69, + 0xf3, 0x6f, 0xf4, 0x1c, 0x5a, 0x8e, 0x02, 0x9e, 0x91, 0x45, 0xd4, 0xae, 0x74, 0xab, 0xbd, 0xc6, + 0x61, 0xab, 0xcf, 0xd8, 0x2f, 0xe7, 0xef, 0x3d, 0x77, 0x74, 0x46, 0x16, 0x76, 0x06, 0x85, 0xee, + 0xc3, 0xca, 0x0c, 0xd3, 0x49, 0xd4, 0xae, 0x76, 0xab, 0x3d, 0xd3, 0x16, 0x82, 0x35, 0x85, 0x47, + 0x29, 0xcb, 0x76, 0xe0, 0x91, 0x81, 0xef, 0x30, 0x8d, 0xff, 0xc1, 0x09, 0xeb, 0x04, 0x1e, 0xa4, + 0xcc, 0x5d, 0x32, 0x27, 0x6e, 0x32, 0xa4, 0xbc, 0xae, 0xe8, 0x5e, 0x8f, 0x61, 0xcf, 0x26, 0xd3, + 0xe0, 0x9a, 0x1c, 0xa7, 0xe8, 0x07, 0xbe, 0x73, 0x2b, 0xe1, 0x26, 0xd4, 0xaf, 0xc8, 0xe2, 0xf4, + 0x38, 0x66, 0x94, 0x52, 0x49, 0x78, 0x0e, 0xe0, 0x61, 0xd6, 0x10, 0x8b, 0xd0, 0x0d, 0x06, 0xac, + 0xd7, 0xb0, 0x9d, 0x55, 0x59, 0x72, 0x95, 0xa7, 0x79, 0xe3, 0xb7, 0xed, 0x4b, 0xc9, 0xea, 0xd8, + 0x3a, 0x8e, 0x3c, 0x82, 0xc3, 0x72, 0x9f, 0xc2, 0xc0, 0x53, 0x54, 0xec, 0xdb, 0x9a, 0x41, 0xe3, + 0xd4, 0x77, 0x69, 0x0c, 0xd9, 0x05, 0x08, 0x83, 0x80, 0x9e, 0x09, 0x76, 0x83, 0xb3, 0x6b, 0x23, + 0x68, 0x00, 0x28, 0x22, 0xe1, 0x35, 0x09, 0xcf, 0xb1, 0x8f, 0xc7, 0xc4, 0x61, 0x61, 0x62, 0x5e, + 0x18, 0xbd, 0xc6, 0xe1, 0x3d, 0x7e, 0x2a, 0xd8, 0xc8, 0x05, 0x9e, 0x92, 0xef, 0xdd, 0x88, 0xda, + 0x05, 0x60, 0x6b, 0x1f, 0x9a, 0x3a, 0x86, 0x45, 0x25, 0xe4, 0x2c, 0xc2, 0x9a, 0x10, 0xac, 0x2e, + 0xc0, 0x0f, 0x38, 0x1c, 0x13, 0xca, 0x70, 0x85, 0x3b, 0xf0, 0x97, 0x01, 0x75, 0x01, 0x41, 0xeb, + 0x50, 0x1d, 0xcf, 0x7d, 0x39, 0xcb, 0x3e, 0x95, 0x42, 0x25, 0x1d, 0x35, 0x8f, 0xf8, 0x63, 0x3a, + 0x69, 0x57, 0xbb, 0x46, 0xaf, 0x6a, 0x4b, 0x09, 0x3d, 0x85, 0xfa, 0x04, 0x47, 0x13, 0x12, 0xb5, + 0x6b, 0xfc, 0x74, 0x6f, 0xf1, 0x75, 0x08, 0xea, 0xfe, 0x6b, 0x3e, 0x73, 0xe2, 0xd3, 0x70, 0x61, + 0x4b, 0x18, 0x23, 0x1a, 0xcd, 0x23, 0x1a, 0x4c, 0xdb, 0x2b, 0x5d, 0xa3, 0xd7, 0xb4, 0xa5, 0xd4, + 0x79, 0x01, 0x0d, 0x0d, 0xce, 0xbc, 0xba, 0x22, 0x8b, 0xd8, 0xab, 0x2b, 0xb2, 0x60, 0x4b, 0xbd, + 0xc6, 0xde, 0x5c, 0xb8, 0xd5, 0xb4, 0x85, 0xf0, 0x55, 0xe5, 0x4b, 0xc3, 0x3a, 0x85, 0x96, 0x30, + 0xf8, 0xa3, 0x4b, 0x27, 0x2c, 0x3c, 0x68, 0x0f, 0xea, 0x94, 0x8f, 0x70, 0x82, 0xc6, 0x61, 0x43, + 0xf3, 0xca, 0x96, 0x53, 0x6a, 0x47, 0x2b, 0xda, 0x8e, 0xfe, 0x66, 0xc0, 0x66, 0x9a, 0xcb, 0x26, + 0xd1, 0x2c, 0xf0, 0x23, 0x82, 0xbe, 0x86, 0x16, 0x4d, 0xcd, 0x48, 0xee, 0x8f, 0x35, 0x6e, 0xa5, + 0x94, 0x81, 0xa2, 0x36, 0xac, 0x46, 0xf3, 0xd1, 0x88, 0x44, 0x62, 0xbf, 0xef, 0xd8, 0xb1, 0xc8, + 0x66, 0xa6, 0xe2, 0xfc, 0xf0, 0xc8, 0x9a, 0x76, 0x2c, 0x5a, 0xc3, 0xac, 0x2b, 0x6a, 0xd7, 0x3f, + 0x87, 0x55, 0xc1, 0x2f, 0xf6, 0xbd, 0xc4, 0x87, 0x18, 0x63, 0xfd, 0x69, 0xc0, 0x6e, 0x31, 0x93, + 0x5a, 0xdc, 0x5b, 0xd8, 0xa4, 0x85, 0x08, 0xb9, 0xc8, 0x87, 0x05, 0x06, 0x14, 0x49, 0x89, 0xea, + 0x52, 0x8b, 0x7e, 0x03, 0x48, 0x58, 0x79, 0xb5, 0x60, 0x3c, 0x83, 0x11, 0x4b, 0xc4, 0xc2, 0x3c, + 0x7e, 0x1c, 0x1f, 0xfd, 0xd2, 0x04, 0x92, 0xd9, 0xf0, 0x0b, 0x98, 0x6f, 0xdd, 0xb1, 0x8f, 0xe9, + 0x3c, 0xe4, 0x65, 0x84, 0xe7, 0xbb, 0xa4, 0x12, 0x02, 0x3b, 0x94, 0x53, 0x42, 0x27, 0x81, 0x23, + 0x0f, 0x83, 0x94, 0xd0, 0x36, 0x98, 0x51, 0xac, 0xca, 0x3d, 0x6d, 0xda, 0xc9, 0x00, 0x5b, 0x85, + 0x1b, 0xbd, 0xc3, 0x9e, 0xeb, 0xb4, 0x6b, 0x62, 0x7d, 0x52, 0xb4, 0xde, 0x80, 0xa9, 0x0a, 0x3c, + 0x6a, 0x41, 0xc5, 0x75, 0xa4, 0xbd, 0x8a, 0xcb, 0x49, 0xb1, 0x37, 0x0e, 0x42, 0x97, 0x4e, 0xa6, + 0xd2, 0x5e, 0x32, 0xc0, 0x5c, 0x99, 0x71, 0x55, 0x69, 0x4f, 0x4a, 0xd6, 0xdf, 0x06, 0xb4, 0xd2, + 0x15, 0x16, 0x1d, 0x40, 0xed, 0x8a, 0xdd, 0x2b, 0xe2, 0x0c, 0xec, 0xf0, 0x00, 0xa4, 0x21, 0x7d, + 0x56, 0x0c, 0x45, 0xfe, 0x71, 0x68, 0x61, 0x6a, 0x6f, 0x83, 0x49, 0x27, 0x21, 0x89, 0x26, 0x81, + 0xe7, 0x70, 0xa3, 0x2b, 0x76, 0x32, 0x90, 0xd4, 0xdd, 0x9a, 0x56, 0x77, 0x3b, 0x43, 0x30, 0x15, + 0x75, 0x41, 0xae, 0xee, 0xeb, 0xb9, 0x9a, 0xbf, 0xf2, 0xb4, 0xdc, 0xfd, 0xdd, 0x80, 0xa6, 0xd8, + 0x70, 0xb6, 0x47, 0xc4, 0x41, 0x8f, 0xb5, 0x3a, 0x1b, 0x1f, 0xec, 0xf4, 0xa2, 0x44, 0xaa, 0x6a, + 0x39, 0x5e, 0x29, 0xcf, 0xf1, 0x3e, 0x80, 0xda, 0x2f, 0x71, 0x6f, 0xc5, 0xde, 0xa8, 0x23, 0x61, + 0x6b, 0x08, 0xeb, 0x5b, 0x58, 0xd7, 0xbd, 0xe1, 0xc7, 0xf8, 0x49, 0x36, 0xdb, 0xee, 0x69, 0x96, + 0x04, 0x2e, 0xc9, 0xb5, 0x3f, 0x0c, 0x68, 0x67, 0x19, 0x54, 0x96, 0x0d, 0x60, 0x9d, 0x66, 0xe6, + 0xe4, 0x3a, 0x37, 0x72, 0x94, 0x5c, 0x31, 0x07, 0x5f, 0x2a, 0xa7, 0x8e, 0x60, 0xed, 0x15, 0x8e, + 0xdc, 0x91, 0xf2, 0x43, 0x23, 0x31, 0x4a, 0x49, 0x2a, 0x69, 0x92, 0x0f, 0x50, 0x3f, 0x9a, 0x60, + 0x7f, 0xcc, 0xaf, 0x02, 0xcc, 0xd3, 0x52, 0xee, 0xb8, 0x94, 0xd8, 0x49, 0x89, 0x46, 0xc1, 0x2c, + 0xd6, 0x14, 0x02, 0x3b, 0x71, 0x74, 0x31, 0x8b, 0x7d, 0xe2, 0xdf, 0x6c, 0x8c, 0x1d, 0x23, 0x9e, + 0x35, 0xa6, 0xcd, 0xbf, 0x99, 0xe5, 0x51, 0xe0, 0x53, 0xe2, 0x53, 0x79, 0x31, 0xc4, 0xa2, 0xf5, + 0x0c, 0x40, 0x58, 0xe6, 0x01, 0xf8, 0x14, 0x56, 0x47, 0x5c, 0x8a, 0x77, 0x43, 0xec, 0xbb, 0x40, + 0xd8, 0xf1, 0x9c, 0xb5, 0x00, 0x94, 0x28, 0xa9, 0x85, 0x3f, 0x05, 0x10, 0x00, 0x2f, 0x09, 0xfd, + 0x5d, 0x4d, 0x9f, 0x83, 0x35, 0xc8, 0x52, 0xe1, 0x7e, 0x09, 0x77, 0xec, 0x20, 0xa0, 0x3c, 0x45, + 0x93, 0xc7, 0x86, 0x91, 0x7a, 0x4a, 0xa5, 0x72, 0xae, 0x92, 0xc9, 0x39, 0xeb, 0x27, 0xa8, 0x71, + 0xed, 0xcf, 0xe0, 0x4e, 0x28, 0x99, 0xa4, 0xb3, 0x6b, 0xb2, 0xca, 0x89, 0x41, 0x5b, 0x4d, 0x17, + 0x26, 0x76, 0xf1, 0x7b, 0xed, 0x09, 0x73, 0xcf, 0x13, 0xc1, 0x7c, 0xa4, 0x3f, 0x1f, 0x1a, 0x87, + 0xa6, 0xaa, 0xa1, 0x49, 0xed, 0x5c, 0x8f, 0xc1, 0x2a, 0x88, 0xdc, 0x2b, 0x4f, 0xbf, 0x1d, 0xd6, + 0x94, 0x1e, 0x07, 0xaa, 0xe9, 0xa5, 0xc2, 0x37, 0x02, 0xc4, 0x98, 0xd8, 0x6d, 0xa2, 0x72, 0x34, + 0xca, 0x24, 0xb2, 0x71, 0x5b, 0x22, 0xa3, 0x1d, 0xed, 0x72, 0x4f, 0x2d, 0x4c, 0xdc, 0xf3, 0x18, + 0x36, 0xf3, 0x46, 0xb8, 0xcb, 0x43, 0x40, 0x61, 0x6e, 0x46, 0x1a, 0xdc, 0x52, 0x34, 0xe9, 0x69, + 0xbb, 0x40, 0x85, 0xdf, 0xba, 0xc5, 0x36, 0xf4, 0x5b, 0x37, 0x2c, 0x44, 0xa4, 0x6e, 0xdd, 0x12, + 0x92, 0x12, 0xd5, 0x65, 0x62, 0x7e, 0xf8, 0x8f, 0x09, 0xf5, 0x8b, 0x80, 0xe2, 0x70, 0x81, 0xbe, + 0x00, 0x60, 0x6f, 0x5a, 0x17, 0x7b, 0xee, 0xaf, 0x04, 0xad, 0x73, 0x0f, 0xb4, 0x47, 0x6e, 0x07, + 0xf1, 0x91, 0x54, 0x3d, 0xb1, 0x3e, 0x62, 0x35, 0x92, 0x97, 0xf7, 0x68, 0x82, 0x80, 0x03, 0x78, + 0xd3, 0x56, 0x02, 0xee, 0x83, 0x39, 0x70, 0x1c, 0xf9, 0xfc, 0xd4, 0xcb, 0x76, 0x09, 0xfe, 0x00, + 0x9a, 0xe2, 0x91, 0xff, 0xdf, 0x55, 0x86, 0xd0, 0x60, 0xc1, 0x10, 0x98, 0x08, 0xe5, 0x1f, 0x07, + 0x9d, 0xbd, 0x9b, 0x5e, 0x34, 0x09, 0xd1, 0x29, 0xdc, 0x1d, 0x12, 0xaa, 0x3f, 0x49, 0x90, 0xfe, + 0xc4, 0xd5, 0x5f, 0x29, 0x9d, 0xa2, 0x47, 0x92, 0x46, 0x75, 0x01, 0x9d, 0x21, 0xa1, 0x03, 0xcf, + 0x13, 0x88, 0x73, 0x42, 0xb1, 0x83, 0x29, 0x96, 0xac, 0x77, 0x35, 0x65, 0x36, 0xd0, 0xd9, 0x29, + 0xbe, 0x12, 0x12, 0xbe, 0xe7, 0xb0, 0x36, 0x24, 0xf4, 0x28, 0x29, 0x56, 0x7a, 0xe4, 0xb7, 0xb2, + 0x55, 0x2d, 0xd1, 0xfb, 0x06, 0x4c, 0x3e, 0xc2, 0x12, 0x3c, 0xa5, 0xb3, 0x77, 0xd3, 0x71, 0x4b, + 0xf4, 0x5f, 0x00, 0x1a, 0x12, 0x9a, 0xbe, 0x93, 0xd3, 0x44, 0x1b, 0xe9, 0x7a, 0x90, 0xa8, 0xbe, + 0x84, 0xb5, 0x54, 0x6f, 0x8b, 0x1e, 0x70, 0x64, 0x51, 0x63, 0x5f, 0xb2, 0xb1, 0xef, 0xa0, 0x5d, + 0xd6, 0x8c, 0xa3, 0xfd, 0x3c, 0x59, 0xbe, 0x57, 0x2f, 0xe1, 0xfd, 0x0e, 0x50, 0xbe, 0xeb, 0x46, + 0xbb, 0x79, 0x46, 0xbd, 0x29, 0x2c, 0xe1, 0xfa, 0x39, 0xdf, 0xde, 0xea, 0xad, 0x37, 0xea, 0x89, + 0xf0, 0xdc, 0xde, 0x9d, 0x97, 0xf0, 0x5f, 0xc0, 0xfd, 0xa2, 0x8e, 0x1b, 0x75, 0x0b, 0x79, 0xb5, + 0x66, 0xbc, 0x84, 0xef, 0x12, 0x36, 0x0a, 0xdb, 0x71, 0xf4, 0x49, 0x21, 0xe1, 0x72, 0x1e, 0xf2, + 0x1d, 0xea, 0x96, 0xae, 0xfc, 0x56, 0xbe, 0xa2, 0xde, 0x5c, 0xf2, 0xdd, 0xd0, 0xb6, 0x17, 0xf3, + 0xbd, 0xaf, 0xf3, 0x3f, 0x4c, 0xcf, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x25, 0x35, 0xc2, 0x3c, + 0x6e, 0x12, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index 41d5ec838..c94959a2a 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -5,42 +5,88 @@ package api; // Notary Interface service Notary { rpc Initialize(InitMessage) returns (BasicResponse) {} - rpc Publish(Empty) returns (BasicResponse) {} // AddTarget adds a target to the TUF repository and re-signs. rpc AddTarget(Target) returns (BasicResponse) {} - // RemoveTarget deletes a target from the TUF repository and re-signs. It only // uses the `name` field from the Target object, ignoring all other fields rpc RemoveTarget(Target) returns (BasicResponse) {} - // ListTargets list the targets for the specified roles in the TUF repository - rpc ListTargets(RoleList) returns (TargetWithRoleListResponse) {} - + rpc ListTargets(RoleNameList) returns (TargetWithRoleNameListResponse) {} // GetTargetByName returns a target by the given name. rpc GetTargetByName(TargetByNameAction) returns (TargetWithRoleResponse) {} - // GetAllTargetMetadataByName rpc GetAllTargetMetadataByName(TargetName) returns (TargetSignedListResponse) {} // GetChangelist returns the list of the repository's unpublished changes rpc GetChangelist(Empty) returns (ChangeListResponse) {} + + rpc ListRoles(Empty) returns (RoleWithSignaturesListResponse) {} + rpc GetDelegationRoles(Empty) returns (RoleListResponse) {} + rpc AddDelegation(AddDelegationMessage) returns (BasicResponse) {} + rpc AddDelegationRoleAndKeys(AddDelegationRoleAndKeysMessage) returns (BasicResponse) {} + rpc AddDelegationPaths(AddDelegationPathsMessage) returns (BasicResponse) {} + rpc RemoveDelegationKeysAndPaths(RemoveDelegationKeysAndPathsMessage) returns (BasicResponse) {} + rpc RemoveDelegationRole(RemoveDelegationRoleMessage) returns (BasicResponse) {} + rpc RemoveDelegationPaths(RemoveDelegationPathsMessage) returns (BasicResponse) {} + rpc RemoveDelegationKeys(RemoveDelegationKeysMessage) returns (BasicResponse) {} + rpc ClearDelegationPaths(ClearDelegationPathsMessage) returns (BasicResponse) {} } message Empty { } +message AddDelegationMessage { + string name = 1; + repeated PublicKey delegationKeys = 2; + repeated string paths = 3; +} + +message AddDelegationRoleAndKeysMessage { + string name = 1; + repeated PublicKey delegationKeys = 2; +} + +message AddDelegationPathsMessage { + string name = 1; + repeated string paths = 2; +} + +message RemoveDelegationKeysAndPathsMessage { + string name = 1; + repeated string keyIDs = 2; + repeated string paths = 3; +} + +message RemoveDelegationRoleMessage { + string name = 1; +} + +message RemoveDelegationPathsMessage { + string name = 1; + repeated string paths = 2; +} + +message RemoveDelegationKeysMessage { + string name = 1; + repeated string keyIDs = 2; +} + +message ClearDelegationPathsMessage { + string role = 1; +} + // InitMessage holds a list of root key IDs and a list of roles for which // the server automatically should manage the keys message InitMessage { repeated string rootKeyIDs = 1; - RoleList serverManagedRoles = 2; + RoleNameList serverManagedRoles = 2; } -// RoleList message holds a list of TUF role names -message RoleList { +// RoleNameList message holds a list of TUF role names +message RoleNameList { repeated string roles = 1; } @@ -69,19 +115,19 @@ message TargetWithRoleResponse { string message = 3; } -message TargetWithRoleList { +message TargetWithRoleNameList { repeated TargetWithRole targets = 1; } -message TargetWithRoleListResponse { - TargetWithRoleList targetWithRoleList = 1; +message TargetWithRoleNameListResponse { + TargetWithRoleNameList targetWithRoleNameList = 1; bool success = 2; string message = 3; } message TargetByNameAction { string name = 1; - RoleList roles = 2; + RoleNameList roles = 2; } message Signature { @@ -91,8 +137,10 @@ message Signature { bool isValid = 4; } -// FIXME: implement message PublicKey { + string id = 1; + string algorithm = 2; + bytes public = 3; } message DelegationRole { @@ -147,4 +195,40 @@ message ChangeListResponse { string message = 3; } +message RootRole { + repeated string keyIDs = 1; + int32 threshold = 2; +} + +message Role { + RootRole rootRole = 1; + string name = 2; + repeated string paths = 3; +} + +message RoleList { + repeated Role roles = 1; +} + +message RoleListResponse { + RoleList roleList = 1; + bool success = 2; + string message = 3; +} + +message RoleWithSignatures { + repeated Signature signatures = 1; + Role role = 2; +} + +message RoleWithSignaturesList { + repeated RoleWithSignatures roleWithSignatures = 1; +} + +message RoleWithSignaturesListResponse { + RoleWithSignaturesList roleWithSignaturesList = 1; + bool success = 2; + string message = 3; +} + From 55ad28146180ce0c291570e6b80449e6a50fc374 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 7 Mar 2017 03:02:01 +0100 Subject: [PATCH 16/62] Add remaining rpc definitions to client gRPC API interface Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 464 +++++++++++++++++++++++++++++---------- client_api/api/api.proto | 26 +++ 2 files changed, 377 insertions(+), 113 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index 8a5794673..e1f279233 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -18,8 +18,10 @@ It has these top-level messages: RemoveDelegationPathsMessage RemoveDelegationKeysMessage ClearDelegationPathsMessage + RotateKeyMessage InitMessage RoleNameList + RoleNameListResponse TargetName Target TargetWithRole @@ -44,6 +46,8 @@ It has these top-level messages: RoleWithSignatures RoleWithSignaturesList RoleWithSignaturesListResponse + CryptoServiceMessage + VersionMessage */ package api @@ -269,6 +273,38 @@ func (m *ClearDelegationPathsMessage) GetRole() string { return "" } +type RotateKeyMessage struct { + Role string `protobuf:"bytes,1,opt,name=role" json:"role,omitempty"` + ServerManagesKey bool `protobuf:"varint,2,opt,name=serverManagesKey" json:"serverManagesKey,omitempty"` + KeyList []string `protobuf:"bytes,3,rep,name=keyList" json:"keyList,omitempty"` +} + +func (m *RotateKeyMessage) Reset() { *m = RotateKeyMessage{} } +func (m *RotateKeyMessage) String() string { return proto.CompactTextString(m) } +func (*RotateKeyMessage) ProtoMessage() {} +func (*RotateKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +func (m *RotateKeyMessage) GetRole() string { + if m != nil { + return m.Role + } + return "" +} + +func (m *RotateKeyMessage) GetServerManagesKey() bool { + if m != nil { + return m.ServerManagesKey + } + return false +} + +func (m *RotateKeyMessage) GetKeyList() []string { + if m != nil { + return m.KeyList + } + return nil +} + // InitMessage holds a list of root key IDs and a list of roles for which // the server automatically should manage the keys type InitMessage struct { @@ -279,7 +315,7 @@ type InitMessage struct { func (m *InitMessage) Reset() { *m = InitMessage{} } func (m *InitMessage) String() string { return proto.CompactTextString(m) } func (*InitMessage) ProtoMessage() {} -func (*InitMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*InitMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *InitMessage) GetRootKeyIDs() []string { if m != nil { @@ -303,7 +339,7 @@ type RoleNameList struct { func (m *RoleNameList) Reset() { *m = RoleNameList{} } func (m *RoleNameList) String() string { return proto.CompactTextString(m) } func (*RoleNameList) ProtoMessage() {} -func (*RoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*RoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *RoleNameList) GetRoles() []string { if m != nil { @@ -312,6 +348,38 @@ func (m *RoleNameList) GetRoles() []string { return nil } +type RoleNameListResponse struct { + RoleNameList *RoleNameList `protobuf:"bytes,1,opt,name=roleNameList" json:"roleNameList,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *RoleNameListResponse) Reset() { *m = RoleNameListResponse{} } +func (m *RoleNameListResponse) String() string { return proto.CompactTextString(m) } +func (*RoleNameListResponse) ProtoMessage() {} +func (*RoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } + +func (m *RoleNameListResponse) GetRoleNameList() *RoleNameList { + if m != nil { + return m.RoleNameList + } + return nil +} + +func (m *RoleNameListResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *RoleNameListResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + type TargetName struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` } @@ -319,7 +387,7 @@ type TargetName struct { func (m *TargetName) Reset() { *m = TargetName{} } func (m *TargetName) String() string { return proto.CompactTextString(m) } func (*TargetName) ProtoMessage() {} -func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *TargetName) GetName() string { if m != nil { @@ -340,7 +408,7 @@ type Target struct { func (m *Target) Reset() { *m = Target{} } func (m *Target) String() string { return proto.CompactTextString(m) } func (*Target) ProtoMessage() {} -func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *Target) GetGun() string { if m != nil { @@ -386,7 +454,7 @@ type TargetWithRole struct { func (m *TargetWithRole) Reset() { *m = TargetWithRole{} } func (m *TargetWithRole) String() string { return proto.CompactTextString(m) } func (*TargetWithRole) ProtoMessage() {} -func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } func (m *TargetWithRole) GetTarget() *Target { if m != nil { @@ -411,7 +479,7 @@ type TargetWithRoleResponse struct { func (m *TargetWithRoleResponse) Reset() { *m = TargetWithRoleResponse{} } func (m *TargetWithRoleResponse) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleResponse) ProtoMessage() {} -func (*TargetWithRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*TargetWithRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *TargetWithRoleResponse) GetTargetWithRole() *TargetWithRole { if m != nil { @@ -441,7 +509,7 @@ type TargetWithRoleNameList struct { func (m *TargetWithRoleNameList) Reset() { *m = TargetWithRoleNameList{} } func (m *TargetWithRoleNameList) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleNameList) ProtoMessage() {} -func (*TargetWithRoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*TargetWithRoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *TargetWithRoleNameList) GetTargets() []*TargetWithRole { if m != nil { @@ -459,7 +527,7 @@ type TargetWithRoleNameListResponse struct { func (m *TargetWithRoleNameListResponse) Reset() { *m = TargetWithRoleNameListResponse{} } func (m *TargetWithRoleNameListResponse) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleNameListResponse) ProtoMessage() {} -func (*TargetWithRoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*TargetWithRoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *TargetWithRoleNameListResponse) GetTargetWithRoleNameList() *TargetWithRoleNameList { if m != nil { @@ -490,7 +558,7 @@ type TargetByNameAction struct { func (m *TargetByNameAction) Reset() { *m = TargetByNameAction{} } func (m *TargetByNameAction) String() string { return proto.CompactTextString(m) } func (*TargetByNameAction) ProtoMessage() {} -func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } func (m *TargetByNameAction) GetName() string { if m != nil { @@ -516,7 +584,7 @@ type Signature struct { func (m *Signature) Reset() { *m = Signature{} } func (m *Signature) String() string { return proto.CompactTextString(m) } func (*Signature) ProtoMessage() {} -func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *Signature) GetKeyID() string { if m != nil { @@ -555,7 +623,7 @@ type PublicKey struct { func (m *PublicKey) Reset() { *m = PublicKey{} } func (m *PublicKey) String() string { return proto.CompactTextString(m) } func (*PublicKey) ProtoMessage() {} -func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } func (m *PublicKey) GetId() string { if m != nil { @@ -588,7 +656,7 @@ type DelegationRole struct { func (m *DelegationRole) Reset() { *m = DelegationRole{} } func (m *DelegationRole) String() string { return proto.CompactTextString(m) } func (*DelegationRole) ProtoMessage() {} -func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } func (m *DelegationRole) GetKeys() map[string]*PublicKey { if m != nil { @@ -627,7 +695,7 @@ type TargetSigned struct { func (m *TargetSigned) Reset() { *m = TargetSigned{} } func (m *TargetSigned) String() string { return proto.CompactTextString(m) } func (*TargetSigned) ProtoMessage() {} -func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } func (m *TargetSigned) GetRole() *DelegationRole { if m != nil { @@ -657,7 +725,7 @@ type TargetSignedList struct { func (m *TargetSignedList) Reset() { *m = TargetSignedList{} } func (m *TargetSignedList) String() string { return proto.CompactTextString(m) } func (*TargetSignedList) ProtoMessage() {} -func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } +func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } func (m *TargetSignedList) GetTargets() []*TargetSigned { if m != nil { @@ -675,7 +743,7 @@ type TargetSignedListResponse struct { func (m *TargetSignedListResponse) Reset() { *m = TargetSignedListResponse{} } func (m *TargetSignedListResponse) String() string { return proto.CompactTextString(m) } func (*TargetSignedListResponse) ProtoMessage() {} -func (*TargetSignedListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } +func (*TargetSignedListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } func (m *TargetSignedListResponse) GetTargetSignedList() *TargetSignedList { if m != nil { @@ -710,7 +778,7 @@ type BasicResponse struct { func (m *BasicResponse) Reset() { *m = BasicResponse{} } func (m *BasicResponse) String() string { return proto.CompactTextString(m) } func (*BasicResponse) ProtoMessage() {} -func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } +func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } func (m *BasicResponse) GetSuccess() bool { if m != nil { @@ -738,7 +806,7 @@ type Change struct { func (m *Change) Reset() { *m = Change{} } func (m *Change) String() string { return proto.CompactTextString(m) } func (*Change) ProtoMessage() {} -func (*Change) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +func (*Change) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } func (m *Change) GetAction() string { if m != nil { @@ -783,7 +851,7 @@ type ChangeList struct { func (m *ChangeList) Reset() { *m = ChangeList{} } func (m *ChangeList) String() string { return proto.CompactTextString(m) } func (*ChangeList) ProtoMessage() {} -func (*ChangeList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } +func (*ChangeList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } func (m *ChangeList) GetChanges() []*Change { if m != nil { @@ -801,7 +869,7 @@ type ChangeListResponse struct { func (m *ChangeListResponse) Reset() { *m = ChangeListResponse{} } func (m *ChangeListResponse) String() string { return proto.CompactTextString(m) } func (*ChangeListResponse) ProtoMessage() {} -func (*ChangeListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } +func (*ChangeListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } func (m *ChangeListResponse) GetChangelist() *ChangeList { if m != nil { @@ -832,7 +900,7 @@ type RootRole struct { func (m *RootRole) Reset() { *m = RootRole{} } func (m *RootRole) String() string { return proto.CompactTextString(m) } func (*RootRole) ProtoMessage() {} -func (*RootRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } +func (*RootRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } func (m *RootRole) GetKeyIDs() []string { if m != nil { @@ -857,7 +925,7 @@ type Role struct { func (m *Role) Reset() { *m = Role{} } func (m *Role) String() string { return proto.CompactTextString(m) } func (*Role) ProtoMessage() {} -func (*Role) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } +func (*Role) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } func (m *Role) GetRootRole() *RootRole { if m != nil { @@ -887,7 +955,7 @@ type RoleList struct { func (m *RoleList) Reset() { *m = RoleList{} } func (m *RoleList) String() string { return proto.CompactTextString(m) } func (*RoleList) ProtoMessage() {} -func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } +func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } func (m *RoleList) GetRoles() []*Role { if m != nil { @@ -905,7 +973,7 @@ type RoleListResponse struct { func (m *RoleListResponse) Reset() { *m = RoleListResponse{} } func (m *RoleListResponse) String() string { return proto.CompactTextString(m) } func (*RoleListResponse) ProtoMessage() {} -func (*RoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } +func (*RoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } func (m *RoleListResponse) GetRoleList() *RoleList { if m != nil { @@ -936,7 +1004,7 @@ type RoleWithSignatures struct { func (m *RoleWithSignatures) Reset() { *m = RoleWithSignatures{} } func (m *RoleWithSignatures) String() string { return proto.CompactTextString(m) } func (*RoleWithSignatures) ProtoMessage() {} -func (*RoleWithSignatures) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } +func (*RoleWithSignatures) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } func (m *RoleWithSignatures) GetSignatures() []*Signature { if m != nil { @@ -959,7 +1027,7 @@ type RoleWithSignaturesList struct { func (m *RoleWithSignaturesList) Reset() { *m = RoleWithSignaturesList{} } func (m *RoleWithSignaturesList) String() string { return proto.CompactTextString(m) } func (*RoleWithSignaturesList) ProtoMessage() {} -func (*RoleWithSignaturesList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } +func (*RoleWithSignaturesList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} } func (m *RoleWithSignaturesList) GetRoleWithSignatures() []*RoleWithSignatures { if m != nil { @@ -977,7 +1045,7 @@ type RoleWithSignaturesListResponse struct { func (m *RoleWithSignaturesListResponse) Reset() { *m = RoleWithSignaturesListResponse{} } func (m *RoleWithSignaturesListResponse) String() string { return proto.CompactTextString(m) } func (*RoleWithSignaturesListResponse) ProtoMessage() {} -func (*RoleWithSignaturesListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } +func (*RoleWithSignaturesListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} } func (m *RoleWithSignaturesListResponse) GetRoleWithSignaturesList() *RoleWithSignaturesList { if m != nil { @@ -1000,6 +1068,31 @@ func (m *RoleWithSignaturesListResponse) GetMessage() string { return "" } +// FIXME: unimplemented +type CryptoServiceMessage struct { +} + +func (m *CryptoServiceMessage) Reset() { *m = CryptoServiceMessage{} } +func (m *CryptoServiceMessage) String() string { return proto.CompactTextString(m) } +func (*CryptoServiceMessage) ProtoMessage() {} +func (*CryptoServiceMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } + +type VersionMessage struct { + Version int32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` +} + +func (m *VersionMessage) Reset() { *m = VersionMessage{} } +func (m *VersionMessage) String() string { return proto.CompactTextString(m) } +func (*VersionMessage) ProtoMessage() {} +func (*VersionMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} } + +func (m *VersionMessage) GetVersion() int32 { + if m != nil { + return m.Version + } + return 0 +} + func init() { proto.RegisterType((*Empty)(nil), "api.Empty") proto.RegisterType((*AddDelegationMessage)(nil), "api.AddDelegationMessage") @@ -1010,8 +1103,10 @@ func init() { proto.RegisterType((*RemoveDelegationPathsMessage)(nil), "api.RemoveDelegationPathsMessage") proto.RegisterType((*RemoveDelegationKeysMessage)(nil), "api.RemoveDelegationKeysMessage") proto.RegisterType((*ClearDelegationPathsMessage)(nil), "api.ClearDelegationPathsMessage") + proto.RegisterType((*RotateKeyMessage)(nil), "api.RotateKeyMessage") proto.RegisterType((*InitMessage)(nil), "api.InitMessage") proto.RegisterType((*RoleNameList)(nil), "api.RoleNameList") + proto.RegisterType((*RoleNameListResponse)(nil), "api.RoleNameListResponse") proto.RegisterType((*TargetName)(nil), "api.TargetName") proto.RegisterType((*Target)(nil), "api.Target") proto.RegisterType((*TargetWithRole)(nil), "api.TargetWithRole") @@ -1036,6 +1131,8 @@ func init() { proto.RegisterType((*RoleWithSignatures)(nil), "api.RoleWithSignatures") proto.RegisterType((*RoleWithSignaturesList)(nil), "api.RoleWithSignaturesList") proto.RegisterType((*RoleWithSignaturesListResponse)(nil), "api.RoleWithSignaturesListResponse") + proto.RegisterType((*CryptoServiceMessage)(nil), "api.CryptoServiceMessage") + proto.RegisterType((*VersionMessage)(nil), "api.VersionMessage") } // Reference imports to suppress errors if they are not otherwise used. @@ -1074,6 +1171,10 @@ type NotaryClient interface { RemoveDelegationPaths(ctx context.Context, in *RemoveDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) RemoveDelegationKeys(ctx context.Context, in *RemoveDelegationKeysMessage, opts ...grpc.CallOption) (*BasicResponse, error) ClearDelegationPaths(ctx context.Context, in *ClearDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) + Witness(ctx context.Context, in *RoleNameList, opts ...grpc.CallOption) (*RoleNameListResponse, error) + RotateKey(ctx context.Context, in *RotateKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) + CryptoService(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CryptoServiceMessage, error) + SetLegacyVersions(ctx context.Context, in *VersionMessage, opts ...grpc.CallOption) (*Empty, error) } type notaryClient struct { @@ -1246,6 +1347,42 @@ func (c *notaryClient) ClearDelegationPaths(ctx context.Context, in *ClearDelega return out, nil } +func (c *notaryClient) Witness(ctx context.Context, in *RoleNameList, opts ...grpc.CallOption) (*RoleNameListResponse, error) { + out := new(RoleNameListResponse) + err := grpc.Invoke(ctx, "/api.Notary/Witness", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) RotateKey(ctx context.Context, in *RotateKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/RotateKey", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) CryptoService(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CryptoServiceMessage, error) { + out := new(CryptoServiceMessage) + err := grpc.Invoke(ctx, "/api.Notary/CryptoService", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) SetLegacyVersions(ctx context.Context, in *VersionMessage, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := grpc.Invoke(ctx, "/api.Notary/SetLegacyVersions", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Notary service type NotaryServer interface { @@ -1274,6 +1411,10 @@ type NotaryServer interface { RemoveDelegationPaths(context.Context, *RemoveDelegationPathsMessage) (*BasicResponse, error) RemoveDelegationKeys(context.Context, *RemoveDelegationKeysMessage) (*BasicResponse, error) ClearDelegationPaths(context.Context, *ClearDelegationPathsMessage) (*BasicResponse, error) + Witness(context.Context, *RoleNameList) (*RoleNameListResponse, error) + RotateKey(context.Context, *RotateKeyMessage) (*BasicResponse, error) + CryptoService(context.Context, *Empty) (*CryptoServiceMessage, error) + SetLegacyVersions(context.Context, *VersionMessage) (*Empty, error) } func RegisterNotaryServer(s *grpc.Server, srv NotaryServer) { @@ -1604,6 +1745,78 @@ func _Notary_ClearDelegationPaths_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _Notary_Witness_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RoleNameList) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).Witness(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/Witness", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).Witness(ctx, req.(*RoleNameList)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_RotateKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RotateKeyMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).RotateKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/RotateKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).RotateKey(ctx, req.(*RotateKeyMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_CryptoService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).CryptoService(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/CryptoService", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).CryptoService(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_SetLegacyVersions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(VersionMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).SetLegacyVersions(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/SetLegacyVersions", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).SetLegacyVersions(ctx, req.(*VersionMessage)) + } + return interceptor(ctx, in, info, handler) +} + var _Notary_serviceDesc = grpc.ServiceDesc{ ServiceName: "api.Notary", HandlerType: (*NotaryServer)(nil), @@ -1680,6 +1893,22 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "ClearDelegationPaths", Handler: _Notary_ClearDelegationPaths_Handler, }, + { + MethodName: "Witness", + Handler: _Notary_Witness_Handler, + }, + { + MethodName: "RotateKey", + Handler: _Notary_RotateKey_Handler, + }, + { + MethodName: "CryptoService", + Handler: _Notary_CryptoService_Handler, + }, + { + MethodName: "SetLegacyVersions", + Handler: _Notary_SetLegacyVersions_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "api.proto", @@ -1688,91 +1917,100 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1364 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0xef, 0x6e, 0x1b, 0x45, - 0x10, 0xe7, 0x6c, 0xc7, 0xe9, 0x8d, 0x1d, 0x37, 0x5d, 0x9a, 0xc4, 0x75, 0x93, 0xd4, 0x5c, 0x82, - 0x6a, 0x54, 0xe1, 0x2a, 0x29, 0xaa, 0x28, 0x48, 0x50, 0x37, 0x89, 0xdc, 0x10, 0x12, 0xa5, 0x57, - 0x54, 0x3e, 0x20, 0x21, 0x6d, 0x7d, 0x2b, 0xfb, 0x94, 0xf3, 0x9d, 0xb9, 0x5b, 0x47, 0x35, 0x6f, - 0x80, 0xc4, 0x17, 0x1e, 0x83, 0x57, 0xe1, 0x33, 0xaf, 0xc1, 0x3b, 0xa0, 0xfd, 0x73, 0x7b, 0x7b, - 0xff, 0x12, 0x64, 0x89, 0x6f, 0x37, 0xbb, 0xbf, 0xf9, 0xcd, 0xec, 0xec, 0xce, 0xec, 0xce, 0x81, - 0x89, 0x67, 0x6e, 0x7f, 0x16, 0x06, 0x34, 0x40, 0x55, 0x3c, 0x73, 0xad, 0x55, 0x58, 0x39, 0x99, - 0xce, 0xe8, 0xc2, 0xfa, 0x00, 0xf7, 0x07, 0x8e, 0x73, 0x4c, 0x3c, 0x32, 0xc6, 0xd4, 0x0d, 0xfc, - 0x73, 0x12, 0x45, 0x78, 0x4c, 0x10, 0x82, 0x9a, 0x8f, 0xa7, 0xa4, 0x6d, 0x74, 0x8d, 0x9e, 0x69, - 0xf3, 0x6f, 0xf4, 0x1c, 0x5a, 0x8e, 0x02, 0x9e, 0x91, 0x45, 0xd4, 0xae, 0x74, 0xab, 0xbd, 0xc6, - 0x61, 0xab, 0xcf, 0xd8, 0x2f, 0xe7, 0xef, 0x3d, 0x77, 0x74, 0x46, 0x16, 0x76, 0x06, 0x85, 0xee, - 0xc3, 0xca, 0x0c, 0xd3, 0x49, 0xd4, 0xae, 0x76, 0xab, 0x3d, 0xd3, 0x16, 0x82, 0x35, 0x85, 0x47, - 0x29, 0xcb, 0x76, 0xe0, 0x91, 0x81, 0xef, 0x30, 0x8d, 0xff, 0xc1, 0x09, 0xeb, 0x04, 0x1e, 0xa4, - 0xcc, 0x5d, 0x32, 0x27, 0x6e, 0x32, 0xa4, 0xbc, 0xae, 0xe8, 0x5e, 0x8f, 0x61, 0xcf, 0x26, 0xd3, - 0xe0, 0x9a, 0x1c, 0xa7, 0xe8, 0x07, 0xbe, 0x73, 0x2b, 0xe1, 0x26, 0xd4, 0xaf, 0xc8, 0xe2, 0xf4, - 0x38, 0x66, 0x94, 0x52, 0x49, 0x78, 0x0e, 0xe0, 0x61, 0xd6, 0x10, 0x8b, 0xd0, 0x0d, 0x06, 0xac, - 0xd7, 0xb0, 0x9d, 0x55, 0x59, 0x72, 0x95, 0xa7, 0x79, 0xe3, 0xb7, 0xed, 0x4b, 0xc9, 0xea, 0xd8, - 0x3a, 0x8e, 0x3c, 0x82, 0xc3, 0x72, 0x9f, 0xc2, 0xc0, 0x53, 0x54, 0xec, 0xdb, 0x9a, 0x41, 0xe3, - 0xd4, 0x77, 0x69, 0x0c, 0xd9, 0x05, 0x08, 0x83, 0x80, 0x9e, 0x09, 0x76, 0x83, 0xb3, 0x6b, 0x23, - 0x68, 0x00, 0x28, 0x22, 0xe1, 0x35, 0x09, 0xcf, 0xb1, 0x8f, 0xc7, 0xc4, 0x61, 0x61, 0x62, 0x5e, - 0x18, 0xbd, 0xc6, 0xe1, 0x3d, 0x7e, 0x2a, 0xd8, 0xc8, 0x05, 0x9e, 0x92, 0xef, 0xdd, 0x88, 0xda, - 0x05, 0x60, 0x6b, 0x1f, 0x9a, 0x3a, 0x86, 0x45, 0x25, 0xe4, 0x2c, 0xc2, 0x9a, 0x10, 0xac, 0x2e, - 0xc0, 0x0f, 0x38, 0x1c, 0x13, 0xca, 0x70, 0x85, 0x3b, 0xf0, 0x97, 0x01, 0x75, 0x01, 0x41, 0xeb, - 0x50, 0x1d, 0xcf, 0x7d, 0x39, 0xcb, 0x3e, 0x95, 0x42, 0x25, 0x1d, 0x35, 0x8f, 0xf8, 0x63, 0x3a, - 0x69, 0x57, 0xbb, 0x46, 0xaf, 0x6a, 0x4b, 0x09, 0x3d, 0x85, 0xfa, 0x04, 0x47, 0x13, 0x12, 0xb5, - 0x6b, 0xfc, 0x74, 0x6f, 0xf1, 0x75, 0x08, 0xea, 0xfe, 0x6b, 0x3e, 0x73, 0xe2, 0xd3, 0x70, 0x61, - 0x4b, 0x18, 0x23, 0x1a, 0xcd, 0x23, 0x1a, 0x4c, 0xdb, 0x2b, 0x5d, 0xa3, 0xd7, 0xb4, 0xa5, 0xd4, - 0x79, 0x01, 0x0d, 0x0d, 0xce, 0xbc, 0xba, 0x22, 0x8b, 0xd8, 0xab, 0x2b, 0xb2, 0x60, 0x4b, 0xbd, - 0xc6, 0xde, 0x5c, 0xb8, 0xd5, 0xb4, 0x85, 0xf0, 0x55, 0xe5, 0x4b, 0xc3, 0x3a, 0x85, 0x96, 0x30, - 0xf8, 0xa3, 0x4b, 0x27, 0x2c, 0x3c, 0x68, 0x0f, 0xea, 0x94, 0x8f, 0x70, 0x82, 0xc6, 0x61, 0x43, - 0xf3, 0xca, 0x96, 0x53, 0x6a, 0x47, 0x2b, 0xda, 0x8e, 0xfe, 0x66, 0xc0, 0x66, 0x9a, 0xcb, 0x26, - 0xd1, 0x2c, 0xf0, 0x23, 0x82, 0xbe, 0x86, 0x16, 0x4d, 0xcd, 0x48, 0xee, 0x8f, 0x35, 0x6e, 0xa5, - 0x94, 0x81, 0xa2, 0x36, 0xac, 0x46, 0xf3, 0xd1, 0x88, 0x44, 0x62, 0xbf, 0xef, 0xd8, 0xb1, 0xc8, - 0x66, 0xa6, 0xe2, 0xfc, 0xf0, 0xc8, 0x9a, 0x76, 0x2c, 0x5a, 0xc3, 0xac, 0x2b, 0x6a, 0xd7, 0x3f, - 0x87, 0x55, 0xc1, 0x2f, 0xf6, 0xbd, 0xc4, 0x87, 0x18, 0x63, 0xfd, 0x69, 0xc0, 0x6e, 0x31, 0x93, - 0x5a, 0xdc, 0x5b, 0xd8, 0xa4, 0x85, 0x08, 0xb9, 0xc8, 0x87, 0x05, 0x06, 0x14, 0x49, 0x89, 0xea, - 0x52, 0x8b, 0x7e, 0x03, 0x48, 0x58, 0x79, 0xb5, 0x60, 0x3c, 0x83, 0x11, 0x4b, 0xc4, 0xc2, 0x3c, - 0x7e, 0x1c, 0x1f, 0xfd, 0xd2, 0x04, 0x92, 0xd9, 0xf0, 0x0b, 0x98, 0x6f, 0xdd, 0xb1, 0x8f, 0xe9, - 0x3c, 0xe4, 0x65, 0x84, 0xe7, 0xbb, 0xa4, 0x12, 0x02, 0x3b, 0x94, 0x53, 0x42, 0x27, 0x81, 0x23, - 0x0f, 0x83, 0x94, 0xd0, 0x36, 0x98, 0x51, 0xac, 0xca, 0x3d, 0x6d, 0xda, 0xc9, 0x00, 0x5b, 0x85, - 0x1b, 0xbd, 0xc3, 0x9e, 0xeb, 0xb4, 0x6b, 0x62, 0x7d, 0x52, 0xb4, 0xde, 0x80, 0xa9, 0x0a, 0x3c, - 0x6a, 0x41, 0xc5, 0x75, 0xa4, 0xbd, 0x8a, 0xcb, 0x49, 0xb1, 0x37, 0x0e, 0x42, 0x97, 0x4e, 0xa6, - 0xd2, 0x5e, 0x32, 0xc0, 0x5c, 0x99, 0x71, 0x55, 0x69, 0x4f, 0x4a, 0xd6, 0xdf, 0x06, 0xb4, 0xd2, - 0x15, 0x16, 0x1d, 0x40, 0xed, 0x8a, 0xdd, 0x2b, 0xe2, 0x0c, 0xec, 0xf0, 0x00, 0xa4, 0x21, 0x7d, - 0x56, 0x0c, 0x45, 0xfe, 0x71, 0x68, 0x61, 0x6a, 0x6f, 0x83, 0x49, 0x27, 0x21, 0x89, 0x26, 0x81, - 0xe7, 0x70, 0xa3, 0x2b, 0x76, 0x32, 0x90, 0xd4, 0xdd, 0x9a, 0x56, 0x77, 0x3b, 0x43, 0x30, 0x15, - 0x75, 0x41, 0xae, 0xee, 0xeb, 0xb9, 0x9a, 0xbf, 0xf2, 0xb4, 0xdc, 0xfd, 0xdd, 0x80, 0xa6, 0xd8, - 0x70, 0xb6, 0x47, 0xc4, 0x41, 0x8f, 0xb5, 0x3a, 0x1b, 0x1f, 0xec, 0xf4, 0xa2, 0x44, 0xaa, 0x6a, - 0x39, 0x5e, 0x29, 0xcf, 0xf1, 0x3e, 0x80, 0xda, 0x2f, 0x71, 0x6f, 0xc5, 0xde, 0xa8, 0x23, 0x61, - 0x6b, 0x08, 0xeb, 0x5b, 0x58, 0xd7, 0xbd, 0xe1, 0xc7, 0xf8, 0x49, 0x36, 0xdb, 0xee, 0x69, 0x96, - 0x04, 0x2e, 0xc9, 0xb5, 0x3f, 0x0c, 0x68, 0x67, 0x19, 0x54, 0x96, 0x0d, 0x60, 0x9d, 0x66, 0xe6, - 0xe4, 0x3a, 0x37, 0x72, 0x94, 0x5c, 0x31, 0x07, 0x5f, 0x2a, 0xa7, 0x8e, 0x60, 0xed, 0x15, 0x8e, - 0xdc, 0x91, 0xf2, 0x43, 0x23, 0x31, 0x4a, 0x49, 0x2a, 0x69, 0x92, 0x0f, 0x50, 0x3f, 0x9a, 0x60, - 0x7f, 0xcc, 0xaf, 0x02, 0xcc, 0xd3, 0x52, 0xee, 0xb8, 0x94, 0xd8, 0x49, 0x89, 0x46, 0xc1, 0x2c, - 0xd6, 0x14, 0x02, 0x3b, 0x71, 0x74, 0x31, 0x8b, 0x7d, 0xe2, 0xdf, 0x6c, 0x8c, 0x1d, 0x23, 0x9e, - 0x35, 0xa6, 0xcd, 0xbf, 0x99, 0xe5, 0x51, 0xe0, 0x53, 0xe2, 0x53, 0x79, 0x31, 0xc4, 0xa2, 0xf5, - 0x0c, 0x40, 0x58, 0xe6, 0x01, 0xf8, 0x14, 0x56, 0x47, 0x5c, 0x8a, 0x77, 0x43, 0xec, 0xbb, 0x40, - 0xd8, 0xf1, 0x9c, 0xb5, 0x00, 0x94, 0x28, 0xa9, 0x85, 0x3f, 0x05, 0x10, 0x00, 0x2f, 0x09, 0xfd, - 0x5d, 0x4d, 0x9f, 0x83, 0x35, 0xc8, 0x52, 0xe1, 0x7e, 0x09, 0x77, 0xec, 0x20, 0xa0, 0x3c, 0x45, - 0x93, 0xc7, 0x86, 0x91, 0x7a, 0x4a, 0xa5, 0x72, 0xae, 0x92, 0xc9, 0x39, 0xeb, 0x27, 0xa8, 0x71, - 0xed, 0xcf, 0xe0, 0x4e, 0x28, 0x99, 0xa4, 0xb3, 0x6b, 0xb2, 0xca, 0x89, 0x41, 0x5b, 0x4d, 0x17, - 0x26, 0x76, 0xf1, 0x7b, 0xed, 0x09, 0x73, 0xcf, 0x13, 0xc1, 0x7c, 0xa4, 0x3f, 0x1f, 0x1a, 0x87, - 0xa6, 0xaa, 0xa1, 0x49, 0xed, 0x5c, 0x8f, 0xc1, 0x2a, 0x88, 0xdc, 0x2b, 0x4f, 0xbf, 0x1d, 0xd6, - 0x94, 0x1e, 0x07, 0xaa, 0xe9, 0xa5, 0xc2, 0x37, 0x02, 0xc4, 0x98, 0xd8, 0x6d, 0xa2, 0x72, 0x34, - 0xca, 0x24, 0xb2, 0x71, 0x5b, 0x22, 0xa3, 0x1d, 0xed, 0x72, 0x4f, 0x2d, 0x4c, 0xdc, 0xf3, 0x18, - 0x36, 0xf3, 0x46, 0xb8, 0xcb, 0x43, 0x40, 0x61, 0x6e, 0x46, 0x1a, 0xdc, 0x52, 0x34, 0xe9, 0x69, - 0xbb, 0x40, 0x85, 0xdf, 0xba, 0xc5, 0x36, 0xf4, 0x5b, 0x37, 0x2c, 0x44, 0xa4, 0x6e, 0xdd, 0x12, - 0x92, 0x12, 0xd5, 0x65, 0x62, 0x7e, 0xf8, 0x8f, 0x09, 0xf5, 0x8b, 0x80, 0xe2, 0x70, 0x81, 0xbe, - 0x00, 0x60, 0x6f, 0x5a, 0x17, 0x7b, 0xee, 0xaf, 0x04, 0xad, 0x73, 0x0f, 0xb4, 0x47, 0x6e, 0x07, - 0xf1, 0x91, 0x54, 0x3d, 0xb1, 0x3e, 0x62, 0x35, 0x92, 0x97, 0xf7, 0x68, 0x82, 0x80, 0x03, 0x78, - 0xd3, 0x56, 0x02, 0xee, 0x83, 0x39, 0x70, 0x1c, 0xf9, 0xfc, 0xd4, 0xcb, 0x76, 0x09, 0xfe, 0x00, - 0x9a, 0xe2, 0x91, 0xff, 0xdf, 0x55, 0x86, 0xd0, 0x60, 0xc1, 0x10, 0x98, 0x08, 0xe5, 0x1f, 0x07, - 0x9d, 0xbd, 0x9b, 0x5e, 0x34, 0x09, 0xd1, 0x29, 0xdc, 0x1d, 0x12, 0xaa, 0x3f, 0x49, 0x90, 0xfe, - 0xc4, 0xd5, 0x5f, 0x29, 0x9d, 0xa2, 0x47, 0x92, 0x46, 0x75, 0x01, 0x9d, 0x21, 0xa1, 0x03, 0xcf, - 0x13, 0x88, 0x73, 0x42, 0xb1, 0x83, 0x29, 0x96, 0xac, 0x77, 0x35, 0x65, 0x36, 0xd0, 0xd9, 0x29, - 0xbe, 0x12, 0x12, 0xbe, 0xe7, 0xb0, 0x36, 0x24, 0xf4, 0x28, 0x29, 0x56, 0x7a, 0xe4, 0xb7, 0xb2, - 0x55, 0x2d, 0xd1, 0xfb, 0x06, 0x4c, 0x3e, 0xc2, 0x12, 0x3c, 0xa5, 0xb3, 0x77, 0xd3, 0x71, 0x4b, - 0xf4, 0x5f, 0x00, 0x1a, 0x12, 0x9a, 0xbe, 0x93, 0xd3, 0x44, 0x1b, 0xe9, 0x7a, 0x90, 0xa8, 0xbe, - 0x84, 0xb5, 0x54, 0x6f, 0x8b, 0x1e, 0x70, 0x64, 0x51, 0x63, 0x5f, 0xb2, 0xb1, 0xef, 0xa0, 0x5d, - 0xd6, 0x8c, 0xa3, 0xfd, 0x3c, 0x59, 0xbe, 0x57, 0x2f, 0xe1, 0xfd, 0x0e, 0x50, 0xbe, 0xeb, 0x46, - 0xbb, 0x79, 0x46, 0xbd, 0x29, 0x2c, 0xe1, 0xfa, 0x39, 0xdf, 0xde, 0xea, 0xad, 0x37, 0xea, 0x89, - 0xf0, 0xdc, 0xde, 0x9d, 0x97, 0xf0, 0x5f, 0xc0, 0xfd, 0xa2, 0x8e, 0x1b, 0x75, 0x0b, 0x79, 0xb5, - 0x66, 0xbc, 0x84, 0xef, 0x12, 0x36, 0x0a, 0xdb, 0x71, 0xf4, 0x49, 0x21, 0xe1, 0x72, 0x1e, 0xf2, - 0x1d, 0xea, 0x96, 0xae, 0xfc, 0x56, 0xbe, 0xa2, 0xde, 0x5c, 0xf2, 0xdd, 0xd0, 0xb6, 0x17, 0xf3, - 0xbd, 0xaf, 0xf3, 0x3f, 0x4c, 0xcf, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x25, 0x35, 0xc2, 0x3c, - 0x6e, 0x12, 0x00, 0x00, + // 1517 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0x5b, 0x6f, 0xdb, 0x36, + 0x14, 0xae, 0xec, 0xc4, 0xa9, 0x8e, 0x1d, 0xd7, 0xe5, 0xd2, 0xd4, 0x75, 0x6f, 0x9e, 0xd2, 0xa1, + 0x59, 0x8b, 0xa5, 0x68, 0xba, 0x15, 0xed, 0x06, 0x6c, 0x75, 0xd3, 0xc2, 0xcd, 0xd2, 0x06, 0xad, + 0x32, 0xa4, 0x0f, 0x03, 0x06, 0xb0, 0x16, 0x61, 0x0b, 0x91, 0x25, 0x4f, 0x64, 0x82, 0x6a, 0x6f, + 0x7b, 0x1c, 0xb0, 0x97, 0xfd, 0x8c, 0xfd, 0x95, 0x3d, 0xf7, 0x07, 0x0d, 0xbc, 0x48, 0x22, 0x2d, + 0xc9, 0x19, 0x0c, 0xec, 0x4d, 0x87, 0x3c, 0xe7, 0x3b, 0x17, 0x9e, 0x0b, 0x45, 0xb0, 0xf1, 0xcc, + 0xdf, 0x99, 0xc5, 0x11, 0x8b, 0x50, 0x1d, 0xcf, 0x7c, 0x67, 0x0d, 0x56, 0x5f, 0x4e, 0x67, 0x2c, + 0x71, 0x3e, 0xc2, 0xc6, 0xc0, 0xf3, 0x5e, 0x90, 0x80, 0x8c, 0x31, 0xf3, 0xa3, 0xf0, 0x0d, 0xa1, + 0x14, 0x8f, 0x09, 0x42, 0xb0, 0x12, 0xe2, 0x29, 0xe9, 0x5a, 0x7d, 0x6b, 0xdb, 0x76, 0xc5, 0x37, + 0x7a, 0x0c, 0x6d, 0x2f, 0x63, 0x3c, 0x20, 0x09, 0xed, 0xd6, 0xfa, 0xf5, 0xed, 0xe6, 0x6e, 0x7b, + 0x87, 0xa3, 0xbf, 0x3d, 0xfd, 0x10, 0xf8, 0xa3, 0x03, 0x92, 0xb8, 0x73, 0x5c, 0x68, 0x03, 0x56, + 0x67, 0x98, 0x4d, 0x68, 0xb7, 0xde, 0xaf, 0x6f, 0xdb, 0xae, 0x24, 0x9c, 0x29, 0xdc, 0x36, 0x34, + 0xbb, 0x51, 0x40, 0x06, 0xa1, 0xc7, 0x25, 0xfe, 0x07, 0x23, 0x9c, 0x97, 0x70, 0xcd, 0x50, 0xf7, + 0x96, 0x1b, 0xb1, 0x48, 0x51, 0x66, 0x75, 0x4d, 0xb7, 0x7a, 0x0c, 0x5b, 0x2e, 0x99, 0x46, 0x67, + 0xe4, 0x85, 0x01, 0x3f, 0x08, 0xbd, 0x73, 0x01, 0x37, 0xa1, 0x71, 0x42, 0x92, 0xfd, 0x17, 0x29, + 0xa2, 0xa2, 0x2a, 0xc2, 0xf3, 0x10, 0xae, 0xcf, 0x2b, 0xe2, 0x11, 0x5a, 0xa0, 0xc0, 0x79, 0x05, + 0x37, 0xe6, 0x45, 0x96, 0xf4, 0x72, 0xbf, 0xa8, 0xfc, 0xbc, 0x73, 0xa9, 0xf0, 0x8e, 0xfb, 0xb1, + 0x17, 0x10, 0x1c, 0x57, 0xdb, 0x14, 0x47, 0x41, 0x06, 0xc5, 0xbf, 0x9d, 0x00, 0x3a, 0x6e, 0xc4, + 0x30, 0x23, 0x07, 0x24, 0x59, 0xc0, 0x87, 0xee, 0x41, 0x87, 0x92, 0xf8, 0x8c, 0xc4, 0x6f, 0x70, + 0x88, 0xc7, 0x84, 0x1e, 0x90, 0xa4, 0x5b, 0xeb, 0x5b, 0xdb, 0x17, 0xdd, 0xc2, 0x3a, 0xea, 0xc2, + 0xda, 0x09, 0x49, 0x5e, 0xfb, 0x94, 0xa9, 0x30, 0xa7, 0xa4, 0x33, 0x83, 0xe6, 0x7e, 0xe8, 0xb3, + 0x54, 0xd1, 0x2d, 0x80, 0x38, 0x8a, 0xd8, 0x81, 0xf4, 0xc5, 0x12, 0xbc, 0xda, 0x0a, 0x1a, 0x00, + 0xd2, 0xc1, 0x3d, 0x7e, 0x28, 0x54, 0xa8, 0x6d, 0xee, 0x5e, 0x16, 0x39, 0xc8, 0x57, 0x0e, 0xf1, + 0x94, 0x70, 0x74, 0xb7, 0x84, 0xd9, 0xb9, 0x03, 0x2d, 0x9d, 0x87, 0x9f, 0x41, 0x2c, 0x50, 0xa4, + 0x36, 0x49, 0x38, 0xbf, 0x5b, 0xb0, 0x61, 0x40, 0x11, 0x3a, 0x8b, 0x42, 0x4a, 0xd0, 0x37, 0xd0, + 0x8a, 0xb5, 0x75, 0x11, 0x92, 0x52, 0xdd, 0x06, 0x1b, 0x8f, 0x00, 0x3d, 0x1d, 0x8d, 0x08, 0xa5, + 0x2a, 0x48, 0x29, 0xc9, 0x77, 0xa6, 0xd2, 0xfb, 0x6e, 0x5d, 0x84, 0x37, 0x25, 0x9d, 0x3e, 0xc0, + 0x4f, 0x38, 0x1e, 0x13, 0xc6, 0x51, 0x4a, 0x73, 0xee, 0x1f, 0x0b, 0x1a, 0x92, 0x05, 0x75, 0xa0, + 0x3e, 0x3e, 0x0d, 0xd5, 0x2e, 0xff, 0xcc, 0x04, 0x6a, 0x66, 0x9e, 0x04, 0x24, 0x1c, 0xb3, 0x89, + 0xd0, 0x55, 0x77, 0x15, 0x85, 0x1e, 0x40, 0x63, 0x82, 0xe9, 0x84, 0xd0, 0xee, 0x8a, 0xa8, 0xe7, + 0xab, 0xc2, 0x1f, 0x09, 0xbd, 0xf3, 0x4a, 0xec, 0xbc, 0x0c, 0x59, 0x9c, 0xb8, 0x8a, 0x8d, 0x03, + 0x8d, 0x4e, 0x29, 0x8b, 0xa6, 0xdd, 0xd5, 0xbe, 0xb5, 0xdd, 0x72, 0x15, 0xd5, 0x7b, 0x0a, 0x4d, + 0x8d, 0x9d, 0x5b, 0x75, 0x42, 0x92, 0xd4, 0xaa, 0x13, 0x92, 0xf0, 0x70, 0x9f, 0xe1, 0xe0, 0x54, + 0x9a, 0xd5, 0x72, 0x25, 0xf1, 0x6d, 0xed, 0x89, 0xe5, 0xec, 0x43, 0x5b, 0x2a, 0x7c, 0xef, 0xb3, + 0x09, 0x0f, 0x25, 0xda, 0x82, 0x06, 0x13, 0x2b, 0x2a, 0xca, 0x4d, 0xcd, 0x2a, 0x57, 0x6d, 0x65, + 0xb9, 0x59, 0xd3, 0x72, 0xf8, 0x0f, 0x0b, 0x36, 0x4d, 0xac, 0xec, 0xfc, 0xbe, 0x83, 0x36, 0x33, + 0x76, 0x14, 0xf6, 0x67, 0x1a, 0x76, 0x26, 0x34, 0xc7, 0xba, 0xd4, 0x29, 0x0e, 0xe7, 0x4d, 0xc9, + 0x72, 0xe2, 0x2b, 0x58, 0x93, 0xf8, 0x32, 0xf7, 0x2a, 0x6c, 0x48, 0x79, 0x9c, 0xbf, 0x2d, 0xb8, + 0x55, 0x8e, 0x94, 0x39, 0x77, 0x04, 0x9b, 0xac, 0x94, 0x43, 0x39, 0x79, 0xbd, 0x44, 0x41, 0x06, + 0x52, 0x21, 0xba, 0x94, 0xd3, 0xef, 0x00, 0x49, 0x2d, 0xcf, 0x13, 0x8e, 0x33, 0x18, 0xf1, 0xd6, + 0x53, 0xda, 0xb9, 0xee, 0xa6, 0xe5, 0x57, 0x59, 0xc4, 0xaa, 0x22, 0x7f, 0x05, 0xfb, 0xc8, 0x1f, + 0x87, 0x98, 0x9d, 0xc6, 0xa2, 0x71, 0x8a, 0x0e, 0xa7, 0xa0, 0x24, 0xc1, 0x93, 0x72, 0x4a, 0xd8, + 0x24, 0xf2, 0x54, 0x32, 0x28, 0x0a, 0xdd, 0x00, 0x9b, 0xa6, 0xa2, 0xc2, 0xd2, 0x96, 0x9b, 0x2f, + 0x70, 0x2f, 0x7c, 0x7a, 0x8c, 0x03, 0xdf, 0xeb, 0xae, 0x48, 0xff, 0x14, 0xe9, 0xbc, 0x03, 0x3b, + 0x1b, 0x69, 0xa8, 0x0d, 0x35, 0xdf, 0x53, 0xfa, 0x6a, 0xbe, 0x00, 0xc5, 0xc1, 0x38, 0x8a, 0x7d, + 0x36, 0x99, 0x2a, 0x7d, 0xf9, 0x02, 0x37, 0x65, 0x26, 0x44, 0x95, 0x3e, 0x45, 0x39, 0x9f, 0x2c, + 0x68, 0x9b, 0x33, 0x05, 0x3d, 0x84, 0x95, 0x13, 0x3e, 0x49, 0x65, 0x0e, 0xdc, 0x14, 0x01, 0x30, + 0x59, 0x76, 0x78, 0xfb, 0x97, 0xf5, 0x27, 0x58, 0x4b, 0x4b, 0xfb, 0x06, 0xd8, 0x6c, 0x12, 0x13, + 0x3a, 0x89, 0x02, 0x4f, 0x28, 0x5d, 0x75, 0xf3, 0x85, 0x7c, 0xd2, 0xac, 0x68, 0x93, 0xa6, 0x37, + 0x04, 0x3b, 0x83, 0x2e, 0xa9, 0xd5, 0x3b, 0x7a, 0xad, 0x16, 0x87, 0xbc, 0x56, 0xbb, 0x7f, 0x5a, + 0xd0, 0x92, 0x07, 0xce, 0xcf, 0x88, 0x78, 0xe8, 0xae, 0x36, 0x31, 0xd2, 0xc4, 0x36, 0x9d, 0x52, + 0x63, 0x24, 0xaf, 0xf1, 0x5a, 0x75, 0x8d, 0xef, 0x00, 0x64, 0xe7, 0x25, 0x27, 0x75, 0x6a, 0x4d, + 0x96, 0x12, 0xae, 0xc6, 0xe1, 0xfc, 0x00, 0x1d, 0xdd, 0x1a, 0x91, 0xc6, 0xf7, 0xe7, 0xab, 0xed, + 0xb2, 0xa6, 0x49, 0xf2, 0xe5, 0xb5, 0xf6, 0x97, 0x05, 0xdd, 0x79, 0x84, 0xac, 0xca, 0x06, 0xd0, + 0x61, 0x73, 0x7b, 0xca, 0xcf, 0x2b, 0x05, 0x48, 0x21, 0x58, 0x60, 0x5f, 0xaa, 0xa6, 0xf6, 0x60, + 0xfd, 0x39, 0xa6, 0xfe, 0x28, 0xb3, 0x43, 0x03, 0xb1, 0x2a, 0x41, 0x6a, 0x26, 0xc8, 0x47, 0x68, + 0xec, 0x4d, 0x70, 0x38, 0x16, 0xa3, 0x00, 0x8b, 0xb2, 0x54, 0x27, 0xae, 0x28, 0x9e, 0x29, 0x74, + 0x14, 0xcd, 0x52, 0x49, 0x49, 0xf0, 0x8c, 0x63, 0xc9, 0x2c, 0xb5, 0x49, 0x7c, 0xf3, 0x35, 0x9e, + 0x46, 0xa2, 0x6a, 0x6c, 0x57, 0x7c, 0x73, 0xcd, 0xa3, 0x28, 0x64, 0x24, 0x64, 0x6a, 0x30, 0xa4, + 0xa4, 0xf3, 0x08, 0x40, 0x6a, 0x16, 0x01, 0xf8, 0x02, 0xd6, 0x46, 0x82, 0x4a, 0x4f, 0x43, 0x9e, + 0xbb, 0xe4, 0x70, 0xd3, 0x3d, 0x27, 0x01, 0x94, 0x0b, 0x65, 0x8e, 0x3f, 0x00, 0x90, 0x0c, 0x41, + 0x1e, 0xfa, 0x4b, 0x9a, 0xbc, 0x60, 0xd6, 0x58, 0x96, 0x0a, 0xf7, 0x33, 0xb8, 0xe8, 0x46, 0x11, + 0x13, 0x25, 0x9a, 0x5f, 0xaf, 0x2c, 0xe3, 0xf2, 0x68, 0xd4, 0x5c, 0x6d, 0xae, 0xe6, 0x9c, 0x9f, + 0x61, 0x45, 0x48, 0x7f, 0x09, 0x17, 0x63, 0x85, 0xa4, 0x8c, 0x5d, 0x57, 0x5d, 0x4e, 0x2e, 0xba, + 0xd9, 0x76, 0x69, 0x61, 0x97, 0xdf, 0x50, 0xef, 0x73, 0xf3, 0x02, 0x19, 0xcc, 0xdb, 0xfa, 0x15, + 0xa6, 0xb9, 0x6b, 0x67, 0x3d, 0x34, 0xef, 0x9d, 0x9d, 0x94, 0x39, 0x0b, 0xa2, 0xb0, 0x2a, 0xd0, + 0xa7, 0xc3, 0x7a, 0x26, 0x27, 0x18, 0xb3, 0xed, 0xa5, 0xc2, 0x37, 0x02, 0xc4, 0x91, 0xf8, 0x34, + 0xc9, 0x6a, 0x94, 0xce, 0x15, 0xb2, 0x75, 0x5e, 0x21, 0xa3, 0x9b, 0xda, 0x70, 0x37, 0x1c, 0x93, + 0x73, 0x1e, 0xc3, 0x66, 0x51, 0x89, 0x30, 0x79, 0x08, 0x28, 0x2e, 0xec, 0x28, 0x85, 0x57, 0x33, + 0x18, 0x73, 0xdb, 0x2d, 0x11, 0x11, 0x53, 0xb7, 0x5c, 0x87, 0x3e, 0x75, 0xe3, 0x52, 0x0e, 0x63, + 0xea, 0x56, 0x80, 0x54, 0x88, 0x2e, 0x15, 0xf3, 0x4d, 0xd8, 0xd8, 0x8b, 0x93, 0x19, 0x8b, 0x8e, + 0x48, 0x7c, 0xe6, 0x8f, 0xd2, 0xdf, 0x15, 0xe7, 0x1e, 0xb4, 0x8f, 0x49, 0x4c, 0xb5, 0x1f, 0xcc, + 0x2e, 0xac, 0x9d, 0xc9, 0x15, 0x61, 0xe3, 0xaa, 0x9b, 0x92, 0xbb, 0x9f, 0x9a, 0xd0, 0x38, 0x8c, + 0x18, 0x8e, 0x13, 0xf4, 0x35, 0x00, 0xbf, 0x9b, 0xfb, 0x38, 0xf0, 0x7f, 0x23, 0xa8, 0x23, 0xbc, + 0xd0, 0x2e, 0xeb, 0x3d, 0x24, 0x56, 0x8c, 0x9e, 0xe4, 0x5c, 0xe0, 0x7d, 0x56, 0x8c, 0x08, 0x3a, + 0x41, 0x20, 0x18, 0xc4, 0xaf, 0x6e, 0x05, 0xf3, 0x0e, 0xd8, 0x03, 0xcf, 0x53, 0x57, 0x58, 0xbd, + 0xf5, 0x57, 0xf0, 0x3f, 0x84, 0x96, 0xfc, 0x35, 0xfa, 0xef, 0x22, 0x43, 0x68, 0xf2, 0x80, 0x4a, + 0x1e, 0x8a, 0x8a, 0x17, 0x8c, 0xde, 0xd6, 0xa2, 0x5b, 0x51, 0x0e, 0xb4, 0x0f, 0x97, 0x86, 0x84, + 0xe9, 0xd7, 0x1a, 0xa4, 0x5f, 0x93, 0xf5, 0x9b, 0x4e, 0xaf, 0xec, 0xa2, 0xa5, 0x41, 0x1d, 0x42, + 0x6f, 0x48, 0xd8, 0x20, 0x08, 0x24, 0xc7, 0x1b, 0xc2, 0xb0, 0x87, 0x19, 0x56, 0xa8, 0x97, 0x34, + 0x61, 0xbe, 0xd0, 0xbb, 0x59, 0x3e, 0x56, 0x72, 0xbc, 0xc7, 0xb0, 0x3e, 0x24, 0x6c, 0x2f, 0x6f, + 0x78, 0x7a, 0xe4, 0xaf, 0xce, 0x77, 0xc6, 0x5c, 0xee, 0x7b, 0xb0, 0xc5, 0x0a, 0x6f, 0x12, 0x86, + 0xcc, 0xd6, 0xa2, 0x94, 0xcd, 0xe5, 0x9f, 0x02, 0x1a, 0x12, 0x66, 0xce, 0x75, 0x13, 0xe8, 0x8a, + 0xd9, 0x53, 0x72, 0xd1, 0x67, 0xb0, 0x6e, 0xbc, 0x08, 0xa0, 0x6b, 0x82, 0xb3, 0xec, 0x39, 0xa4, + 0xe2, 0x60, 0x8f, 0xa1, 0x5b, 0xf5, 0x84, 0x81, 0xee, 0x14, 0xc1, 0x8a, 0x2f, 0x1c, 0x15, 0xb8, + 0x3f, 0x02, 0x2a, 0xbe, 0x55, 0xa0, 0x5b, 0x45, 0x44, 0xfd, 0x57, 0xba, 0x02, 0xeb, 0x97, 0xe2, + 0xa3, 0x80, 0xfe, 0x60, 0x81, 0xb6, 0x65, 0x78, 0xce, 0x7f, 0xd3, 0xa8, 0xc0, 0x3f, 0x84, 0x8d, + 0xb2, 0x77, 0x0a, 0xd4, 0x2f, 0xc5, 0xd5, 0x9e, 0x30, 0x2a, 0xf0, 0xde, 0xc2, 0x95, 0xd2, 0x47, + 0x0c, 0xf4, 0x79, 0x29, 0xe0, 0x72, 0x16, 0x8a, 0x13, 0xea, 0x57, 0x7a, 0x7e, 0x2e, 0x5e, 0xd9, + 0x8b, 0x86, 0xc2, 0x5b, 0xf0, 0xd8, 0x51, 0x81, 0xf7, 0x14, 0xd6, 0xde, 0xfb, 0x2c, 0xe4, 0x8d, + 0xb5, 0xa4, 0x35, 0x5c, 0x2b, 0xfe, 0x8e, 0xe4, 0xa2, 0x4f, 0xc0, 0xce, 0x5e, 0x4a, 0x50, 0x9a, + 0xe8, 0xe6, 0xcb, 0x49, 0x85, 0xd2, 0x27, 0xb0, 0x6e, 0x34, 0x6a, 0xa3, 0x64, 0xa4, 0xce, 0xd2, + 0x46, 0xce, 0x2b, 0xfd, 0xf2, 0x11, 0x61, 0xaf, 0xc9, 0x18, 0x8f, 0x12, 0xd5, 0xd3, 0x29, 0x92, + 0xd7, 0x6b, 0xb3, 0xc5, 0xf7, 0x34, 0x48, 0xe7, 0xc2, 0x87, 0x86, 0x78, 0x7e, 0x7c, 0xf4, 0x6f, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xd7, 0x83, 0x48, 0x86, 0x8b, 0x14, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index c94959a2a..f25e257a6 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -32,6 +32,13 @@ service Notary { rpc RemoveDelegationPaths(RemoveDelegationPathsMessage) returns (BasicResponse) {} rpc RemoveDelegationKeys(RemoveDelegationKeysMessage) returns (BasicResponse) {} rpc ClearDelegationPaths(ClearDelegationPathsMessage) returns (BasicResponse) {} + + rpc Witness(RoleNameList) returns (RoleNameListResponse) {} + + rpc RotateKey(RotateKeyMessage) returns (BasicResponse) {} + + rpc CryptoService(Empty) returns (CryptoServiceMessage) {} + rpc SetLegacyVersions(VersionMessage) returns (Empty) {} } message Empty { @@ -78,6 +85,12 @@ message ClearDelegationPathsMessage { string role = 1; } +message RotateKeyMessage { + string role = 1; + bool serverManagesKey = 2; + repeated string keyList = 3; +} + // InitMessage holds a list of root key IDs and a list of roles for which // the server automatically should manage the keys message InitMessage { @@ -90,6 +103,12 @@ message RoleNameList { repeated string roles = 1; } +message RoleNameListResponse { + RoleNameList roleNameList = 1; + bool success = 2; + string message = 3; +} + message TargetName { string name = 1; } @@ -231,4 +250,11 @@ message RoleWithSignaturesListResponse { string message = 3; } +// FIXME: unimplemented +message CryptoServiceMessage { +} + +message VersionMessage { + int32 version = 1; +} From 0da0e826b32171d93d03a040018e5550471616c6 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Sat, 11 Mar 2017 18:14:37 +0100 Subject: [PATCH 17/62] Implement client api ListTargets Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/client.go | 34 +++++++++++++++++++++++++++++++--- client_api/api/server.go | 4 ++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/client_api/api/client.go b/client_api/api/client.go index afc91dbe8..46560f1f6 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -36,7 +36,7 @@ func (c *Client) DeleteTrustData(deleteRemote bool) error { } func (c *Client) AddTarget(target *client.Target, roles ...data.RoleName) error { - t := &TargetAction{ + t := &Target{ Gun: c.gun.String(), Name: target.Name, Length: target.Length, @@ -47,7 +47,7 @@ func (c *Client) AddTarget(target *client.Target, roles ...data.RoleName) error } func (c *Client) RemoveTarget(targetName string, roles ...data.RoleName) error { - t := &TargetAction{ + t := &Target{ Gun: c.gun.String(), Name: targetName, } @@ -56,7 +56,35 @@ func (c *Client) RemoveTarget(targetName string, roles ...data.RoleName) error { } func (c *Client) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) { - return nil, ErrNotImplemented + targetWithRoleList, err := c.client.ListTargets(context.Background(), roles) + if err { + return []*client.TargetWithRole{}, err + } + + targets := targetWithRoleList.TargetWithRoleNameList.Targets + res := make([]*client.TargetWithRole, len(targets)) + + for _, target := range(targets) { + t := target.Target + r := target.Role + + currTarget := client.Target{ + Name: t.GetName(), + Hashes: data.Hashes(t.Hashes), + Length: t.GetLength(), + } + + currRole := data.RoleName(r) + + targetWithRole := &client.TargetWithRole{ + Target: currTarget, + Role: currRole, + } + + res = append(res, targetWithRole) + } + + return res, nil } func (c *Client) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) { diff --git a/client_api/api/server.go b/client_api/api/server.go index 11ddfd95f..0e6942a7d 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -34,7 +34,7 @@ type Server struct { upstreamCAPath string } -func (srv *Server) AddTarget(ctx context.Context, t *TargetAction) (*BasicResponse, error) { +func (srv *Server) AddTarget(ctx context.Context, t *Target) (*BasicResponse, error) { r, err := srv.initRepo(data.GUN(t.GetGun())) if err != nil { return nil, err @@ -57,7 +57,7 @@ func (srv *Server) AddTarget(ctx context.Context, t *TargetAction) (*BasicRespon }, nil } -func (srv *Server) RemoveTarget(ctx context.Context, t *TargetAction) (*BasicResponse, error) { +func (srv *Server) RemoveTarget(ctx context.Context, t *Target) (*BasicResponse, error) { r, err := srv.initRepo(data.GUN(t.GetGun())) if err != nil { return nil, err From 8cd27766ce0bbbb2929c95cf78ed090260282a98 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Sun, 12 Mar 2017 02:48:28 +0100 Subject: [PATCH 18/62] Implement more client api calls Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/client.go | 58 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/client_api/api/client.go b/client_api/api/client.go index 46560f1f6..252564eb9 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -56,15 +56,20 @@ func (c *Client) RemoveTarget(targetName string, roles ...data.RoleName) error { } func (c *Client) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) { - targetWithRoleList, err := c.client.ListTargets(context.Background(), roles) - if err { + rolesList := make([]string, len(roles)) + for index, value := range roles { + rolesList[index] = value.String() + } + + targetWithRoleList, err := c.client.ListTargets(context.Background(), &RoleNameList{Roles:rolesList}) + if err != nil { return []*client.TargetWithRole{}, err } targets := targetWithRoleList.TargetWithRoleNameList.Targets res := make([]*client.TargetWithRole, len(targets)) - for _, target := range(targets) { + for index, target := range targets { t := target.Target r := target.Role @@ -81,17 +86,60 @@ func (c *Client) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, Role: currRole, } - res = append(res, targetWithRole) + res[index] = targetWithRole } return res, nil } func (c *Client) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) { - return nil, ErrNotImplemented + rolesList := make([]string, len(roles)) + for index, value := range roles { + rolesList[index] = value.String() + } + + targetByNameAction := &TargetByNameAction{ + Name: name, + Roles: &RoleNameList{Roles:rolesList}, + } + + targetWithRole, err := c.client.GetTargetByName(context.Background(), targetByNameAction) + if err != nil { + return nil, err + } + + target := targetWithRole.TargetWithRole.Target + role := targetWithRole.TargetWithRole.Role + + res := &client.TargetWithRole{ + Target: client.Target{ + Name: target.GetName(), + Hashes: data.Hashes(target.Hashes), + Length: target.GetLength(), + }, + Role: data.RoleName(role), + } + + return res, nil } func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) { + targetName := &TargetName{ + Name: name, + } + + targetSignedListResponse, err := c.client.GetAllTargetMetadataByName(context.Background(), targetName) + if err != nil { + return nil, err + } + + targetsSigned := targetSignedListResponse.TargetSignedList.Targets + + res := make([]*client.TargetWithRole, len(targetsSigned)) + for index, value := range targetsSigned { + + } + return nil, ErrNotImplemented } From 4d8d088d61a2fa667ca4eb68acf2aed7c8b309a9 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Sun, 12 Mar 2017 13:00:53 +0100 Subject: [PATCH 19/62] Implement more client api calls - part 2 Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/client.go | 49 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/client_api/api/client.go b/client_api/api/client.go index 252564eb9..e6767ae2c 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -135,12 +135,53 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS targetsSigned := targetSignedListResponse.TargetSignedList.Targets - res := make([]*client.TargetWithRole, len(targetsSigned)) - for index, value := range targetsSigned { - + res := make([]*client.TargetSignedStruct, len(targetsSigned)) + for indexT, value := range targetsSigned { + r := value.Role + s := value.Signatures + t := value.Target + + + currTarget := client.Target{ + Name: t.Name, + Hashes: t.Hashes, + Length: t.Length, + } + + currSignatures := make([]data.Signature, len(s)) + for indexS, sig := range s { + currSignature := data.Signature{ + Signature: sig.Signature, + KeyID: sig.KeyID, + IsValid: sig.IsValid, + Method: data.SigAlgorithm(sig.Method), + } + + currSignatures[indexS] = currSignature + } + + currKeys := make(map[string]data.PublicKey, len(r.Keys)) + for pubStr, pubKey := range r.Keys { + currKeys[pubStr] = data.NewPublicKey(pubKey.Algorithm, pubKey.Public) + } + + currRole := data.DelegationRole{ + BaseRole: data.BaseRole{ + Keys: currKeys, + Name: data.RoleName(r.Name), + Threshold: int(r.Threshold), // FIXME + }, + Paths: r.Paths, + } + + res[indexT] = &client.TargetSignedStruct{ + Role: currRole, + Target: currTarget, + Signatures: currSignatures, + } } - return nil, ErrNotImplemented + return res, nil } func (c *Client) GetChangelist() (changelist.Changelist, error) { From 6c0fd1e8a0d4fc418e7928ef89ebfb5cc9ce0fa1 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Sun, 12 Mar 2017 22:00:56 +0100 Subject: [PATCH 20/62] Implement more client api calls - part 3 Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/client.go | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/client_api/api/client.go b/client_api/api/client.go index e6767ae2c..1dac5bb3e 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -24,11 +24,22 @@ func NewClient(conn *grpc.ClientConn, gun data.GUN) *Client { } func (c *Client) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error { - return ErrNotImplemented + roles := make([]string, len(serverManagedRoles)) + for index, value := range serverManagedRoles { + roles[index] = value.String() + } + + initMsg := &InitMessage{ + RootKeyIDs: rootKeyIDs, + ServerManagedRoles: &RoleNameList{Roles:roles}, + } + _, err := c.client.Initialize(context.Background(), initMsg) + return err } func (c *Client) Publish() error { - return ErrNotImplemented + _, err := c.client.Publish(context.Background(), &Empty{}) + return err } func (c *Client) DeleteTrustData(deleteRemote bool) error { @@ -135,7 +146,7 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS targetsSigned := targetSignedListResponse.TargetSignedList.Targets - res := make([]*client.TargetSignedStruct, len(targetsSigned)) + res := make([]client.TargetSignedStruct, len(targetsSigned)) for indexT, value := range targetsSigned { r := value.Role s := value.Signatures @@ -174,7 +185,7 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS Paths: r.Paths, } - res[indexT] = &client.TargetSignedStruct{ + res[indexT] = client.TargetSignedStruct{ Role: currRole, Target: currTarget, Signatures: currSignatures, @@ -185,7 +196,18 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS } func (c *Client) GetChangelist() (changelist.Changelist, error) { - return nil, ErrNotImplemented + changes, err := c.client.GetChangelist(context.Background(), &Empty{}) + + currChangeList := changelist.NewMemChangelist() + for _, change := range changes.Changelist.Changes { + c := changelist.NewTUFChange(change.Action, data.RoleName(change.Scope), change.Type, change.Path, change.Content) + err := currChangeList.Add(c) + if err != nil { + return nil, err + } + } + + return currChangeList, err } func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { @@ -283,11 +305,13 @@ func (cs *CryptoService) RemoveKey(keyID string) error { // ListKeys returns a list of key IDs for the role, or an empty list or // nil if there are no keys. func (cs *CryptoService) ListKeys(role data.RoleName) []string { + keys := cs.ListKeys(role) return nil } // ListAllKeys returns a map of all available signing key IDs to role, or // an empty map or nil if there are no keys. func (cs *CryptoService) ListAllKeys() map[string]data.RoleName { - return nil + keys := cs.ListAllKeys() + return keys } From 3c4ca952eacacf562845a7aa19214ffa84728847 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Sun, 12 Mar 2017 23:03:36 +0100 Subject: [PATCH 21/62] Implement more client api calls - part 4 Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/client.go | 63 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/client_api/api/client.go b/client_api/api/client.go index 1dac5bb3e..0a60d5c28 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -197,6 +197,9 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS func (c *Client) GetChangelist() (changelist.Changelist, error) { changes, err := c.client.GetChangelist(context.Background(), &Empty{}) + if err != nil { + return nil, err + } currChangeList := changelist.NewMemChangelist() for _, change := range changes.Changelist.Changes { @@ -211,10 +214,68 @@ func (c *Client) GetChangelist() (changelist.Changelist, error) { } func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { - return nil, ErrNotImplemented + roleWithSigsListResp, err := c.client.ListRoles(context.Background(), &Empty{}) + if err != nil { + return nil, err + } + + roleWithSignaturesList := roleWithSigsListResp.RoleWithSignaturesList.RoleWithSignatures + + res := make([]client.RoleWithSignatures, len(roleWithSignaturesList)) + for index, value := range roleWithSignaturesList { + r := value.Role + s := value.Signatures + + currSignatures := make([]data.Signature, len(s)) + for indexSig, sig := range value.Signatures { + currSignature := data.Signature{ + Signature: sig.Signature, + KeyID: sig.KeyID, + IsValid: sig.IsValid, + Method: data.SigAlgorithm(sig.Method), + } + + currSignatures[indexSig] = currSignature + } + + currRole := data.Role{ + RootRole: data.RootRole{ + KeyIDs: r.RootRole.KeyIDs, + Threshold: int(r.RootRole.Threshold), // FIXME + }, + Name: data.RoleName(r.Name), + Paths: r.Paths, + } + + res[index] = client.RoleWithSignatures{ + Signatures: currSignatures, + Role: currRole, + } + } + + return res, nil } func (c *Client) GetDelegationRoles() ([]data.Role, error) { + roleListResp, err := c.client.GetDelegationRoles(context.Background(), &Empty{}) + if err != nil { + return nil, err + } + + res := make([]data.Role, len(roleListResp.RoleList.Roles)) + for index, role := range roleListResp.RoleList.Roles { + currRole := data.Role{ + RootRole: data.RootRole{ + KeyIDs: role.RootRole.KeyIDs, + Threshold: int(role.RootRole.Threshold), + }, + Name: data.RoleName(role.Name), + Paths: role.Paths, + } + + res[index] = currRole + } + return nil, ErrNotImplemented } From c5208b667756200008cfff88f46b442a5a790868 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 13 Mar 2017 09:39:22 +0100 Subject: [PATCH 22/62] Implement more client api calls - part 5 Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/client.go | 104 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 8 deletions(-) diff --git a/client_api/api/client.go b/client_api/api/client.go index 0a60d5c28..f6aba00b2 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -280,42 +280,130 @@ func (c *Client) GetDelegationRoles() ([]data.Role, error) { } func (c *Client) AddDelegation(name data.RoleName, delegationKeys []data.PublicKey, paths []string) error { - return ErrNotImplemented + currDelegationKeys := make([]*PublicKey, len(delegationKeys)) + for index, key := range delegationKeys { + currDelegationKeys[index] = &PublicKey{ + Id: key.ID(), + Algorithm: key.Algorithm(), + Public: key.Public(), + } + } + + addDelegationMessage := &AddDelegationMessage{ + Name: name.String(), + DelegationKeys: currDelegationKeys, + Paths: paths, + } + + _, err := c.client.AddDelegation(context.Background(), addDelegationMessage) + return err } func (c *Client) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []data.PublicKey) error { - return ErrNotImplemented + pubKeys := make([]*PublicKey, len(delegationKeys)) + for index, delegationKey := range delegationKeys { + pubKeys[index] = &PublicKey{ + Id: delegationKey.ID(), + Algorithm: delegationKey.Algorithm(), + Public: delegationKey.Public(), + } + } + + addDelegationRoleAndKeysMessage := &AddDelegationRoleAndKeysMessage{ + Name: name.String(), + DelegationKeys: pubKeys, + } + + _, err := c.client.AddDelegationRoleAndKeys(context.Background(), addDelegationRoleAndKeysMessage) + return err } func (c *Client) AddDelegationPaths(name data.RoleName, paths []string) error { + addDelegationPathsMessage := &AddDelegationPathsMessage{ + Name: name.String(), + Paths: paths, + } + + _, err := c.client.AddDelegationPaths(context.Background(), addDelegationPathsMessage) return ErrNotImplemented } func (c *Client) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error { - return ErrNotImplemented + r := &RemoveDelegationKeysAndPathsMessage{ + Name: name.String(), + KeyIDs: keyIDs, + Paths: paths, + } + + _, err := c.client.RemoveDelegationKeysAndPaths(context.Background(), r) + return err } func (c *Client) RemoveDelegationRole(name data.RoleName) error { - return ErrNotImplemented + r := &RemoveDelegationRoleMessage{ + Name: name.String(), + } + + _, err := c.client.RemoveDelegationRole(context.Background(), r) + return err } func (c *Client) RemoveDelegationPaths(name data.RoleName, paths []string) error { - return ErrNotImplemented + r := &RemoveDelegationPathsMessage{ + Name: name.String(), + Paths: paths, + } + + _, err := c.client.RemoveDelegationPaths(context.Background(), r) + return err } func (c *Client) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error { - return ErrNotImplemented + r := &RemoveDelegationKeysMessage{ + Name: name.String(), + KeyIDs: keyIDs, + } + + _, err := c.client.RemoveDelegationKeys(context.Background(), r) + return err } func (c *Client) ClearDelegationPaths(name data.RoleName) error { - return ErrNotImplemented + r := &ClearDelegationPathsMessage{ + Role: name.String(), + } + + _, err := c.client.ClearDelegationPaths(context.Background(), r) + return err } func (c *Client) Witness(roles ...data.RoleName) ([]data.RoleName, error) { - return nil, ErrNotImplemented + roleNames := make([]string, len(roles)) + for index, roleName := range roles { + roleNames[index] = roleName.String() + } + + roleNameList := &RoleNameList{ + Roles: roleNames, + } + + roleNameListResponse, err := c.client.Witness(context.Background(), roleNameList) + if err != nil { + return nil, err + } + + roleList := roleNameListResponse.RoleNameList.Roles + + res := make([]data.RoleName, len(roleList)) + for index, role := range roleList { + res[index] = data.RoleName(role) + } + + return res, nil } func (c *Client) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error { + return ErrNotImplemented } From 822b5e4303c21fd3a1dd46a7440cc06a21eb5e7e Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 13 Mar 2017 09:47:37 +0100 Subject: [PATCH 23/62] Finish implementing main part of client API endpoint Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/client.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client_api/api/client.go b/client_api/api/client.go index f6aba00b2..c7d02d052 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -403,8 +403,13 @@ func (c *Client) Witness(roles ...data.RoleName) ([]data.RoleName, error) { } func (c *Client) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error { - - return ErrNotImplemented + rotateKeyMessage := &RotateKeyMessage{ + Role: role.String(), + ServerManagesKey: serverManagesKey, + KeyList: keyList, + } + _, err := c.client.RotateKey(context.Background(), rotateKeyMessage) + return err } func (c *Client) SetLegacyVersions(n int) { From 1af58450494b6aa483a33d76ab8ba44f430c49f1 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 13 Mar 2017 10:13:54 +0100 Subject: [PATCH 24/62] Switch Empty type to google protobuf's Empty type Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.proto | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/client_api/api/api.proto b/client_api/api/api.proto index f25e257a6..3d857b713 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -2,10 +2,12 @@ syntax = "proto3"; package api; +import "google/protobuf/Empty.proto"; + // Notary Interface service Notary { rpc Initialize(InitMessage) returns (BasicResponse) {} - rpc Publish(Empty) returns (BasicResponse) {} + rpc Publish(google.protobuf.Empty) returns (BasicResponse) {} // AddTarget adds a target to the TUF repository and re-signs. rpc AddTarget(Target) returns (BasicResponse) {} @@ -20,10 +22,10 @@ service Notary { rpc GetAllTargetMetadataByName(TargetName) returns (TargetSignedListResponse) {} // GetChangelist returns the list of the repository's unpublished changes - rpc GetChangelist(Empty) returns (ChangeListResponse) {} + rpc GetChangelist(google.protobuf.Empty) returns (ChangeListResponse) {} - rpc ListRoles(Empty) returns (RoleWithSignaturesListResponse) {} - rpc GetDelegationRoles(Empty) returns (RoleListResponse) {} + rpc ListRoles(google.protobuf.Empty) returns (RoleWithSignaturesListResponse) {} + rpc GetDelegationRoles(google.protobuf.Empty) returns (RoleListResponse) {} rpc AddDelegation(AddDelegationMessage) returns (BasicResponse) {} rpc AddDelegationRoleAndKeys(AddDelegationRoleAndKeysMessage) returns (BasicResponse) {} rpc AddDelegationPaths(AddDelegationPathsMessage) returns (BasicResponse) {} @@ -37,12 +39,12 @@ service Notary { rpc RotateKey(RotateKeyMessage) returns (BasicResponse) {} - rpc CryptoService(Empty) returns (CryptoServiceMessage) {} - rpc SetLegacyVersions(VersionMessage) returns (Empty) {} -} + // CryptoService implementation + rpc CryptoService(google.protobuf.Empty) returns (CryptoServiceMessage) {} + rpc CryptoServiceCreate(CryptoServiceCreateMessage) returns (PublicKeyResponse) {} -message Empty { + rpc SetLegacyVersions(VersionMessage) returns (google.protobuf.Empty) {} } message AddDelegationMessage { From dd7c9189aff23f7a3107f54c2cd9f04b44e49362 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 13 Mar 2017 10:46:34 +0100 Subject: [PATCH 25/62] Add cryptoservice interface to client api endpoint Signed-off-by: David Lawrence Signed-off-by: Nassim 'Nass' Eddequiouaq (github: endophage) --- client_api/api/api.proto | 58 +++++++++++++++++++++++++++++++++++++--- client_api/api/client.go | 23 +++++++++++----- 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/client_api/api/api.proto b/client_api/api/api.proto index 3d857b713..a659613ac 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -33,7 +33,7 @@ service Notary { rpc RemoveDelegationRole(RemoveDelegationRoleMessage) returns (BasicResponse) {} rpc RemoveDelegationPaths(RemoveDelegationPathsMessage) returns (BasicResponse) {} rpc RemoveDelegationKeys(RemoveDelegationKeysMessage) returns (BasicResponse) {} - rpc ClearDelegationPaths(ClearDelegationPathsMessage) returns (BasicResponse) {} + rpc ClearDelegationPaths(RoleNameMessage) returns (BasicResponse) {} rpc Witness(RoleNameList) returns (RoleNameListResponse) {} @@ -42,7 +42,12 @@ service Notary { // CryptoService implementation rpc CryptoService(google.protobuf.Empty) returns (CryptoServiceMessage) {} rpc CryptoServiceCreate(CryptoServiceCreateMessage) returns (PublicKeyResponse) {} - + rpc CryptoServiceAddKey(CryptoServiceAddKeyMessage) returns (BasicResponse) {} + rpc CryptoServiceGetKey(KeyIDMessage) returns (PublicKeyResponse) {} + rpc CryptoServiceGetPrivateKey(KeyIDMessage) returns (PrivateKeyResponse) {} + rpc CryptoServiceRemoveKey(KeyIDMessage) returns (BasicResponse) {} + rpc CryptoServiceListKeys(RoleNameMessage) returns (KeyIDsListResponse) {} + rpc CryptoServiceListAllKeys(google.protobuf.Empty) returns (SigningKeyIDsToRolesResponse) {} rpc SetLegacyVersions(VersionMessage) returns (google.protobuf.Empty) {} } @@ -83,7 +88,7 @@ message RemoveDelegationKeysMessage { repeated string keyIDs = 2; } -message ClearDelegationPathsMessage { +message RoleNameMessage { string role = 1; } @@ -164,6 +169,12 @@ message PublicKey { bytes public = 3; } +message PublicKeyResponse { + PublicKey pubkey = 1; + bool success = 2; + string message = 3; +} + message DelegationRole { map keys = 1; string name = 2; @@ -256,6 +267,47 @@ message RoleWithSignaturesListResponse { message CryptoServiceMessage { } +message CryptoServiceCreateMessage { + string roleName = 1; + string gun = 2; + string algorithm = 3; +} + +message Signer { + PublicKey pubkey = 1; + string signature = 2; +} + +message PrivateKey { + PublicKey pubkey = 1; + bytes signature = 2; + bytes privkey = 3; + Signer cryptoSigner = 4; + string sigAlgorithm = 5; +} + +message CryptoServiceAddKeyMessage { + string roleName = 1; + string gun = 2; + PrivateKey key = 3; +} + +message KeyIDMessage { + string keyID = 1; +} + +message KeyIDsListResponse { + repeated string keyIDs = 1; + bool success = 2; + string message = 3; +} + +message SigningKeyIDsToRolesResponse { + map keyIDs = 1; + bool success = 2; + string message = 3; +} + message VersionMessage { int32 version = 1; } diff --git a/client_api/api/client.go b/client_api/api/client.go index c7d02d052..ec1e6f1dd 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -369,7 +369,7 @@ func (c *Client) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error } func (c *Client) ClearDelegationPaths(name data.RoleName) error { - r := &ClearDelegationPathsMessage{ + r := &RoleNameMessage{ Role: name.String(), } @@ -431,36 +431,45 @@ type CryptoService struct { // Create issues a new key pair and is responsible for loading // the private key into the appropriate signing service. func (cs *CryptoService) Create(role data.RoleName, gun data.GUN, algorithm string) (data.PublicKey, error) { - return nil, ErrNotImplemented + pub, err := cs.Create(role, gun, algorithm) + if err != nil { + return nil, err + } + + return pub, nil } // AddKey adds a private key to the specified role and gun func (cs *CryptoService) AddKey(role data.RoleName, gun data.GUN, key data.PrivateKey) error { - return ErrNotImplemented + err := cs.AddKey(role, gun, key) + return err } // GetKey retrieves the public key if present, otherwise it returns nil func (cs *CryptoService) GetKey(keyID string) data.PublicKey { - return nil + pubkey := cs.GetKey(keyID) + return pubkey } // GetPrivateKey retrieves the private key and role if present and retrievable, // otherwise it returns nil and an error func (cs *CryptoService) GetPrivateKey(keyID string) (data.PrivateKey, data.RoleName, error) { - return nil, "", ErrNotImplemented + priv, role, err := cs.GetPrivateKey(keyID) + return priv, role, err } // RemoveKey deletes the specified key, and returns an error only if the key // removal fails. If the key doesn't exist, no error should be returned. func (cs *CryptoService) RemoveKey(keyID string) error { - return ErrNotImplemented + err := cs.RemoveKey(keyID) + return err } // ListKeys returns a list of key IDs for the role, or an empty list or // nil if there are no keys. func (cs *CryptoService) ListKeys(role data.RoleName) []string { keys := cs.ListKeys(role) - return nil + return keys } // ListAllKeys returns a map of all available signing key IDs to role, or From 1ad6d9d2b27d995612f8c1895c2419f6a27719f5 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 13 Mar 2017 10:55:27 +0100 Subject: [PATCH 26/62] Add missing response type and update generated files Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 900 +++++++++++++++++++++++++++++++-------- client_api/api/api.proto | 8 + 2 files changed, 739 insertions(+), 169 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index e1f279233..2c9ce19bd 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -9,7 +9,6 @@ It is generated from these files: api.proto It has these top-level messages: - Empty AddDelegationMessage AddDelegationRoleAndKeysMessage AddDelegationPathsMessage @@ -17,7 +16,7 @@ It has these top-level messages: RemoveDelegationRoleMessage RemoveDelegationPathsMessage RemoveDelegationKeysMessage - ClearDelegationPathsMessage + RoleNameMessage RotateKeyMessage InitMessage RoleNameList @@ -31,6 +30,7 @@ It has these top-level messages: TargetByNameAction Signature PublicKey + PublicKeyResponse DelegationRole TargetSigned TargetSignedList @@ -47,6 +47,14 @@ It has these top-level messages: RoleWithSignaturesList RoleWithSignaturesListResponse CryptoServiceMessage + CryptoServiceCreateMessage + Signer + PrivateKey + CryptoServiceAddKeyMessage + PrivateKeyResponse + KeyIDMessage + KeyIDsListResponse + SigningKeyIDsToRolesResponse VersionMessage */ package api @@ -54,6 +62,7 @@ package api import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import google_protobuf "github.com/golang/protobuf/ptypes/empty" import ( context "golang.org/x/net/context" @@ -71,14 +80,6 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package -type Empty struct { -} - -func (m *Empty) Reset() { *m = Empty{} } -func (m *Empty) String() string { return proto.CompactTextString(m) } -func (*Empty) ProtoMessage() {} -func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - type AddDelegationMessage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` DelegationKeys []*PublicKey `protobuf:"bytes,2,rep,name=delegationKeys" json:"delegationKeys,omitempty"` @@ -88,7 +89,7 @@ type AddDelegationMessage struct { func (m *AddDelegationMessage) Reset() { *m = AddDelegationMessage{} } func (m *AddDelegationMessage) String() string { return proto.CompactTextString(m) } func (*AddDelegationMessage) ProtoMessage() {} -func (*AddDelegationMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*AddDelegationMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (m *AddDelegationMessage) GetName() string { if m != nil { @@ -119,7 +120,7 @@ type AddDelegationRoleAndKeysMessage struct { func (m *AddDelegationRoleAndKeysMessage) Reset() { *m = AddDelegationRoleAndKeysMessage{} } func (m *AddDelegationRoleAndKeysMessage) String() string { return proto.CompactTextString(m) } func (*AddDelegationRoleAndKeysMessage) ProtoMessage() {} -func (*AddDelegationRoleAndKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*AddDelegationRoleAndKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *AddDelegationRoleAndKeysMessage) GetName() string { if m != nil { @@ -143,7 +144,7 @@ type AddDelegationPathsMessage struct { func (m *AddDelegationPathsMessage) Reset() { *m = AddDelegationPathsMessage{} } func (m *AddDelegationPathsMessage) String() string { return proto.CompactTextString(m) } func (*AddDelegationPathsMessage) ProtoMessage() {} -func (*AddDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*AddDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *AddDelegationPathsMessage) GetName() string { if m != nil { @@ -169,7 +170,7 @@ func (m *RemoveDelegationKeysAndPathsMessage) Reset() { *m = RemoveDeleg func (m *RemoveDelegationKeysAndPathsMessage) String() string { return proto.CompactTextString(m) } func (*RemoveDelegationKeysAndPathsMessage) ProtoMessage() {} func (*RemoveDelegationKeysAndPathsMessage) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{4} + return fileDescriptor0, []int{3} } func (m *RemoveDelegationKeysAndPathsMessage) GetName() string { @@ -200,7 +201,7 @@ type RemoveDelegationRoleMessage struct { func (m *RemoveDelegationRoleMessage) Reset() { *m = RemoveDelegationRoleMessage{} } func (m *RemoveDelegationRoleMessage) String() string { return proto.CompactTextString(m) } func (*RemoveDelegationRoleMessage) ProtoMessage() {} -func (*RemoveDelegationRoleMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*RemoveDelegationRoleMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *RemoveDelegationRoleMessage) GetName() string { if m != nil { @@ -217,7 +218,7 @@ type RemoveDelegationPathsMessage struct { func (m *RemoveDelegationPathsMessage) Reset() { *m = RemoveDelegationPathsMessage{} } func (m *RemoveDelegationPathsMessage) String() string { return proto.CompactTextString(m) } func (*RemoveDelegationPathsMessage) ProtoMessage() {} -func (*RemoveDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*RemoveDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *RemoveDelegationPathsMessage) GetName() string { if m != nil { @@ -241,7 +242,7 @@ type RemoveDelegationKeysMessage struct { func (m *RemoveDelegationKeysMessage) Reset() { *m = RemoveDelegationKeysMessage{} } func (m *RemoveDelegationKeysMessage) String() string { return proto.CompactTextString(m) } func (*RemoveDelegationKeysMessage) ProtoMessage() {} -func (*RemoveDelegationKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*RemoveDelegationKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (m *RemoveDelegationKeysMessage) GetName() string { if m != nil { @@ -257,16 +258,16 @@ func (m *RemoveDelegationKeysMessage) GetKeyIDs() []string { return nil } -type ClearDelegationPathsMessage struct { +type RoleNameMessage struct { Role string `protobuf:"bytes,1,opt,name=role" json:"role,omitempty"` } -func (m *ClearDelegationPathsMessage) Reset() { *m = ClearDelegationPathsMessage{} } -func (m *ClearDelegationPathsMessage) String() string { return proto.CompactTextString(m) } -func (*ClearDelegationPathsMessage) ProtoMessage() {} -func (*ClearDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (m *RoleNameMessage) Reset() { *m = RoleNameMessage{} } +func (m *RoleNameMessage) String() string { return proto.CompactTextString(m) } +func (*RoleNameMessage) ProtoMessage() {} +func (*RoleNameMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } -func (m *ClearDelegationPathsMessage) GetRole() string { +func (m *RoleNameMessage) GetRole() string { if m != nil { return m.Role } @@ -282,7 +283,7 @@ type RotateKeyMessage struct { func (m *RotateKeyMessage) Reset() { *m = RotateKeyMessage{} } func (m *RotateKeyMessage) String() string { return proto.CompactTextString(m) } func (*RotateKeyMessage) ProtoMessage() {} -func (*RotateKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*RotateKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func (m *RotateKeyMessage) GetRole() string { if m != nil { @@ -315,7 +316,7 @@ type InitMessage struct { func (m *InitMessage) Reset() { *m = InitMessage{} } func (m *InitMessage) String() string { return proto.CompactTextString(m) } func (*InitMessage) ProtoMessage() {} -func (*InitMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*InitMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (m *InitMessage) GetRootKeyIDs() []string { if m != nil { @@ -339,7 +340,7 @@ type RoleNameList struct { func (m *RoleNameList) Reset() { *m = RoleNameList{} } func (m *RoleNameList) String() string { return proto.CompactTextString(m) } func (*RoleNameList) ProtoMessage() {} -func (*RoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*RoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *RoleNameList) GetRoles() []string { if m != nil { @@ -357,7 +358,7 @@ type RoleNameListResponse struct { func (m *RoleNameListResponse) Reset() { *m = RoleNameListResponse{} } func (m *RoleNameListResponse) String() string { return proto.CompactTextString(m) } func (*RoleNameListResponse) ProtoMessage() {} -func (*RoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*RoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *RoleNameListResponse) GetRoleNameList() *RoleNameList { if m != nil { @@ -387,7 +388,7 @@ type TargetName struct { func (m *TargetName) Reset() { *m = TargetName{} } func (m *TargetName) String() string { return proto.CompactTextString(m) } func (*TargetName) ProtoMessage() {} -func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } func (m *TargetName) GetName() string { if m != nil { @@ -408,7 +409,7 @@ type Target struct { func (m *Target) Reset() { *m = Target{} } func (m *Target) String() string { return proto.CompactTextString(m) } func (*Target) ProtoMessage() {} -func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *Target) GetGun() string { if m != nil { @@ -454,7 +455,7 @@ type TargetWithRole struct { func (m *TargetWithRole) Reset() { *m = TargetWithRole{} } func (m *TargetWithRole) String() string { return proto.CompactTextString(m) } func (*TargetWithRole) ProtoMessage() {} -func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *TargetWithRole) GetTarget() *Target { if m != nil { @@ -479,7 +480,7 @@ type TargetWithRoleResponse struct { func (m *TargetWithRoleResponse) Reset() { *m = TargetWithRoleResponse{} } func (m *TargetWithRoleResponse) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleResponse) ProtoMessage() {} -func (*TargetWithRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*TargetWithRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } func (m *TargetWithRoleResponse) GetTargetWithRole() *TargetWithRole { if m != nil { @@ -509,7 +510,7 @@ type TargetWithRoleNameList struct { func (m *TargetWithRoleNameList) Reset() { *m = TargetWithRoleNameList{} } func (m *TargetWithRoleNameList) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleNameList) ProtoMessage() {} -func (*TargetWithRoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*TargetWithRoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *TargetWithRoleNameList) GetTargets() []*TargetWithRole { if m != nil { @@ -527,7 +528,7 @@ type TargetWithRoleNameListResponse struct { func (m *TargetWithRoleNameListResponse) Reset() { *m = TargetWithRoleNameListResponse{} } func (m *TargetWithRoleNameListResponse) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleNameListResponse) ProtoMessage() {} -func (*TargetWithRoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*TargetWithRoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *TargetWithRoleNameListResponse) GetTargetWithRoleNameList() *TargetWithRoleNameList { if m != nil { @@ -558,7 +559,7 @@ type TargetByNameAction struct { func (m *TargetByNameAction) Reset() { *m = TargetByNameAction{} } func (m *TargetByNameAction) String() string { return proto.CompactTextString(m) } func (*TargetByNameAction) ProtoMessage() {} -func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *TargetByNameAction) GetName() string { if m != nil { @@ -584,7 +585,7 @@ type Signature struct { func (m *Signature) Reset() { *m = Signature{} } func (m *Signature) String() string { return proto.CompactTextString(m) } func (*Signature) ProtoMessage() {} -func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } func (m *Signature) GetKeyID() string { if m != nil { @@ -623,7 +624,7 @@ type PublicKey struct { func (m *PublicKey) Reset() { *m = PublicKey{} } func (m *PublicKey) String() string { return proto.CompactTextString(m) } func (*PublicKey) ProtoMessage() {} -func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *PublicKey) GetId() string { if m != nil { @@ -646,6 +647,38 @@ func (m *PublicKey) GetPublic() []byte { return nil } +type PublicKeyResponse struct { + Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *PublicKeyResponse) Reset() { *m = PublicKeyResponse{} } +func (m *PublicKeyResponse) String() string { return proto.CompactTextString(m) } +func (*PublicKeyResponse) ProtoMessage() {} +func (*PublicKeyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } + +func (m *PublicKeyResponse) GetPubkey() *PublicKey { + if m != nil { + return m.Pubkey + } + return nil +} + +func (m *PublicKeyResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *PublicKeyResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + type DelegationRole struct { Keys map[string]*PublicKey `protobuf:"bytes,1,rep,name=keys" json:"keys,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` @@ -1077,6 +1110,270 @@ func (m *CryptoServiceMessage) String() string { return proto.Compact func (*CryptoServiceMessage) ProtoMessage() {} func (*CryptoServiceMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } +type CryptoServiceCreateMessage struct { + RoleName string `protobuf:"bytes,1,opt,name=roleName" json:"roleName,omitempty"` + Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` + Algorithm string `protobuf:"bytes,3,opt,name=algorithm" json:"algorithm,omitempty"` +} + +func (m *CryptoServiceCreateMessage) Reset() { *m = CryptoServiceCreateMessage{} } +func (m *CryptoServiceCreateMessage) String() string { return proto.CompactTextString(m) } +func (*CryptoServiceCreateMessage) ProtoMessage() {} +func (*CryptoServiceCreateMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} } + +func (m *CryptoServiceCreateMessage) GetRoleName() string { + if m != nil { + return m.RoleName + } + return "" +} + +func (m *CryptoServiceCreateMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + +func (m *CryptoServiceCreateMessage) GetAlgorithm() string { + if m != nil { + return m.Algorithm + } + return "" +} + +type Signer struct { + Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` + Signature string `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` +} + +func (m *Signer) Reset() { *m = Signer{} } +func (m *Signer) String() string { return proto.CompactTextString(m) } +func (*Signer) ProtoMessage() {} +func (*Signer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} } + +func (m *Signer) GetPubkey() *PublicKey { + if m != nil { + return m.Pubkey + } + return nil +} + +func (m *Signer) GetSignature() string { + if m != nil { + return m.Signature + } + return "" +} + +type PrivateKey struct { + Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` + Privkey []byte `protobuf:"bytes,3,opt,name=privkey,proto3" json:"privkey,omitempty"` + CryptoSigner *Signer `protobuf:"bytes,4,opt,name=cryptoSigner" json:"cryptoSigner,omitempty"` + SigAlgorithm string `protobuf:"bytes,5,opt,name=sigAlgorithm" json:"sigAlgorithm,omitempty"` +} + +func (m *PrivateKey) Reset() { *m = PrivateKey{} } +func (m *PrivateKey) String() string { return proto.CompactTextString(m) } +func (*PrivateKey) ProtoMessage() {} +func (*PrivateKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{40} } + +func (m *PrivateKey) GetPubkey() *PublicKey { + if m != nil { + return m.Pubkey + } + return nil +} + +func (m *PrivateKey) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *PrivateKey) GetPrivkey() []byte { + if m != nil { + return m.Privkey + } + return nil +} + +func (m *PrivateKey) GetCryptoSigner() *Signer { + if m != nil { + return m.CryptoSigner + } + return nil +} + +func (m *PrivateKey) GetSigAlgorithm() string { + if m != nil { + return m.SigAlgorithm + } + return "" +} + +type CryptoServiceAddKeyMessage struct { + RoleName string `protobuf:"bytes,1,opt,name=roleName" json:"roleName,omitempty"` + Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` + Key *PrivateKey `protobuf:"bytes,3,opt,name=key" json:"key,omitempty"` +} + +func (m *CryptoServiceAddKeyMessage) Reset() { *m = CryptoServiceAddKeyMessage{} } +func (m *CryptoServiceAddKeyMessage) String() string { return proto.CompactTextString(m) } +func (*CryptoServiceAddKeyMessage) ProtoMessage() {} +func (*CryptoServiceAddKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41} } + +func (m *CryptoServiceAddKeyMessage) GetRoleName() string { + if m != nil { + return m.RoleName + } + return "" +} + +func (m *CryptoServiceAddKeyMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + +func (m *CryptoServiceAddKeyMessage) GetKey() *PrivateKey { + if m != nil { + return m.Key + } + return nil +} + +type PrivateKeyResponse struct { + Role string `protobuf:"bytes,1,opt,name=role" json:"role,omitempty"` + Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` + Privkey *PrivateKey `protobuf:"bytes,3,opt,name=privkey" json:"privkey,omitempty"` + Success bool `protobuf:"varint,4,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,5,opt,name=message" json:"message,omitempty"` +} + +func (m *PrivateKeyResponse) Reset() { *m = PrivateKeyResponse{} } +func (m *PrivateKeyResponse) String() string { return proto.CompactTextString(m) } +func (*PrivateKeyResponse) ProtoMessage() {} +func (*PrivateKeyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{42} } + +func (m *PrivateKeyResponse) GetRole() string { + if m != nil { + return m.Role + } + return "" +} + +func (m *PrivateKeyResponse) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + +func (m *PrivateKeyResponse) GetPrivkey() *PrivateKey { + if m != nil { + return m.Privkey + } + return nil +} + +func (m *PrivateKeyResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *PrivateKeyResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +type KeyIDMessage struct { + KeyID string `protobuf:"bytes,1,opt,name=keyID" json:"keyID,omitempty"` +} + +func (m *KeyIDMessage) Reset() { *m = KeyIDMessage{} } +func (m *KeyIDMessage) String() string { return proto.CompactTextString(m) } +func (*KeyIDMessage) ProtoMessage() {} +func (*KeyIDMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{43} } + +func (m *KeyIDMessage) GetKeyID() string { + if m != nil { + return m.KeyID + } + return "" +} + +type KeyIDsListResponse struct { + KeyIDs []string `protobuf:"bytes,1,rep,name=keyIDs" json:"keyIDs,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *KeyIDsListResponse) Reset() { *m = KeyIDsListResponse{} } +func (m *KeyIDsListResponse) String() string { return proto.CompactTextString(m) } +func (*KeyIDsListResponse) ProtoMessage() {} +func (*KeyIDsListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{44} } + +func (m *KeyIDsListResponse) GetKeyIDs() []string { + if m != nil { + return m.KeyIDs + } + return nil +} + +func (m *KeyIDsListResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *KeyIDsListResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +type SigningKeyIDsToRolesResponse struct { + KeyIDs map[string]string `protobuf:"bytes,1,rep,name=keyIDs" json:"keyIDs,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *SigningKeyIDsToRolesResponse) Reset() { *m = SigningKeyIDsToRolesResponse{} } +func (m *SigningKeyIDsToRolesResponse) String() string { return proto.CompactTextString(m) } +func (*SigningKeyIDsToRolesResponse) ProtoMessage() {} +func (*SigningKeyIDsToRolesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{45} } + +func (m *SigningKeyIDsToRolesResponse) GetKeyIDs() map[string]string { + if m != nil { + return m.KeyIDs + } + return nil +} + +func (m *SigningKeyIDsToRolesResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *SigningKeyIDsToRolesResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + type VersionMessage struct { Version int32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` } @@ -1084,7 +1381,7 @@ type VersionMessage struct { func (m *VersionMessage) Reset() { *m = VersionMessage{} } func (m *VersionMessage) String() string { return proto.CompactTextString(m) } func (*VersionMessage) ProtoMessage() {} -func (*VersionMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} } +func (*VersionMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{46} } func (m *VersionMessage) GetVersion() int32 { if m != nil { @@ -1094,7 +1391,6 @@ func (m *VersionMessage) GetVersion() int32 { } func init() { - proto.RegisterType((*Empty)(nil), "api.Empty") proto.RegisterType((*AddDelegationMessage)(nil), "api.AddDelegationMessage") proto.RegisterType((*AddDelegationRoleAndKeysMessage)(nil), "api.AddDelegationRoleAndKeysMessage") proto.RegisterType((*AddDelegationPathsMessage)(nil), "api.AddDelegationPathsMessage") @@ -1102,7 +1398,7 @@ func init() { proto.RegisterType((*RemoveDelegationRoleMessage)(nil), "api.RemoveDelegationRoleMessage") proto.RegisterType((*RemoveDelegationPathsMessage)(nil), "api.RemoveDelegationPathsMessage") proto.RegisterType((*RemoveDelegationKeysMessage)(nil), "api.RemoveDelegationKeysMessage") - proto.RegisterType((*ClearDelegationPathsMessage)(nil), "api.ClearDelegationPathsMessage") + proto.RegisterType((*RoleNameMessage)(nil), "api.RoleNameMessage") proto.RegisterType((*RotateKeyMessage)(nil), "api.RotateKeyMessage") proto.RegisterType((*InitMessage)(nil), "api.InitMessage") proto.RegisterType((*RoleNameList)(nil), "api.RoleNameList") @@ -1116,6 +1412,7 @@ func init() { proto.RegisterType((*TargetByNameAction)(nil), "api.TargetByNameAction") proto.RegisterType((*Signature)(nil), "api.Signature") proto.RegisterType((*PublicKey)(nil), "api.PublicKey") + proto.RegisterType((*PublicKeyResponse)(nil), "api.PublicKeyResponse") proto.RegisterType((*DelegationRole)(nil), "api.DelegationRole") proto.RegisterType((*TargetSigned)(nil), "api.TargetSigned") proto.RegisterType((*TargetSignedList)(nil), "api.TargetSignedList") @@ -1132,6 +1429,14 @@ func init() { proto.RegisterType((*RoleWithSignaturesList)(nil), "api.RoleWithSignaturesList") proto.RegisterType((*RoleWithSignaturesListResponse)(nil), "api.RoleWithSignaturesListResponse") proto.RegisterType((*CryptoServiceMessage)(nil), "api.CryptoServiceMessage") + proto.RegisterType((*CryptoServiceCreateMessage)(nil), "api.CryptoServiceCreateMessage") + proto.RegisterType((*Signer)(nil), "api.Signer") + proto.RegisterType((*PrivateKey)(nil), "api.PrivateKey") + proto.RegisterType((*CryptoServiceAddKeyMessage)(nil), "api.CryptoServiceAddKeyMessage") + proto.RegisterType((*PrivateKeyResponse)(nil), "api.PrivateKeyResponse") + proto.RegisterType((*KeyIDMessage)(nil), "api.KeyIDMessage") + proto.RegisterType((*KeyIDsListResponse)(nil), "api.KeyIDsListResponse") + proto.RegisterType((*SigningKeyIDsToRolesResponse)(nil), "api.SigningKeyIDsToRolesResponse") proto.RegisterType((*VersionMessage)(nil), "api.VersionMessage") } @@ -1147,7 +1452,7 @@ const _ = grpc.SupportPackageIsVersion4 type NotaryClient interface { Initialize(ctx context.Context, in *InitMessage, opts ...grpc.CallOption) (*BasicResponse, error) - Publish(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BasicResponse, error) + Publish(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*BasicResponse, error) // AddTarget adds a target to the TUF repository and re-signs. AddTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) // RemoveTarget deletes a target from the TUF repository and re-signs. It only @@ -1160,9 +1465,9 @@ type NotaryClient interface { // GetAllTargetMetadataByName GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes - GetChangelist(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ChangeListResponse, error) - ListRoles(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) - GetDelegationRoles(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*RoleListResponse, error) + GetChangelist(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*ChangeListResponse, error) + ListRoles(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) + GetDelegationRoles(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*RoleListResponse, error) AddDelegation(ctx context.Context, in *AddDelegationMessage, opts ...grpc.CallOption) (*BasicResponse, error) AddDelegationRoleAndKeys(ctx context.Context, in *AddDelegationRoleAndKeysMessage, opts ...grpc.CallOption) (*BasicResponse, error) AddDelegationPaths(ctx context.Context, in *AddDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) @@ -1170,11 +1475,19 @@ type NotaryClient interface { RemoveDelegationRole(ctx context.Context, in *RemoveDelegationRoleMessage, opts ...grpc.CallOption) (*BasicResponse, error) RemoveDelegationPaths(ctx context.Context, in *RemoveDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) RemoveDelegationKeys(ctx context.Context, in *RemoveDelegationKeysMessage, opts ...grpc.CallOption) (*BasicResponse, error) - ClearDelegationPaths(ctx context.Context, in *ClearDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) + ClearDelegationPaths(ctx context.Context, in *RoleNameMessage, opts ...grpc.CallOption) (*BasicResponse, error) Witness(ctx context.Context, in *RoleNameList, opts ...grpc.CallOption) (*RoleNameListResponse, error) RotateKey(ctx context.Context, in *RotateKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) - CryptoService(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CryptoServiceMessage, error) - SetLegacyVersions(ctx context.Context, in *VersionMessage, opts ...grpc.CallOption) (*Empty, error) + // CryptoService implementation + CryptoService(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*CryptoServiceMessage, error) + CryptoServiceCreate(ctx context.Context, in *CryptoServiceCreateMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) + CryptoServiceAddKey(ctx context.Context, in *CryptoServiceAddKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) + CryptoServiceGetKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) + CryptoServiceGetPrivateKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PrivateKeyResponse, error) + CryptoServiceRemoveKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*BasicResponse, error) + CryptoServiceListKeys(ctx context.Context, in *RoleNameMessage, opts ...grpc.CallOption) (*KeyIDsListResponse, error) + CryptoServiceListAllKeys(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*SigningKeyIDsToRolesResponse, error) + SetLegacyVersions(ctx context.Context, in *VersionMessage, opts ...grpc.CallOption) (*google_protobuf.Empty, error) } type notaryClient struct { @@ -1194,7 +1507,7 @@ func (c *notaryClient) Initialize(ctx context.Context, in *InitMessage, opts ... return out, nil } -func (c *notaryClient) Publish(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*BasicResponse, error) { +func (c *notaryClient) Publish(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*BasicResponse, error) { out := new(BasicResponse) err := grpc.Invoke(ctx, "/api.Notary/Publish", in, out, c.cc, opts...) if err != nil { @@ -1248,7 +1561,7 @@ func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *Targe return out, nil } -func (c *notaryClient) GetChangelist(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ChangeListResponse, error) { +func (c *notaryClient) GetChangelist(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*ChangeListResponse, error) { out := new(ChangeListResponse) err := grpc.Invoke(ctx, "/api.Notary/GetChangelist", in, out, c.cc, opts...) if err != nil { @@ -1257,7 +1570,7 @@ func (c *notaryClient) GetChangelist(ctx context.Context, in *Empty, opts ...grp return out, nil } -func (c *notaryClient) ListRoles(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) { +func (c *notaryClient) ListRoles(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) { out := new(RoleWithSignaturesListResponse) err := grpc.Invoke(ctx, "/api.Notary/ListRoles", in, out, c.cc, opts...) if err != nil { @@ -1266,7 +1579,7 @@ func (c *notaryClient) ListRoles(ctx context.Context, in *Empty, opts ...grpc.Ca return out, nil } -func (c *notaryClient) GetDelegationRoles(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*RoleListResponse, error) { +func (c *notaryClient) GetDelegationRoles(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*RoleListResponse, error) { out := new(RoleListResponse) err := grpc.Invoke(ctx, "/api.Notary/GetDelegationRoles", in, out, c.cc, opts...) if err != nil { @@ -1338,7 +1651,7 @@ func (c *notaryClient) RemoveDelegationKeys(ctx context.Context, in *RemoveDeleg return out, nil } -func (c *notaryClient) ClearDelegationPaths(ctx context.Context, in *ClearDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) { +func (c *notaryClient) ClearDelegationPaths(ctx context.Context, in *RoleNameMessage, opts ...grpc.CallOption) (*BasicResponse, error) { out := new(BasicResponse) err := grpc.Invoke(ctx, "/api.Notary/ClearDelegationPaths", in, out, c.cc, opts...) if err != nil { @@ -1365,7 +1678,7 @@ func (c *notaryClient) RotateKey(ctx context.Context, in *RotateKeyMessage, opts return out, nil } -func (c *notaryClient) CryptoService(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CryptoServiceMessage, error) { +func (c *notaryClient) CryptoService(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*CryptoServiceMessage, error) { out := new(CryptoServiceMessage) err := grpc.Invoke(ctx, "/api.Notary/CryptoService", in, out, c.cc, opts...) if err != nil { @@ -1374,8 +1687,71 @@ func (c *notaryClient) CryptoService(ctx context.Context, in *Empty, opts ...grp return out, nil } -func (c *notaryClient) SetLegacyVersions(ctx context.Context, in *VersionMessage, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *notaryClient) CryptoServiceCreate(ctx context.Context, in *CryptoServiceCreateMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) { + out := new(PublicKeyResponse) + err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceCreate", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) CryptoServiceAddKey(ctx context.Context, in *CryptoServiceAddKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceAddKey", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) CryptoServiceGetKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) { + out := new(PublicKeyResponse) + err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceGetKey", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) CryptoServiceGetPrivateKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PrivateKeyResponse, error) { + out := new(PrivateKeyResponse) + err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceGetPrivateKey", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) CryptoServiceRemoveKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*BasicResponse, error) { + out := new(BasicResponse) + err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceRemoveKey", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) CryptoServiceListKeys(ctx context.Context, in *RoleNameMessage, opts ...grpc.CallOption) (*KeyIDsListResponse, error) { + out := new(KeyIDsListResponse) + err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceListKeys", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) CryptoServiceListAllKeys(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*SigningKeyIDsToRolesResponse, error) { + out := new(SigningKeyIDsToRolesResponse) + err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceListAllKeys", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *notaryClient) SetLegacyVersions(ctx context.Context, in *VersionMessage, opts ...grpc.CallOption) (*google_protobuf.Empty, error) { + out := new(google_protobuf.Empty) err := grpc.Invoke(ctx, "/api.Notary/SetLegacyVersions", in, out, c.cc, opts...) if err != nil { return nil, err @@ -1387,7 +1763,7 @@ func (c *notaryClient) SetLegacyVersions(ctx context.Context, in *VersionMessage type NotaryServer interface { Initialize(context.Context, *InitMessage) (*BasicResponse, error) - Publish(context.Context, *Empty) (*BasicResponse, error) + Publish(context.Context, *google_protobuf.Empty) (*BasicResponse, error) // AddTarget adds a target to the TUF repository and re-signs. AddTarget(context.Context, *Target) (*BasicResponse, error) // RemoveTarget deletes a target from the TUF repository and re-signs. It only @@ -1400,9 +1776,9 @@ type NotaryServer interface { // GetAllTargetMetadataByName GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes - GetChangelist(context.Context, *Empty) (*ChangeListResponse, error) - ListRoles(context.Context, *Empty) (*RoleWithSignaturesListResponse, error) - GetDelegationRoles(context.Context, *Empty) (*RoleListResponse, error) + GetChangelist(context.Context, *google_protobuf.Empty) (*ChangeListResponse, error) + ListRoles(context.Context, *google_protobuf.Empty) (*RoleWithSignaturesListResponse, error) + GetDelegationRoles(context.Context, *google_protobuf.Empty) (*RoleListResponse, error) AddDelegation(context.Context, *AddDelegationMessage) (*BasicResponse, error) AddDelegationRoleAndKeys(context.Context, *AddDelegationRoleAndKeysMessage) (*BasicResponse, error) AddDelegationPaths(context.Context, *AddDelegationPathsMessage) (*BasicResponse, error) @@ -1410,11 +1786,19 @@ type NotaryServer interface { RemoveDelegationRole(context.Context, *RemoveDelegationRoleMessage) (*BasicResponse, error) RemoveDelegationPaths(context.Context, *RemoveDelegationPathsMessage) (*BasicResponse, error) RemoveDelegationKeys(context.Context, *RemoveDelegationKeysMessage) (*BasicResponse, error) - ClearDelegationPaths(context.Context, *ClearDelegationPathsMessage) (*BasicResponse, error) + ClearDelegationPaths(context.Context, *RoleNameMessage) (*BasicResponse, error) Witness(context.Context, *RoleNameList) (*RoleNameListResponse, error) RotateKey(context.Context, *RotateKeyMessage) (*BasicResponse, error) - CryptoService(context.Context, *Empty) (*CryptoServiceMessage, error) - SetLegacyVersions(context.Context, *VersionMessage) (*Empty, error) + // CryptoService implementation + CryptoService(context.Context, *google_protobuf.Empty) (*CryptoServiceMessage, error) + CryptoServiceCreate(context.Context, *CryptoServiceCreateMessage) (*PublicKeyResponse, error) + CryptoServiceAddKey(context.Context, *CryptoServiceAddKeyMessage) (*BasicResponse, error) + CryptoServiceGetKey(context.Context, *KeyIDMessage) (*PublicKeyResponse, error) + CryptoServiceGetPrivateKey(context.Context, *KeyIDMessage) (*PrivateKeyResponse, error) + CryptoServiceRemoveKey(context.Context, *KeyIDMessage) (*BasicResponse, error) + CryptoServiceListKeys(context.Context, *RoleNameMessage) (*KeyIDsListResponse, error) + CryptoServiceListAllKeys(context.Context, *google_protobuf.Empty) (*SigningKeyIDsToRolesResponse, error) + SetLegacyVersions(context.Context, *VersionMessage) (*google_protobuf.Empty, error) } func RegisterNotaryServer(s *grpc.Server, srv NotaryServer) { @@ -1440,7 +1824,7 @@ func _Notary_Initialize_Handler(srv interface{}, ctx context.Context, dec func(i } func _Notary_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(google_protobuf.Empty) if err := dec(in); err != nil { return nil, err } @@ -1452,7 +1836,7 @@ func _Notary_Publish_Handler(srv interface{}, ctx context.Context, dec func(inte FullMethod: "/api.Notary/Publish", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).Publish(ctx, req.(*Empty)) + return srv.(NotaryServer).Publish(ctx, req.(*google_protobuf.Empty)) } return interceptor(ctx, in, info, handler) } @@ -1548,7 +1932,7 @@ func _Notary_GetAllTargetMetadataByName_Handler(srv interface{}, ctx context.Con } func _Notary_GetChangelist_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(google_protobuf.Empty) if err := dec(in); err != nil { return nil, err } @@ -1560,13 +1944,13 @@ func _Notary_GetChangelist_Handler(srv interface{}, ctx context.Context, dec fun FullMethod: "/api.Notary/GetChangelist", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).GetChangelist(ctx, req.(*Empty)) + return srv.(NotaryServer).GetChangelist(ctx, req.(*google_protobuf.Empty)) } return interceptor(ctx, in, info, handler) } func _Notary_ListRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(google_protobuf.Empty) if err := dec(in); err != nil { return nil, err } @@ -1578,13 +1962,13 @@ func _Notary_ListRoles_Handler(srv interface{}, ctx context.Context, dec func(in FullMethod: "/api.Notary/ListRoles", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).ListRoles(ctx, req.(*Empty)) + return srv.(NotaryServer).ListRoles(ctx, req.(*google_protobuf.Empty)) } return interceptor(ctx, in, info, handler) } func _Notary_GetDelegationRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(google_protobuf.Empty) if err := dec(in); err != nil { return nil, err } @@ -1596,7 +1980,7 @@ func _Notary_GetDelegationRoles_Handler(srv interface{}, ctx context.Context, de FullMethod: "/api.Notary/GetDelegationRoles", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).GetDelegationRoles(ctx, req.(*Empty)) + return srv.(NotaryServer).GetDelegationRoles(ctx, req.(*google_protobuf.Empty)) } return interceptor(ctx, in, info, handler) } @@ -1728,7 +2112,7 @@ func _Notary_RemoveDelegationKeys_Handler(srv interface{}, ctx context.Context, } func _Notary_ClearDelegationPaths_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ClearDelegationPathsMessage) + in := new(RoleNameMessage) if err := dec(in); err != nil { return nil, err } @@ -1740,7 +2124,7 @@ func _Notary_ClearDelegationPaths_Handler(srv interface{}, ctx context.Context, FullMethod: "/api.Notary/ClearDelegationPaths", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).ClearDelegationPaths(ctx, req.(*ClearDelegationPathsMessage)) + return srv.(NotaryServer).ClearDelegationPaths(ctx, req.(*RoleNameMessage)) } return interceptor(ctx, in, info, handler) } @@ -1782,7 +2166,7 @@ func _Notary_RotateKey_Handler(srv interface{}, ctx context.Context, dec func(in } func _Notary_CryptoService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(google_protobuf.Empty) if err := dec(in); err != nil { return nil, err } @@ -1794,7 +2178,133 @@ func _Notary_CryptoService_Handler(srv interface{}, ctx context.Context, dec fun FullMethod: "/api.Notary/CryptoService", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).CryptoService(ctx, req.(*Empty)) + return srv.(NotaryServer).CryptoService(ctx, req.(*google_protobuf.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_CryptoServiceCreate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CryptoServiceCreateMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).CryptoServiceCreate(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/CryptoServiceCreate", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).CryptoServiceCreate(ctx, req.(*CryptoServiceCreateMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_CryptoServiceAddKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CryptoServiceAddKeyMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).CryptoServiceAddKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/CryptoServiceAddKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).CryptoServiceAddKey(ctx, req.(*CryptoServiceAddKeyMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_CryptoServiceGetKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KeyIDMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).CryptoServiceGetKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/CryptoServiceGetKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).CryptoServiceGetKey(ctx, req.(*KeyIDMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_CryptoServiceGetPrivateKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KeyIDMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).CryptoServiceGetPrivateKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/CryptoServiceGetPrivateKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).CryptoServiceGetPrivateKey(ctx, req.(*KeyIDMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_CryptoServiceRemoveKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KeyIDMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).CryptoServiceRemoveKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/CryptoServiceRemoveKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).CryptoServiceRemoveKey(ctx, req.(*KeyIDMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_CryptoServiceListKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RoleNameMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).CryptoServiceListKeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/CryptoServiceListKeys", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).CryptoServiceListKeys(ctx, req.(*RoleNameMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Notary_CryptoServiceListAllKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(google_protobuf.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).CryptoServiceListAllKeys(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/CryptoServiceListAllKeys", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).CryptoServiceListAllKeys(ctx, req.(*google_protobuf.Empty)) } return interceptor(ctx, in, info, handler) } @@ -1905,6 +2415,34 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "CryptoService", Handler: _Notary_CryptoService_Handler, }, + { + MethodName: "CryptoServiceCreate", + Handler: _Notary_CryptoServiceCreate_Handler, + }, + { + MethodName: "CryptoServiceAddKey", + Handler: _Notary_CryptoServiceAddKey_Handler, + }, + { + MethodName: "CryptoServiceGetKey", + Handler: _Notary_CryptoServiceGetKey_Handler, + }, + { + MethodName: "CryptoServiceGetPrivateKey", + Handler: _Notary_CryptoServiceGetPrivateKey_Handler, + }, + { + MethodName: "CryptoServiceRemoveKey", + Handler: _Notary_CryptoServiceRemoveKey_Handler, + }, + { + MethodName: "CryptoServiceListKeys", + Handler: _Notary_CryptoServiceListKeys_Handler, + }, + { + MethodName: "CryptoServiceListAllKeys", + Handler: _Notary_CryptoServiceListAllKeys_Handler, + }, { MethodName: "SetLegacyVersions", Handler: _Notary_SetLegacyVersions_Handler, @@ -1917,100 +2455,124 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1517 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x58, 0x5b, 0x6f, 0xdb, 0x36, - 0x14, 0xae, 0xec, 0xc4, 0xa9, 0x8e, 0x1d, 0xd7, 0xe5, 0xd2, 0xd4, 0x75, 0x6f, 0x9e, 0xd2, 0xa1, - 0x59, 0x8b, 0xa5, 0x68, 0xba, 0x15, 0xed, 0x06, 0x6c, 0x75, 0xd3, 0xc2, 0xcd, 0xd2, 0x06, 0xad, - 0x32, 0xa4, 0x0f, 0x03, 0x06, 0xb0, 0x16, 0x61, 0x0b, 0x91, 0x25, 0x4f, 0x64, 0x82, 0x6a, 0x6f, - 0x7b, 0x1c, 0xb0, 0x97, 0xfd, 0x8c, 0xfd, 0x95, 0x3d, 0xf7, 0x07, 0x0d, 0xbc, 0x48, 0x22, 0x2d, - 0xc9, 0x19, 0x0c, 0xec, 0x4d, 0x87, 0x3c, 0xe7, 0x3b, 0x17, 0x9e, 0x0b, 0x45, 0xb0, 0xf1, 0xcc, - 0xdf, 0x99, 0xc5, 0x11, 0x8b, 0x50, 0x1d, 0xcf, 0x7c, 0x67, 0x0d, 0x56, 0x5f, 0x4e, 0x67, 0x2c, - 0x71, 0x3e, 0xc2, 0xc6, 0xc0, 0xf3, 0x5e, 0x90, 0x80, 0x8c, 0x31, 0xf3, 0xa3, 0xf0, 0x0d, 0xa1, - 0x14, 0x8f, 0x09, 0x42, 0xb0, 0x12, 0xe2, 0x29, 0xe9, 0x5a, 0x7d, 0x6b, 0xdb, 0x76, 0xc5, 0x37, - 0x7a, 0x0c, 0x6d, 0x2f, 0x63, 0x3c, 0x20, 0x09, 0xed, 0xd6, 0xfa, 0xf5, 0xed, 0xe6, 0x6e, 0x7b, - 0x87, 0xa3, 0xbf, 0x3d, 0xfd, 0x10, 0xf8, 0xa3, 0x03, 0x92, 0xb8, 0x73, 0x5c, 0x68, 0x03, 0x56, - 0x67, 0x98, 0x4d, 0x68, 0xb7, 0xde, 0xaf, 0x6f, 0xdb, 0xae, 0x24, 0x9c, 0x29, 0xdc, 0x36, 0x34, - 0xbb, 0x51, 0x40, 0x06, 0xa1, 0xc7, 0x25, 0xfe, 0x07, 0x23, 0x9c, 0x97, 0x70, 0xcd, 0x50, 0xf7, - 0x96, 0x1b, 0xb1, 0x48, 0x51, 0x66, 0x75, 0x4d, 0xb7, 0x7a, 0x0c, 0x5b, 0x2e, 0x99, 0x46, 0x67, - 0xe4, 0x85, 0x01, 0x3f, 0x08, 0xbd, 0x73, 0x01, 0x37, 0xa1, 0x71, 0x42, 0x92, 0xfd, 0x17, 0x29, - 0xa2, 0xa2, 0x2a, 0xc2, 0xf3, 0x10, 0xae, 0xcf, 0x2b, 0xe2, 0x11, 0x5a, 0xa0, 0xc0, 0x79, 0x05, - 0x37, 0xe6, 0x45, 0x96, 0xf4, 0x72, 0xbf, 0xa8, 0xfc, 0xbc, 0x73, 0xa9, 0xf0, 0x8e, 0xfb, 0xb1, - 0x17, 0x10, 0x1c, 0x57, 0xdb, 0x14, 0x47, 0x41, 0x06, 0xc5, 0xbf, 0x9d, 0x00, 0x3a, 0x6e, 0xc4, - 0x30, 0x23, 0x07, 0x24, 0x59, 0xc0, 0x87, 0xee, 0x41, 0x87, 0x92, 0xf8, 0x8c, 0xc4, 0x6f, 0x70, - 0x88, 0xc7, 0x84, 0x1e, 0x90, 0xa4, 0x5b, 0xeb, 0x5b, 0xdb, 0x17, 0xdd, 0xc2, 0x3a, 0xea, 0xc2, - 0xda, 0x09, 0x49, 0x5e, 0xfb, 0x94, 0xa9, 0x30, 0xa7, 0xa4, 0x33, 0x83, 0xe6, 0x7e, 0xe8, 0xb3, - 0x54, 0xd1, 0x2d, 0x80, 0x38, 0x8a, 0xd8, 0x81, 0xf4, 0xc5, 0x12, 0xbc, 0xda, 0x0a, 0x1a, 0x00, - 0xd2, 0xc1, 0x3d, 0x7e, 0x28, 0x54, 0xa8, 0x6d, 0xee, 0x5e, 0x16, 0x39, 0xc8, 0x57, 0x0e, 0xf1, - 0x94, 0x70, 0x74, 0xb7, 0x84, 0xd9, 0xb9, 0x03, 0x2d, 0x9d, 0x87, 0x9f, 0x41, 0x2c, 0x50, 0xa4, - 0x36, 0x49, 0x38, 0xbf, 0x5b, 0xb0, 0x61, 0x40, 0x11, 0x3a, 0x8b, 0x42, 0x4a, 0xd0, 0x37, 0xd0, - 0x8a, 0xb5, 0x75, 0x11, 0x92, 0x52, 0xdd, 0x06, 0x1b, 0x8f, 0x00, 0x3d, 0x1d, 0x8d, 0x08, 0xa5, - 0x2a, 0x48, 0x29, 0xc9, 0x77, 0xa6, 0xd2, 0xfb, 0x6e, 0x5d, 0x84, 0x37, 0x25, 0x9d, 0x3e, 0xc0, - 0x4f, 0x38, 0x1e, 0x13, 0xc6, 0x51, 0x4a, 0x73, 0xee, 0x1f, 0x0b, 0x1a, 0x92, 0x05, 0x75, 0xa0, - 0x3e, 0x3e, 0x0d, 0xd5, 0x2e, 0xff, 0xcc, 0x04, 0x6a, 0x66, 0x9e, 0x04, 0x24, 0x1c, 0xb3, 0x89, - 0xd0, 0x55, 0x77, 0x15, 0x85, 0x1e, 0x40, 0x63, 0x82, 0xe9, 0x84, 0xd0, 0xee, 0x8a, 0xa8, 0xe7, - 0xab, 0xc2, 0x1f, 0x09, 0xbd, 0xf3, 0x4a, 0xec, 0xbc, 0x0c, 0x59, 0x9c, 0xb8, 0x8a, 0x8d, 0x03, - 0x8d, 0x4e, 0x29, 0x8b, 0xa6, 0xdd, 0xd5, 0xbe, 0xb5, 0xdd, 0x72, 0x15, 0xd5, 0x7b, 0x0a, 0x4d, - 0x8d, 0x9d, 0x5b, 0x75, 0x42, 0x92, 0xd4, 0xaa, 0x13, 0x92, 0xf0, 0x70, 0x9f, 0xe1, 0xe0, 0x54, - 0x9a, 0xd5, 0x72, 0x25, 0xf1, 0x6d, 0xed, 0x89, 0xe5, 0xec, 0x43, 0x5b, 0x2a, 0x7c, 0xef, 0xb3, - 0x09, 0x0f, 0x25, 0xda, 0x82, 0x06, 0x13, 0x2b, 0x2a, 0xca, 0x4d, 0xcd, 0x2a, 0x57, 0x6d, 0x65, - 0xb9, 0x59, 0xd3, 0x72, 0xf8, 0x0f, 0x0b, 0x36, 0x4d, 0xac, 0xec, 0xfc, 0xbe, 0x83, 0x36, 0x33, - 0x76, 0x14, 0xf6, 0x67, 0x1a, 0x76, 0x26, 0x34, 0xc7, 0xba, 0xd4, 0x29, 0x0e, 0xe7, 0x4d, 0xc9, - 0x72, 0xe2, 0x2b, 0x58, 0x93, 0xf8, 0x32, 0xf7, 0x2a, 0x6c, 0x48, 0x79, 0x9c, 0xbf, 0x2d, 0xb8, - 0x55, 0x8e, 0x94, 0x39, 0x77, 0x04, 0x9b, 0xac, 0x94, 0x43, 0x39, 0x79, 0xbd, 0x44, 0x41, 0x06, - 0x52, 0x21, 0xba, 0x94, 0xd3, 0xef, 0x00, 0x49, 0x2d, 0xcf, 0x13, 0x8e, 0x33, 0x18, 0xf1, 0xd6, - 0x53, 0xda, 0xb9, 0xee, 0xa6, 0xe5, 0x57, 0x59, 0xc4, 0xaa, 0x22, 0x7f, 0x05, 0xfb, 0xc8, 0x1f, - 0x87, 0x98, 0x9d, 0xc6, 0xa2, 0x71, 0x8a, 0x0e, 0xa7, 0xa0, 0x24, 0xc1, 0x93, 0x72, 0x4a, 0xd8, - 0x24, 0xf2, 0x54, 0x32, 0x28, 0x0a, 0xdd, 0x00, 0x9b, 0xa6, 0xa2, 0xc2, 0xd2, 0x96, 0x9b, 0x2f, - 0x70, 0x2f, 0x7c, 0x7a, 0x8c, 0x03, 0xdf, 0xeb, 0xae, 0x48, 0xff, 0x14, 0xe9, 0xbc, 0x03, 0x3b, - 0x1b, 0x69, 0xa8, 0x0d, 0x35, 0xdf, 0x53, 0xfa, 0x6a, 0xbe, 0x00, 0xc5, 0xc1, 0x38, 0x8a, 0x7d, - 0x36, 0x99, 0x2a, 0x7d, 0xf9, 0x02, 0x37, 0x65, 0x26, 0x44, 0x95, 0x3e, 0x45, 0x39, 0x9f, 0x2c, - 0x68, 0x9b, 0x33, 0x05, 0x3d, 0x84, 0x95, 0x13, 0x3e, 0x49, 0x65, 0x0e, 0xdc, 0x14, 0x01, 0x30, - 0x59, 0x76, 0x78, 0xfb, 0x97, 0xf5, 0x27, 0x58, 0x4b, 0x4b, 0xfb, 0x06, 0xd8, 0x6c, 0x12, 0x13, - 0x3a, 0x89, 0x02, 0x4f, 0x28, 0x5d, 0x75, 0xf3, 0x85, 0x7c, 0xd2, 0xac, 0x68, 0x93, 0xa6, 0x37, - 0x04, 0x3b, 0x83, 0x2e, 0xa9, 0xd5, 0x3b, 0x7a, 0xad, 0x16, 0x87, 0xbc, 0x56, 0xbb, 0x7f, 0x5a, - 0xd0, 0x92, 0x07, 0xce, 0xcf, 0x88, 0x78, 0xe8, 0xae, 0x36, 0x31, 0xd2, 0xc4, 0x36, 0x9d, 0x52, - 0x63, 0x24, 0xaf, 0xf1, 0x5a, 0x75, 0x8d, 0xef, 0x00, 0x64, 0xe7, 0x25, 0x27, 0x75, 0x6a, 0x4d, - 0x96, 0x12, 0xae, 0xc6, 0xe1, 0xfc, 0x00, 0x1d, 0xdd, 0x1a, 0x91, 0xc6, 0xf7, 0xe7, 0xab, 0xed, - 0xb2, 0xa6, 0x49, 0xf2, 0xe5, 0xb5, 0xf6, 0x97, 0x05, 0xdd, 0x79, 0x84, 0xac, 0xca, 0x06, 0xd0, - 0x61, 0x73, 0x7b, 0xca, 0xcf, 0x2b, 0x05, 0x48, 0x21, 0x58, 0x60, 0x5f, 0xaa, 0xa6, 0xf6, 0x60, - 0xfd, 0x39, 0xa6, 0xfe, 0x28, 0xb3, 0x43, 0x03, 0xb1, 0x2a, 0x41, 0x6a, 0x26, 0xc8, 0x47, 0x68, - 0xec, 0x4d, 0x70, 0x38, 0x16, 0xa3, 0x00, 0x8b, 0xb2, 0x54, 0x27, 0xae, 0x28, 0x9e, 0x29, 0x74, - 0x14, 0xcd, 0x52, 0x49, 0x49, 0xf0, 0x8c, 0x63, 0xc9, 0x2c, 0xb5, 0x49, 0x7c, 0xf3, 0x35, 0x9e, - 0x46, 0xa2, 0x6a, 0x6c, 0x57, 0x7c, 0x73, 0xcd, 0xa3, 0x28, 0x64, 0x24, 0x64, 0x6a, 0x30, 0xa4, - 0xa4, 0xf3, 0x08, 0x40, 0x6a, 0x16, 0x01, 0xf8, 0x02, 0xd6, 0x46, 0x82, 0x4a, 0x4f, 0x43, 0x9e, - 0xbb, 0xe4, 0x70, 0xd3, 0x3d, 0x27, 0x01, 0x94, 0x0b, 0x65, 0x8e, 0x3f, 0x00, 0x90, 0x0c, 0x41, - 0x1e, 0xfa, 0x4b, 0x9a, 0xbc, 0x60, 0xd6, 0x58, 0x96, 0x0a, 0xf7, 0x33, 0xb8, 0xe8, 0x46, 0x11, - 0x13, 0x25, 0x9a, 0x5f, 0xaf, 0x2c, 0xe3, 0xf2, 0x68, 0xd4, 0x5c, 0x6d, 0xae, 0xe6, 0x9c, 0x9f, - 0x61, 0x45, 0x48, 0x7f, 0x09, 0x17, 0x63, 0x85, 0xa4, 0x8c, 0x5d, 0x57, 0x5d, 0x4e, 0x2e, 0xba, - 0xd9, 0x76, 0x69, 0x61, 0x97, 0xdf, 0x50, 0xef, 0x73, 0xf3, 0x02, 0x19, 0xcc, 0xdb, 0xfa, 0x15, - 0xa6, 0xb9, 0x6b, 0x67, 0x3d, 0x34, 0xef, 0x9d, 0x9d, 0x94, 0x39, 0x0b, 0xa2, 0xb0, 0x2a, 0xd0, - 0xa7, 0xc3, 0x7a, 0x26, 0x27, 0x18, 0xb3, 0xed, 0xa5, 0xc2, 0x37, 0x02, 0xc4, 0x91, 0xf8, 0x34, - 0xc9, 0x6a, 0x94, 0xce, 0x15, 0xb2, 0x75, 0x5e, 0x21, 0xa3, 0x9b, 0xda, 0x70, 0x37, 0x1c, 0x93, - 0x73, 0x1e, 0xc3, 0x66, 0x51, 0x89, 0x30, 0x79, 0x08, 0x28, 0x2e, 0xec, 0x28, 0x85, 0x57, 0x33, - 0x18, 0x73, 0xdb, 0x2d, 0x11, 0x11, 0x53, 0xb7, 0x5c, 0x87, 0x3e, 0x75, 0xe3, 0x52, 0x0e, 0x63, - 0xea, 0x56, 0x80, 0x54, 0x88, 0x2e, 0x15, 0xf3, 0x4d, 0xd8, 0xd8, 0x8b, 0x93, 0x19, 0x8b, 0x8e, - 0x48, 0x7c, 0xe6, 0x8f, 0xd2, 0xdf, 0x15, 0xe7, 0x1e, 0xb4, 0x8f, 0x49, 0x4c, 0xb5, 0x1f, 0xcc, - 0x2e, 0xac, 0x9d, 0xc9, 0x15, 0x61, 0xe3, 0xaa, 0x9b, 0x92, 0xbb, 0x9f, 0x9a, 0xd0, 0x38, 0x8c, - 0x18, 0x8e, 0x13, 0xf4, 0x35, 0x00, 0xbf, 0x9b, 0xfb, 0x38, 0xf0, 0x7f, 0x23, 0xa8, 0x23, 0xbc, - 0xd0, 0x2e, 0xeb, 0x3d, 0x24, 0x56, 0x8c, 0x9e, 0xe4, 0x5c, 0xe0, 0x7d, 0x56, 0x8c, 0x08, 0x3a, - 0x41, 0x20, 0x18, 0xc4, 0xaf, 0x6e, 0x05, 0xf3, 0x0e, 0xd8, 0x03, 0xcf, 0x53, 0x57, 0x58, 0xbd, - 0xf5, 0x57, 0xf0, 0x3f, 0x84, 0x96, 0xfc, 0x35, 0xfa, 0xef, 0x22, 0x43, 0x68, 0xf2, 0x80, 0x4a, - 0x1e, 0x8a, 0x8a, 0x17, 0x8c, 0xde, 0xd6, 0xa2, 0x5b, 0x51, 0x0e, 0xb4, 0x0f, 0x97, 0x86, 0x84, - 0xe9, 0xd7, 0x1a, 0xa4, 0x5f, 0x93, 0xf5, 0x9b, 0x4e, 0xaf, 0xec, 0xa2, 0xa5, 0x41, 0x1d, 0x42, - 0x6f, 0x48, 0xd8, 0x20, 0x08, 0x24, 0xc7, 0x1b, 0xc2, 0xb0, 0x87, 0x19, 0x56, 0xa8, 0x97, 0x34, - 0x61, 0xbe, 0xd0, 0xbb, 0x59, 0x3e, 0x56, 0x72, 0xbc, 0xc7, 0xb0, 0x3e, 0x24, 0x6c, 0x2f, 0x6f, - 0x78, 0x7a, 0xe4, 0xaf, 0xce, 0x77, 0xc6, 0x5c, 0xee, 0x7b, 0xb0, 0xc5, 0x0a, 0x6f, 0x12, 0x86, - 0xcc, 0xd6, 0xa2, 0x94, 0xcd, 0xe5, 0x9f, 0x02, 0x1a, 0x12, 0x66, 0xce, 0x75, 0x13, 0xe8, 0x8a, - 0xd9, 0x53, 0x72, 0xd1, 0x67, 0xb0, 0x6e, 0xbc, 0x08, 0xa0, 0x6b, 0x82, 0xb3, 0xec, 0x39, 0xa4, - 0xe2, 0x60, 0x8f, 0xa1, 0x5b, 0xf5, 0x84, 0x81, 0xee, 0x14, 0xc1, 0x8a, 0x2f, 0x1c, 0x15, 0xb8, - 0x3f, 0x02, 0x2a, 0xbe, 0x55, 0xa0, 0x5b, 0x45, 0x44, 0xfd, 0x57, 0xba, 0x02, 0xeb, 0x97, 0xe2, - 0xa3, 0x80, 0xfe, 0x60, 0x81, 0xb6, 0x65, 0x78, 0xce, 0x7f, 0xd3, 0xa8, 0xc0, 0x3f, 0x84, 0x8d, - 0xb2, 0x77, 0x0a, 0xd4, 0x2f, 0xc5, 0xd5, 0x9e, 0x30, 0x2a, 0xf0, 0xde, 0xc2, 0x95, 0xd2, 0x47, - 0x0c, 0xf4, 0x79, 0x29, 0xe0, 0x72, 0x16, 0x8a, 0x13, 0xea, 0x57, 0x7a, 0x7e, 0x2e, 0x5e, 0xd9, - 0x8b, 0x86, 0xc2, 0x5b, 0xf0, 0xd8, 0x51, 0x81, 0xf7, 0x14, 0xd6, 0xde, 0xfb, 0x2c, 0xe4, 0x8d, - 0xb5, 0xa4, 0x35, 0x5c, 0x2b, 0xfe, 0x8e, 0xe4, 0xa2, 0x4f, 0xc0, 0xce, 0x5e, 0x4a, 0x50, 0x9a, - 0xe8, 0xe6, 0xcb, 0x49, 0x85, 0xd2, 0x27, 0xb0, 0x6e, 0x34, 0x6a, 0xa3, 0x64, 0xa4, 0xce, 0xd2, - 0x46, 0xce, 0x2b, 0xfd, 0xf2, 0x11, 0x61, 0xaf, 0xc9, 0x18, 0x8f, 0x12, 0xd5, 0xd3, 0x29, 0x92, - 0xd7, 0x6b, 0xb3, 0xc5, 0xf7, 0x34, 0x48, 0xe7, 0xc2, 0x87, 0x86, 0x78, 0x7e, 0x7c, 0xf4, 0x6f, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xd7, 0x83, 0x48, 0x86, 0x8b, 0x14, 0x00, 0x00, + // 1891 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0x4b, 0x6f, 0x1b, 0xc9, + 0x11, 0xde, 0x21, 0x25, 0xca, 0x2c, 0x52, 0x12, 0xd5, 0x2b, 0x51, 0x34, 0x2d, 0xdb, 0xf4, 0x48, + 0x9b, 0xd5, 0xee, 0x62, 0x29, 0x58, 0xce, 0xc3, 0x4e, 0x0e, 0x31, 0xf5, 0x00, 0x2d, 0xcb, 0x16, + 0xe4, 0x91, 0x61, 0x1f, 0x02, 0x04, 0x19, 0x73, 0x3a, 0xe4, 0x40, 0xc3, 0x19, 0x66, 0xa6, 0x25, + 0x78, 0x72, 0xcb, 0x31, 0x40, 0x2e, 0x39, 0xe6, 0x0f, 0x04, 0xc8, 0xcf, 0xc8, 0x35, 0xe7, 0xfc, + 0xa0, 0xa0, 0x1f, 0xd3, 0xd3, 0x3d, 0x0f, 0xca, 0x21, 0xb0, 0x37, 0x76, 0x4f, 0xd5, 0x57, 0xd5, + 0xd5, 0xf5, 0xea, 0x22, 0xd4, 0xed, 0x99, 0xdb, 0x9f, 0x85, 0x01, 0x09, 0x50, 0xd5, 0x9e, 0xb9, + 0xdd, 0x07, 0xe3, 0x20, 0x18, 0x7b, 0xf8, 0x80, 0x6d, 0x7d, 0xba, 0xf9, 0xe3, 0xc1, 0xe9, 0x74, + 0x46, 0x62, 0x4e, 0x61, 0x7e, 0x86, 0xcd, 0x81, 0xe3, 0x9c, 0x60, 0x0f, 0x8f, 0x6d, 0xe2, 0x06, + 0xfe, 0x5b, 0x1c, 0x45, 0xf6, 0x18, 0x23, 0x04, 0x4b, 0xbe, 0x3d, 0xc5, 0x1d, 0xa3, 0x67, 0xec, + 0xd7, 0x2d, 0xf6, 0x1b, 0xfd, 0x12, 0xd6, 0x1c, 0x49, 0x78, 0x8e, 0xe3, 0xa8, 0x53, 0xe9, 0x55, + 0xf7, 0x1b, 0x87, 0x6b, 0x7d, 0x2a, 0xf1, 0xf2, 0xe6, 0x93, 0xe7, 0x8e, 0xce, 0x71, 0x6c, 0x65, + 0xa8, 0xd0, 0x26, 0x2c, 0xcf, 0x6c, 0x32, 0x89, 0x3a, 0xd5, 0x5e, 0x75, 0xbf, 0x6e, 0xf1, 0x85, + 0x39, 0x85, 0xc7, 0x9a, 0x64, 0x2b, 0xf0, 0xf0, 0xc0, 0x77, 0x28, 0xc7, 0x4f, 0xa0, 0x84, 0x79, + 0x0a, 0xf7, 0x35, 0x71, 0x97, 0x54, 0x89, 0x79, 0x82, 0xa4, 0xd6, 0x15, 0x55, 0xeb, 0x31, 0xec, + 0x5a, 0x78, 0x1a, 0xdc, 0xe2, 0x13, 0x0d, 0x7e, 0xe0, 0x3b, 0x77, 0x02, 0xb6, 0xa1, 0x76, 0x8d, + 0xe3, 0xb3, 0x93, 0x04, 0x51, 0xac, 0x4a, 0xcc, 0xf3, 0x14, 0x1e, 0x64, 0x05, 0x51, 0x0b, 0xcd, + 0x11, 0x60, 0xbe, 0x82, 0x9d, 0x2c, 0xcb, 0x82, 0xa7, 0x3c, 0xcb, 0x0b, 0xbf, 0xeb, 0x5e, 0x4a, + 0x4e, 0x67, 0x7e, 0x03, 0xeb, 0x54, 0xef, 0x0b, 0x7b, 0xaa, 0xea, 0x1e, 0x06, 0x9e, 0x64, 0xa7, + 0xbf, 0x4d, 0x0f, 0x5a, 0x56, 0x40, 0x6c, 0x82, 0xcf, 0x71, 0x3c, 0x87, 0x0e, 0x7d, 0x0f, 0xad, + 0x08, 0x87, 0xb7, 0x38, 0x7c, 0x6b, 0xfb, 0xf6, 0x18, 0x47, 0xe7, 0x38, 0xee, 0x54, 0x7a, 0xc6, + 0xfe, 0x3d, 0x2b, 0xb7, 0x8f, 0x3a, 0xb0, 0x72, 0x8d, 0xe3, 0x37, 0x6e, 0x44, 0x84, 0x69, 0x93, + 0xa5, 0x39, 0x83, 0xc6, 0x99, 0xef, 0x92, 0x44, 0xd0, 0x23, 0x80, 0x30, 0x08, 0xc8, 0x39, 0xd7, + 0xdf, 0x60, 0xb4, 0xca, 0x0e, 0x1a, 0x00, 0x52, 0xc1, 0x1d, 0x7a, 0xa0, 0x88, 0x89, 0x6d, 0x1c, + 0x6e, 0x30, 0xbf, 0x4b, 0x8e, 0x48, 0xd1, 0xad, 0x02, 0x62, 0x73, 0x0f, 0x9a, 0x2a, 0x0d, 0xb5, + 0x7b, 0xc8, 0x50, 0xb8, 0x34, 0xbe, 0x30, 0xff, 0x62, 0xc0, 0xa6, 0x06, 0x85, 0xa3, 0x59, 0xe0, + 0x47, 0x18, 0xfd, 0x02, 0x9a, 0xa1, 0xb2, 0xcf, 0x4c, 0x52, 0x28, 0x5b, 0x23, 0xa3, 0x16, 0x88, + 0x6e, 0x46, 0x23, 0x1c, 0x45, 0xc2, 0x48, 0xc9, 0x92, 0x7e, 0x99, 0xf2, 0xd3, 0x77, 0xaa, 0xcc, + 0xbc, 0xc9, 0xd2, 0xec, 0x01, 0xbc, 0xb7, 0xc3, 0x31, 0x26, 0x14, 0xa5, 0xd0, 0xcf, 0xfe, 0x63, + 0x40, 0x8d, 0x93, 0xa0, 0x16, 0x54, 0xc7, 0x37, 0xbe, 0xf8, 0x4a, 0x7f, 0x4a, 0x86, 0x8a, 0xee, + 0x1b, 0x1e, 0xf6, 0xc7, 0x64, 0xc2, 0x64, 0x55, 0x2d, 0xb1, 0x42, 0x07, 0x50, 0x9b, 0xd8, 0xd1, + 0x04, 0x47, 0x9d, 0x25, 0x16, 0xc3, 0xdb, 0xec, 0x3c, 0x1c, 0xba, 0xff, 0x8a, 0x7d, 0x39, 0xf5, + 0x49, 0x18, 0x5b, 0x82, 0x8c, 0x02, 0x8d, 0x6e, 0x22, 0x12, 0x4c, 0x3b, 0xcb, 0x3d, 0x63, 0xbf, + 0x69, 0x89, 0x55, 0xf7, 0x05, 0x34, 0x14, 0x72, 0xaa, 0xd5, 0x35, 0x8e, 0x13, 0xad, 0xae, 0x71, + 0x4c, 0xcd, 0x7d, 0x6b, 0x7b, 0x37, 0x5c, 0xad, 0xa6, 0xc5, 0x17, 0xbf, 0xae, 0x3c, 0x37, 0xcc, + 0x33, 0x58, 0xe3, 0x02, 0x3f, 0xba, 0x64, 0x42, 0x4d, 0x89, 0x76, 0xa1, 0x46, 0xd8, 0x8e, 0xb0, + 0x72, 0x43, 0xd1, 0xca, 0x12, 0x9f, 0xa4, 0x6f, 0x56, 0x14, 0x1f, 0xfe, 0xab, 0x01, 0x6d, 0x1d, + 0x4b, 0xde, 0xdf, 0x6f, 0x60, 0x8d, 0x68, 0x5f, 0x04, 0xf6, 0xd7, 0x0a, 0xb6, 0x64, 0xca, 0x90, + 0x2e, 0x74, 0x8b, 0xc3, 0xac, 0x2a, 0xd2, 0x27, 0x7e, 0x84, 0x15, 0x8e, 0xcf, 0x7d, 0xaf, 0x44, + 0x87, 0x84, 0xc6, 0xfc, 0x97, 0x01, 0x8f, 0x8a, 0x91, 0xe4, 0xe1, 0xae, 0xa0, 0x4d, 0x0a, 0x29, + 0xc4, 0x21, 0x1f, 0x14, 0x08, 0x90, 0x20, 0x25, 0xac, 0x0b, 0x1d, 0xfa, 0x1d, 0x20, 0x2e, 0xe5, + 0x28, 0xa6, 0x38, 0x83, 0x11, 0x4d, 0x5c, 0x85, 0xd9, 0xea, 0xdb, 0x24, 0xfc, 0x4a, 0x83, 0x58, + 0x44, 0xe4, 0x9f, 0xa0, 0x7e, 0xe5, 0x8e, 0x7d, 0x9b, 0xdc, 0x84, 0x2c, 0x59, 0xb2, 0xac, 0x26, + 0xa0, 0xf8, 0x82, 0x3a, 0xe5, 0x14, 0x93, 0x49, 0xe0, 0x08, 0x67, 0x10, 0x2b, 0xb4, 0x03, 0xf5, + 0x28, 0x61, 0x65, 0x9a, 0x36, 0xad, 0x74, 0x83, 0x9e, 0xc2, 0x8d, 0x3e, 0xd8, 0x9e, 0xeb, 0x74, + 0x96, 0xf8, 0xf9, 0xc4, 0xd2, 0x7c, 0x07, 0x75, 0x59, 0xc6, 0xd0, 0x1a, 0x54, 0x5c, 0x47, 0xc8, + 0xab, 0xb8, 0x0c, 0xd4, 0xf6, 0xc6, 0x41, 0xe8, 0x92, 0xc9, 0x54, 0xc8, 0x4b, 0x37, 0xa8, 0x2a, + 0x33, 0xc6, 0x2a, 0xe4, 0x89, 0x95, 0x19, 0xc0, 0x46, 0x5a, 0x19, 0x93, 0x6b, 0xfb, 0x19, 0x23, + 0x4e, 0x02, 0x25, 0x5f, 0x41, 0xc5, 0xd7, 0x85, 0x6e, 0xe2, 0xbf, 0x06, 0xac, 0xe9, 0x85, 0x0b, + 0x3d, 0x85, 0xa5, 0x6b, 0x5a, 0xae, 0xb9, 0xd3, 0x3d, 0x64, 0xc2, 0x74, 0x92, 0x3e, 0xad, 0x31, + 0x3c, 0xe0, 0x19, 0x69, 0x61, 0x2e, 0xd9, 0x81, 0x3a, 0x99, 0x84, 0x38, 0x9a, 0x04, 0x9e, 0xc3, + 0xa4, 0x2e, 0x5b, 0xe9, 0x46, 0x5a, 0xce, 0x96, 0x94, 0x72, 0xd6, 0x1d, 0x42, 0x5d, 0x42, 0x17, + 0x24, 0x87, 0x3d, 0x35, 0x39, 0xe4, 0xed, 0xa0, 0x24, 0x8b, 0xbf, 0x19, 0xd0, 0xe4, 0x1e, 0x46, + 0x9d, 0x02, 0x3b, 0xe8, 0x5b, 0xa5, 0x44, 0x25, 0x91, 0xa4, 0x1f, 0x4a, 0xd4, 0xad, 0x34, 0xa9, + 0x54, 0xca, 0x93, 0x4a, 0x1f, 0x40, 0x3a, 0x08, 0x6f, 0x07, 0x12, 0x6d, 0xa4, 0x0f, 0x5a, 0x0a, + 0x85, 0xf9, 0x5b, 0x68, 0xa9, 0xda, 0xb0, 0xb8, 0xf9, 0x21, 0x1b, 0xde, 0x1b, 0x8a, 0x24, 0x4e, + 0x97, 0x06, 0xf7, 0xdf, 0x0d, 0xe8, 0x64, 0x11, 0xa4, 0x7f, 0x0c, 0xa0, 0x45, 0x32, 0xdf, 0xc4, + 0x39, 0xb7, 0x72, 0x90, 0x8c, 0x31, 0x47, 0xbe, 0x90, 0xeb, 0x1c, 0xc3, 0xea, 0x91, 0x1d, 0xb9, + 0x23, 0xa9, 0x87, 0x02, 0x62, 0x94, 0x82, 0x54, 0x74, 0x90, 0xcf, 0x50, 0x3b, 0x9e, 0xd8, 0xfe, + 0x98, 0xd5, 0x1e, 0x9b, 0xe5, 0x01, 0x71, 0xe3, 0x62, 0x45, 0x3d, 0x25, 0x1a, 0x05, 0xb3, 0x84, + 0x93, 0x2f, 0xa8, 0xc7, 0x91, 0x78, 0x96, 0xe8, 0xc4, 0x7e, 0xd3, 0x3d, 0xea, 0x46, 0x2c, 0x4c, + 0xeb, 0x16, 0xfb, 0x4d, 0x25, 0x8f, 0x02, 0x9f, 0x60, 0x9f, 0x88, 0x4a, 0x94, 0x2c, 0xcd, 0x67, + 0x00, 0x5c, 0x32, 0x33, 0xc0, 0x37, 0xb0, 0x32, 0x62, 0xab, 0xe4, 0x36, 0xf8, 0xbd, 0x73, 0x0a, + 0x2b, 0xf9, 0x66, 0xc6, 0x80, 0x52, 0x26, 0x79, 0xf0, 0x03, 0x00, 0x4e, 0xe0, 0xa5, 0xa6, 0x5f, + 0x57, 0xf8, 0x19, 0xb1, 0x42, 0xb2, 0x90, 0xb9, 0x5f, 0xc2, 0x3d, 0x2b, 0x08, 0x08, 0x0b, 0xd1, + 0xb4, 0x87, 0x33, 0xb4, 0x0e, 0x55, 0x8b, 0xb9, 0x4a, 0x26, 0xe6, 0xcc, 0xdf, 0xc1, 0x12, 0xe3, + 0xfe, 0x0e, 0xee, 0x85, 0x02, 0x49, 0x28, 0xbb, 0x2a, 0xd2, 0x2a, 0xdf, 0xb4, 0xe4, 0xe7, 0xc2, + 0xc0, 0x2e, 0x6e, 0x83, 0x7f, 0xa0, 0xea, 0x79, 0xdc, 0x98, 0x8f, 0xd5, 0x9e, 0xa9, 0x71, 0x58, + 0x97, 0x49, 0x3b, 0x4d, 0xd6, 0xad, 0x84, 0x58, 0x1a, 0x91, 0x69, 0xe5, 0xa9, 0xe5, 0x68, 0x55, + 0xf2, 0x31, 0x42, 0xf9, 0x79, 0x21, 0xf3, 0x8d, 0x00, 0x51, 0x24, 0x5a, 0xbe, 0x64, 0x8c, 0x46, + 0x99, 0x40, 0x36, 0xee, 0x0a, 0x64, 0xf4, 0x50, 0xe9, 0x26, 0xb4, 0x83, 0xf1, 0xc6, 0xc2, 0x86, + 0x76, 0x5e, 0x08, 0x53, 0x79, 0x08, 0x28, 0xcc, 0x7d, 0x11, 0x02, 0xb7, 0x25, 0x8c, 0xfe, 0xd9, + 0x2a, 0x60, 0x61, 0x65, 0xbe, 0x58, 0x86, 0x5a, 0xe6, 0xc3, 0x42, 0x0a, 0xad, 0xcc, 0x97, 0x80, + 0x94, 0xb0, 0x2e, 0x64, 0xf3, 0x36, 0x6c, 0x1e, 0x87, 0xf1, 0x8c, 0x04, 0x57, 0x38, 0xbc, 0x75, + 0x47, 0xc9, 0xbb, 0xc2, 0x9c, 0x40, 0x57, 0xdb, 0x3f, 0x0e, 0xb1, 0x4d, 0xe4, 0xab, 0xa3, 0xcb, + 0x1d, 0xe1, 0x22, 0x6d, 0x05, 0xe4, 0x3a, 0x69, 0x63, 0x2b, 0x69, 0x1b, 0xab, 0xd5, 0xd9, 0x6a, + 0xa6, 0xce, 0x9a, 0x17, 0x50, 0x63, 0x59, 0x2e, 0xfc, 0xe2, 0x22, 0xaa, 0x35, 0x03, 0xa2, 0x6e, + 0xcb, 0x0d, 0xf3, 0xdf, 0x06, 0xc0, 0x65, 0xe8, 0xde, 0xf2, 0xf7, 0xcf, 0xe2, 0xa0, 0xd9, 0x0e, + 0x63, 0x16, 0xba, 0xb7, 0x14, 0x86, 0x77, 0x03, 0xc9, 0x12, 0x1d, 0x40, 0x73, 0xc4, 0x0d, 0xc5, + 0x0e, 0xc1, 0x32, 0x5b, 0x92, 0x9a, 0xf8, 0x96, 0xa5, 0x11, 0x20, 0x13, 0x9a, 0x91, 0x3b, 0x1e, + 0x48, 0x83, 0x2c, 0xb3, 0x03, 0x68, 0x7b, 0xe6, 0x34, 0x63, 0xfd, 0x81, 0xe3, 0x28, 0x6f, 0xb9, + 0xff, 0xcf, 0xfa, 0x4f, 0x78, 0x8d, 0xae, 0x2a, 0x29, 0x2f, 0x35, 0x0f, 0x2b, 0xda, 0xe6, 0x3f, + 0x0c, 0x40, 0xca, 0x5e, 0xe2, 0xa4, 0x45, 0x6f, 0xc6, 0x3c, 0xfe, 0x77, 0xba, 0x69, 0x0a, 0x64, + 0x48, 0x5b, 0x29, 0x0e, 0xba, 0x54, 0xea, 0xa0, 0xcb, 0xba, 0x83, 0xee, 0x41, 0x93, 0xbd, 0x1c, + 0x93, 0xc3, 0x17, 0xf6, 0x8d, 0xe6, 0x1f, 0x00, 0xf1, 0xf7, 0xa5, 0x16, 0x65, 0x65, 0x39, 0x78, + 0xc1, 0x2e, 0x6c, 0x87, 0xde, 0xa0, 0xeb, 0x8f, 0xb9, 0xa4, 0xf7, 0x01, 0x7b, 0x8d, 0x4a, 0x61, + 0xa7, 0x9a, 0xb0, 0xc6, 0xe1, 0x8f, 0xd2, 0x05, 0xca, 0x58, 0xfa, 0x7c, 0x57, 0x3c, 0xcb, 0x16, + 0xd7, 0x8d, 0x3e, 0xd9, 0x14, 0xa8, 0xbb, 0x9e, 0x6c, 0x75, 0xb5, 0x0b, 0xfb, 0x1e, 0xd6, 0x3e, + 0xe0, 0x30, 0x52, 0xa6, 0x55, 0x1d, 0x58, 0xb9, 0xe5, 0x3b, 0x0c, 0x61, 0xd9, 0x4a, 0x96, 0x87, + 0xff, 0x6c, 0x41, 0xed, 0x22, 0x20, 0x76, 0x18, 0xa3, 0x9f, 0x03, 0xd0, 0x47, 0xbf, 0x6b, 0x7b, + 0xee, 0x9f, 0x31, 0x6a, 0xb1, 0xa3, 0x2a, 0x53, 0x80, 0x2e, 0x62, 0x3b, 0x5a, 0xef, 0x61, 0x7e, + 0x85, 0x7e, 0x05, 0x2b, 0x2c, 0xf0, 0xa2, 0x09, 0x6a, 0xf7, 0xf9, 0x24, 0xad, 0x9f, 0x4c, 0xd2, + 0xfa, 0x6c, 0x92, 0x56, 0xc2, 0xd8, 0x87, 0xfa, 0xc0, 0x71, 0xc4, 0x3b, 0x59, 0x6d, 0xf7, 0x4a, + 0xe8, 0x9f, 0x42, 0x93, 0xcf, 0x5c, 0xbe, 0x9c, 0x65, 0x08, 0x0d, 0xea, 0x3b, 0x9c, 0x26, 0x42, + 0xf9, 0x57, 0x4c, 0x77, 0x77, 0xde, 0xd3, 0x2b, 0x05, 0x3a, 0x83, 0xf5, 0x21, 0x26, 0xea, 0xdb, + 0x09, 0xa9, 0x6f, 0x71, 0xf5, 0x39, 0xd5, 0x2d, 0x7a, 0xcd, 0x29, 0x50, 0x17, 0xd0, 0x1d, 0x62, + 0x32, 0xf0, 0x3c, 0x4e, 0xf1, 0x16, 0x13, 0xdb, 0xb1, 0x89, 0x2d, 0x50, 0xd7, 0x15, 0x66, 0xba, + 0xd1, 0x7d, 0x58, 0xdc, 0x4a, 0xa6, 0x78, 0x47, 0xb0, 0x3a, 0xc4, 0xe4, 0x38, 0x6d, 0x72, 0xca, + 0x6e, 0x61, 0x3b, 0xdb, 0x19, 0xa5, 0x18, 0xaf, 0xa1, 0xce, 0x76, 0xa8, 0x23, 0x97, 0xf2, 0xef, + 0xce, 0x2b, 0x5f, 0x29, 0xd6, 0x29, 0xa0, 0x21, 0x26, 0x7a, 0x8f, 0x5f, 0x0e, 0xba, 0xa5, 0xf7, + 0x1a, 0x29, 0xcc, 0x4b, 0x58, 0xd5, 0xc6, 0x91, 0xe8, 0x3e, 0xa3, 0x2c, 0x9a, 0xc5, 0x96, 0x5c, + 0xfe, 0x07, 0xe8, 0x94, 0xcd, 0x4f, 0xd1, 0x5e, 0x1e, 0x2c, 0x3f, 0x5e, 0x2d, 0xc1, 0x7d, 0x0d, + 0x28, 0x3f, 0x28, 0x45, 0x8f, 0xf2, 0x88, 0xea, 0x6c, 0xb1, 0x04, 0xeb, 0xf7, 0xf9, 0x89, 0xa4, + 0x3a, 0x2d, 0x45, 0xfb, 0xdc, 0x3c, 0x77, 0x0f, 0x54, 0x4b, 0xf0, 0x2f, 0x60, 0xb3, 0x68, 0x48, + 0x8a, 0x7a, 0x85, 0xb8, 0xca, 0xfc, 0xb4, 0x04, 0xef, 0x12, 0xb6, 0x0a, 0x27, 0xa8, 0xe8, 0x49, + 0x21, 0xe0, 0x62, 0x1a, 0xb2, 0x1b, 0xea, 0x95, 0x9e, 0x7c, 0x3e, 0xde, 0x11, 0x6c, 0x1e, 0x7b, + 0xd8, 0x0e, 0xb3, 0x0a, 0x6e, 0x6a, 0xb1, 0x3f, 0x1f, 0xe3, 0x05, 0xac, 0x7c, 0x74, 0x89, 0x4f, + 0xf3, 0x73, 0x41, 0xca, 0xb8, 0x9f, 0x9f, 0x85, 0xa4, 0xac, 0xcf, 0xa1, 0x2e, 0xc7, 0xb4, 0x28, + 0x71, 0x6e, 0x7d, 0x6c, 0x5b, 0x22, 0xf4, 0x04, 0x56, 0xb5, 0xf6, 0xa0, 0x34, 0x64, 0xb8, 0xfc, + 0xc2, 0x06, 0x8f, 0x5e, 0xd0, 0xd7, 0x05, 0x2d, 0x1e, 0x7a, 0x9c, 0xe7, 0xd1, 0x9a, 0xbf, 0x6e, + 0x3b, 0xd3, 0x41, 0xa5, 0x7a, 0xbd, 0xc9, 0x20, 0xf2, 0xb6, 0xa5, 0x08, 0x51, 0x6b, 0x68, 0x4a, + 0xaf, 0x47, 0x47, 0x1b, 0x62, 0x42, 0xd1, 0xb8, 0x99, 0xd5, 0x9e, 0x60, 0x8e, 0x46, 0xaf, 0x33, + 0x8d, 0xd4, 0x10, 0x13, 0xa5, 0x37, 0x2c, 0x80, 0xda, 0xce, 0x36, 0x2f, 0x29, 0xd6, 0x00, 0xda, + 0x1a, 0x16, 0x77, 0xb8, 0x12, 0x9c, 0xe2, 0x23, 0xbd, 0x82, 0x2d, 0x0d, 0x82, 0x7a, 0x04, 0xff, + 0x5b, 0xa7, 0xd0, 0xe5, 0xb6, 0x53, 0xdc, 0x6c, 0xea, 0xfc, 0x08, 0x9d, 0x1c, 0xd2, 0xc0, 0xf3, + 0x18, 0x58, 0x99, 0x37, 0x3c, 0xb9, 0xb3, 0x23, 0x61, 0x56, 0xdf, 0xb8, 0xc2, 0xe4, 0x0d, 0x1e, + 0xdb, 0xa3, 0x58, 0x74, 0x06, 0x11, 0xe2, 0xc3, 0x18, 0xbd, 0x51, 0xe8, 0x96, 0x88, 0x31, 0xbf, + 0xfa, 0x54, 0x63, 0x3b, 0xcf, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0x71, 0xa2, 0xcd, 0x3c, 0x3e, + 0x1b, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index a659613ac..bacb5ab58 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -292,6 +292,14 @@ message CryptoServiceAddKeyMessage { PrivateKey key = 3; } +message PrivateKeyResponse { + string role = 1; + string gun = 2; + PrivateKey privkey = 3; + bool success = 4; + string message = 5; +} + message KeyIDMessage { string keyID = 1; } From adca046de1885530eb58681fe6b0ed5d2e040ba3 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 13 Mar 2017 16:03:28 +0100 Subject: [PATCH 27/62] Add client api prototypes to server interface Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/client.go | 24 +++++++---- client_api/api/server.go | 91 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 7 deletions(-) diff --git a/client_api/api/client.go b/client_api/api/client.go index ec1e6f1dd..48a92b0f9 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -2,6 +2,7 @@ package api import ( "google.golang.org/grpc" + google_protobuf "github.com/golang/protobuf/ptypes/empty" "github.com/docker/notary/client" "github.com/docker/notary/client/changelist" @@ -38,7 +39,7 @@ func (c *Client) Initialize(rootKeyIDs []string, serverManagedRoles ...data.Role } func (c *Client) Publish() error { - _, err := c.client.Publish(context.Background(), &Empty{}) + _, err := c.client.Publish(context.Background(), &google_protobuf.Empty{}) return err } @@ -196,7 +197,7 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS } func (c *Client) GetChangelist() (changelist.Changelist, error) { - changes, err := c.client.GetChangelist(context.Background(), &Empty{}) + changes, err := c.client.GetChangelist(context.Background(), &google_protobuf.Empty{}) if err != nil { return nil, err } @@ -214,7 +215,7 @@ func (c *Client) GetChangelist() (changelist.Changelist, error) { } func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { - roleWithSigsListResp, err := c.client.ListRoles(context.Background(), &Empty{}) + roleWithSigsListResp, err := c.client.ListRoles(context.Background(), &google_protobuf.Empty{}) if err != nil { return nil, err } @@ -257,7 +258,7 @@ func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { } func (c *Client) GetDelegationRoles() ([]data.Role, error) { - roleListResp, err := c.client.GetDelegationRoles(context.Background(), &Empty{}) + roleListResp, err := c.client.GetDelegationRoles(context.Background(), &google_protobuf.Empty{}) if err != nil { return nil, err } @@ -325,7 +326,7 @@ func (c *Client) AddDelegationPaths(name data.RoleName, paths []string) error { } _, err := c.client.AddDelegationPaths(context.Background(), addDelegationPathsMessage) - return ErrNotImplemented + return err } func (c *Client) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error { @@ -475,6 +476,15 @@ func (cs *CryptoService) ListKeys(role data.RoleName) []string { // ListAllKeys returns a map of all available signing key IDs to role, or // an empty map or nil if there are no keys. func (cs *CryptoService) ListAllKeys() map[string]data.RoleName { - keys := cs.ListAllKeys() - return keys + keyIDsToRoles, err := cs.client.CryptoServiceListAllKeys(context.Background(), &google_protobuf.Empty{}) + if err != nil { + return nil + } + + res := make(map[string]data.RoleName, len(keyIDsToRoles.KeyIDs)) + for key, role := range keyIDsToRoles.KeyIDs { + res[key] = data.RoleName(role) + } + + return res } diff --git a/client_api/api/server.go b/client_api/api/server.go index 0e6942a7d..0fc61e16b 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -6,6 +6,7 @@ import ( "github.com/Sirupsen/logrus" "golang.org/x/net/context" "google.golang.org/grpc" + google_protobuf "github.com/golang/protobuf/ptypes/empty" "github.com/docker/notary" "github.com/docker/notary/client" @@ -34,6 +35,14 @@ type Server struct { upstreamCAPath string } +func (srv *Server) Initialize(ctx context.Context, initMessage *InitMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) Publish(ctx context.Context, empty *google_protobuf.Empty) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + func (srv *Server) AddTarget(ctx context.Context, t *Target) (*BasicResponse, error) { r, err := srv.initRepo(data.GUN(t.GetGun())) if err != nil { @@ -76,6 +85,88 @@ func (srv *Server) RemoveTarget(ctx context.Context, t *Target) (*BasicResponse, }, nil } +func (srv *Server) ListTargets(context.Context, *RoleNameList) (*TargetWithRoleNameListResponse, error) { + return nil, ErrNotImplemented +} + +// GetTargetByName returns a target by the given name. +func (srv *Server) GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRoleResponse, error) { + return nil, ErrNotImplemented +} + +// GetAllTargetMetadataByName +func (srv *Server) GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedListResponse, error) { + return nil, ErrNotImplemented +} + +// GetChangelist returns the list of the repository's unpublished changes +func (srv *Server) GetChangelist(context.Context, *google_protobuf.Empty) (*ChangeListResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) ListRoles(context.Context, *google_protobuf.Empty) (*RoleWithSignaturesListResponse, error) { + return nil, ErrNotImplemented +} + + +func (srv *Server) GetDelegationRoles(context.Context, *google_protobuf.Empty) (*RoleListResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) AddDelegation(context.Context, *AddDelegationMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) AddDelegationRoleAndKeys(context.Context, *AddDelegationRoleAndKeysMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) AddDelegationPaths(context.Context, *AddDelegationPathsMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) RemoveDelegationKeysAndPaths(context.Context, *RemoveDelegationKeysAndPathsMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) RemoveDelegationRole(context.Context, *RemoveDelegationRoleMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) RemoveDelegationPaths(context.Context, *RemoveDelegationPathsMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) RemoveDelegationKeys(context.Context, *RemoveDelegationKeysMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) ClearDelegationPaths(context.Context, *RoleNameMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + + +func (srv *Server) Witness(context.Context, *RoleNameList) (*RoleNameListResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) RotateKey(context.Context, *RotateKeyMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + + +// CryptoService implementation +func (srv *Server) CryptoService(context.Context, *google_protobuf.Empty) (*CryptoServiceMessage, error) +func (srv *Server) CryptoServiceCreate(context.Context, *CryptoServiceCreateMessage) (*PublicKeyResponse, error) +func (srv *Server) CryptoServiceAddKey(context.Context, *CryptoServiceAddKeyMessage) (*BasicResponse, error) +func (srv *Server) CryptoServiceGetKey(context.Context, *KeyIDMessage) (*PublicKeyResponse, error) +func (srv *Server) CryptoServiceGetPrivateKey(context.Context, *KeyIDMessage) (*PrivateKeyResponse, error) +func (srv *Server) CryptoServiceRemoveKey(context.Context, *KeyIDMessage) (*BasicResponse, error) +func (srv *Server) CryptoServiceListKeys(context.Context, *RoleNameMessage) (*KeyIDsListResponse, error) +func (srv *Server) CryptoServiceListAllKeys(context.Context, *google_protobuf.Empty) (*SigningKeyIDsToRolesResponse, error) + +SetLegacyVersions(context.Context, *VersionMessage) (*google_protobuf.Empty, error) + func publishRepo(r *client.NotaryRepository) error { if err := r.Publish(); err != nil { if _, ok := err.(client.ErrRepoNotInitialized); !ok { From c63fb30ad616fb12d471dd373ccb07654676edf0 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 14 Mar 2017 15:09:18 +0100 Subject: [PATCH 28/62] Fix cherry-pick conflicts Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 575 ++++++++++++++++++++++------------ client_api/api/api.proto | 39 ++- client_api/api/client.go | 79 +++-- client_api/api/server.go | 52 ++- cmd/clientapi/setup/config.go | 2 +- 5 files changed, 475 insertions(+), 272 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index 2c9ce19bd..7bb0c1cec 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -9,6 +9,7 @@ It is generated from these files: api.proto It has these top-level messages: + GunMessage AddDelegationMessage AddDelegationRoleAndKeysMessage AddDelegationPathsMessage @@ -20,6 +21,7 @@ It has these top-level messages: RotateKeyMessage InitMessage RoleNameList + RoleNameListMessage RoleNameListResponse TargetName Target @@ -80,16 +82,33 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +type GunMessage struct { + Gun string `protobuf:"bytes,1,opt,name=gun" json:"gun,omitempty"` +} + +func (m *GunMessage) Reset() { *m = GunMessage{} } +func (m *GunMessage) String() string { return proto.CompactTextString(m) } +func (*GunMessage) ProtoMessage() {} +func (*GunMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *GunMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type AddDelegationMessage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` DelegationKeys []*PublicKey `protobuf:"bytes,2,rep,name=delegationKeys" json:"delegationKeys,omitempty"` Paths []string `protobuf:"bytes,3,rep,name=paths" json:"paths,omitempty"` + Gun string `protobuf:"bytes,4,opt,name=gun" json:"gun,omitempty"` } func (m *AddDelegationMessage) Reset() { *m = AddDelegationMessage{} } func (m *AddDelegationMessage) String() string { return proto.CompactTextString(m) } func (*AddDelegationMessage) ProtoMessage() {} -func (*AddDelegationMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*AddDelegationMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (m *AddDelegationMessage) GetName() string { if m != nil { @@ -112,15 +131,23 @@ func (m *AddDelegationMessage) GetPaths() []string { return nil } +func (m *AddDelegationMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type AddDelegationRoleAndKeysMessage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` DelegationKeys []*PublicKey `protobuf:"bytes,2,rep,name=delegationKeys" json:"delegationKeys,omitempty"` + Gun string `protobuf:"bytes,3,opt,name=gun" json:"gun,omitempty"` } func (m *AddDelegationRoleAndKeysMessage) Reset() { *m = AddDelegationRoleAndKeysMessage{} } func (m *AddDelegationRoleAndKeysMessage) String() string { return proto.CompactTextString(m) } func (*AddDelegationRoleAndKeysMessage) ProtoMessage() {} -func (*AddDelegationRoleAndKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*AddDelegationRoleAndKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *AddDelegationRoleAndKeysMessage) GetName() string { if m != nil { @@ -136,15 +163,23 @@ func (m *AddDelegationRoleAndKeysMessage) GetDelegationKeys() []*PublicKey { return nil } +func (m *AddDelegationRoleAndKeysMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type AddDelegationPathsMessage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Paths []string `protobuf:"bytes,2,rep,name=paths" json:"paths,omitempty"` + Gun string `protobuf:"bytes,3,opt,name=gun" json:"gun,omitempty"` } func (m *AddDelegationPathsMessage) Reset() { *m = AddDelegationPathsMessage{} } func (m *AddDelegationPathsMessage) String() string { return proto.CompactTextString(m) } func (*AddDelegationPathsMessage) ProtoMessage() {} -func (*AddDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*AddDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *AddDelegationPathsMessage) GetName() string { if m != nil { @@ -160,17 +195,25 @@ func (m *AddDelegationPathsMessage) GetPaths() []string { return nil } +func (m *AddDelegationPathsMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type RemoveDelegationKeysAndPathsMessage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` KeyIDs []string `protobuf:"bytes,2,rep,name=keyIDs" json:"keyIDs,omitempty"` Paths []string `protobuf:"bytes,3,rep,name=paths" json:"paths,omitempty"` + Gun string `protobuf:"bytes,4,opt,name=gun" json:"gun,omitempty"` } func (m *RemoveDelegationKeysAndPathsMessage) Reset() { *m = RemoveDelegationKeysAndPathsMessage{} } func (m *RemoveDelegationKeysAndPathsMessage) String() string { return proto.CompactTextString(m) } func (*RemoveDelegationKeysAndPathsMessage) ProtoMessage() {} func (*RemoveDelegationKeysAndPathsMessage) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{3} + return fileDescriptor0, []int{4} } func (m *RemoveDelegationKeysAndPathsMessage) GetName() string { @@ -194,14 +237,22 @@ func (m *RemoveDelegationKeysAndPathsMessage) GetPaths() []string { return nil } +func (m *RemoveDelegationKeysAndPathsMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type RemoveDelegationRoleMessage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` } func (m *RemoveDelegationRoleMessage) Reset() { *m = RemoveDelegationRoleMessage{} } func (m *RemoveDelegationRoleMessage) String() string { return proto.CompactTextString(m) } func (*RemoveDelegationRoleMessage) ProtoMessage() {} -func (*RemoveDelegationRoleMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*RemoveDelegationRoleMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *RemoveDelegationRoleMessage) GetName() string { if m != nil { @@ -210,15 +261,23 @@ func (m *RemoveDelegationRoleMessage) GetName() string { return "" } +func (m *RemoveDelegationRoleMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type RemoveDelegationPathsMessage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Paths []string `protobuf:"bytes,2,rep,name=paths" json:"paths,omitempty"` + Gun string `protobuf:"bytes,3,opt,name=gun" json:"gun,omitempty"` } func (m *RemoveDelegationPathsMessage) Reset() { *m = RemoveDelegationPathsMessage{} } func (m *RemoveDelegationPathsMessage) String() string { return proto.CompactTextString(m) } func (*RemoveDelegationPathsMessage) ProtoMessage() {} -func (*RemoveDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*RemoveDelegationPathsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (m *RemoveDelegationPathsMessage) GetName() string { if m != nil { @@ -234,15 +293,23 @@ func (m *RemoveDelegationPathsMessage) GetPaths() []string { return nil } +func (m *RemoveDelegationPathsMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type RemoveDelegationKeysMessage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` KeyIDs []string `protobuf:"bytes,2,rep,name=keyIDs" json:"keyIDs,omitempty"` + Gun string `protobuf:"bytes,3,opt,name=gun" json:"gun,omitempty"` } func (m *RemoveDelegationKeysMessage) Reset() { *m = RemoveDelegationKeysMessage{} } func (m *RemoveDelegationKeysMessage) String() string { return proto.CompactTextString(m) } func (*RemoveDelegationKeysMessage) ProtoMessage() {} -func (*RemoveDelegationKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*RemoveDelegationKeysMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *RemoveDelegationKeysMessage) GetName() string { if m != nil { @@ -258,14 +325,22 @@ func (m *RemoveDelegationKeysMessage) GetKeyIDs() []string { return nil } +func (m *RemoveDelegationKeysMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type RoleNameMessage struct { Role string `protobuf:"bytes,1,opt,name=role" json:"role,omitempty"` + Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` } func (m *RoleNameMessage) Reset() { *m = RoleNameMessage{} } func (m *RoleNameMessage) String() string { return proto.CompactTextString(m) } func (*RoleNameMessage) ProtoMessage() {} -func (*RoleNameMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*RoleNameMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func (m *RoleNameMessage) GetRole() string { if m != nil { @@ -274,16 +349,24 @@ func (m *RoleNameMessage) GetRole() string { return "" } +func (m *RoleNameMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type RotateKeyMessage struct { Role string `protobuf:"bytes,1,opt,name=role" json:"role,omitempty"` ServerManagesKey bool `protobuf:"varint,2,opt,name=serverManagesKey" json:"serverManagesKey,omitempty"` KeyList []string `protobuf:"bytes,3,rep,name=keyList" json:"keyList,omitempty"` + Gun string `protobuf:"bytes,4,opt,name=gun" json:"gun,omitempty"` } func (m *RotateKeyMessage) Reset() { *m = RotateKeyMessage{} } func (m *RotateKeyMessage) String() string { return proto.CompactTextString(m) } func (*RotateKeyMessage) ProtoMessage() {} -func (*RotateKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*RotateKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (m *RotateKeyMessage) GetRole() string { if m != nil { @@ -306,17 +389,25 @@ func (m *RotateKeyMessage) GetKeyList() []string { return nil } +func (m *RotateKeyMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + // InitMessage holds a list of root key IDs and a list of roles for which // the server automatically should manage the keys type InitMessage struct { RootKeyIDs []string `protobuf:"bytes,1,rep,name=rootKeyIDs" json:"rootKeyIDs,omitempty"` ServerManagedRoles *RoleNameList `protobuf:"bytes,2,opt,name=serverManagedRoles" json:"serverManagedRoles,omitempty"` + Gun string `protobuf:"bytes,3,opt,name=gun" json:"gun,omitempty"` } func (m *InitMessage) Reset() { *m = InitMessage{} } func (m *InitMessage) String() string { return proto.CompactTextString(m) } func (*InitMessage) ProtoMessage() {} -func (*InitMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*InitMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *InitMessage) GetRootKeyIDs() []string { if m != nil { @@ -332,6 +423,13 @@ func (m *InitMessage) GetServerManagedRoles() *RoleNameList { return nil } +func (m *InitMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + // RoleNameList message holds a list of TUF role names type RoleNameList struct { Roles []string `protobuf:"bytes,1,rep,name=roles" json:"roles,omitempty"` @@ -340,7 +438,7 @@ type RoleNameList struct { func (m *RoleNameList) Reset() { *m = RoleNameList{} } func (m *RoleNameList) String() string { return proto.CompactTextString(m) } func (*RoleNameList) ProtoMessage() {} -func (*RoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*RoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *RoleNameList) GetRoles() []string { if m != nil { @@ -349,6 +447,30 @@ func (m *RoleNameList) GetRoles() []string { return nil } +type RoleNameListMessage struct { + Roles []string `protobuf:"bytes,1,rep,name=roles" json:"roles,omitempty"` + Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` +} + +func (m *RoleNameListMessage) Reset() { *m = RoleNameListMessage{} } +func (m *RoleNameListMessage) String() string { return proto.CompactTextString(m) } +func (*RoleNameListMessage) ProtoMessage() {} +func (*RoleNameListMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } + +func (m *RoleNameListMessage) GetRoles() []string { + if m != nil { + return m.Roles + } + return nil +} + +func (m *RoleNameListMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type RoleNameListResponse struct { RoleNameList *RoleNameList `protobuf:"bytes,1,opt,name=roleNameList" json:"roleNameList,omitempty"` Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` @@ -358,7 +480,7 @@ type RoleNameListResponse struct { func (m *RoleNameListResponse) Reset() { *m = RoleNameListResponse{} } func (m *RoleNameListResponse) String() string { return proto.CompactTextString(m) } func (*RoleNameListResponse) ProtoMessage() {} -func (*RoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*RoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *RoleNameListResponse) GetRoleNameList() *RoleNameList { if m != nil { @@ -383,12 +505,13 @@ func (m *RoleNameListResponse) GetMessage() string { type TargetName struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` } func (m *TargetName) Reset() { *m = TargetName{} } func (m *TargetName) String() string { return proto.CompactTextString(m) } func (*TargetName) ProtoMessage() {} -func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *TargetName) GetName() string { if m != nil { @@ -397,6 +520,13 @@ func (m *TargetName) GetName() string { return "" } +func (m *TargetName) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + // Target message describes a TUF target type Target struct { Gun string `protobuf:"bytes,1,opt,name=gun" json:"gun,omitempty"` @@ -409,7 +539,7 @@ type Target struct { func (m *Target) Reset() { *m = Target{} } func (m *Target) String() string { return proto.CompactTextString(m) } func (*Target) ProtoMessage() {} -func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } func (m *Target) GetGun() string { if m != nil { @@ -455,7 +585,7 @@ type TargetWithRole struct { func (m *TargetWithRole) Reset() { *m = TargetWithRole{} } func (m *TargetWithRole) String() string { return proto.CompactTextString(m) } func (*TargetWithRole) ProtoMessage() {} -func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*TargetWithRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *TargetWithRole) GetTarget() *Target { if m != nil { @@ -480,7 +610,7 @@ type TargetWithRoleResponse struct { func (m *TargetWithRoleResponse) Reset() { *m = TargetWithRoleResponse{} } func (m *TargetWithRoleResponse) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleResponse) ProtoMessage() {} -func (*TargetWithRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*TargetWithRoleResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *TargetWithRoleResponse) GetTargetWithRole() *TargetWithRole { if m != nil { @@ -510,7 +640,7 @@ type TargetWithRoleNameList struct { func (m *TargetWithRoleNameList) Reset() { *m = TargetWithRoleNameList{} } func (m *TargetWithRoleNameList) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleNameList) ProtoMessage() {} -func (*TargetWithRoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*TargetWithRoleNameList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *TargetWithRoleNameList) GetTargets() []*TargetWithRole { if m != nil { @@ -528,7 +658,7 @@ type TargetWithRoleNameListResponse struct { func (m *TargetWithRoleNameListResponse) Reset() { *m = TargetWithRoleNameListResponse{} } func (m *TargetWithRoleNameListResponse) String() string { return proto.CompactTextString(m) } func (*TargetWithRoleNameListResponse) ProtoMessage() {} -func (*TargetWithRoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*TargetWithRoleNameListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } func (m *TargetWithRoleNameListResponse) GetTargetWithRoleNameList() *TargetWithRoleNameList { if m != nil { @@ -554,12 +684,13 @@ func (m *TargetWithRoleNameListResponse) GetMessage() string { type TargetByNameAction struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Roles *RoleNameList `protobuf:"bytes,2,opt,name=roles" json:"roles,omitempty"` + Gun string `protobuf:"bytes,3,opt,name=gun" json:"gun,omitempty"` } func (m *TargetByNameAction) Reset() { *m = TargetByNameAction{} } func (m *TargetByNameAction) String() string { return proto.CompactTextString(m) } func (*TargetByNameAction) ProtoMessage() {} -func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*TargetByNameAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *TargetByNameAction) GetName() string { if m != nil { @@ -575,6 +706,13 @@ func (m *TargetByNameAction) GetRoles() *RoleNameList { return nil } +func (m *TargetByNameAction) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type Signature struct { KeyID string `protobuf:"bytes,1,opt,name=keyID" json:"keyID,omitempty"` Method string `protobuf:"bytes,2,opt,name=method" json:"method,omitempty"` @@ -585,7 +723,7 @@ type Signature struct { func (m *Signature) Reset() { *m = Signature{} } func (m *Signature) String() string { return proto.CompactTextString(m) } func (*Signature) ProtoMessage() {} -func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*Signature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } func (m *Signature) GetKeyID() string { if m != nil { @@ -624,7 +762,7 @@ type PublicKey struct { func (m *PublicKey) Reset() { *m = PublicKey{} } func (m *PublicKey) String() string { return proto.CompactTextString(m) } func (*PublicKey) ProtoMessage() {} -func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } func (m *PublicKey) GetId() string { if m != nil { @@ -656,7 +794,7 @@ type PublicKeyResponse struct { func (m *PublicKeyResponse) Reset() { *m = PublicKeyResponse{} } func (m *PublicKeyResponse) String() string { return proto.CompactTextString(m) } func (*PublicKeyResponse) ProtoMessage() {} -func (*PublicKeyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*PublicKeyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } func (m *PublicKeyResponse) GetPubkey() *PublicKey { if m != nil { @@ -689,7 +827,7 @@ type DelegationRole struct { func (m *DelegationRole) Reset() { *m = DelegationRole{} } func (m *DelegationRole) String() string { return proto.CompactTextString(m) } func (*DelegationRole) ProtoMessage() {} -func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } +func (*DelegationRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } func (m *DelegationRole) GetKeys() map[string]*PublicKey { if m != nil { @@ -728,7 +866,7 @@ type TargetSigned struct { func (m *TargetSigned) Reset() { *m = TargetSigned{} } func (m *TargetSigned) String() string { return proto.CompactTextString(m) } func (*TargetSigned) ProtoMessage() {} -func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } +func (*TargetSigned) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } func (m *TargetSigned) GetRole() *DelegationRole { if m != nil { @@ -758,7 +896,7 @@ type TargetSignedList struct { func (m *TargetSignedList) Reset() { *m = TargetSignedList{} } func (m *TargetSignedList) String() string { return proto.CompactTextString(m) } func (*TargetSignedList) ProtoMessage() {} -func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } +func (*TargetSignedList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } func (m *TargetSignedList) GetTargets() []*TargetSigned { if m != nil { @@ -776,7 +914,7 @@ type TargetSignedListResponse struct { func (m *TargetSignedListResponse) Reset() { *m = TargetSignedListResponse{} } func (m *TargetSignedListResponse) String() string { return proto.CompactTextString(m) } func (*TargetSignedListResponse) ProtoMessage() {} -func (*TargetSignedListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } +func (*TargetSignedListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } func (m *TargetSignedListResponse) GetTargetSignedList() *TargetSignedList { if m != nil { @@ -811,7 +949,7 @@ type BasicResponse struct { func (m *BasicResponse) Reset() { *m = BasicResponse{} } func (m *BasicResponse) String() string { return proto.CompactTextString(m) } func (*BasicResponse) ProtoMessage() {} -func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } +func (*BasicResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } func (m *BasicResponse) GetSuccess() bool { if m != nil { @@ -839,7 +977,7 @@ type Change struct { func (m *Change) Reset() { *m = Change{} } func (m *Change) String() string { return proto.CompactTextString(m) } func (*Change) ProtoMessage() {} -func (*Change) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } +func (*Change) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } func (m *Change) GetAction() string { if m != nil { @@ -884,7 +1022,7 @@ type ChangeList struct { func (m *ChangeList) Reset() { *m = ChangeList{} } func (m *ChangeList) String() string { return proto.CompactTextString(m) } func (*ChangeList) ProtoMessage() {} -func (*ChangeList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } +func (*ChangeList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } func (m *ChangeList) GetChanges() []*Change { if m != nil { @@ -902,7 +1040,7 @@ type ChangeListResponse struct { func (m *ChangeListResponse) Reset() { *m = ChangeListResponse{} } func (m *ChangeListResponse) String() string { return proto.CompactTextString(m) } func (*ChangeListResponse) ProtoMessage() {} -func (*ChangeListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } +func (*ChangeListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } func (m *ChangeListResponse) GetChangelist() *ChangeList { if m != nil { @@ -933,7 +1071,7 @@ type RootRole struct { func (m *RootRole) Reset() { *m = RootRole{} } func (m *RootRole) String() string { return proto.CompactTextString(m) } func (*RootRole) ProtoMessage() {} -func (*RootRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } +func (*RootRole) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } func (m *RootRole) GetKeyIDs() []string { if m != nil { @@ -958,7 +1096,7 @@ type Role struct { func (m *Role) Reset() { *m = Role{} } func (m *Role) String() string { return proto.CompactTextString(m) } func (*Role) ProtoMessage() {} -func (*Role) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{31} } +func (*Role) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } func (m *Role) GetRootRole() *RootRole { if m != nil { @@ -988,7 +1126,7 @@ type RoleList struct { func (m *RoleList) Reset() { *m = RoleList{} } func (m *RoleList) String() string { return proto.CompactTextString(m) } func (*RoleList) ProtoMessage() {} -func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{32} } +func (*RoleList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } func (m *RoleList) GetRoles() []*Role { if m != nil { @@ -1006,7 +1144,7 @@ type RoleListResponse struct { func (m *RoleListResponse) Reset() { *m = RoleListResponse{} } func (m *RoleListResponse) String() string { return proto.CompactTextString(m) } func (*RoleListResponse) ProtoMessage() {} -func (*RoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{33} } +func (*RoleListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} } func (m *RoleListResponse) GetRoleList() *RoleList { if m != nil { @@ -1037,7 +1175,7 @@ type RoleWithSignatures struct { func (m *RoleWithSignatures) Reset() { *m = RoleWithSignatures{} } func (m *RoleWithSignatures) String() string { return proto.CompactTextString(m) } func (*RoleWithSignatures) ProtoMessage() {} -func (*RoleWithSignatures) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{34} } +func (*RoleWithSignatures) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} } func (m *RoleWithSignatures) GetSignatures() []*Signature { if m != nil { @@ -1060,7 +1198,7 @@ type RoleWithSignaturesList struct { func (m *RoleWithSignaturesList) Reset() { *m = RoleWithSignaturesList{} } func (m *RoleWithSignaturesList) String() string { return proto.CompactTextString(m) } func (*RoleWithSignaturesList) ProtoMessage() {} -func (*RoleWithSignaturesList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{35} } +func (*RoleWithSignaturesList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } func (m *RoleWithSignaturesList) GetRoleWithSignatures() []*RoleWithSignatures { if m != nil { @@ -1078,7 +1216,7 @@ type RoleWithSignaturesListResponse struct { func (m *RoleWithSignaturesListResponse) Reset() { *m = RoleWithSignaturesListResponse{} } func (m *RoleWithSignaturesListResponse) String() string { return proto.CompactTextString(m) } func (*RoleWithSignaturesListResponse) ProtoMessage() {} -func (*RoleWithSignaturesListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{36} } +func (*RoleWithSignaturesListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} } func (m *RoleWithSignaturesListResponse) GetRoleWithSignaturesList() *RoleWithSignaturesList { if m != nil { @@ -1108,7 +1246,7 @@ type CryptoServiceMessage struct { func (m *CryptoServiceMessage) Reset() { *m = CryptoServiceMessage{} } func (m *CryptoServiceMessage) String() string { return proto.CompactTextString(m) } func (*CryptoServiceMessage) ProtoMessage() {} -func (*CryptoServiceMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{37} } +func (*CryptoServiceMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} } type CryptoServiceCreateMessage struct { RoleName string `protobuf:"bytes,1,opt,name=roleName" json:"roleName,omitempty"` @@ -1119,7 +1257,7 @@ type CryptoServiceCreateMessage struct { func (m *CryptoServiceCreateMessage) Reset() { *m = CryptoServiceCreateMessage{} } func (m *CryptoServiceCreateMessage) String() string { return proto.CompactTextString(m) } func (*CryptoServiceCreateMessage) ProtoMessage() {} -func (*CryptoServiceCreateMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{38} } +func (*CryptoServiceCreateMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{40} } func (m *CryptoServiceCreateMessage) GetRoleName() string { if m != nil { @@ -1150,7 +1288,7 @@ type Signer struct { func (m *Signer) Reset() { *m = Signer{} } func (m *Signer) String() string { return proto.CompactTextString(m) } func (*Signer) ProtoMessage() {} -func (*Signer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} } +func (*Signer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41} } func (m *Signer) GetPubkey() *PublicKey { if m != nil { @@ -1177,7 +1315,7 @@ type PrivateKey struct { func (m *PrivateKey) Reset() { *m = PrivateKey{} } func (m *PrivateKey) String() string { return proto.CompactTextString(m) } func (*PrivateKey) ProtoMessage() {} -func (*PrivateKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{40} } +func (*PrivateKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{42} } func (m *PrivateKey) GetPubkey() *PublicKey { if m != nil { @@ -1223,7 +1361,7 @@ type CryptoServiceAddKeyMessage struct { func (m *CryptoServiceAddKeyMessage) Reset() { *m = CryptoServiceAddKeyMessage{} } func (m *CryptoServiceAddKeyMessage) String() string { return proto.CompactTextString(m) } func (*CryptoServiceAddKeyMessage) ProtoMessage() {} -func (*CryptoServiceAddKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41} } +func (*CryptoServiceAddKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{43} } func (m *CryptoServiceAddKeyMessage) GetRoleName() string { if m != nil { @@ -1257,7 +1395,7 @@ type PrivateKeyResponse struct { func (m *PrivateKeyResponse) Reset() { *m = PrivateKeyResponse{} } func (m *PrivateKeyResponse) String() string { return proto.CompactTextString(m) } func (*PrivateKeyResponse) ProtoMessage() {} -func (*PrivateKeyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{42} } +func (*PrivateKeyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{44} } func (m *PrivateKeyResponse) GetRole() string { if m != nil { @@ -1296,12 +1434,13 @@ func (m *PrivateKeyResponse) GetMessage() string { type KeyIDMessage struct { KeyID string `protobuf:"bytes,1,opt,name=keyID" json:"keyID,omitempty"` + Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` } func (m *KeyIDMessage) Reset() { *m = KeyIDMessage{} } func (m *KeyIDMessage) String() string { return proto.CompactTextString(m) } func (*KeyIDMessage) ProtoMessage() {} -func (*KeyIDMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{43} } +func (*KeyIDMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{45} } func (m *KeyIDMessage) GetKeyID() string { if m != nil { @@ -1310,6 +1449,13 @@ func (m *KeyIDMessage) GetKeyID() string { return "" } +func (m *KeyIDMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + type KeyIDsListResponse struct { KeyIDs []string `protobuf:"bytes,1,rep,name=keyIDs" json:"keyIDs,omitempty"` Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` @@ -1319,7 +1465,7 @@ type KeyIDsListResponse struct { func (m *KeyIDsListResponse) Reset() { *m = KeyIDsListResponse{} } func (m *KeyIDsListResponse) String() string { return proto.CompactTextString(m) } func (*KeyIDsListResponse) ProtoMessage() {} -func (*KeyIDsListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{44} } +func (*KeyIDsListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{46} } func (m *KeyIDsListResponse) GetKeyIDs() []string { if m != nil { @@ -1351,7 +1497,7 @@ type SigningKeyIDsToRolesResponse struct { func (m *SigningKeyIDsToRolesResponse) Reset() { *m = SigningKeyIDsToRolesResponse{} } func (m *SigningKeyIDsToRolesResponse) String() string { return proto.CompactTextString(m) } func (*SigningKeyIDsToRolesResponse) ProtoMessage() {} -func (*SigningKeyIDsToRolesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{45} } +func (*SigningKeyIDsToRolesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{47} } func (m *SigningKeyIDsToRolesResponse) GetKeyIDs() map[string]string { if m != nil { @@ -1375,13 +1521,14 @@ func (m *SigningKeyIDsToRolesResponse) GetMessage() string { } type VersionMessage struct { - Version int32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` + Version int32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` + Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` } func (m *VersionMessage) Reset() { *m = VersionMessage{} } func (m *VersionMessage) String() string { return proto.CompactTextString(m) } func (*VersionMessage) ProtoMessage() {} -func (*VersionMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{46} } +func (*VersionMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{48} } func (m *VersionMessage) GetVersion() int32 { if m != nil { @@ -1390,7 +1537,15 @@ func (m *VersionMessage) GetVersion() int32 { return 0 } +func (m *VersionMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + func init() { + proto.RegisterType((*GunMessage)(nil), "api.GunMessage") proto.RegisterType((*AddDelegationMessage)(nil), "api.AddDelegationMessage") proto.RegisterType((*AddDelegationRoleAndKeysMessage)(nil), "api.AddDelegationRoleAndKeysMessage") proto.RegisterType((*AddDelegationPathsMessage)(nil), "api.AddDelegationPathsMessage") @@ -1402,6 +1557,7 @@ func init() { proto.RegisterType((*RotateKeyMessage)(nil), "api.RotateKeyMessage") proto.RegisterType((*InitMessage)(nil), "api.InitMessage") proto.RegisterType((*RoleNameList)(nil), "api.RoleNameList") + proto.RegisterType((*RoleNameListMessage)(nil), "api.RoleNameListMessage") proto.RegisterType((*RoleNameListResponse)(nil), "api.RoleNameListResponse") proto.RegisterType((*TargetName)(nil), "api.TargetName") proto.RegisterType((*Target)(nil), "api.Target") @@ -1452,22 +1608,22 @@ const _ = grpc.SupportPackageIsVersion4 type NotaryClient interface { Initialize(ctx context.Context, in *InitMessage, opts ...grpc.CallOption) (*BasicResponse, error) - Publish(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*BasicResponse, error) + Publish(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*BasicResponse, error) // AddTarget adds a target to the TUF repository and re-signs. AddTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) // RemoveTarget deletes a target from the TUF repository and re-signs. It only // uses the `name` field from the Target object, ignoring all other fields RemoveTarget(ctx context.Context, in *Target, opts ...grpc.CallOption) (*BasicResponse, error) // ListTargets list the targets for the specified roles in the TUF repository - ListTargets(ctx context.Context, in *RoleNameList, opts ...grpc.CallOption) (*TargetWithRoleNameListResponse, error) + ListTargets(ctx context.Context, in *RoleNameListMessage, opts ...grpc.CallOption) (*TargetWithRoleNameListResponse, error) // GetTargetByName returns a target by the given name. GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes - GetChangelist(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*ChangeListResponse, error) - ListRoles(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) - GetDelegationRoles(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*RoleListResponse, error) + GetChangelist(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*ChangeListResponse, error) + ListRoles(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) + GetDelegationRoles(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*RoleListResponse, error) AddDelegation(ctx context.Context, in *AddDelegationMessage, opts ...grpc.CallOption) (*BasicResponse, error) AddDelegationRoleAndKeys(ctx context.Context, in *AddDelegationRoleAndKeysMessage, opts ...grpc.CallOption) (*BasicResponse, error) AddDelegationPaths(ctx context.Context, in *AddDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) @@ -1476,17 +1632,17 @@ type NotaryClient interface { RemoveDelegationPaths(ctx context.Context, in *RemoveDelegationPathsMessage, opts ...grpc.CallOption) (*BasicResponse, error) RemoveDelegationKeys(ctx context.Context, in *RemoveDelegationKeysMessage, opts ...grpc.CallOption) (*BasicResponse, error) ClearDelegationPaths(ctx context.Context, in *RoleNameMessage, opts ...grpc.CallOption) (*BasicResponse, error) - Witness(ctx context.Context, in *RoleNameList, opts ...grpc.CallOption) (*RoleNameListResponse, error) + Witness(ctx context.Context, in *RoleNameListMessage, opts ...grpc.CallOption) (*RoleNameListResponse, error) RotateKey(ctx context.Context, in *RotateKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) // CryptoService implementation - CryptoService(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*CryptoServiceMessage, error) + CryptoService(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*CryptoServiceMessage, error) CryptoServiceCreate(ctx context.Context, in *CryptoServiceCreateMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) CryptoServiceAddKey(ctx context.Context, in *CryptoServiceAddKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) CryptoServiceGetKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) CryptoServiceGetPrivateKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PrivateKeyResponse, error) CryptoServiceRemoveKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*BasicResponse, error) CryptoServiceListKeys(ctx context.Context, in *RoleNameMessage, opts ...grpc.CallOption) (*KeyIDsListResponse, error) - CryptoServiceListAllKeys(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*SigningKeyIDsToRolesResponse, error) + CryptoServiceListAllKeys(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*SigningKeyIDsToRolesResponse, error) SetLegacyVersions(ctx context.Context, in *VersionMessage, opts ...grpc.CallOption) (*google_protobuf.Empty, error) } @@ -1507,7 +1663,7 @@ func (c *notaryClient) Initialize(ctx context.Context, in *InitMessage, opts ... return out, nil } -func (c *notaryClient) Publish(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*BasicResponse, error) { +func (c *notaryClient) Publish(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*BasicResponse, error) { out := new(BasicResponse) err := grpc.Invoke(ctx, "/api.Notary/Publish", in, out, c.cc, opts...) if err != nil { @@ -1534,7 +1690,7 @@ func (c *notaryClient) RemoveTarget(ctx context.Context, in *Target, opts ...grp return out, nil } -func (c *notaryClient) ListTargets(ctx context.Context, in *RoleNameList, opts ...grpc.CallOption) (*TargetWithRoleNameListResponse, error) { +func (c *notaryClient) ListTargets(ctx context.Context, in *RoleNameListMessage, opts ...grpc.CallOption) (*TargetWithRoleNameListResponse, error) { out := new(TargetWithRoleNameListResponse) err := grpc.Invoke(ctx, "/api.Notary/ListTargets", in, out, c.cc, opts...) if err != nil { @@ -1561,7 +1717,7 @@ func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *Targe return out, nil } -func (c *notaryClient) GetChangelist(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*ChangeListResponse, error) { +func (c *notaryClient) GetChangelist(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*ChangeListResponse, error) { out := new(ChangeListResponse) err := grpc.Invoke(ctx, "/api.Notary/GetChangelist", in, out, c.cc, opts...) if err != nil { @@ -1570,7 +1726,7 @@ func (c *notaryClient) GetChangelist(ctx context.Context, in *google_protobuf.Em return out, nil } -func (c *notaryClient) ListRoles(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) { +func (c *notaryClient) ListRoles(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) { out := new(RoleWithSignaturesListResponse) err := grpc.Invoke(ctx, "/api.Notary/ListRoles", in, out, c.cc, opts...) if err != nil { @@ -1579,7 +1735,7 @@ func (c *notaryClient) ListRoles(ctx context.Context, in *google_protobuf.Empty, return out, nil } -func (c *notaryClient) GetDelegationRoles(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*RoleListResponse, error) { +func (c *notaryClient) GetDelegationRoles(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*RoleListResponse, error) { out := new(RoleListResponse) err := grpc.Invoke(ctx, "/api.Notary/GetDelegationRoles", in, out, c.cc, opts...) if err != nil { @@ -1660,7 +1816,7 @@ func (c *notaryClient) ClearDelegationPaths(ctx context.Context, in *RoleNameMes return out, nil } -func (c *notaryClient) Witness(ctx context.Context, in *RoleNameList, opts ...grpc.CallOption) (*RoleNameListResponse, error) { +func (c *notaryClient) Witness(ctx context.Context, in *RoleNameListMessage, opts ...grpc.CallOption) (*RoleNameListResponse, error) { out := new(RoleNameListResponse) err := grpc.Invoke(ctx, "/api.Notary/Witness", in, out, c.cc, opts...) if err != nil { @@ -1678,7 +1834,7 @@ func (c *notaryClient) RotateKey(ctx context.Context, in *RotateKeyMessage, opts return out, nil } -func (c *notaryClient) CryptoService(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*CryptoServiceMessage, error) { +func (c *notaryClient) CryptoService(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*CryptoServiceMessage, error) { out := new(CryptoServiceMessage) err := grpc.Invoke(ctx, "/api.Notary/CryptoService", in, out, c.cc, opts...) if err != nil { @@ -1741,7 +1897,7 @@ func (c *notaryClient) CryptoServiceListKeys(ctx context.Context, in *RoleNameMe return out, nil } -func (c *notaryClient) CryptoServiceListAllKeys(ctx context.Context, in *google_protobuf.Empty, opts ...grpc.CallOption) (*SigningKeyIDsToRolesResponse, error) { +func (c *notaryClient) CryptoServiceListAllKeys(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*SigningKeyIDsToRolesResponse, error) { out := new(SigningKeyIDsToRolesResponse) err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceListAllKeys", in, out, c.cc, opts...) if err != nil { @@ -1763,22 +1919,22 @@ func (c *notaryClient) SetLegacyVersions(ctx context.Context, in *VersionMessage type NotaryServer interface { Initialize(context.Context, *InitMessage) (*BasicResponse, error) - Publish(context.Context, *google_protobuf.Empty) (*BasicResponse, error) + Publish(context.Context, *GunMessage) (*BasicResponse, error) // AddTarget adds a target to the TUF repository and re-signs. AddTarget(context.Context, *Target) (*BasicResponse, error) // RemoveTarget deletes a target from the TUF repository and re-signs. It only // uses the `name` field from the Target object, ignoring all other fields RemoveTarget(context.Context, *Target) (*BasicResponse, error) // ListTargets list the targets for the specified roles in the TUF repository - ListTargets(context.Context, *RoleNameList) (*TargetWithRoleNameListResponse, error) + ListTargets(context.Context, *RoleNameListMessage) (*TargetWithRoleNameListResponse, error) // GetTargetByName returns a target by the given name. GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes - GetChangelist(context.Context, *google_protobuf.Empty) (*ChangeListResponse, error) - ListRoles(context.Context, *google_protobuf.Empty) (*RoleWithSignaturesListResponse, error) - GetDelegationRoles(context.Context, *google_protobuf.Empty) (*RoleListResponse, error) + GetChangelist(context.Context, *GunMessage) (*ChangeListResponse, error) + ListRoles(context.Context, *GunMessage) (*RoleWithSignaturesListResponse, error) + GetDelegationRoles(context.Context, *GunMessage) (*RoleListResponse, error) AddDelegation(context.Context, *AddDelegationMessage) (*BasicResponse, error) AddDelegationRoleAndKeys(context.Context, *AddDelegationRoleAndKeysMessage) (*BasicResponse, error) AddDelegationPaths(context.Context, *AddDelegationPathsMessage) (*BasicResponse, error) @@ -1787,17 +1943,17 @@ type NotaryServer interface { RemoveDelegationPaths(context.Context, *RemoveDelegationPathsMessage) (*BasicResponse, error) RemoveDelegationKeys(context.Context, *RemoveDelegationKeysMessage) (*BasicResponse, error) ClearDelegationPaths(context.Context, *RoleNameMessage) (*BasicResponse, error) - Witness(context.Context, *RoleNameList) (*RoleNameListResponse, error) + Witness(context.Context, *RoleNameListMessage) (*RoleNameListResponse, error) RotateKey(context.Context, *RotateKeyMessage) (*BasicResponse, error) // CryptoService implementation - CryptoService(context.Context, *google_protobuf.Empty) (*CryptoServiceMessage, error) + CryptoService(context.Context, *GunMessage) (*CryptoServiceMessage, error) CryptoServiceCreate(context.Context, *CryptoServiceCreateMessage) (*PublicKeyResponse, error) CryptoServiceAddKey(context.Context, *CryptoServiceAddKeyMessage) (*BasicResponse, error) CryptoServiceGetKey(context.Context, *KeyIDMessage) (*PublicKeyResponse, error) CryptoServiceGetPrivateKey(context.Context, *KeyIDMessage) (*PrivateKeyResponse, error) CryptoServiceRemoveKey(context.Context, *KeyIDMessage) (*BasicResponse, error) CryptoServiceListKeys(context.Context, *RoleNameMessage) (*KeyIDsListResponse, error) - CryptoServiceListAllKeys(context.Context, *google_protobuf.Empty) (*SigningKeyIDsToRolesResponse, error) + CryptoServiceListAllKeys(context.Context, *GunMessage) (*SigningKeyIDsToRolesResponse, error) SetLegacyVersions(context.Context, *VersionMessage) (*google_protobuf.Empty, error) } @@ -1824,7 +1980,7 @@ func _Notary_Initialize_Handler(srv interface{}, ctx context.Context, dec func(i } func _Notary_Publish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(google_protobuf.Empty) + in := new(GunMessage) if err := dec(in); err != nil { return nil, err } @@ -1836,7 +1992,7 @@ func _Notary_Publish_Handler(srv interface{}, ctx context.Context, dec func(inte FullMethod: "/api.Notary/Publish", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).Publish(ctx, req.(*google_protobuf.Empty)) + return srv.(NotaryServer).Publish(ctx, req.(*GunMessage)) } return interceptor(ctx, in, info, handler) } @@ -1878,7 +2034,7 @@ func _Notary_RemoveTarget_Handler(srv interface{}, ctx context.Context, dec func } func _Notary_ListTargets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RoleNameList) + in := new(RoleNameListMessage) if err := dec(in); err != nil { return nil, err } @@ -1890,7 +2046,7 @@ func _Notary_ListTargets_Handler(srv interface{}, ctx context.Context, dec func( FullMethod: "/api.Notary/ListTargets", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).ListTargets(ctx, req.(*RoleNameList)) + return srv.(NotaryServer).ListTargets(ctx, req.(*RoleNameListMessage)) } return interceptor(ctx, in, info, handler) } @@ -1932,7 +2088,7 @@ func _Notary_GetAllTargetMetadataByName_Handler(srv interface{}, ctx context.Con } func _Notary_GetChangelist_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(google_protobuf.Empty) + in := new(GunMessage) if err := dec(in); err != nil { return nil, err } @@ -1944,13 +2100,13 @@ func _Notary_GetChangelist_Handler(srv interface{}, ctx context.Context, dec fun FullMethod: "/api.Notary/GetChangelist", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).GetChangelist(ctx, req.(*google_protobuf.Empty)) + return srv.(NotaryServer).GetChangelist(ctx, req.(*GunMessage)) } return interceptor(ctx, in, info, handler) } func _Notary_ListRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(google_protobuf.Empty) + in := new(GunMessage) if err := dec(in); err != nil { return nil, err } @@ -1962,13 +2118,13 @@ func _Notary_ListRoles_Handler(srv interface{}, ctx context.Context, dec func(in FullMethod: "/api.Notary/ListRoles", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).ListRoles(ctx, req.(*google_protobuf.Empty)) + return srv.(NotaryServer).ListRoles(ctx, req.(*GunMessage)) } return interceptor(ctx, in, info, handler) } func _Notary_GetDelegationRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(google_protobuf.Empty) + in := new(GunMessage) if err := dec(in); err != nil { return nil, err } @@ -1980,7 +2136,7 @@ func _Notary_GetDelegationRoles_Handler(srv interface{}, ctx context.Context, de FullMethod: "/api.Notary/GetDelegationRoles", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).GetDelegationRoles(ctx, req.(*google_protobuf.Empty)) + return srv.(NotaryServer).GetDelegationRoles(ctx, req.(*GunMessage)) } return interceptor(ctx, in, info, handler) } @@ -2130,7 +2286,7 @@ func _Notary_ClearDelegationPaths_Handler(srv interface{}, ctx context.Context, } func _Notary_Witness_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RoleNameList) + in := new(RoleNameListMessage) if err := dec(in); err != nil { return nil, err } @@ -2142,7 +2298,7 @@ func _Notary_Witness_Handler(srv interface{}, ctx context.Context, dec func(inte FullMethod: "/api.Notary/Witness", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).Witness(ctx, req.(*RoleNameList)) + return srv.(NotaryServer).Witness(ctx, req.(*RoleNameListMessage)) } return interceptor(ctx, in, info, handler) } @@ -2166,7 +2322,7 @@ func _Notary_RotateKey_Handler(srv interface{}, ctx context.Context, dec func(in } func _Notary_CryptoService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(google_protobuf.Empty) + in := new(GunMessage) if err := dec(in); err != nil { return nil, err } @@ -2178,7 +2334,7 @@ func _Notary_CryptoService_Handler(srv interface{}, ctx context.Context, dec fun FullMethod: "/api.Notary/CryptoService", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).CryptoService(ctx, req.(*google_protobuf.Empty)) + return srv.(NotaryServer).CryptoService(ctx, req.(*GunMessage)) } return interceptor(ctx, in, info, handler) } @@ -2292,7 +2448,7 @@ func _Notary_CryptoServiceListKeys_Handler(srv interface{}, ctx context.Context, } func _Notary_CryptoServiceListAllKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(google_protobuf.Empty) + in := new(GunMessage) if err := dec(in); err != nil { return nil, err } @@ -2304,7 +2460,7 @@ func _Notary_CryptoServiceListAllKeys_Handler(srv interface{}, ctx context.Conte FullMethod: "/api.Notary/CryptoServiceListAllKeys", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).CryptoServiceListAllKeys(ctx, req.(*google_protobuf.Empty)) + return srv.(NotaryServer).CryptoServiceListAllKeys(ctx, req.(*GunMessage)) } return interceptor(ctx, in, info, handler) } @@ -2455,124 +2611,127 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1891 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0x4b, 0x6f, 0x1b, 0xc9, - 0x11, 0xde, 0x21, 0x25, 0xca, 0x2c, 0x52, 0x12, 0xd5, 0x2b, 0x51, 0x34, 0x2d, 0xdb, 0xf4, 0x48, - 0x9b, 0xd5, 0xee, 0x62, 0x29, 0x58, 0xce, 0xc3, 0x4e, 0x0e, 0x31, 0xf5, 0x00, 0x2d, 0xcb, 0x16, - 0xe4, 0x91, 0x61, 0x1f, 0x02, 0x04, 0x19, 0x73, 0x3a, 0xe4, 0x40, 0xc3, 0x19, 0x66, 0xa6, 0x25, - 0x78, 0x72, 0xcb, 0x31, 0x40, 0x2e, 0x39, 0xe6, 0x0f, 0x04, 0xc8, 0xcf, 0xc8, 0x35, 0xe7, 0xfc, - 0xa0, 0xa0, 0x1f, 0xd3, 0xd3, 0x3d, 0x0f, 0xca, 0x21, 0xb0, 0x37, 0x76, 0x4f, 0xd5, 0x57, 0xd5, - 0xd5, 0xf5, 0xea, 0x22, 0xd4, 0xed, 0x99, 0xdb, 0x9f, 0x85, 0x01, 0x09, 0x50, 0xd5, 0x9e, 0xb9, - 0xdd, 0x07, 0xe3, 0x20, 0x18, 0x7b, 0xf8, 0x80, 0x6d, 0x7d, 0xba, 0xf9, 0xe3, 0xc1, 0xe9, 0x74, - 0x46, 0x62, 0x4e, 0x61, 0x7e, 0x86, 0xcd, 0x81, 0xe3, 0x9c, 0x60, 0x0f, 0x8f, 0x6d, 0xe2, 0x06, - 0xfe, 0x5b, 0x1c, 0x45, 0xf6, 0x18, 0x23, 0x04, 0x4b, 0xbe, 0x3d, 0xc5, 0x1d, 0xa3, 0x67, 0xec, - 0xd7, 0x2d, 0xf6, 0x1b, 0xfd, 0x12, 0xd6, 0x1c, 0x49, 0x78, 0x8e, 0xe3, 0xa8, 0x53, 0xe9, 0x55, - 0xf7, 0x1b, 0x87, 0x6b, 0x7d, 0x2a, 0xf1, 0xf2, 0xe6, 0x93, 0xe7, 0x8e, 0xce, 0x71, 0x6c, 0x65, - 0xa8, 0xd0, 0x26, 0x2c, 0xcf, 0x6c, 0x32, 0x89, 0x3a, 0xd5, 0x5e, 0x75, 0xbf, 0x6e, 0xf1, 0x85, - 0x39, 0x85, 0xc7, 0x9a, 0x64, 0x2b, 0xf0, 0xf0, 0xc0, 0x77, 0x28, 0xc7, 0x4f, 0xa0, 0x84, 0x79, - 0x0a, 0xf7, 0x35, 0x71, 0x97, 0x54, 0x89, 0x79, 0x82, 0xa4, 0xd6, 0x15, 0x55, 0xeb, 0x31, 0xec, - 0x5a, 0x78, 0x1a, 0xdc, 0xe2, 0x13, 0x0d, 0x7e, 0xe0, 0x3b, 0x77, 0x02, 0xb6, 0xa1, 0x76, 0x8d, - 0xe3, 0xb3, 0x93, 0x04, 0x51, 0xac, 0x4a, 0xcc, 0xf3, 0x14, 0x1e, 0x64, 0x05, 0x51, 0x0b, 0xcd, - 0x11, 0x60, 0xbe, 0x82, 0x9d, 0x2c, 0xcb, 0x82, 0xa7, 0x3c, 0xcb, 0x0b, 0xbf, 0xeb, 0x5e, 0x4a, - 0x4e, 0x67, 0x7e, 0x03, 0xeb, 0x54, 0xef, 0x0b, 0x7b, 0xaa, 0xea, 0x1e, 0x06, 0x9e, 0x64, 0xa7, - 0xbf, 0x4d, 0x0f, 0x5a, 0x56, 0x40, 0x6c, 0x82, 0xcf, 0x71, 0x3c, 0x87, 0x0e, 0x7d, 0x0f, 0xad, - 0x08, 0x87, 0xb7, 0x38, 0x7c, 0x6b, 0xfb, 0xf6, 0x18, 0x47, 0xe7, 0x38, 0xee, 0x54, 0x7a, 0xc6, - 0xfe, 0x3d, 0x2b, 0xb7, 0x8f, 0x3a, 0xb0, 0x72, 0x8d, 0xe3, 0x37, 0x6e, 0x44, 0x84, 0x69, 0x93, - 0xa5, 0x39, 0x83, 0xc6, 0x99, 0xef, 0x92, 0x44, 0xd0, 0x23, 0x80, 0x30, 0x08, 0xc8, 0x39, 0xd7, - 0xdf, 0x60, 0xb4, 0xca, 0x0e, 0x1a, 0x00, 0x52, 0xc1, 0x1d, 0x7a, 0xa0, 0x88, 0x89, 0x6d, 0x1c, - 0x6e, 0x30, 0xbf, 0x4b, 0x8e, 0x48, 0xd1, 0xad, 0x02, 0x62, 0x73, 0x0f, 0x9a, 0x2a, 0x0d, 0xb5, - 0x7b, 0xc8, 0x50, 0xb8, 0x34, 0xbe, 0x30, 0xff, 0x62, 0xc0, 0xa6, 0x06, 0x85, 0xa3, 0x59, 0xe0, - 0x47, 0x18, 0xfd, 0x02, 0x9a, 0xa1, 0xb2, 0xcf, 0x4c, 0x52, 0x28, 0x5b, 0x23, 0xa3, 0x16, 0x88, - 0x6e, 0x46, 0x23, 0x1c, 0x45, 0xc2, 0x48, 0xc9, 0x92, 0x7e, 0x99, 0xf2, 0xd3, 0x77, 0xaa, 0xcc, - 0xbc, 0xc9, 0xd2, 0xec, 0x01, 0xbc, 0xb7, 0xc3, 0x31, 0x26, 0x14, 0xa5, 0xd0, 0xcf, 0xfe, 0x63, - 0x40, 0x8d, 0x93, 0xa0, 0x16, 0x54, 0xc7, 0x37, 0xbe, 0xf8, 0x4a, 0x7f, 0x4a, 0x86, 0x8a, 0xee, - 0x1b, 0x1e, 0xf6, 0xc7, 0x64, 0xc2, 0x64, 0x55, 0x2d, 0xb1, 0x42, 0x07, 0x50, 0x9b, 0xd8, 0xd1, - 0x04, 0x47, 0x9d, 0x25, 0x16, 0xc3, 0xdb, 0xec, 0x3c, 0x1c, 0xba, 0xff, 0x8a, 0x7d, 0x39, 0xf5, - 0x49, 0x18, 0x5b, 0x82, 0x8c, 0x02, 0x8d, 0x6e, 0x22, 0x12, 0x4c, 0x3b, 0xcb, 0x3d, 0x63, 0xbf, - 0x69, 0x89, 0x55, 0xf7, 0x05, 0x34, 0x14, 0x72, 0xaa, 0xd5, 0x35, 0x8e, 0x13, 0xad, 0xae, 0x71, - 0x4c, 0xcd, 0x7d, 0x6b, 0x7b, 0x37, 0x5c, 0xad, 0xa6, 0xc5, 0x17, 0xbf, 0xae, 0x3c, 0x37, 0xcc, - 0x33, 0x58, 0xe3, 0x02, 0x3f, 0xba, 0x64, 0x42, 0x4d, 0x89, 0x76, 0xa1, 0x46, 0xd8, 0x8e, 0xb0, - 0x72, 0x43, 0xd1, 0xca, 0x12, 0x9f, 0xa4, 0x6f, 0x56, 0x14, 0x1f, 0xfe, 0xab, 0x01, 0x6d, 0x1d, - 0x4b, 0xde, 0xdf, 0x6f, 0x60, 0x8d, 0x68, 0x5f, 0x04, 0xf6, 0xd7, 0x0a, 0xb6, 0x64, 0xca, 0x90, - 0x2e, 0x74, 0x8b, 0xc3, 0xac, 0x2a, 0xd2, 0x27, 0x7e, 0x84, 0x15, 0x8e, 0xcf, 0x7d, 0xaf, 0x44, - 0x87, 0x84, 0xc6, 0xfc, 0x97, 0x01, 0x8f, 0x8a, 0x91, 0xe4, 0xe1, 0xae, 0xa0, 0x4d, 0x0a, 0x29, - 0xc4, 0x21, 0x1f, 0x14, 0x08, 0x90, 0x20, 0x25, 0xac, 0x0b, 0x1d, 0xfa, 0x1d, 0x20, 0x2e, 0xe5, - 0x28, 0xa6, 0x38, 0x83, 0x11, 0x4d, 0x5c, 0x85, 0xd9, 0xea, 0xdb, 0x24, 0xfc, 0x4a, 0x83, 0x58, - 0x44, 0xe4, 0x9f, 0xa0, 0x7e, 0xe5, 0x8e, 0x7d, 0x9b, 0xdc, 0x84, 0x2c, 0x59, 0xb2, 0xac, 0x26, - 0xa0, 0xf8, 0x82, 0x3a, 0xe5, 0x14, 0x93, 0x49, 0xe0, 0x08, 0x67, 0x10, 0x2b, 0xb4, 0x03, 0xf5, - 0x28, 0x61, 0x65, 0x9a, 0x36, 0xad, 0x74, 0x83, 0x9e, 0xc2, 0x8d, 0x3e, 0xd8, 0x9e, 0xeb, 0x74, - 0x96, 0xf8, 0xf9, 0xc4, 0xd2, 0x7c, 0x07, 0x75, 0x59, 0xc6, 0xd0, 0x1a, 0x54, 0x5c, 0x47, 0xc8, - 0xab, 0xb8, 0x0c, 0xd4, 0xf6, 0xc6, 0x41, 0xe8, 0x92, 0xc9, 0x54, 0xc8, 0x4b, 0x37, 0xa8, 0x2a, - 0x33, 0xc6, 0x2a, 0xe4, 0x89, 0x95, 0x19, 0xc0, 0x46, 0x5a, 0x19, 0x93, 0x6b, 0xfb, 0x19, 0x23, - 0x4e, 0x02, 0x25, 0x5f, 0x41, 0xc5, 0xd7, 0x85, 0x6e, 0xe2, 0xbf, 0x06, 0xac, 0xe9, 0x85, 0x0b, - 0x3d, 0x85, 0xa5, 0x6b, 0x5a, 0xae, 0xb9, 0xd3, 0x3d, 0x64, 0xc2, 0x74, 0x92, 0x3e, 0xad, 0x31, - 0x3c, 0xe0, 0x19, 0x69, 0x61, 0x2e, 0xd9, 0x81, 0x3a, 0x99, 0x84, 0x38, 0x9a, 0x04, 0x9e, 0xc3, - 0xa4, 0x2e, 0x5b, 0xe9, 0x46, 0x5a, 0xce, 0x96, 0x94, 0x72, 0xd6, 0x1d, 0x42, 0x5d, 0x42, 0x17, - 0x24, 0x87, 0x3d, 0x35, 0x39, 0xe4, 0xed, 0xa0, 0x24, 0x8b, 0xbf, 0x19, 0xd0, 0xe4, 0x1e, 0x46, - 0x9d, 0x02, 0x3b, 0xe8, 0x5b, 0xa5, 0x44, 0x25, 0x91, 0xa4, 0x1f, 0x4a, 0xd4, 0xad, 0x34, 0xa9, - 0x54, 0xca, 0x93, 0x4a, 0x1f, 0x40, 0x3a, 0x08, 0x6f, 0x07, 0x12, 0x6d, 0xa4, 0x0f, 0x5a, 0x0a, - 0x85, 0xf9, 0x5b, 0x68, 0xa9, 0xda, 0xb0, 0xb8, 0xf9, 0x21, 0x1b, 0xde, 0x1b, 0x8a, 0x24, 0x4e, - 0x97, 0x06, 0xf7, 0xdf, 0x0d, 0xe8, 0x64, 0x11, 0xa4, 0x7f, 0x0c, 0xa0, 0x45, 0x32, 0xdf, 0xc4, - 0x39, 0xb7, 0x72, 0x90, 0x8c, 0x31, 0x47, 0xbe, 0x90, 0xeb, 0x1c, 0xc3, 0xea, 0x91, 0x1d, 0xb9, - 0x23, 0xa9, 0x87, 0x02, 0x62, 0x94, 0x82, 0x54, 0x74, 0x90, 0xcf, 0x50, 0x3b, 0x9e, 0xd8, 0xfe, - 0x98, 0xd5, 0x1e, 0x9b, 0xe5, 0x01, 0x71, 0xe3, 0x62, 0x45, 0x3d, 0x25, 0x1a, 0x05, 0xb3, 0x84, - 0x93, 0x2f, 0xa8, 0xc7, 0x91, 0x78, 0x96, 0xe8, 0xc4, 0x7e, 0xd3, 0x3d, 0xea, 0x46, 0x2c, 0x4c, - 0xeb, 0x16, 0xfb, 0x4d, 0x25, 0x8f, 0x02, 0x9f, 0x60, 0x9f, 0x88, 0x4a, 0x94, 0x2c, 0xcd, 0x67, - 0x00, 0x5c, 0x32, 0x33, 0xc0, 0x37, 0xb0, 0x32, 0x62, 0xab, 0xe4, 0x36, 0xf8, 0xbd, 0x73, 0x0a, - 0x2b, 0xf9, 0x66, 0xc6, 0x80, 0x52, 0x26, 0x79, 0xf0, 0x03, 0x00, 0x4e, 0xe0, 0xa5, 0xa6, 0x5f, - 0x57, 0xf8, 0x19, 0xb1, 0x42, 0xb2, 0x90, 0xb9, 0x5f, 0xc2, 0x3d, 0x2b, 0x08, 0x08, 0x0b, 0xd1, - 0xb4, 0x87, 0x33, 0xb4, 0x0e, 0x55, 0x8b, 0xb9, 0x4a, 0x26, 0xe6, 0xcc, 0xdf, 0xc1, 0x12, 0xe3, - 0xfe, 0x0e, 0xee, 0x85, 0x02, 0x49, 0x28, 0xbb, 0x2a, 0xd2, 0x2a, 0xdf, 0xb4, 0xe4, 0xe7, 0xc2, - 0xc0, 0x2e, 0x6e, 0x83, 0x7f, 0xa0, 0xea, 0x79, 0xdc, 0x98, 0x8f, 0xd5, 0x9e, 0xa9, 0x71, 0x58, - 0x97, 0x49, 0x3b, 0x4d, 0xd6, 0xad, 0x84, 0x58, 0x1a, 0x91, 0x69, 0xe5, 0xa9, 0xe5, 0x68, 0x55, - 0xf2, 0x31, 0x42, 0xf9, 0x79, 0x21, 0xf3, 0x8d, 0x00, 0x51, 0x24, 0x5a, 0xbe, 0x64, 0x8c, 0x46, - 0x99, 0x40, 0x36, 0xee, 0x0a, 0x64, 0xf4, 0x50, 0xe9, 0x26, 0xb4, 0x83, 0xf1, 0xc6, 0xc2, 0x86, - 0x76, 0x5e, 0x08, 0x53, 0x79, 0x08, 0x28, 0xcc, 0x7d, 0x11, 0x02, 0xb7, 0x25, 0x8c, 0xfe, 0xd9, - 0x2a, 0x60, 0x61, 0x65, 0xbe, 0x58, 0x86, 0x5a, 0xe6, 0xc3, 0x42, 0x0a, 0xad, 0xcc, 0x97, 0x80, - 0x94, 0xb0, 0x2e, 0x64, 0xf3, 0x36, 0x6c, 0x1e, 0x87, 0xf1, 0x8c, 0x04, 0x57, 0x38, 0xbc, 0x75, - 0x47, 0xc9, 0xbb, 0xc2, 0x9c, 0x40, 0x57, 0xdb, 0x3f, 0x0e, 0xb1, 0x4d, 0xe4, 0xab, 0xa3, 0xcb, - 0x1d, 0xe1, 0x22, 0x6d, 0x05, 0xe4, 0x3a, 0x69, 0x63, 0x2b, 0x69, 0x1b, 0xab, 0xd5, 0xd9, 0x6a, - 0xa6, 0xce, 0x9a, 0x17, 0x50, 0x63, 0x59, 0x2e, 0xfc, 0xe2, 0x22, 0xaa, 0x35, 0x03, 0xa2, 0x6e, - 0xcb, 0x0d, 0xf3, 0xdf, 0x06, 0xc0, 0x65, 0xe8, 0xde, 0xf2, 0xf7, 0xcf, 0xe2, 0xa0, 0xd9, 0x0e, - 0x63, 0x16, 0xba, 0xb7, 0x14, 0x86, 0x77, 0x03, 0xc9, 0x12, 0x1d, 0x40, 0x73, 0xc4, 0x0d, 0xc5, - 0x0e, 0xc1, 0x32, 0x5b, 0x92, 0x9a, 0xf8, 0x96, 0xa5, 0x11, 0x20, 0x13, 0x9a, 0x91, 0x3b, 0x1e, - 0x48, 0x83, 0x2c, 0xb3, 0x03, 0x68, 0x7b, 0xe6, 0x34, 0x63, 0xfd, 0x81, 0xe3, 0x28, 0x6f, 0xb9, - 0xff, 0xcf, 0xfa, 0x4f, 0x78, 0x8d, 0xae, 0x2a, 0x29, 0x2f, 0x35, 0x0f, 0x2b, 0xda, 0xe6, 0x3f, - 0x0c, 0x40, 0xca, 0x5e, 0xe2, 0xa4, 0x45, 0x6f, 0xc6, 0x3c, 0xfe, 0x77, 0xba, 0x69, 0x0a, 0x64, - 0x48, 0x5b, 0x29, 0x0e, 0xba, 0x54, 0xea, 0xa0, 0xcb, 0xba, 0x83, 0xee, 0x41, 0x93, 0xbd, 0x1c, - 0x93, 0xc3, 0x17, 0xf6, 0x8d, 0xe6, 0x1f, 0x00, 0xf1, 0xf7, 0xa5, 0x16, 0x65, 0x65, 0x39, 0x78, - 0xc1, 0x2e, 0x6c, 0x87, 0xde, 0xa0, 0xeb, 0x8f, 0xb9, 0xa4, 0xf7, 0x01, 0x7b, 0x8d, 0x4a, 0x61, - 0xa7, 0x9a, 0xb0, 0xc6, 0xe1, 0x8f, 0xd2, 0x05, 0xca, 0x58, 0xfa, 0x7c, 0x57, 0x3c, 0xcb, 0x16, - 0xd7, 0x8d, 0x3e, 0xd9, 0x14, 0xa8, 0xbb, 0x9e, 0x6c, 0x75, 0xb5, 0x0b, 0xfb, 0x1e, 0xd6, 0x3e, - 0xe0, 0x30, 0x52, 0xa6, 0x55, 0x1d, 0x58, 0xb9, 0xe5, 0x3b, 0x0c, 0x61, 0xd9, 0x4a, 0x96, 0x87, - 0xff, 0x6c, 0x41, 0xed, 0x22, 0x20, 0x76, 0x18, 0xa3, 0x9f, 0x03, 0xd0, 0x47, 0xbf, 0x6b, 0x7b, - 0xee, 0x9f, 0x31, 0x6a, 0xb1, 0xa3, 0x2a, 0x53, 0x80, 0x2e, 0x62, 0x3b, 0x5a, 0xef, 0x61, 0x7e, - 0x85, 0x7e, 0x05, 0x2b, 0x2c, 0xf0, 0xa2, 0x09, 0x6a, 0xf7, 0xf9, 0x24, 0xad, 0x9f, 0x4c, 0xd2, - 0xfa, 0x6c, 0x92, 0x56, 0xc2, 0xd8, 0x87, 0xfa, 0xc0, 0x71, 0xc4, 0x3b, 0x59, 0x6d, 0xf7, 0x4a, - 0xe8, 0x9f, 0x42, 0x93, 0xcf, 0x5c, 0xbe, 0x9c, 0x65, 0x08, 0x0d, 0xea, 0x3b, 0x9c, 0x26, 0x42, - 0xf9, 0x57, 0x4c, 0x77, 0x77, 0xde, 0xd3, 0x2b, 0x05, 0x3a, 0x83, 0xf5, 0x21, 0x26, 0xea, 0xdb, - 0x09, 0xa9, 0x6f, 0x71, 0xf5, 0x39, 0xd5, 0x2d, 0x7a, 0xcd, 0x29, 0x50, 0x17, 0xd0, 0x1d, 0x62, - 0x32, 0xf0, 0x3c, 0x4e, 0xf1, 0x16, 0x13, 0xdb, 0xb1, 0x89, 0x2d, 0x50, 0xd7, 0x15, 0x66, 0xba, - 0xd1, 0x7d, 0x58, 0xdc, 0x4a, 0xa6, 0x78, 0x47, 0xb0, 0x3a, 0xc4, 0xe4, 0x38, 0x6d, 0x72, 0xca, - 0x6e, 0x61, 0x3b, 0xdb, 0x19, 0xa5, 0x18, 0xaf, 0xa1, 0xce, 0x76, 0xa8, 0x23, 0x97, 0xf2, 0xef, - 0xce, 0x2b, 0x5f, 0x29, 0xd6, 0x29, 0xa0, 0x21, 0x26, 0x7a, 0x8f, 0x5f, 0x0e, 0xba, 0xa5, 0xf7, - 0x1a, 0x29, 0xcc, 0x4b, 0x58, 0xd5, 0xc6, 0x91, 0xe8, 0x3e, 0xa3, 0x2c, 0x9a, 0xc5, 0x96, 0x5c, - 0xfe, 0x07, 0xe8, 0x94, 0xcd, 0x4f, 0xd1, 0x5e, 0x1e, 0x2c, 0x3f, 0x5e, 0x2d, 0xc1, 0x7d, 0x0d, - 0x28, 0x3f, 0x28, 0x45, 0x8f, 0xf2, 0x88, 0xea, 0x6c, 0xb1, 0x04, 0xeb, 0xf7, 0xf9, 0x89, 0xa4, - 0x3a, 0x2d, 0x45, 0xfb, 0xdc, 0x3c, 0x77, 0x0f, 0x54, 0x4b, 0xf0, 0x2f, 0x60, 0xb3, 0x68, 0x48, - 0x8a, 0x7a, 0x85, 0xb8, 0xca, 0xfc, 0xb4, 0x04, 0xef, 0x12, 0xb6, 0x0a, 0x27, 0xa8, 0xe8, 0x49, - 0x21, 0xe0, 0x62, 0x1a, 0xb2, 0x1b, 0xea, 0x95, 0x9e, 0x7c, 0x3e, 0xde, 0x11, 0x6c, 0x1e, 0x7b, - 0xd8, 0x0e, 0xb3, 0x0a, 0x6e, 0x6a, 0xb1, 0x3f, 0x1f, 0xe3, 0x05, 0xac, 0x7c, 0x74, 0x89, 0x4f, - 0xf3, 0x73, 0x41, 0xca, 0xb8, 0x9f, 0x9f, 0x85, 0xa4, 0xac, 0xcf, 0xa1, 0x2e, 0xc7, 0xb4, 0x28, - 0x71, 0x6e, 0x7d, 0x6c, 0x5b, 0x22, 0xf4, 0x04, 0x56, 0xb5, 0xf6, 0xa0, 0x34, 0x64, 0xb8, 0xfc, - 0xc2, 0x06, 0x8f, 0x5e, 0xd0, 0xd7, 0x05, 0x2d, 0x1e, 0x7a, 0x9c, 0xe7, 0xd1, 0x9a, 0xbf, 0x6e, - 0x3b, 0xd3, 0x41, 0xa5, 0x7a, 0xbd, 0xc9, 0x20, 0xf2, 0xb6, 0xa5, 0x08, 0x51, 0x6b, 0x68, 0x4a, - 0xaf, 0x47, 0x47, 0x1b, 0x62, 0x42, 0xd1, 0xb8, 0x99, 0xd5, 0x9e, 0x60, 0x8e, 0x46, 0xaf, 0x33, - 0x8d, 0xd4, 0x10, 0x13, 0xa5, 0x37, 0x2c, 0x80, 0xda, 0xce, 0x36, 0x2f, 0x29, 0xd6, 0x00, 0xda, - 0x1a, 0x16, 0x77, 0xb8, 0x12, 0x9c, 0xe2, 0x23, 0xbd, 0x82, 0x2d, 0x0d, 0x82, 0x7a, 0x04, 0xff, - 0x5b, 0xa7, 0xd0, 0xe5, 0xb6, 0x53, 0xdc, 0x6c, 0xea, 0xfc, 0x08, 0x9d, 0x1c, 0xd2, 0xc0, 0xf3, - 0x18, 0x58, 0x99, 0x37, 0x3c, 0xb9, 0xb3, 0x23, 0x61, 0x56, 0xdf, 0xb8, 0xc2, 0xe4, 0x0d, 0x1e, - 0xdb, 0xa3, 0x58, 0x74, 0x06, 0x11, 0xe2, 0xc3, 0x18, 0xbd, 0x51, 0xe8, 0x96, 0x88, 0x31, 0xbf, - 0xfa, 0x54, 0x63, 0x3b, 0xcf, 0xfe, 0x17, 0x00, 0x00, 0xff, 0xff, 0x71, 0xa2, 0xcd, 0x3c, 0x3e, - 0x1b, 0x00, 0x00, + // 1944 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0x5f, 0x73, 0xdb, 0xc6, + 0x11, 0x0f, 0x48, 0x89, 0x32, 0x97, 0x94, 0x2c, 0x9f, 0x65, 0x8a, 0xa6, 0xff, 0xc9, 0x90, 0xdb, + 0x28, 0xcd, 0x84, 0x6a, 0x94, 0x36, 0x4d, 0x9b, 0xa6, 0x35, 0x4d, 0x7b, 0x18, 0x45, 0xb6, 0x46, + 0x85, 0x32, 0xf6, 0x4c, 0x33, 0xd3, 0x29, 0x4c, 0x5c, 0x49, 0x8c, 0x40, 0x80, 0x01, 0x8e, 0x9a, + 0xa2, 0x0f, 0xed, 0xb4, 0x6f, 0xf5, 0xf4, 0xa5, 0x8f, 0xfd, 0x08, 0xfd, 0x18, 0x7d, 0xed, 0x73, + 0x3f, 0x50, 0xe7, 0xfe, 0xe0, 0x70, 0x07, 0x1c, 0x28, 0x95, 0xd3, 0xbc, 0xf1, 0x0e, 0xbb, 0xbf, + 0xfd, 0x73, 0xbb, 0x7b, 0xbb, 0x47, 0x68, 0xba, 0x73, 0xbf, 0x3f, 0x8f, 0x23, 0x12, 0xa1, 0xba, + 0x3b, 0xf7, 0x7b, 0xf7, 0x26, 0x51, 0x34, 0x09, 0xf0, 0x21, 0xdb, 0x7a, 0xbb, 0xf8, 0xdd, 0xe1, + 0x8b, 0xd9, 0x9c, 0xa4, 0x9c, 0xc2, 0x7e, 0x08, 0x30, 0x5a, 0x84, 0xaf, 0x70, 0x92, 0xb8, 0x13, + 0x8c, 0xb6, 0xa1, 0x3e, 0x59, 0x84, 0x5d, 0x6b, 0xcf, 0x3a, 0x68, 0x3a, 0xf4, 0xa7, 0xfd, 0xce, + 0x82, 0x9d, 0x81, 0xe7, 0x3d, 0xc7, 0x01, 0x9e, 0xb8, 0xc4, 0x8f, 0x24, 0x29, 0x82, 0xb5, 0xd0, + 0x9d, 0x61, 0x41, 0xcb, 0x7e, 0xa3, 0x4f, 0x61, 0xcb, 0x93, 0x84, 0x27, 0x38, 0x4d, 0xba, 0xb5, + 0xbd, 0xfa, 0x41, 0xeb, 0x68, 0xab, 0x4f, 0x55, 0x3a, 0x5b, 0xbc, 0x0d, 0xfc, 0xf1, 0x09, 0x4e, + 0x9d, 0x02, 0x15, 0xda, 0x81, 0xf5, 0xb9, 0x4b, 0xa6, 0x49, 0xb7, 0xbe, 0x57, 0x3f, 0x68, 0x3a, + 0x7c, 0x91, 0x29, 0xb3, 0x96, 0x2b, 0xf3, 0x27, 0x78, 0xa4, 0xe9, 0xe2, 0x44, 0x01, 0x1e, 0x84, + 0x1e, 0xc5, 0xf8, 0x2e, 0xd4, 0x12, 0x0a, 0xd4, 0x73, 0x05, 0xde, 0xc0, 0x5d, 0x4d, 0x81, 0x33, + 0xaa, 0xe8, 0x32, 0xd1, 0xd2, 0xb2, 0x9a, 0xc1, 0x32, 0x05, 0x38, 0x85, 0x7d, 0x07, 0xcf, 0xa2, + 0x4b, 0xfc, 0x5c, 0x53, 0x61, 0x10, 0x7a, 0x57, 0x8a, 0xe8, 0x40, 0xe3, 0x02, 0xa7, 0xc7, 0xcf, + 0x33, 0x19, 0x62, 0x75, 0x6d, 0xa7, 0x0e, 0xe1, 0x5e, 0x51, 0x34, 0xf5, 0xeb, 0x32, 0x91, 0x02, + 0xa4, 0x96, 0x83, 0xfc, 0x1a, 0xee, 0x17, 0x41, 0xfe, 0x6f, 0xbe, 0xf9, 0xa6, 0xac, 0xe0, 0x55, + 0x27, 0x5e, 0xe5, 0x93, 0x32, 0xf8, 0x4f, 0xe0, 0x26, 0xb5, 0xf6, 0xd4, 0x9d, 0xa9, 0x16, 0xc7, + 0x51, 0x20, 0x01, 0xe9, 0x6f, 0x83, 0xc5, 0x7f, 0x84, 0x6d, 0x27, 0x22, 0x2e, 0xc1, 0x27, 0x38, + 0x5d, 0xc6, 0xf9, 0x03, 0xd8, 0x4e, 0x70, 0x7c, 0x89, 0xe3, 0x57, 0x6e, 0xe8, 0x4e, 0x70, 0x72, + 0x82, 0x53, 0x06, 0x73, 0xc3, 0x29, 0xed, 0xa3, 0x2e, 0x6c, 0x5c, 0xe0, 0xf4, 0xa5, 0x9f, 0x10, + 0x71, 0x68, 0xd9, 0xd2, 0x70, 0x6c, 0x7f, 0xb1, 0xa0, 0x75, 0x1c, 0xfa, 0x24, 0x93, 0xfd, 0x10, + 0x20, 0x8e, 0x22, 0x72, 0xc2, 0xcd, 0xb6, 0x18, 0xbb, 0xb2, 0x83, 0x06, 0x80, 0x54, 0x79, 0x1e, + 0xb5, 0x3a, 0x61, 0x9a, 0xb4, 0x8e, 0x6e, 0xb1, 0x44, 0xc8, 0xfc, 0x40, 0x05, 0x3a, 0x06, 0x62, + 0x83, 0xf7, 0x9e, 0x40, 0x5b, 0xe5, 0xa2, 0x47, 0x1a, 0x33, 0x5c, 0x2e, 0x9f, 0x2f, 0xec, 0x2f, + 0xe0, 0xb6, 0x4a, 0x95, 0x69, 0x6c, 0x24, 0x36, 0x78, 0xfa, 0xcf, 0x16, 0xec, 0x68, 0xba, 0xe1, + 0x64, 0x1e, 0x85, 0x09, 0x46, 0x3f, 0x86, 0x76, 0xac, 0xec, 0x33, 0xb7, 0x1b, 0x8d, 0xd1, 0xc8, + 0xa8, 0x97, 0x93, 0xc5, 0x78, 0x8c, 0x93, 0x44, 0x1c, 0x44, 0xb6, 0xa4, 0x5f, 0x66, 0x5c, 0x39, + 0x61, 0x64, 0xb6, 0xb4, 0x8f, 0x00, 0xbe, 0x76, 0xe3, 0x09, 0x26, 0x14, 0xe5, 0x9a, 0x39, 0xf1, + 0x6f, 0x0b, 0x1a, 0x9c, 0xa9, 0x5c, 0x57, 0x25, 0x44, 0x4d, 0x8f, 0xda, 0x00, 0x87, 0x13, 0x32, + 0x65, 0xd2, 0xeb, 0x8e, 0x58, 0xa1, 0x43, 0x68, 0x4c, 0xdd, 0x64, 0x8a, 0x93, 0xee, 0x1a, 0xab, + 0x5b, 0xbb, 0xcc, 0x42, 0x0e, 0xdd, 0xff, 0x92, 0x7d, 0x79, 0x11, 0x92, 0x38, 0x75, 0x04, 0x19, + 0x05, 0x1a, 0x2f, 0x12, 0x12, 0xcd, 0xba, 0xeb, 0x7b, 0xd6, 0x41, 0xdb, 0x11, 0xab, 0xde, 0x4f, + 0xa1, 0xa5, 0x90, 0x53, 0xad, 0x2e, 0x70, 0x9a, 0x69, 0x75, 0x81, 0x53, 0x7a, 0x24, 0x97, 0x6e, + 0xb0, 0xe0, 0x6a, 0xb5, 0x1d, 0xbe, 0xf8, 0x59, 0xed, 0x33, 0xcb, 0x3e, 0x86, 0x2d, 0x2e, 0xf0, + 0x8d, 0x4f, 0xa6, 0xd4, 0xb9, 0x68, 0x1f, 0x1a, 0x84, 0xed, 0x08, 0xbf, 0xb7, 0x14, 0xad, 0x1c, + 0xf1, 0x49, 0x66, 0x44, 0x2d, 0xcf, 0x08, 0xfb, 0xaf, 0x16, 0x74, 0x74, 0x2c, 0x79, 0xa2, 0x9f, + 0xc3, 0x16, 0xd1, 0xbe, 0x08, 0xec, 0xdb, 0x0a, 0xb6, 0x64, 0x2a, 0x90, 0xae, 0x74, 0xae, 0xa3, + 0xa2, 0x2a, 0x32, 0x4a, 0x3e, 0x82, 0x0d, 0x8e, 0xcf, 0xe3, 0xb3, 0x42, 0x87, 0x8c, 0xc6, 0xfe, + 0xa7, 0x05, 0x0f, 0xcd, 0x48, 0xd2, 0xb8, 0x73, 0xe8, 0x10, 0x23, 0x85, 0x30, 0xf2, 0x9e, 0x41, + 0x80, 0x04, 0xa9, 0x60, 0x5d, 0xc9, 0xe8, 0x31, 0x20, 0x2e, 0xe5, 0x59, 0x4a, 0x71, 0x06, 0x63, + 0x5a, 0x52, 0x8d, 0x41, 0xfd, 0x7e, 0x96, 0xa2, 0x95, 0x75, 0x42, 0xcf, 0x5a, 0xa5, 0x34, 0x7c, + 0x0b, 0xcd, 0x73, 0x7f, 0x12, 0xba, 0x64, 0x11, 0xb3, 0x54, 0x67, 0x15, 0x58, 0x80, 0xf3, 0x05, + 0x0d, 0xd3, 0x19, 0x26, 0xd3, 0xc8, 0x13, 0xe1, 0x21, 0x56, 0xe8, 0x3e, 0x34, 0x93, 0x8c, 0x95, + 0x41, 0xb6, 0x9d, 0x7c, 0x83, 0xda, 0xe5, 0x27, 0xaf, 0xdd, 0xc0, 0xf7, 0x58, 0x39, 0xbc, 0xe1, + 0x64, 0x4b, 0xfb, 0x57, 0xd0, 0x94, 0x97, 0x39, 0xda, 0x82, 0x9a, 0xef, 0x09, 0x79, 0x35, 0x9f, + 0x81, 0xba, 0xc1, 0x24, 0x8a, 0x7d, 0x32, 0x9d, 0x09, 0x79, 0xf9, 0x06, 0x55, 0x65, 0xce, 0x58, + 0x85, 0x3c, 0xb1, 0xb2, 0x23, 0xb8, 0x95, 0xf7, 0x07, 0xd9, 0x41, 0x7e, 0x9f, 0x11, 0x67, 0xa9, + 0x53, 0xee, 0x23, 0xc4, 0xd7, 0x95, 0xce, 0xe6, 0x3f, 0x16, 0x6c, 0xe9, 0x17, 0x31, 0xfa, 0x18, + 0xd6, 0x2e, 0x68, 0xd3, 0xc2, 0xc3, 0xf0, 0x01, 0x13, 0xa6, 0x93, 0xf4, 0xe9, 0x7d, 0xc8, 0x4b, + 0x00, 0x23, 0x35, 0x56, 0x97, 0xfb, 0xd0, 0x24, 0xd3, 0x18, 0x27, 0xd3, 0x28, 0xf0, 0x98, 0xd4, + 0x75, 0x27, 0xdf, 0xc8, 0x2f, 0xe3, 0x35, 0xe5, 0x32, 0xee, 0x8d, 0xa0, 0x29, 0xa1, 0x0d, 0xe5, + 0xe2, 0x89, 0x5a, 0x2e, 0xca, 0x7e, 0x50, 0xca, 0xc7, 0xdf, 0x2c, 0x68, 0xf3, 0x98, 0xa3, 0x41, + 0x81, 0x3d, 0xf4, 0xbe, 0x72, 0x55, 0x66, 0xb9, 0xa5, 0x1b, 0x25, 0xee, 0xcf, 0xbc, 0xcc, 0xd4, + 0xaa, 0xcb, 0x4c, 0x1f, 0x40, 0x06, 0x08, 0x6f, 0x78, 0x32, 0x6d, 0x64, 0x0c, 0x3a, 0x0a, 0x85, + 0xfd, 0x4b, 0xd8, 0x56, 0xb5, 0x61, 0x99, 0xf4, 0x61, 0x31, 0xe1, 0x6f, 0x29, 0x92, 0x38, 0x5d, + 0x9e, 0xee, 0x7f, 0xb7, 0xa0, 0x5b, 0x44, 0x90, 0xf1, 0x31, 0x80, 0x6d, 0x52, 0xf8, 0x26, 0xec, + 0xbc, 0x53, 0x82, 0x64, 0x8c, 0x25, 0xf2, 0x95, 0x42, 0x67, 0x08, 0x9b, 0xcf, 0xdc, 0xc4, 0x1f, + 0x4b, 0x3d, 0x14, 0x10, 0xab, 0x12, 0xa4, 0xa6, 0x83, 0xfc, 0x1e, 0x1a, 0xc3, 0xa9, 0x1b, 0x4e, + 0xd8, 0x6d, 0xe4, 0xb2, 0xca, 0x20, 0x4e, 0x5c, 0xac, 0x68, 0xa4, 0x24, 0xe3, 0x68, 0x9e, 0x71, + 0xf2, 0x05, 0x8d, 0x38, 0x92, 0xce, 0x33, 0x9d, 0xd8, 0x6f, 0xba, 0x47, 0xc3, 0x48, 0x74, 0x2d, + 0xec, 0x37, 0x95, 0x3c, 0x8e, 0x42, 0x82, 0x43, 0x22, 0xee, 0xa6, 0x6c, 0x69, 0x7f, 0x02, 0xc0, + 0x25, 0x33, 0x07, 0x7c, 0x0f, 0x36, 0xc6, 0x6c, 0x95, 0x9d, 0x06, 0x3f, 0x77, 0x4e, 0xe1, 0x64, + 0xdf, 0xec, 0x14, 0x50, 0xce, 0x24, 0x0d, 0x3f, 0x04, 0xe0, 0x04, 0x41, 0xee, 0xfa, 0x9b, 0x0a, + 0x3f, 0x23, 0x56, 0x48, 0x56, 0x72, 0xf7, 0x53, 0xb8, 0xe1, 0x44, 0x11, 0x61, 0x29, 0x9a, 0xf7, + 0x9b, 0x96, 0xd6, 0x6f, 0x6a, 0x39, 0x57, 0x2b, 0xe4, 0x9c, 0xfd, 0x0d, 0xac, 0x31, 0xee, 0x0f, + 0xe0, 0x46, 0x2c, 0x90, 0x84, 0xb2, 0x9b, 0xa2, 0xd0, 0xf2, 0x4d, 0x47, 0x7e, 0x36, 0x26, 0xb6, + 0xb1, 0xd1, 0xb7, 0x3f, 0xa4, 0xea, 0x05, 0xdc, 0x99, 0x8f, 0xd4, 0x4e, 0xab, 0x75, 0xd4, 0x94, + 0x65, 0x3c, 0xeb, 0xd0, 0xbe, 0xa5, 0xcd, 0x6c, 0xa0, 0x3b, 0x91, 0x69, 0x15, 0xa8, 0x17, 0xd4, + 0xa6, 0xe4, 0x63, 0x84, 0xf2, 0xf3, 0xaa, 0x97, 0x10, 0x45, 0xa2, 0x17, 0x9a, 0xcc, 0xd1, 0xa4, + 0x90, 0xc8, 0xd6, 0x55, 0x89, 0x8c, 0x1e, 0x28, 0xfd, 0x85, 0x66, 0x18, 0x6f, 0x35, 0x5c, 0xe8, + 0x94, 0x85, 0x30, 0x95, 0x47, 0x80, 0xe2, 0xd2, 0x17, 0x21, 0x70, 0x57, 0xc2, 0xe8, 0x9f, 0x1d, + 0x03, 0x0b, 0xbb, 0xf8, 0xcd, 0x32, 0xd4, 0x8b, 0x3f, 0x36, 0x52, 0x68, 0x17, 0x7f, 0x05, 0x48, + 0x05, 0xeb, 0x4a, 0x3e, 0xef, 0xc0, 0xce, 0x30, 0x4e, 0xe7, 0x24, 0x3a, 0xc7, 0xf1, 0xa5, 0x3f, + 0xce, 0x26, 0x1e, 0x7b, 0x0a, 0x3d, 0x6d, 0x7f, 0x18, 0x63, 0x97, 0xc8, 0x79, 0xa8, 0xc7, 0x03, + 0xe1, 0x34, 0x6f, 0x0e, 0xe4, 0xba, 0xdc, 0xf5, 0xea, 0xf7, 0x6c, 0xbd, 0x70, 0xcf, 0xda, 0xa7, + 0xd0, 0x60, 0x55, 0x2e, 0xbe, 0xf6, 0x25, 0xaa, 0x35, 0x03, 0xe2, 0xde, 0x96, 0x1b, 0xf6, 0xbf, + 0x2c, 0x80, 0xb3, 0xd8, 0xbf, 0xe4, 0x73, 0xd8, 0xea, 0xa0, 0xc5, 0x0e, 0x63, 0x1e, 0xfb, 0x97, + 0x14, 0x86, 0x77, 0x03, 0xd9, 0x12, 0x1d, 0x42, 0x7b, 0xcc, 0x1d, 0xc5, 0x8c, 0x60, 0x95, 0x2d, + 0x2b, 0x4d, 0x7c, 0xcb, 0xd1, 0x08, 0x90, 0x0d, 0xed, 0xc4, 0x9f, 0x0c, 0xa4, 0x43, 0xd6, 0x99, + 0x01, 0xda, 0x9e, 0x3d, 0x2b, 0x78, 0x7f, 0xe0, 0x79, 0xca, 0x4c, 0xf9, 0xbf, 0x79, 0xff, 0x31, + 0xbf, 0xa3, 0xeb, 0x4a, 0xc9, 0xcb, 0xdd, 0xc3, 0x2e, 0x6d, 0xfb, 0x1f, 0x16, 0x20, 0x65, 0x2f, + 0x0b, 0xd2, 0x6b, 0x4d, 0xbd, 0xe8, 0x03, 0xdd, 0x35, 0x06, 0x19, 0xd2, 0x57, 0x4a, 0x80, 0xae, + 0x55, 0x06, 0xe8, 0xba, 0x1e, 0xa0, 0x9f, 0x42, 0x9b, 0x8d, 0xab, 0xca, 0x88, 0x68, 0xe8, 0x1b, + 0xcb, 0xa3, 0xd6, 0x6f, 0x01, 0xf1, 0x31, 0x57, 0xcb, 0xbb, 0xaa, 0xaa, 0xbc, 0x62, 0x5f, 0x76, + 0x9f, 0x9e, 0xa9, 0x1f, 0x4e, 0xb8, 0xa4, 0xaf, 0x23, 0x36, 0x14, 0x4b, 0x61, 0x2f, 0x34, 0x61, + 0xad, 0xa3, 0x8f, 0x64, 0x50, 0x54, 0xb1, 0xf4, 0xf9, 0xae, 0x18, 0xdd, 0x56, 0xd7, 0x8d, 0x8e, + 0x75, 0x0a, 0xd4, 0x55, 0x63, 0x5d, 0x53, 0xed, 0xcb, 0x7e, 0x0e, 0x5b, 0xaf, 0x71, 0x9c, 0x28, + 0xef, 0x7a, 0x5d, 0xd8, 0xb8, 0xe4, 0x3b, 0x0c, 0x61, 0xdd, 0xc9, 0x96, 0x65, 0xb7, 0x1f, 0xbd, + 0xdb, 0x86, 0xc6, 0x69, 0x44, 0xdc, 0x38, 0x45, 0x3f, 0x02, 0x38, 0x0e, 0x7d, 0xe2, 0xbb, 0x81, + 0xff, 0x07, 0x8c, 0xb6, 0x99, 0xf1, 0xca, 0xf3, 0x44, 0x0f, 0xb1, 0x1d, 0xad, 0x3f, 0xb1, 0xdf, + 0x43, 0x3f, 0x84, 0x0d, 0x96, 0x9c, 0xc9, 0x14, 0xf1, 0x40, 0xca, 0xdf, 0x22, 0x2b, 0x38, 0xfa, + 0xd0, 0x1c, 0x78, 0x9e, 0x18, 0xab, 0xd5, 0x5e, 0xb0, 0x82, 0xfe, 0x63, 0x68, 0xf3, 0xc7, 0xa3, + 0xeb, 0xb3, 0x9c, 0x42, 0x8b, 0x86, 0x11, 0xa7, 0x49, 0x50, 0xb7, 0x34, 0xf4, 0x64, 0x1a, 0xee, + 0x2f, 0x1b, 0xd8, 0x72, 0xbc, 0x63, 0xb8, 0x39, 0xc2, 0x44, 0x9d, 0xb8, 0x90, 0x3a, 0xc1, 0xab, + 0x43, 0x58, 0xcf, 0x34, 0x03, 0x6a, 0xaa, 0xf5, 0x46, 0x98, 0x0c, 0x82, 0x80, 0x53, 0xbc, 0xc2, + 0xc4, 0xf5, 0x5c, 0xe2, 0x0a, 0xd4, 0x9b, 0x0a, 0x33, 0xdd, 0xe8, 0x3d, 0x30, 0xb7, 0x9b, 0x39, + 0xde, 0xe7, 0xb0, 0x39, 0xc2, 0x64, 0x98, 0x37, 0x42, 0xa5, 0x53, 0xd8, 0x2d, 0xb6, 0x4d, 0x39, + 0xf3, 0x10, 0x9a, 0x6c, 0x87, 0x0d, 0x80, 0x25, 0xc6, 0xfd, 0x65, 0x97, 0x5a, 0x0e, 0xf2, 0x0b, + 0x40, 0x23, 0x4c, 0xf4, 0xce, 0xdf, 0x80, 0x76, 0x47, 0x6f, 0x3d, 0x72, 0xfe, 0xa7, 0xb0, 0xa9, + 0xbd, 0xc8, 0xa2, 0xbb, 0x8c, 0xd2, 0xf4, 0x64, 0x5d, 0x71, 0xdc, 0xaf, 0xa1, 0x5b, 0xf5, 0xa8, + 0x8c, 0x9e, 0x94, 0xc1, 0xca, 0x6f, 0xce, 0x15, 0xb8, 0x5f, 0x01, 0x2a, 0xbf, 0x15, 0xa3, 0x87, + 0x65, 0x44, 0xf5, 0xa1, 0xb4, 0x02, 0xeb, 0x37, 0xe5, 0xe7, 0x55, 0xf5, 0x79, 0x18, 0x1d, 0x70, + 0xf7, 0x5c, 0xfd, 0x82, 0x5c, 0x19, 0xf2, 0x3b, 0xa6, 0x37, 0x60, 0xb4, 0x67, 0xc4, 0x55, 0x9e, + 0x87, 0x2b, 0xf0, 0xce, 0xe0, 0x8e, 0xf1, 0x39, 0x18, 0x3d, 0x36, 0x02, 0xae, 0xa6, 0x21, 0x3b, + 0xa1, 0xbd, 0x4a, 0xcb, 0x97, 0xe3, 0x3d, 0x83, 0x9d, 0x61, 0x80, 0xdd, 0xb8, 0xa8, 0xe0, 0x8e, + 0x96, 0xed, 0xcb, 0x31, 0x9e, 0xc2, 0xc6, 0x1b, 0x9f, 0x84, 0xac, 0x38, 0x57, 0x16, 0x89, 0xbb, + 0xe5, 0x37, 0x93, 0x1c, 0xe1, 0x33, 0x68, 0xca, 0x47, 0x64, 0x94, 0xc5, 0xb8, 0xfe, 0xa8, 0x5c, + 0x21, 0xfb, 0x0b, 0xd8, 0xd4, 0x9a, 0x86, 0x72, 0xca, 0x70, 0xc1, 0xc6, 0x7e, 0x8f, 0x1e, 0xd0, + 0x6d, 0x43, 0xc7, 0x87, 0x1e, 0x95, 0x79, 0xb4, 0x5e, 0xb0, 0xd7, 0x29, 0x34, 0x54, 0xb9, 0x42, + 0x2f, 0x0b, 0x88, 0xbc, 0x8b, 0x31, 0x21, 0x6a, 0xfd, 0x4d, 0xe5, 0xf1, 0xe8, 0x68, 0x23, 0x4c, + 0x28, 0x1a, 0x1f, 0xc9, 0xd5, 0x16, 0x61, 0x89, 0x46, 0x5f, 0x15, 0xfa, 0xaa, 0x11, 0x26, 0x4a, + 0xab, 0x68, 0x80, 0xda, 0x2d, 0xf6, 0x32, 0x39, 0xd6, 0x00, 0x3a, 0x1a, 0x16, 0x0f, 0xb8, 0x0a, + 0x1c, 0xb3, 0x49, 0x5f, 0xc2, 0x1d, 0x0d, 0x82, 0x86, 0x02, 0xff, 0xf7, 0xcb, 0x18, 0x72, 0xbb, + 0x39, 0x6e, 0xb1, 0x66, 0x9e, 0x41, 0xb7, 0x84, 0x34, 0x08, 0x02, 0x06, 0x56, 0x0a, 0x83, 0xc7, + 0x57, 0xf6, 0x21, 0xcc, 0xdd, 0xb7, 0xce, 0x31, 0x79, 0x89, 0x27, 0xee, 0x38, 0x15, 0xfd, 0x40, + 0x82, 0xf8, 0xa3, 0x8c, 0xde, 0x1e, 0xf4, 0x3a, 0x7d, 0xfe, 0x6f, 0x62, 0x3f, 0xfb, 0x37, 0xb1, + 0xcf, 0xfe, 0x4d, 0xb4, 0xdf, 0x7b, 0xdb, 0x60, 0x3b, 0x9f, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, + 0x5a, 0xe0, 0xd0, 0x0b, 0x7f, 0x1c, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index bacb5ab58..c8ce639c3 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -7,7 +7,7 @@ import "google/protobuf/Empty.proto"; // Notary Interface service Notary { rpc Initialize(InitMessage) returns (BasicResponse) {} - rpc Publish(google.protobuf.Empty) returns (BasicResponse) {} + rpc Publish(GunMessage) returns (BasicResponse) {} // AddTarget adds a target to the TUF repository and re-signs. rpc AddTarget(Target) returns (BasicResponse) {} @@ -15,17 +15,17 @@ service Notary { // uses the `name` field from the Target object, ignoring all other fields rpc RemoveTarget(Target) returns (BasicResponse) {} // ListTargets list the targets for the specified roles in the TUF repository - rpc ListTargets(RoleNameList) returns (TargetWithRoleNameListResponse) {} + rpc ListTargets(RoleNameListMessage) returns (TargetWithRoleNameListResponse) {} // GetTargetByName returns a target by the given name. rpc GetTargetByName(TargetByNameAction) returns (TargetWithRoleResponse) {} // GetAllTargetMetadataByName rpc GetAllTargetMetadataByName(TargetName) returns (TargetSignedListResponse) {} // GetChangelist returns the list of the repository's unpublished changes - rpc GetChangelist(google.protobuf.Empty) returns (ChangeListResponse) {} + rpc GetChangelist(GunMessage) returns (ChangeListResponse) {} - rpc ListRoles(google.protobuf.Empty) returns (RoleWithSignaturesListResponse) {} - rpc GetDelegationRoles(google.protobuf.Empty) returns (RoleListResponse) {} + rpc ListRoles(GunMessage) returns (RoleWithSignaturesListResponse) {} + rpc GetDelegationRoles(GunMessage) returns (RoleListResponse) {} rpc AddDelegation(AddDelegationMessage) returns (BasicResponse) {} rpc AddDelegationRoleAndKeys(AddDelegationRoleAndKeysMessage) returns (BasicResponse) {} rpc AddDelegationPaths(AddDelegationPathsMessage) returns (BasicResponse) {} @@ -35,67 +35,80 @@ service Notary { rpc RemoveDelegationKeys(RemoveDelegationKeysMessage) returns (BasicResponse) {} rpc ClearDelegationPaths(RoleNameMessage) returns (BasicResponse) {} - rpc Witness(RoleNameList) returns (RoleNameListResponse) {} + rpc Witness(RoleNameListMessage) returns (RoleNameListResponse) {} rpc RotateKey(RotateKeyMessage) returns (BasicResponse) {} // CryptoService implementation - rpc CryptoService(google.protobuf.Empty) returns (CryptoServiceMessage) {} + rpc CryptoService(GunMessage) returns (CryptoServiceMessage) {} rpc CryptoServiceCreate(CryptoServiceCreateMessage) returns (PublicKeyResponse) {} rpc CryptoServiceAddKey(CryptoServiceAddKeyMessage) returns (BasicResponse) {} rpc CryptoServiceGetKey(KeyIDMessage) returns (PublicKeyResponse) {} rpc CryptoServiceGetPrivateKey(KeyIDMessage) returns (PrivateKeyResponse) {} rpc CryptoServiceRemoveKey(KeyIDMessage) returns (BasicResponse) {} rpc CryptoServiceListKeys(RoleNameMessage) returns (KeyIDsListResponse) {} - rpc CryptoServiceListAllKeys(google.protobuf.Empty) returns (SigningKeyIDsToRolesResponse) {} + rpc CryptoServiceListAllKeys(GunMessage) returns (SigningKeyIDsToRolesResponse) {} rpc SetLegacyVersions(VersionMessage) returns (google.protobuf.Empty) {} } +message GunMessage { + string gun = 1; +} + message AddDelegationMessage { string name = 1; repeated PublicKey delegationKeys = 2; repeated string paths = 3; + string gun = 4; } message AddDelegationRoleAndKeysMessage { string name = 1; repeated PublicKey delegationKeys = 2; + string gun = 3; } message AddDelegationPathsMessage { string name = 1; repeated string paths = 2; + string gun = 3; } message RemoveDelegationKeysAndPathsMessage { string name = 1; repeated string keyIDs = 2; repeated string paths = 3; + string gun = 4; } message RemoveDelegationRoleMessage { string name = 1; + string gun = 2; } message RemoveDelegationPathsMessage { string name = 1; repeated string paths = 2; + string gun = 3; } message RemoveDelegationKeysMessage { string name = 1; repeated string keyIDs = 2; + string gun = 3; } message RoleNameMessage { string role = 1; + string gun = 2; } message RotateKeyMessage { string role = 1; bool serverManagesKey = 2; repeated string keyList = 3; + string gun = 4; } // InitMessage holds a list of root key IDs and a list of roles for which @@ -103,6 +116,7 @@ message RotateKeyMessage { message InitMessage { repeated string rootKeyIDs = 1; RoleNameList serverManagedRoles = 2; + string gun = 3; } // RoleNameList message holds a list of TUF role names @@ -110,6 +124,11 @@ message RoleNameList { repeated string roles = 1; } +message RoleNameListMessage { + repeated string roles = 1; + string gun = 2; +} + message RoleNameListResponse { RoleNameList roleNameList = 1; bool success = 2; @@ -118,6 +137,7 @@ message RoleNameListResponse { message TargetName { string name = 1; + string gun = 2; } // Target message describes a TUF target @@ -154,6 +174,7 @@ message TargetWithRoleNameListResponse { message TargetByNameAction { string name = 1; RoleNameList roles = 2; + string gun = 3; } message Signature { @@ -302,6 +323,7 @@ message PrivateKeyResponse { message KeyIDMessage { string keyID = 1; + string gun = 2; } message KeyIDsListResponse { @@ -318,5 +340,6 @@ message SigningKeyIDsToRolesResponse { message VersionMessage { int32 version = 1; + string gun = 2; } diff --git a/client_api/api/client.go b/client_api/api/client.go index 48a92b0f9..64632219c 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -1,8 +1,8 @@ package api import ( - "google.golang.org/grpc" google_protobuf "github.com/golang/protobuf/ptypes/empty" + "google.golang.org/grpc" "github.com/docker/notary/client" "github.com/docker/notary/client/changelist" @@ -31,8 +31,8 @@ func (c *Client) Initialize(rootKeyIDs []string, serverManagedRoles ...data.Role } initMsg := &InitMessage{ - RootKeyIDs: rootKeyIDs, - ServerManagedRoles: &RoleNameList{Roles:roles}, + RootKeyIDs: rootKeyIDs, + ServerManagedRoles: &RoleNameList{Roles: roles}, } _, err := c.client.Initialize(context.Background(), initMsg) return err @@ -73,7 +73,7 @@ func (c *Client) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, rolesList[index] = value.String() } - targetWithRoleList, err := c.client.ListTargets(context.Background(), &RoleNameList{Roles:rolesList}) + targetWithRoleList, err := c.client.ListTargets(context.Background(), &RoleNameList{Roles: rolesList}) if err != nil { return []*client.TargetWithRole{}, err } @@ -86,7 +86,7 @@ func (c *Client) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, r := target.Role currTarget := client.Target{ - Name: t.GetName(), + Name: t.GetName(), Hashes: data.Hashes(t.Hashes), Length: t.GetLength(), } @@ -95,7 +95,7 @@ func (c *Client) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, targetWithRole := &client.TargetWithRole{ Target: currTarget, - Role: currRole, + Role: currRole, } res[index] = targetWithRole @@ -111,8 +111,8 @@ func (c *Client) GetTargetByName(name string, roles ...data.RoleName) (*client.T } targetByNameAction := &TargetByNameAction{ - Name: name, - Roles: &RoleNameList{Roles:rolesList}, + Name: name, + Roles: &RoleNameList{Roles: rolesList}, } targetWithRole, err := c.client.GetTargetByName(context.Background(), targetByNameAction) @@ -125,7 +125,7 @@ func (c *Client) GetTargetByName(name string, roles ...data.RoleName) (*client.T res := &client.TargetWithRole{ Target: client.Target{ - Name: target.GetName(), + Name: target.GetName(), Hashes: data.Hashes(target.Hashes), Length: target.GetLength(), }, @@ -153,9 +153,8 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS s := value.Signatures t := value.Target - currTarget := client.Target{ - Name: t.Name, + Name: t.Name, Hashes: t.Hashes, Length: t.Length, } @@ -164,9 +163,9 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS for indexS, sig := range s { currSignature := data.Signature{ Signature: sig.Signature, - KeyID: sig.KeyID, - IsValid: sig.IsValid, - Method: data.SigAlgorithm(sig.Method), + KeyID: sig.KeyID, + IsValid: sig.IsValid, + Method: data.SigAlgorithm(sig.Method), } currSignatures[indexS] = currSignature @@ -179,16 +178,16 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS currRole := data.DelegationRole{ BaseRole: data.BaseRole{ - Keys: currKeys, - Name: data.RoleName(r.Name), + Keys: currKeys, + Name: data.RoleName(r.Name), Threshold: int(r.Threshold), // FIXME }, Paths: r.Paths, } res[indexT] = client.TargetSignedStruct{ - Role: currRole, - Target: currTarget, + Role: currRole, + Target: currTarget, Signatures: currSignatures, } } @@ -231,9 +230,9 @@ func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { for indexSig, sig := range value.Signatures { currSignature := data.Signature{ Signature: sig.Signature, - KeyID: sig.KeyID, - IsValid: sig.IsValid, - Method: data.SigAlgorithm(sig.Method), + KeyID: sig.KeyID, + IsValid: sig.IsValid, + Method: data.SigAlgorithm(sig.Method), } currSignatures[indexSig] = currSignature @@ -241,16 +240,16 @@ func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { currRole := data.Role{ RootRole: data.RootRole{ - KeyIDs: r.RootRole.KeyIDs, + KeyIDs: r.RootRole.KeyIDs, Threshold: int(r.RootRole.Threshold), // FIXME }, - Name: data.RoleName(r.Name), + Name: data.RoleName(r.Name), Paths: r.Paths, } res[index] = client.RoleWithSignatures{ Signatures: currSignatures, - Role: currRole, + Role: currRole, } } @@ -267,10 +266,10 @@ func (c *Client) GetDelegationRoles() ([]data.Role, error) { for index, role := range roleListResp.RoleList.Roles { currRole := data.Role{ RootRole: data.RootRole{ - KeyIDs: role.RootRole.KeyIDs, + KeyIDs: role.RootRole.KeyIDs, Threshold: int(role.RootRole.Threshold), }, - Name: data.RoleName(role.Name), + Name: data.RoleName(role.Name), Paths: role.Paths, } @@ -284,16 +283,16 @@ func (c *Client) AddDelegation(name data.RoleName, delegationKeys []data.PublicK currDelegationKeys := make([]*PublicKey, len(delegationKeys)) for index, key := range delegationKeys { currDelegationKeys[index] = &PublicKey{ - Id: key.ID(), + Id: key.ID(), Algorithm: key.Algorithm(), - Public: key.Public(), + Public: key.Public(), } } addDelegationMessage := &AddDelegationMessage{ - Name: name.String(), + Name: name.String(), DelegationKeys: currDelegationKeys, - Paths: paths, + Paths: paths, } _, err := c.client.AddDelegation(context.Background(), addDelegationMessage) @@ -304,14 +303,14 @@ func (c *Client) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []d pubKeys := make([]*PublicKey, len(delegationKeys)) for index, delegationKey := range delegationKeys { pubKeys[index] = &PublicKey{ - Id: delegationKey.ID(), + Id: delegationKey.ID(), Algorithm: delegationKey.Algorithm(), - Public: delegationKey.Public(), + Public: delegationKey.Public(), } } addDelegationRoleAndKeysMessage := &AddDelegationRoleAndKeysMessage{ - Name: name.String(), + Name: name.String(), DelegationKeys: pubKeys, } @@ -321,7 +320,7 @@ func (c *Client) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []d func (c *Client) AddDelegationPaths(name data.RoleName, paths []string) error { addDelegationPathsMessage := &AddDelegationPathsMessage{ - Name: name.String(), + Name: name.String(), Paths: paths, } @@ -331,9 +330,9 @@ func (c *Client) AddDelegationPaths(name data.RoleName, paths []string) error { func (c *Client) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error { r := &RemoveDelegationKeysAndPathsMessage{ - Name: name.String(), + Name: name.String(), KeyIDs: keyIDs, - Paths: paths, + Paths: paths, } _, err := c.client.RemoveDelegationKeysAndPaths(context.Background(), r) @@ -351,7 +350,7 @@ func (c *Client) RemoveDelegationRole(name data.RoleName) error { func (c *Client) RemoveDelegationPaths(name data.RoleName, paths []string) error { r := &RemoveDelegationPathsMessage{ - Name: name.String(), + Name: name.String(), Paths: paths, } @@ -361,7 +360,7 @@ func (c *Client) RemoveDelegationPaths(name data.RoleName, paths []string) error func (c *Client) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error { r := &RemoveDelegationKeysMessage{ - Name: name.String(), + Name: name.String(), KeyIDs: keyIDs, } @@ -405,9 +404,9 @@ func (c *Client) Witness(roles ...data.RoleName) ([]data.RoleName, error) { func (c *Client) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error { rotateKeyMessage := &RotateKeyMessage{ - Role: role.String(), + Role: role.String(), ServerManagesKey: serverManagesKey, - KeyList: keyList, + KeyList: keyList, } _, err := c.client.RotateKey(context.Background(), rotateKeyMessage) return err diff --git a/client_api/api/server.go b/client_api/api/server.go index 0fc61e16b..9a520e8eb 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -4,9 +4,9 @@ import ( "path/filepath" "github.com/Sirupsen/logrus" + google_protobuf "github.com/golang/protobuf/ptypes/empty" "golang.org/x/net/context" "google.golang.org/grpc" - google_protobuf "github.com/golang/protobuf/ptypes/empty" "github.com/docker/notary" "github.com/docker/notary/client" @@ -108,7 +108,6 @@ func (srv *Server) ListRoles(context.Context, *google_protobuf.Empty) (*RoleWith return nil, ErrNotImplemented } - func (srv *Server) GetDelegationRoles(context.Context, *google_protobuf.Empty) (*RoleListResponse, error) { return nil, ErrNotImplemented } @@ -145,7 +144,6 @@ func (srv *Server) ClearDelegationPaths(context.Context, *RoleNameMessage) (*Bas return nil, ErrNotImplemented } - func (srv *Server) Witness(context.Context, *RoleNameList) (*RoleNameListResponse, error) { return nil, ErrNotImplemented } @@ -154,18 +152,42 @@ func (srv *Server) RotateKey(context.Context, *RotateKeyMessage) (*BasicResponse return nil, ErrNotImplemented } - // CryptoService implementation -func (srv *Server) CryptoService(context.Context, *google_protobuf.Empty) (*CryptoServiceMessage, error) -func (srv *Server) CryptoServiceCreate(context.Context, *CryptoServiceCreateMessage) (*PublicKeyResponse, error) -func (srv *Server) CryptoServiceAddKey(context.Context, *CryptoServiceAddKeyMessage) (*BasicResponse, error) -func (srv *Server) CryptoServiceGetKey(context.Context, *KeyIDMessage) (*PublicKeyResponse, error) -func (srv *Server) CryptoServiceGetPrivateKey(context.Context, *KeyIDMessage) (*PrivateKeyResponse, error) -func (srv *Server) CryptoServiceRemoveKey(context.Context, *KeyIDMessage) (*BasicResponse, error) -func (srv *Server) CryptoServiceListKeys(context.Context, *RoleNameMessage) (*KeyIDsListResponse, error) -func (srv *Server) CryptoServiceListAllKeys(context.Context, *google_protobuf.Empty) (*SigningKeyIDsToRolesResponse, error) +func (srv *Server) CryptoService(context.Context, *google_protobuf.Empty) (*CryptoServiceMessage, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) CryptoServiceCreate(context.Context, *CryptoServiceCreateMessage) (*PublicKeyResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) CryptoServiceAddKey(context.Context, *CryptoServiceAddKeyMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} -SetLegacyVersions(context.Context, *VersionMessage) (*google_protobuf.Empty, error) +func (srv *Server) CryptoServiceGetKey(context.Context, *KeyIDMessage) (*PublicKeyResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) CryptoServiceGetPrivateKey(context.Context, *KeyIDMessage) (*PrivateKeyResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) CryptoServiceRemoveKey(context.Context, *KeyIDMessage) (*BasicResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) CryptoServiceListKeys(context.Context, *RoleNameMessage) (*KeyIDsListResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) CryptoServiceListAllKeys(context.Context, *google_protobuf.Empty) (*SigningKeyIDsToRolesResponse, error) { + return nil, ErrNotImplemented +} + +func (srv *Server) SetLegacyVersions(context.Context, *VersionMessage) (*google_protobuf.Empty, error) { + return nil, ErrNotImplemented +} func publishRepo(r *client.NotaryRepository) error { if err := r.Publish(); err != nil { @@ -244,7 +266,7 @@ func retriever(keyName, alias string, createNew bool, attempts int) (string, boo func DefaultPermissions() map[string][]string { return map[string][]string{ - "/api.Notary/AddTarget": {"push", "pull"}, + "/api.Notary/AddTarget": {"push", "pull"}, "/api.Notary/RemoveTarget": {"push", "pull"}, } -} \ No newline at end of file +} diff --git a/cmd/clientapi/setup/config.go b/cmd/clientapi/setup/config.go index 3755c18c7..0dc762cf4 100644 --- a/cmd/clientapi/setup/config.go +++ b/cmd/clientapi/setup/config.go @@ -8,10 +8,10 @@ import ( "github.com/spf13/viper" "net" + "github.com/docker/notary/utils/grpcauth" "google.golang.org/grpc" ghealth "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" - "github.com/docker/notary/utils/grpcauth" ) func ViperConfig(path string) (*viper.Viper, error) { From 270b9f3984775ce79f9a04000dcba71e7f46b136 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 14 Mar 2017 16:04:24 +0100 Subject: [PATCH 29/62] Add GUN parameters to client side of client api Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 274 +++++++++++++++++++-------------------- client_api/api/api.proto | 4 +- client_api/api/client.go | 41 +++--- 3 files changed, 161 insertions(+), 158 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index 7bb0c1cec..d335afa48 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -23,7 +23,7 @@ It has these top-level messages: RoleNameList RoleNameListMessage RoleNameListResponse - TargetName + TargetNameMessage Target TargetWithRole TargetWithRoleResponse @@ -503,24 +503,24 @@ func (m *RoleNameListResponse) GetMessage() string { return "" } -type TargetName struct { +type TargetNameMessage struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` } -func (m *TargetName) Reset() { *m = TargetName{} } -func (m *TargetName) String() string { return proto.CompactTextString(m) } -func (*TargetName) ProtoMessage() {} -func (*TargetName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (m *TargetNameMessage) Reset() { *m = TargetNameMessage{} } +func (m *TargetNameMessage) String() string { return proto.CompactTextString(m) } +func (*TargetNameMessage) ProtoMessage() {} +func (*TargetNameMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } -func (m *TargetName) GetName() string { +func (m *TargetNameMessage) GetName() string { if m != nil { return m.Name } return "" } -func (m *TargetName) GetGun() string { +func (m *TargetNameMessage) GetGun() string { if m != nil { return m.Gun } @@ -1559,7 +1559,7 @@ func init() { proto.RegisterType((*RoleNameList)(nil), "api.RoleNameList") proto.RegisterType((*RoleNameListMessage)(nil), "api.RoleNameListMessage") proto.RegisterType((*RoleNameListResponse)(nil), "api.RoleNameListResponse") - proto.RegisterType((*TargetName)(nil), "api.TargetName") + proto.RegisterType((*TargetNameMessage)(nil), "api.TargetNameMessage") proto.RegisterType((*Target)(nil), "api.Target") proto.RegisterType((*TargetWithRole)(nil), "api.TargetWithRole") proto.RegisterType((*TargetWithRoleResponse)(nil), "api.TargetWithRoleResponse") @@ -1619,7 +1619,7 @@ type NotaryClient interface { // GetTargetByName returns a target by the given name. GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName - GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedListResponse, error) + GetAllTargetMetadataByName(ctx context.Context, in *TargetNameMessage, opts ...grpc.CallOption) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes GetChangelist(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*ChangeListResponse, error) ListRoles(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) @@ -1708,7 +1708,7 @@ func (c *notaryClient) GetTargetByName(ctx context.Context, in *TargetByNameActi return out, nil } -func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *TargetName, opts ...grpc.CallOption) (*TargetSignedListResponse, error) { +func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *TargetNameMessage, opts ...grpc.CallOption) (*TargetSignedListResponse, error) { out := new(TargetSignedListResponse) err := grpc.Invoke(ctx, "/api.Notary/GetAllTargetMetadataByName", in, out, c.cc, opts...) if err != nil { @@ -1930,7 +1930,7 @@ type NotaryServer interface { // GetTargetByName returns a target by the given name. GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName - GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedListResponse, error) + GetAllTargetMetadataByName(context.Context, *TargetNameMessage) (*TargetSignedListResponse, error) // GetChangelist returns the list of the repository's unpublished changes GetChangelist(context.Context, *GunMessage) (*ChangeListResponse, error) ListRoles(context.Context, *GunMessage) (*RoleWithSignaturesListResponse, error) @@ -2070,7 +2070,7 @@ func _Notary_GetTargetByName_Handler(srv interface{}, ctx context.Context, dec f } func _Notary_GetAllTargetMetadataByName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(TargetName) + in := new(TargetNameMessage) if err := dec(in); err != nil { return nil, err } @@ -2082,7 +2082,7 @@ func _Notary_GetAllTargetMetadataByName_Handler(srv interface{}, ctx context.Con FullMethod: "/api.Notary/GetAllTargetMetadataByName", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).GetAllTargetMetadataByName(ctx, req.(*TargetName)) + return srv.(NotaryServer).GetAllTargetMetadataByName(ctx, req.(*TargetNameMessage)) } return interceptor(ctx, in, info, handler) } @@ -2611,127 +2611,127 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1944 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0x5f, 0x73, 0xdb, 0xc6, - 0x11, 0x0f, 0x48, 0x89, 0x32, 0x97, 0x94, 0x2c, 0x9f, 0x65, 0x8a, 0xa6, 0xff, 0xc9, 0x90, 0xdb, - 0x28, 0xcd, 0x84, 0x6a, 0x94, 0x36, 0x4d, 0x9b, 0xa6, 0x35, 0x4d, 0x7b, 0x18, 0x45, 0xb6, 0x46, - 0x85, 0x32, 0xf6, 0x4c, 0x33, 0xd3, 0x29, 0x4c, 0x5c, 0x49, 0x8c, 0x40, 0x80, 0x01, 0x8e, 0x9a, - 0xa2, 0x0f, 0xed, 0xb4, 0x6f, 0xf5, 0xf4, 0xa5, 0x8f, 0xfd, 0x08, 0xfd, 0x18, 0x7d, 0xed, 0x73, - 0x3f, 0x50, 0xe7, 0xfe, 0xe0, 0x70, 0x07, 0x1c, 0x28, 0x95, 0xd3, 0xbc, 0xf1, 0x0e, 0xbb, 0xbf, - 0xfd, 0x73, 0xbb, 0x7b, 0xbb, 0x47, 0x68, 0xba, 0x73, 0xbf, 0x3f, 0x8f, 0x23, 0x12, 0xa1, 0xba, - 0x3b, 0xf7, 0x7b, 0xf7, 0x26, 0x51, 0x34, 0x09, 0xf0, 0x21, 0xdb, 0x7a, 0xbb, 0xf8, 0xdd, 0xe1, - 0x8b, 0xd9, 0x9c, 0xa4, 0x9c, 0xc2, 0x7e, 0x08, 0x30, 0x5a, 0x84, 0xaf, 0x70, 0x92, 0xb8, 0x13, - 0x8c, 0xb6, 0xa1, 0x3e, 0x59, 0x84, 0x5d, 0x6b, 0xcf, 0x3a, 0x68, 0x3a, 0xf4, 0xa7, 0xfd, 0xce, - 0x82, 0x9d, 0x81, 0xe7, 0x3d, 0xc7, 0x01, 0x9e, 0xb8, 0xc4, 0x8f, 0x24, 0x29, 0x82, 0xb5, 0xd0, - 0x9d, 0x61, 0x41, 0xcb, 0x7e, 0xa3, 0x4f, 0x61, 0xcb, 0x93, 0x84, 0x27, 0x38, 0x4d, 0xba, 0xb5, - 0xbd, 0xfa, 0x41, 0xeb, 0x68, 0xab, 0x4f, 0x55, 0x3a, 0x5b, 0xbc, 0x0d, 0xfc, 0xf1, 0x09, 0x4e, - 0x9d, 0x02, 0x15, 0xda, 0x81, 0xf5, 0xb9, 0x4b, 0xa6, 0x49, 0xb7, 0xbe, 0x57, 0x3f, 0x68, 0x3a, - 0x7c, 0x91, 0x29, 0xb3, 0x96, 0x2b, 0xf3, 0x27, 0x78, 0xa4, 0xe9, 0xe2, 0x44, 0x01, 0x1e, 0x84, - 0x1e, 0xc5, 0xf8, 0x2e, 0xd4, 0x12, 0x0a, 0xd4, 0x73, 0x05, 0xde, 0xc0, 0x5d, 0x4d, 0x81, 0x33, - 0xaa, 0xe8, 0x32, 0xd1, 0xd2, 0xb2, 0x9a, 0xc1, 0x32, 0x05, 0x38, 0x85, 0x7d, 0x07, 0xcf, 0xa2, - 0x4b, 0xfc, 0x5c, 0x53, 0x61, 0x10, 0x7a, 0x57, 0x8a, 0xe8, 0x40, 0xe3, 0x02, 0xa7, 0xc7, 0xcf, - 0x33, 0x19, 0x62, 0x75, 0x6d, 0xa7, 0x0e, 0xe1, 0x5e, 0x51, 0x34, 0xf5, 0xeb, 0x32, 0x91, 0x02, - 0xa4, 0x96, 0x83, 0xfc, 0x1a, 0xee, 0x17, 0x41, 0xfe, 0x6f, 0xbe, 0xf9, 0xa6, 0xac, 0xe0, 0x55, - 0x27, 0x5e, 0xe5, 0x93, 0x32, 0xf8, 0x4f, 0xe0, 0x26, 0xb5, 0xf6, 0xd4, 0x9d, 0xa9, 0x16, 0xc7, - 0x51, 0x20, 0x01, 0xe9, 0x6f, 0x83, 0xc5, 0x7f, 0x84, 0x6d, 0x27, 0x22, 0x2e, 0xc1, 0x27, 0x38, - 0x5d, 0xc6, 0xf9, 0x03, 0xd8, 0x4e, 0x70, 0x7c, 0x89, 0xe3, 0x57, 0x6e, 0xe8, 0x4e, 0x70, 0x72, - 0x82, 0x53, 0x06, 0x73, 0xc3, 0x29, 0xed, 0xa3, 0x2e, 0x6c, 0x5c, 0xe0, 0xf4, 0xa5, 0x9f, 0x10, - 0x71, 0x68, 0xd9, 0xd2, 0x70, 0x6c, 0x7f, 0xb1, 0xa0, 0x75, 0x1c, 0xfa, 0x24, 0x93, 0xfd, 0x10, - 0x20, 0x8e, 0x22, 0x72, 0xc2, 0xcd, 0xb6, 0x18, 0xbb, 0xb2, 0x83, 0x06, 0x80, 0x54, 0x79, 0x1e, - 0xb5, 0x3a, 0x61, 0x9a, 0xb4, 0x8e, 0x6e, 0xb1, 0x44, 0xc8, 0xfc, 0x40, 0x05, 0x3a, 0x06, 0x62, - 0x83, 0xf7, 0x9e, 0x40, 0x5b, 0xe5, 0xa2, 0x47, 0x1a, 0x33, 0x5c, 0x2e, 0x9f, 0x2f, 0xec, 0x2f, - 0xe0, 0xb6, 0x4a, 0x95, 0x69, 0x6c, 0x24, 0x36, 0x78, 0xfa, 0xcf, 0x16, 0xec, 0x68, 0xba, 0xe1, - 0x64, 0x1e, 0x85, 0x09, 0x46, 0x3f, 0x86, 0x76, 0xac, 0xec, 0x33, 0xb7, 0x1b, 0x8d, 0xd1, 0xc8, - 0xa8, 0x97, 0x93, 0xc5, 0x78, 0x8c, 0x93, 0x44, 0x1c, 0x44, 0xb6, 0xa4, 0x5f, 0x66, 0x5c, 0x39, - 0x61, 0x64, 0xb6, 0xb4, 0x8f, 0x00, 0xbe, 0x76, 0xe3, 0x09, 0x26, 0x14, 0xe5, 0x9a, 0x39, 0xf1, - 0x6f, 0x0b, 0x1a, 0x9c, 0xa9, 0x5c, 0x57, 0x25, 0x44, 0x4d, 0x8f, 0xda, 0x00, 0x87, 0x13, 0x32, - 0x65, 0xd2, 0xeb, 0x8e, 0x58, 0xa1, 0x43, 0x68, 0x4c, 0xdd, 0x64, 0x8a, 0x93, 0xee, 0x1a, 0xab, - 0x5b, 0xbb, 0xcc, 0x42, 0x0e, 0xdd, 0xff, 0x92, 0x7d, 0x79, 0x11, 0x92, 0x38, 0x75, 0x04, 0x19, - 0x05, 0x1a, 0x2f, 0x12, 0x12, 0xcd, 0xba, 0xeb, 0x7b, 0xd6, 0x41, 0xdb, 0x11, 0xab, 0xde, 0x4f, - 0xa1, 0xa5, 0x90, 0x53, 0xad, 0x2e, 0x70, 0x9a, 0x69, 0x75, 0x81, 0x53, 0x7a, 0x24, 0x97, 0x6e, - 0xb0, 0xe0, 0x6a, 0xb5, 0x1d, 0xbe, 0xf8, 0x59, 0xed, 0x33, 0xcb, 0x3e, 0x86, 0x2d, 0x2e, 0xf0, - 0x8d, 0x4f, 0xa6, 0xd4, 0xb9, 0x68, 0x1f, 0x1a, 0x84, 0xed, 0x08, 0xbf, 0xb7, 0x14, 0xad, 0x1c, - 0xf1, 0x49, 0x66, 0x44, 0x2d, 0xcf, 0x08, 0xfb, 0xaf, 0x16, 0x74, 0x74, 0x2c, 0x79, 0xa2, 0x9f, - 0xc3, 0x16, 0xd1, 0xbe, 0x08, 0xec, 0xdb, 0x0a, 0xb6, 0x64, 0x2a, 0x90, 0xae, 0x74, 0xae, 0xa3, - 0xa2, 0x2a, 0x32, 0x4a, 0x3e, 0x82, 0x0d, 0x8e, 0xcf, 0xe3, 0xb3, 0x42, 0x87, 0x8c, 0xc6, 0xfe, - 0xa7, 0x05, 0x0f, 0xcd, 0x48, 0xd2, 0xb8, 0x73, 0xe8, 0x10, 0x23, 0x85, 0x30, 0xf2, 0x9e, 0x41, - 0x80, 0x04, 0xa9, 0x60, 0x5d, 0xc9, 0xe8, 0x31, 0x20, 0x2e, 0xe5, 0x59, 0x4a, 0x71, 0x06, 0x63, - 0x5a, 0x52, 0x8d, 0x41, 0xfd, 0x7e, 0x96, 0xa2, 0x95, 0x75, 0x42, 0xcf, 0x5a, 0xa5, 0x34, 0x7c, - 0x0b, 0xcd, 0x73, 0x7f, 0x12, 0xba, 0x64, 0x11, 0xb3, 0x54, 0x67, 0x15, 0x58, 0x80, 0xf3, 0x05, - 0x0d, 0xd3, 0x19, 0x26, 0xd3, 0xc8, 0x13, 0xe1, 0x21, 0x56, 0xe8, 0x3e, 0x34, 0x93, 0x8c, 0x95, - 0x41, 0xb6, 0x9d, 0x7c, 0x83, 0xda, 0xe5, 0x27, 0xaf, 0xdd, 0xc0, 0xf7, 0x58, 0x39, 0xbc, 0xe1, - 0x64, 0x4b, 0xfb, 0x57, 0xd0, 0x94, 0x97, 0x39, 0xda, 0x82, 0x9a, 0xef, 0x09, 0x79, 0x35, 0x9f, - 0x81, 0xba, 0xc1, 0x24, 0x8a, 0x7d, 0x32, 0x9d, 0x09, 0x79, 0xf9, 0x06, 0x55, 0x65, 0xce, 0x58, - 0x85, 0x3c, 0xb1, 0xb2, 0x23, 0xb8, 0x95, 0xf7, 0x07, 0xd9, 0x41, 0x7e, 0x9f, 0x11, 0x67, 0xa9, - 0x53, 0xee, 0x23, 0xc4, 0xd7, 0x95, 0xce, 0xe6, 0x3f, 0x16, 0x6c, 0xe9, 0x17, 0x31, 0xfa, 0x18, - 0xd6, 0x2e, 0x68, 0xd3, 0xc2, 0xc3, 0xf0, 0x01, 0x13, 0xa6, 0x93, 0xf4, 0xe9, 0x7d, 0xc8, 0x4b, - 0x00, 0x23, 0x35, 0x56, 0x97, 0xfb, 0xd0, 0x24, 0xd3, 0x18, 0x27, 0xd3, 0x28, 0xf0, 0x98, 0xd4, - 0x75, 0x27, 0xdf, 0xc8, 0x2f, 0xe3, 0x35, 0xe5, 0x32, 0xee, 0x8d, 0xa0, 0x29, 0xa1, 0x0d, 0xe5, - 0xe2, 0x89, 0x5a, 0x2e, 0xca, 0x7e, 0x50, 0xca, 0xc7, 0xdf, 0x2c, 0x68, 0xf3, 0x98, 0xa3, 0x41, - 0x81, 0x3d, 0xf4, 0xbe, 0x72, 0x55, 0x66, 0xb9, 0xa5, 0x1b, 0x25, 0xee, 0xcf, 0xbc, 0xcc, 0xd4, - 0xaa, 0xcb, 0x4c, 0x1f, 0x40, 0x06, 0x08, 0x6f, 0x78, 0x32, 0x6d, 0x64, 0x0c, 0x3a, 0x0a, 0x85, - 0xfd, 0x4b, 0xd8, 0x56, 0xb5, 0x61, 0x99, 0xf4, 0x61, 0x31, 0xe1, 0x6f, 0x29, 0x92, 0x38, 0x5d, - 0x9e, 0xee, 0x7f, 0xb7, 0xa0, 0x5b, 0x44, 0x90, 0xf1, 0x31, 0x80, 0x6d, 0x52, 0xf8, 0x26, 0xec, - 0xbc, 0x53, 0x82, 0x64, 0x8c, 0x25, 0xf2, 0x95, 0x42, 0x67, 0x08, 0x9b, 0xcf, 0xdc, 0xc4, 0x1f, - 0x4b, 0x3d, 0x14, 0x10, 0xab, 0x12, 0xa4, 0xa6, 0x83, 0xfc, 0x1e, 0x1a, 0xc3, 0xa9, 0x1b, 0x4e, - 0xd8, 0x6d, 0xe4, 0xb2, 0xca, 0x20, 0x4e, 0x5c, 0xac, 0x68, 0xa4, 0x24, 0xe3, 0x68, 0x9e, 0x71, - 0xf2, 0x05, 0x8d, 0x38, 0x92, 0xce, 0x33, 0x9d, 0xd8, 0x6f, 0xba, 0x47, 0xc3, 0x48, 0x74, 0x2d, - 0xec, 0x37, 0x95, 0x3c, 0x8e, 0x42, 0x82, 0x43, 0x22, 0xee, 0xa6, 0x6c, 0x69, 0x7f, 0x02, 0xc0, - 0x25, 0x33, 0x07, 0x7c, 0x0f, 0x36, 0xc6, 0x6c, 0x95, 0x9d, 0x06, 0x3f, 0x77, 0x4e, 0xe1, 0x64, - 0xdf, 0xec, 0x14, 0x50, 0xce, 0x24, 0x0d, 0x3f, 0x04, 0xe0, 0x04, 0x41, 0xee, 0xfa, 0x9b, 0x0a, - 0x3f, 0x23, 0x56, 0x48, 0x56, 0x72, 0xf7, 0x53, 0xb8, 0xe1, 0x44, 0x11, 0x61, 0x29, 0x9a, 0xf7, - 0x9b, 0x96, 0xd6, 0x6f, 0x6a, 0x39, 0x57, 0x2b, 0xe4, 0x9c, 0xfd, 0x0d, 0xac, 0x31, 0xee, 0x0f, - 0xe0, 0x46, 0x2c, 0x90, 0x84, 0xb2, 0x9b, 0xa2, 0xd0, 0xf2, 0x4d, 0x47, 0x7e, 0x36, 0x26, 0xb6, - 0xb1, 0xd1, 0xb7, 0x3f, 0xa4, 0xea, 0x05, 0xdc, 0x99, 0x8f, 0xd4, 0x4e, 0xab, 0x75, 0xd4, 0x94, - 0x65, 0x3c, 0xeb, 0xd0, 0xbe, 0xa5, 0xcd, 0x6c, 0xa0, 0x3b, 0x91, 0x69, 0x15, 0xa8, 0x17, 0xd4, - 0xa6, 0xe4, 0x63, 0x84, 0xf2, 0xf3, 0xaa, 0x97, 0x10, 0x45, 0xa2, 0x17, 0x9a, 0xcc, 0xd1, 0xa4, - 0x90, 0xc8, 0xd6, 0x55, 0x89, 0x8c, 0x1e, 0x28, 0xfd, 0x85, 0x66, 0x18, 0x6f, 0x35, 0x5c, 0xe8, - 0x94, 0x85, 0x30, 0x95, 0x47, 0x80, 0xe2, 0xd2, 0x17, 0x21, 0x70, 0x57, 0xc2, 0xe8, 0x9f, 0x1d, - 0x03, 0x0b, 0xbb, 0xf8, 0xcd, 0x32, 0xd4, 0x8b, 0x3f, 0x36, 0x52, 0x68, 0x17, 0x7f, 0x05, 0x48, - 0x05, 0xeb, 0x4a, 0x3e, 0xef, 0xc0, 0xce, 0x30, 0x4e, 0xe7, 0x24, 0x3a, 0xc7, 0xf1, 0xa5, 0x3f, - 0xce, 0x26, 0x1e, 0x7b, 0x0a, 0x3d, 0x6d, 0x7f, 0x18, 0x63, 0x97, 0xc8, 0x79, 0xa8, 0xc7, 0x03, - 0xe1, 0x34, 0x6f, 0x0e, 0xe4, 0xba, 0xdc, 0xf5, 0xea, 0xf7, 0x6c, 0xbd, 0x70, 0xcf, 0xda, 0xa7, - 0xd0, 0x60, 0x55, 0x2e, 0xbe, 0xf6, 0x25, 0xaa, 0x35, 0x03, 0xe2, 0xde, 0x96, 0x1b, 0xf6, 0xbf, - 0x2c, 0x80, 0xb3, 0xd8, 0xbf, 0xe4, 0x73, 0xd8, 0xea, 0xa0, 0xc5, 0x0e, 0x63, 0x1e, 0xfb, 0x97, - 0x14, 0x86, 0x77, 0x03, 0xd9, 0x12, 0x1d, 0x42, 0x7b, 0xcc, 0x1d, 0xc5, 0x8c, 0x60, 0x95, 0x2d, - 0x2b, 0x4d, 0x7c, 0xcb, 0xd1, 0x08, 0x90, 0x0d, 0xed, 0xc4, 0x9f, 0x0c, 0xa4, 0x43, 0xd6, 0x99, - 0x01, 0xda, 0x9e, 0x3d, 0x2b, 0x78, 0x7f, 0xe0, 0x79, 0xca, 0x4c, 0xf9, 0xbf, 0x79, 0xff, 0x31, - 0xbf, 0xa3, 0xeb, 0x4a, 0xc9, 0xcb, 0xdd, 0xc3, 0x2e, 0x6d, 0xfb, 0x1f, 0x16, 0x20, 0x65, 0x2f, - 0x0b, 0xd2, 0x6b, 0x4d, 0xbd, 0xe8, 0x03, 0xdd, 0x35, 0x06, 0x19, 0xd2, 0x57, 0x4a, 0x80, 0xae, - 0x55, 0x06, 0xe8, 0xba, 0x1e, 0xa0, 0x9f, 0x42, 0x9b, 0x8d, 0xab, 0xca, 0x88, 0x68, 0xe8, 0x1b, - 0xcb, 0xa3, 0xd6, 0x6f, 0x01, 0xf1, 0x31, 0x57, 0xcb, 0xbb, 0xaa, 0xaa, 0xbc, 0x62, 0x5f, 0x76, - 0x9f, 0x9e, 0xa9, 0x1f, 0x4e, 0xb8, 0xa4, 0xaf, 0x23, 0x36, 0x14, 0x4b, 0x61, 0x2f, 0x34, 0x61, - 0xad, 0xa3, 0x8f, 0x64, 0x50, 0x54, 0xb1, 0xf4, 0xf9, 0xae, 0x18, 0xdd, 0x56, 0xd7, 0x8d, 0x8e, - 0x75, 0x0a, 0xd4, 0x55, 0x63, 0x5d, 0x53, 0xed, 0xcb, 0x7e, 0x0e, 0x5b, 0xaf, 0x71, 0x9c, 0x28, - 0xef, 0x7a, 0x5d, 0xd8, 0xb8, 0xe4, 0x3b, 0x0c, 0x61, 0xdd, 0xc9, 0x96, 0x65, 0xb7, 0x1f, 0xbd, - 0xdb, 0x86, 0xc6, 0x69, 0x44, 0xdc, 0x38, 0x45, 0x3f, 0x02, 0x38, 0x0e, 0x7d, 0xe2, 0xbb, 0x81, - 0xff, 0x07, 0x8c, 0xb6, 0x99, 0xf1, 0xca, 0xf3, 0x44, 0x0f, 0xb1, 0x1d, 0xad, 0x3f, 0xb1, 0xdf, - 0x43, 0x3f, 0x84, 0x0d, 0x96, 0x9c, 0xc9, 0x14, 0xf1, 0x40, 0xca, 0xdf, 0x22, 0x2b, 0x38, 0xfa, - 0xd0, 0x1c, 0x78, 0x9e, 0x18, 0xab, 0xd5, 0x5e, 0xb0, 0x82, 0xfe, 0x63, 0x68, 0xf3, 0xc7, 0xa3, - 0xeb, 0xb3, 0x9c, 0x42, 0x8b, 0x86, 0x11, 0xa7, 0x49, 0x50, 0xb7, 0x34, 0xf4, 0x64, 0x1a, 0xee, - 0x2f, 0x1b, 0xd8, 0x72, 0xbc, 0x63, 0xb8, 0x39, 0xc2, 0x44, 0x9d, 0xb8, 0x90, 0x3a, 0xc1, 0xab, - 0x43, 0x58, 0xcf, 0x34, 0x03, 0x6a, 0xaa, 0xf5, 0x46, 0x98, 0x0c, 0x82, 0x80, 0x53, 0xbc, 0xc2, - 0xc4, 0xf5, 0x5c, 0xe2, 0x0a, 0xd4, 0x9b, 0x0a, 0x33, 0xdd, 0xe8, 0x3d, 0x30, 0xb7, 0x9b, 0x39, - 0xde, 0xe7, 0xb0, 0x39, 0xc2, 0x64, 0x98, 0x37, 0x42, 0xa5, 0x53, 0xd8, 0x2d, 0xb6, 0x4d, 0x39, - 0xf3, 0x10, 0x9a, 0x6c, 0x87, 0x0d, 0x80, 0x25, 0xc6, 0xfd, 0x65, 0x97, 0x5a, 0x0e, 0xf2, 0x0b, - 0x40, 0x23, 0x4c, 0xf4, 0xce, 0xdf, 0x80, 0x76, 0x47, 0x6f, 0x3d, 0x72, 0xfe, 0xa7, 0xb0, 0xa9, - 0xbd, 0xc8, 0xa2, 0xbb, 0x8c, 0xd2, 0xf4, 0x64, 0x5d, 0x71, 0xdc, 0xaf, 0xa1, 0x5b, 0xf5, 0xa8, - 0x8c, 0x9e, 0x94, 0xc1, 0xca, 0x6f, 0xce, 0x15, 0xb8, 0x5f, 0x01, 0x2a, 0xbf, 0x15, 0xa3, 0x87, - 0x65, 0x44, 0xf5, 0xa1, 0xb4, 0x02, 0xeb, 0x37, 0xe5, 0xe7, 0x55, 0xf5, 0x79, 0x18, 0x1d, 0x70, - 0xf7, 0x5c, 0xfd, 0x82, 0x5c, 0x19, 0xf2, 0x3b, 0xa6, 0x37, 0x60, 0xb4, 0x67, 0xc4, 0x55, 0x9e, - 0x87, 0x2b, 0xf0, 0xce, 0xe0, 0x8e, 0xf1, 0x39, 0x18, 0x3d, 0x36, 0x02, 0xae, 0xa6, 0x21, 0x3b, - 0xa1, 0xbd, 0x4a, 0xcb, 0x97, 0xe3, 0x3d, 0x83, 0x9d, 0x61, 0x80, 0xdd, 0xb8, 0xa8, 0xe0, 0x8e, - 0x96, 0xed, 0xcb, 0x31, 0x9e, 0xc2, 0xc6, 0x1b, 0x9f, 0x84, 0xac, 0x38, 0x57, 0x16, 0x89, 0xbb, - 0xe5, 0x37, 0x93, 0x1c, 0xe1, 0x33, 0x68, 0xca, 0x47, 0x64, 0x94, 0xc5, 0xb8, 0xfe, 0xa8, 0x5c, - 0x21, 0xfb, 0x0b, 0xd8, 0xd4, 0x9a, 0x86, 0x72, 0xca, 0x70, 0xc1, 0xc6, 0x7e, 0x8f, 0x1e, 0xd0, - 0x6d, 0x43, 0xc7, 0x87, 0x1e, 0x95, 0x79, 0xb4, 0x5e, 0xb0, 0xd7, 0x29, 0x34, 0x54, 0xb9, 0x42, - 0x2f, 0x0b, 0x88, 0xbc, 0x8b, 0x31, 0x21, 0x6a, 0xfd, 0x4d, 0xe5, 0xf1, 0xe8, 0x68, 0x23, 0x4c, - 0x28, 0x1a, 0x1f, 0xc9, 0xd5, 0x16, 0x61, 0x89, 0x46, 0x5f, 0x15, 0xfa, 0xaa, 0x11, 0x26, 0x4a, - 0xab, 0x68, 0x80, 0xda, 0x2d, 0xf6, 0x32, 0x39, 0xd6, 0x00, 0x3a, 0x1a, 0x16, 0x0f, 0xb8, 0x0a, - 0x1c, 0xb3, 0x49, 0x5f, 0xc2, 0x1d, 0x0d, 0x82, 0x86, 0x02, 0xff, 0xf7, 0xcb, 0x18, 0x72, 0xbb, - 0x39, 0x6e, 0xb1, 0x66, 0x9e, 0x41, 0xb7, 0x84, 0x34, 0x08, 0x02, 0x06, 0x56, 0x0a, 0x83, 0xc7, - 0x57, 0xf6, 0x21, 0xcc, 0xdd, 0xb7, 0xce, 0x31, 0x79, 0x89, 0x27, 0xee, 0x38, 0x15, 0xfd, 0x40, - 0x82, 0xf8, 0xa3, 0x8c, 0xde, 0x1e, 0xf4, 0x3a, 0x7d, 0xfe, 0x6f, 0x62, 0x3f, 0xfb, 0x37, 0xb1, - 0xcf, 0xfe, 0x4d, 0xb4, 0xdf, 0x7b, 0xdb, 0x60, 0x3b, 0x9f, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, - 0x5a, 0xe0, 0xd0, 0x0b, 0x7f, 0x1c, 0x00, 0x00, + // 1947 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0x5b, 0x73, 0xdb, 0xc6, + 0x15, 0x0e, 0x48, 0x89, 0x32, 0x0f, 0x29, 0x59, 0x5a, 0xcb, 0x14, 0x4d, 0xdf, 0x64, 0xd8, 0x6d, + 0x94, 0x66, 0x42, 0x35, 0x4a, 0x9b, 0x26, 0x4d, 0xd3, 0x9a, 0xa6, 0x3d, 0x8c, 0x22, 0x5b, 0xa3, + 0x42, 0xa9, 0x3d, 0xd3, 0xcc, 0x74, 0x0a, 0x13, 0x5b, 0x12, 0x23, 0x10, 0x60, 0x80, 0xa5, 0xa6, + 0xe8, 0x43, 0x3b, 0xed, 0x5b, 0x3b, 0x7d, 0xc9, 0x63, 0x7f, 0x42, 0x7f, 0x46, 0x5f, 0xfb, 0xdc, + 0x1f, 0xd4, 0xd9, 0x0b, 0x16, 0xbb, 0xc0, 0x82, 0x52, 0x39, 0xcd, 0x1b, 0x77, 0x71, 0xce, 0x77, + 0x2e, 0x7b, 0x6e, 0xbb, 0x84, 0xa6, 0x3b, 0xf7, 0xfb, 0xf3, 0x38, 0x22, 0x11, 0xaa, 0xbb, 0x73, + 0xbf, 0x77, 0x77, 0x12, 0x45, 0x93, 0x00, 0x1f, 0xb2, 0xad, 0xb7, 0x8b, 0xdf, 0x1d, 0xbe, 0x98, + 0xcd, 0x49, 0xca, 0x29, 0xec, 0x07, 0x00, 0xa3, 0x45, 0xf8, 0x0a, 0x27, 0x89, 0x3b, 0xc1, 0x68, + 0x1b, 0xea, 0x93, 0x45, 0xd8, 0xb5, 0xf6, 0xad, 0x83, 0xa6, 0x43, 0x7f, 0xda, 0x7f, 0xb3, 0x60, + 0x77, 0xe0, 0x79, 0xcf, 0x71, 0x80, 0x27, 0x2e, 0xf1, 0x23, 0x49, 0x8a, 0x60, 0x2d, 0x74, 0x67, + 0x58, 0xd0, 0xb2, 0xdf, 0xe8, 0x63, 0xd8, 0xf2, 0x24, 0xe1, 0x09, 0x4e, 0x93, 0x6e, 0x6d, 0xbf, + 0x7e, 0xd0, 0x3a, 0xda, 0xea, 0x53, 0x95, 0xce, 0x16, 0x6f, 0x03, 0x7f, 0x7c, 0x82, 0x53, 0xa7, + 0x40, 0x85, 0x76, 0x61, 0x7d, 0xee, 0x92, 0x69, 0xd2, 0xad, 0xef, 0xd7, 0x0f, 0x9a, 0x0e, 0x5f, + 0x64, 0xca, 0xac, 0xe5, 0xca, 0xfc, 0x09, 0x1e, 0x6a, 0xba, 0x38, 0x51, 0x80, 0x07, 0xa1, 0x47, + 0x31, 0xbe, 0x0b, 0xb5, 0x84, 0x02, 0xf5, 0x5c, 0x81, 0x37, 0x70, 0x47, 0x53, 0xe0, 0x8c, 0x2a, + 0xba, 0x4c, 0xb4, 0xb4, 0xac, 0x66, 0xb0, 0x4c, 0x01, 0x4e, 0xe1, 0xb1, 0x83, 0x67, 0xd1, 0x25, + 0x7e, 0xae, 0xa9, 0x30, 0x08, 0xbd, 0x2b, 0x45, 0x74, 0xa0, 0x71, 0x81, 0xd3, 0xe3, 0xe7, 0x99, + 0x0c, 0xb1, 0xba, 0xb6, 0x53, 0x87, 0x70, 0xb7, 0x28, 0x9a, 0xfa, 0x75, 0x99, 0x48, 0x01, 0x52, + 0xcb, 0x41, 0x7e, 0x0d, 0xf7, 0x8a, 0x20, 0xff, 0x37, 0xdf, 0x7c, 0x5d, 0x56, 0xf0, 0xaa, 0x13, + 0xaf, 0xf2, 0x49, 0x19, 0xfc, 0x27, 0x70, 0x93, 0x5a, 0x7b, 0xea, 0xce, 0x54, 0x8b, 0xe3, 0x28, + 0x90, 0x80, 0xf4, 0xb7, 0xc1, 0xe2, 0x3f, 0xc2, 0xb6, 0x13, 0x11, 0x97, 0xe0, 0x13, 0x9c, 0x2e, + 0xe3, 0xfc, 0x01, 0x6c, 0x27, 0x38, 0xbe, 0xc4, 0xf1, 0x2b, 0x37, 0x74, 0x27, 0x38, 0x39, 0xc1, + 0x29, 0x83, 0xb9, 0xe1, 0x94, 0xf6, 0x51, 0x17, 0x36, 0x2e, 0x70, 0xfa, 0xd2, 0x4f, 0x88, 0x38, + 0xb4, 0x6c, 0x69, 0x38, 0xb6, 0xbf, 0x58, 0xd0, 0x3a, 0x0e, 0x7d, 0x92, 0xc9, 0x7e, 0x00, 0x10, + 0x47, 0x11, 0x39, 0xe1, 0x66, 0x5b, 0x8c, 0x5d, 0xd9, 0x41, 0x03, 0x40, 0xaa, 0x3c, 0x8f, 0x5a, + 0x9d, 0x30, 0x4d, 0x5a, 0x47, 0x3b, 0x2c, 0x11, 0x32, 0x3f, 0x50, 0x81, 0x8e, 0x81, 0xd8, 0xe0, + 0xbd, 0x27, 0xd0, 0x56, 0xb9, 0xe8, 0x91, 0xc6, 0x0c, 0x97, 0xcb, 0xe7, 0x0b, 0xfb, 0x73, 0xb8, + 0xa5, 0x52, 0x65, 0x1a, 0x1b, 0x89, 0x0d, 0x9e, 0xfe, 0xb3, 0x05, 0xbb, 0x9a, 0x6e, 0x38, 0x99, + 0x47, 0x61, 0x82, 0xd1, 0x8f, 0xa1, 0x1d, 0x2b, 0xfb, 0xcc, 0xed, 0x46, 0x63, 0x34, 0x32, 0xea, + 0xe5, 0x64, 0x31, 0x1e, 0xe3, 0x24, 0x11, 0x07, 0x91, 0x2d, 0xe9, 0x97, 0x19, 0x57, 0x4e, 0x18, + 0x99, 0x2d, 0xed, 0x4f, 0x61, 0xe7, 0x2b, 0x37, 0x9e, 0x60, 0x52, 0x08, 0x94, 0x6b, 0xa4, 0xc6, + 0xbf, 0x2d, 0x68, 0x70, 0xde, 0x72, 0x79, 0x95, 0x10, 0x35, 0x3d, 0x78, 0x03, 0x1c, 0x4e, 0xc8, + 0x94, 0x29, 0x51, 0x77, 0xc4, 0x0a, 0x1d, 0x42, 0x63, 0xea, 0x26, 0x53, 0x9c, 0x74, 0xd7, 0x58, + 0xf9, 0xda, 0x63, 0x86, 0x72, 0xe8, 0xfe, 0x17, 0xec, 0xcb, 0x8b, 0x90, 0xc4, 0xa9, 0x23, 0xc8, + 0x28, 0xd0, 0x78, 0x91, 0x90, 0x68, 0xd6, 0x5d, 0xdf, 0xb7, 0x0e, 0xda, 0x8e, 0x58, 0xf5, 0x3e, + 0x85, 0x96, 0x42, 0x4e, 0xb5, 0xba, 0xc0, 0x69, 0xa6, 0xd5, 0x05, 0x4e, 0xe9, 0xc9, 0x5c, 0xba, + 0xc1, 0x82, 0xab, 0xd5, 0x76, 0xf8, 0xe2, 0xa7, 0xb5, 0x4f, 0x2c, 0xfb, 0x18, 0xb6, 0xb8, 0xc0, + 0x37, 0x3e, 0x99, 0x52, 0x1f, 0xa3, 0xc7, 0xd0, 0x20, 0x6c, 0x47, 0xb8, 0xbf, 0xa5, 0x68, 0xe5, + 0x88, 0x4f, 0x32, 0x31, 0x6a, 0x79, 0x62, 0xd8, 0x7f, 0xb5, 0xa0, 0xa3, 0x63, 0xc9, 0x83, 0xfd, + 0x0c, 0xb6, 0x88, 0xf6, 0x45, 0x60, 0xdf, 0x52, 0xb0, 0x25, 0x53, 0x81, 0x74, 0xa5, 0xe3, 0x1d, + 0x15, 0x55, 0x91, 0xc1, 0xf2, 0x01, 0x6c, 0x70, 0x7c, 0x1e, 0xa6, 0x15, 0x3a, 0x64, 0x34, 0xf6, + 0x3f, 0x2d, 0x78, 0x60, 0x46, 0x92, 0xc6, 0x9d, 0x43, 0x87, 0x18, 0x29, 0x84, 0x91, 0x77, 0x0d, + 0x02, 0x24, 0x48, 0x05, 0xeb, 0x4a, 0x46, 0x8f, 0x01, 0x71, 0x29, 0xcf, 0x52, 0x8a, 0x33, 0x18, + 0xd3, 0xca, 0x6a, 0x0c, 0xea, 0x77, 0xb3, 0x4c, 0xad, 0x2c, 0x17, 0x7a, 0xf2, 0x2a, 0x15, 0xe2, + 0x1b, 0x68, 0x9e, 0xfb, 0x93, 0xd0, 0x25, 0x8b, 0x98, 0x65, 0x3c, 0x2b, 0xc4, 0x02, 0x9c, 0x2f, + 0x68, 0x98, 0xce, 0x30, 0x99, 0x46, 0x9e, 0x08, 0x0f, 0xb1, 0x42, 0xf7, 0xa0, 0x99, 0x64, 0xac, + 0x0c, 0xb2, 0xed, 0xe4, 0x1b, 0xd4, 0x2e, 0x3f, 0x79, 0xed, 0x06, 0xbe, 0xc7, 0xaa, 0xe2, 0x0d, + 0x27, 0x5b, 0xda, 0xbf, 0x84, 0xa6, 0xec, 0xe9, 0x68, 0x0b, 0x6a, 0xbe, 0x27, 0xe4, 0xd5, 0x7c, + 0x06, 0xea, 0x06, 0x93, 0x28, 0xf6, 0xc9, 0x74, 0x26, 0xe4, 0xe5, 0x1b, 0x54, 0x95, 0x39, 0x63, + 0x15, 0xf2, 0xc4, 0xca, 0x8e, 0x60, 0x27, 0x1f, 0x13, 0xb2, 0x83, 0xfc, 0x3e, 0x23, 0xce, 0x52, + 0xa7, 0x3c, 0x4e, 0x88, 0xaf, 0x2b, 0x9d, 0xcd, 0x7f, 0x2c, 0xd8, 0xd2, 0xfb, 0x31, 0xfa, 0x10, + 0xd6, 0x2e, 0xe8, 0xec, 0xc2, 0xc3, 0xf0, 0x3e, 0x13, 0xa6, 0x93, 0xf4, 0x69, 0x5b, 0xe4, 0x25, + 0x80, 0x91, 0x1a, 0xab, 0xcb, 0x3d, 0x68, 0x92, 0x69, 0x8c, 0x93, 0x69, 0x14, 0x78, 0x4c, 0xea, + 0xba, 0x93, 0x6f, 0xe4, 0x3d, 0x79, 0x4d, 0xe9, 0xc9, 0xbd, 0x11, 0x34, 0x25, 0xb4, 0xa1, 0x5c, + 0x3c, 0x51, 0xcb, 0x45, 0xd9, 0x0f, 0x4a, 0xf9, 0xf8, 0xbb, 0x05, 0x6d, 0x1e, 0x73, 0x34, 0x28, + 0xb0, 0x87, 0xde, 0x55, 0x3a, 0x66, 0x96, 0x5b, 0xba, 0x51, 0xa2, 0x8d, 0xe6, 0x65, 0xa6, 0x56, + 0x5d, 0x66, 0xfa, 0x00, 0x32, 0x40, 0xf8, 0xdc, 0x93, 0x69, 0x23, 0x63, 0xd0, 0x51, 0x28, 0xec, + 0x5f, 0xc0, 0xb6, 0xaa, 0x0d, 0xcb, 0xa4, 0xf7, 0x8b, 0x09, 0xbf, 0xa3, 0x48, 0xe2, 0x74, 0x79, + 0xba, 0x7f, 0x6b, 0x41, 0xb7, 0x88, 0x20, 0xe3, 0x63, 0x00, 0xdb, 0xa4, 0xf0, 0x4d, 0xd8, 0x79, + 0xbb, 0x04, 0xc9, 0x18, 0x4b, 0xe4, 0x2b, 0x85, 0xce, 0x10, 0x36, 0x9f, 0xb9, 0x89, 0x3f, 0x96, + 0x7a, 0x28, 0x20, 0x56, 0x25, 0x48, 0x4d, 0x07, 0xf9, 0x3d, 0x34, 0x86, 0x53, 0x37, 0x9c, 0xb0, + 0x6e, 0xe4, 0xb2, 0xca, 0x20, 0x4e, 0x5c, 0xac, 0x68, 0xa4, 0x24, 0xe3, 0x68, 0x9e, 0x71, 0xf2, + 0x05, 0x8d, 0x38, 0x92, 0xce, 0x33, 0x9d, 0xd8, 0x6f, 0xba, 0x47, 0xc3, 0x48, 0x0c, 0x2f, 0xec, + 0x37, 0x95, 0x3c, 0x8e, 0x42, 0x82, 0x43, 0x22, 0x7a, 0x53, 0xb6, 0xb4, 0x3f, 0x02, 0xe0, 0x92, + 0x99, 0x03, 0xbe, 0x07, 0x1b, 0x63, 0xb6, 0xca, 0x4e, 0x83, 0x9f, 0x3b, 0xa7, 0x70, 0xb2, 0x6f, + 0x76, 0x0a, 0x28, 0x67, 0x92, 0x86, 0x1f, 0x02, 0x70, 0x82, 0x20, 0x77, 0xfd, 0x4d, 0x85, 0x9f, + 0x11, 0x2b, 0x24, 0x2b, 0xb9, 0xfb, 0x29, 0xdc, 0x70, 0xa2, 0x88, 0xb0, 0x14, 0xcd, 0xc7, 0x4e, + 0x4b, 0x1b, 0x3b, 0xb5, 0x9c, 0xab, 0x15, 0x72, 0xce, 0xfe, 0x1a, 0xd6, 0x18, 0xf7, 0x7b, 0x70, + 0x23, 0x16, 0x48, 0x42, 0xd9, 0x4d, 0x51, 0x68, 0xf9, 0xa6, 0x23, 0x3f, 0x1b, 0x13, 0xdb, 0x38, + 0xef, 0xdb, 0xef, 0x53, 0xf5, 0x02, 0xee, 0xcc, 0x87, 0xea, 0xc0, 0xd5, 0x3a, 0x6a, 0xca, 0x32, + 0x9e, 0x0d, 0x6a, 0xdf, 0xd0, 0x99, 0x36, 0xd0, 0x9d, 0xc8, 0xb4, 0x0a, 0xd4, 0x06, 0xb5, 0x29, + 0xf9, 0x18, 0xa1, 0xfc, 0xbc, 0x6a, 0x13, 0xa2, 0x48, 0xb4, 0xa1, 0xc9, 0x1c, 0x4d, 0x0a, 0x89, + 0x6c, 0x5d, 0x95, 0xc8, 0xe8, 0xbe, 0x32, 0x5f, 0x68, 0x86, 0xf1, 0x51, 0xc3, 0x85, 0x4e, 0x59, + 0x08, 0x53, 0x79, 0x04, 0x28, 0x2e, 0x7d, 0x11, 0x02, 0xf7, 0x24, 0x8c, 0xfe, 0xd9, 0x31, 0xb0, + 0xb0, 0xc6, 0x6f, 0x96, 0xa1, 0x36, 0xfe, 0xd8, 0x48, 0xa1, 0x35, 0xfe, 0x0a, 0x90, 0x0a, 0xd6, + 0x95, 0x7c, 0xde, 0x81, 0xdd, 0x61, 0x9c, 0xce, 0x49, 0x74, 0x8e, 0xe3, 0x4b, 0x7f, 0x9c, 0xcd, + 0xb3, 0xf6, 0x14, 0x7a, 0xda, 0xfe, 0x30, 0xc6, 0x2e, 0x91, 0xd3, 0x6e, 0x8f, 0x07, 0xc2, 0x69, + 0x3e, 0x1c, 0xc8, 0x75, 0x79, 0xea, 0xd5, 0xfb, 0x6c, 0xbd, 0xd0, 0x67, 0xed, 0x53, 0x68, 0xb0, + 0x2a, 0x17, 0x5f, 0xbb, 0x89, 0x6a, 0xc3, 0x80, 0xe8, 0xdb, 0x72, 0xc3, 0xfe, 0x97, 0x05, 0x70, + 0x16, 0xfb, 0x97, 0xfc, 0x3a, 0xb6, 0x3a, 0x68, 0x71, 0xc2, 0x98, 0xc7, 0xfe, 0x25, 0x85, 0xe1, + 0xd3, 0x40, 0xb6, 0x44, 0x87, 0xd0, 0x1e, 0x73, 0x47, 0x31, 0x23, 0x58, 0x65, 0xcb, 0x4a, 0x13, + 0xdf, 0x72, 0x34, 0x02, 0x64, 0x43, 0x3b, 0xf1, 0x27, 0x03, 0xe9, 0x90, 0x75, 0x66, 0x80, 0xb6, + 0x67, 0xcf, 0x0a, 0xde, 0x1f, 0x78, 0x9e, 0x72, 0xb5, 0xfc, 0xdf, 0xbc, 0xff, 0x88, 0xf7, 0xe8, + 0xba, 0x52, 0xf2, 0x72, 0xf7, 0xb0, 0xa6, 0x6d, 0xff, 0xc3, 0x02, 0xa4, 0xec, 0x65, 0x41, 0x7a, + 0xad, 0xcb, 0x2f, 0x7a, 0x4f, 0x77, 0x8d, 0x41, 0x86, 0xf4, 0x95, 0x12, 0xa0, 0x6b, 0x95, 0x01, + 0xba, 0xae, 0x07, 0xe8, 0xc7, 0xd0, 0x66, 0xb7, 0x56, 0xe5, 0xa6, 0x68, 0x98, 0x1b, 0xcb, 0x57, + 0xad, 0xdf, 0x02, 0xe2, 0xb7, 0x5d, 0x2d, 0xef, 0xaa, 0xaa, 0xf2, 0x8a, 0x73, 0xd9, 0x3d, 0x7a, + 0xa6, 0x7e, 0x38, 0xe1, 0x92, 0xbe, 0x8a, 0xd8, 0xdd, 0x58, 0x0a, 0x7b, 0xa1, 0x09, 0x6b, 0x1d, + 0x7d, 0x20, 0x83, 0xa2, 0x8a, 0xa5, 0xcf, 0x77, 0xc5, 0xd5, 0x6d, 0x75, 0xdd, 0xe8, 0xb5, 0x4e, + 0x81, 0xba, 0xea, 0x5a, 0xd7, 0x54, 0xe7, 0xb2, 0x9f, 0xc1, 0xd6, 0x6b, 0x1c, 0x27, 0xca, 0xf3, + 0x5e, 0x17, 0x36, 0x2e, 0xf9, 0x0e, 0x43, 0x58, 0x77, 0xb2, 0x65, 0xd9, 0xed, 0x47, 0xdf, 0x6e, + 0x43, 0xe3, 0x34, 0x22, 0x6e, 0x9c, 0xa2, 0x1f, 0x01, 0x1c, 0x87, 0x3e, 0xf1, 0xdd, 0xc0, 0xff, + 0x03, 0x46, 0xdb, 0xcc, 0x78, 0xe5, 0x95, 0xa2, 0x87, 0xd8, 0x8e, 0x36, 0x9f, 0xd8, 0xef, 0xa0, + 0x1f, 0xc2, 0x06, 0x4b, 0xce, 0x64, 0x8a, 0x78, 0x20, 0xe5, 0x4f, 0x92, 0x15, 0x1c, 0x7d, 0x68, + 0x0e, 0x3c, 0x4f, 0x5c, 0xab, 0xd5, 0x59, 0xb0, 0x82, 0xfe, 0x43, 0x68, 0xf3, 0x37, 0xa4, 0xeb, + 0xb3, 0x9c, 0x42, 0x8b, 0x86, 0x11, 0xa7, 0x49, 0x50, 0xb7, 0x74, 0xe9, 0xc9, 0x34, 0x7c, 0xbc, + 0xec, 0xc2, 0x96, 0xe3, 0x1d, 0xc3, 0xcd, 0x11, 0x26, 0xea, 0x8d, 0x0b, 0xa9, 0x37, 0x78, 0xf5, + 0x12, 0xd6, 0x33, 0xdd, 0x01, 0x15, 0xa8, 0x5f, 0x41, 0x6f, 0x84, 0xc9, 0x20, 0x08, 0x38, 0xc5, + 0x2b, 0x4c, 0x5c, 0xcf, 0x25, 0xae, 0x40, 0xed, 0x28, 0xcc, 0xca, 0x73, 0x45, 0xef, 0xbe, 0x79, + 0xea, 0xcc, 0x61, 0x3f, 0x83, 0xcd, 0x11, 0x26, 0xc3, 0x7c, 0x1e, 0x2a, 0x1d, 0xc6, 0x5e, 0x71, + 0x7a, 0xca, 0x99, 0x87, 0xd0, 0x64, 0x3b, 0xec, 0x1e, 0x58, 0x62, 0x7c, 0xbc, 0xac, 0xb7, 0xe5, + 0x20, 0x3f, 0x07, 0x34, 0xc2, 0x44, 0xbf, 0x00, 0x18, 0xd0, 0x6e, 0xeb, 0x13, 0x48, 0xce, 0xff, + 0x14, 0x36, 0xb5, 0xf7, 0x59, 0x74, 0x87, 0x51, 0x9a, 0x1e, 0xb0, 0x2b, 0x4e, 0xfd, 0x35, 0x74, + 0xab, 0x9e, 0x98, 0xd1, 0x93, 0x32, 0x58, 0xf9, 0x05, 0xba, 0x02, 0xf7, 0x4b, 0x40, 0xe5, 0x97, + 0x63, 0xf4, 0xa0, 0x8c, 0xa8, 0x3e, 0x9b, 0x56, 0x60, 0xfd, 0xa6, 0xfc, 0xd8, 0xaa, 0x3e, 0x16, + 0xa3, 0x03, 0xee, 0x9e, 0xab, 0xdf, 0x93, 0x2b, 0x23, 0x7f, 0xd7, 0xf4, 0x22, 0x8c, 0xf6, 0x8d, + 0xb8, 0xca, 0x63, 0x71, 0x05, 0xde, 0x19, 0xdc, 0x36, 0x3e, 0x0e, 0xa3, 0x47, 0x46, 0xc0, 0xd5, + 0x34, 0x64, 0x27, 0xb4, 0x5f, 0x69, 0xf9, 0x72, 0xbc, 0x67, 0xb0, 0x3b, 0x0c, 0xb0, 0x1b, 0x17, + 0x15, 0xdc, 0xd5, 0x92, 0x7e, 0x39, 0xc6, 0x53, 0xd8, 0x78, 0xe3, 0x93, 0x90, 0xd5, 0xe8, 0xca, + 0x5a, 0x71, 0xa7, 0xfc, 0x74, 0x92, 0x23, 0x7c, 0x02, 0x4d, 0xf9, 0xa4, 0x8c, 0xb2, 0x18, 0xd7, + 0x9f, 0x98, 0x2b, 0x64, 0x7f, 0x0e, 0x9b, 0xda, 0xec, 0x50, 0x4e, 0x19, 0x2e, 0xd8, 0x38, 0xf6, + 0xd1, 0x03, 0xba, 0x65, 0x18, 0xfc, 0xd0, 0xc3, 0x32, 0x8f, 0x36, 0x12, 0xf6, 0x3a, 0x85, 0xb9, + 0x2a, 0x57, 0xe8, 0x65, 0x01, 0x91, 0x0f, 0x33, 0x26, 0x44, 0x6d, 0xcc, 0xa9, 0x3c, 0x1e, 0x1d, + 0x6d, 0x84, 0x09, 0x45, 0xe3, 0x37, 0x73, 0x75, 0x52, 0x58, 0xa2, 0xd1, 0x97, 0x85, 0xf1, 0x6a, + 0x84, 0x89, 0x32, 0x31, 0x1a, 0xa0, 0xf6, 0x8a, 0x23, 0x4d, 0x8e, 0x35, 0x80, 0x8e, 0x86, 0xc5, + 0x03, 0xae, 0x02, 0xc7, 0x6c, 0xd2, 0x17, 0x70, 0x5b, 0x83, 0xa0, 0xa1, 0xc0, 0xff, 0x0b, 0x33, + 0x86, 0xdc, 0x5e, 0x8e, 0x5b, 0xac, 0x99, 0x67, 0xd0, 0x2d, 0x21, 0x0d, 0x82, 0x80, 0x81, 0x95, + 0xc2, 0xe0, 0xd1, 0x95, 0xe3, 0x08, 0x73, 0xf7, 0xce, 0x39, 0x26, 0x2f, 0xf1, 0xc4, 0x1d, 0xa7, + 0x62, 0x2c, 0x48, 0x10, 0x7f, 0x9b, 0xd1, 0xa7, 0x84, 0x5e, 0xa7, 0xcf, 0xff, 0x5b, 0xec, 0x67, + 0xff, 0x2d, 0xf6, 0xd9, 0x7f, 0x8b, 0xf6, 0x3b, 0x6f, 0x1b, 0x6c, 0xe7, 0xa3, 0xff, 0x06, 0x00, + 0x00, 0xff, 0xff, 0xa4, 0x5e, 0xd4, 0xbc, 0x8d, 0x1c, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index c8ce639c3..8baea3cf0 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -19,7 +19,7 @@ service Notary { // GetTargetByName returns a target by the given name. rpc GetTargetByName(TargetByNameAction) returns (TargetWithRoleResponse) {} // GetAllTargetMetadataByName - rpc GetAllTargetMetadataByName(TargetName) returns (TargetSignedListResponse) {} + rpc GetAllTargetMetadataByName(TargetNameMessage) returns (TargetSignedListResponse) {} // GetChangelist returns the list of the repository's unpublished changes rpc GetChangelist(GunMessage) returns (ChangeListResponse) {} @@ -135,7 +135,7 @@ message RoleNameListResponse { string message = 3; } -message TargetName { +message TargetNameMessage { string name = 1; string gun = 2; } diff --git a/client_api/api/client.go b/client_api/api/client.go index 64632219c..c5af197a7 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -1,7 +1,6 @@ package api import ( - google_protobuf "github.com/golang/protobuf/ptypes/empty" "google.golang.org/grpc" "github.com/docker/notary/client" @@ -33,13 +32,14 @@ func (c *Client) Initialize(rootKeyIDs []string, serverManagedRoles ...data.Role initMsg := &InitMessage{ RootKeyIDs: rootKeyIDs, ServerManagedRoles: &RoleNameList{Roles: roles}, + Gun: c.gun.String(), } _, err := c.client.Initialize(context.Background(), initMsg) return err } func (c *Client) Publish() error { - _, err := c.client.Publish(context.Background(), &google_protobuf.Empty{}) + _, err := c.client.Publish(context.Background(), &GunMessage{Gun: c.gun.String()}) return err } @@ -73,7 +73,7 @@ func (c *Client) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, rolesList[index] = value.String() } - targetWithRoleList, err := c.client.ListTargets(context.Background(), &RoleNameList{Roles: rolesList}) + targetWithRoleList, err := c.client.ListTargets(context.Background(), &RoleNameListMessage{Roles: rolesList, Gun: c.gun.String()}) if err != nil { return []*client.TargetWithRole{}, err } @@ -113,6 +113,7 @@ func (c *Client) GetTargetByName(name string, roles ...data.RoleName) (*client.T targetByNameAction := &TargetByNameAction{ Name: name, Roles: &RoleNameList{Roles: rolesList}, + Gun: c.gun.String(), } targetWithRole, err := c.client.GetTargetByName(context.Background(), targetByNameAction) @@ -136,8 +137,9 @@ func (c *Client) GetTargetByName(name string, roles ...data.RoleName) (*client.T } func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) { - targetName := &TargetName{ + targetName := &TargetNameMessage{ Name: name, + Gun: c.gun.String(), } targetSignedListResponse, err := c.client.GetAllTargetMetadataByName(context.Background(), targetName) @@ -196,7 +198,7 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS } func (c *Client) GetChangelist() (changelist.Changelist, error) { - changes, err := c.client.GetChangelist(context.Background(), &google_protobuf.Empty{}) + changes, err := c.client.GetChangelist(context.Background(), &GunMessage{Gun: c.gun.String()}) if err != nil { return nil, err } @@ -214,7 +216,7 @@ func (c *Client) GetChangelist() (changelist.Changelist, error) { } func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { - roleWithSigsListResp, err := c.client.ListRoles(context.Background(), &google_protobuf.Empty{}) + roleWithSigsListResp, err := c.client.ListRoles(context.Background(), &GunMessage{c.gun.String()}) if err != nil { return nil, err } @@ -257,7 +259,7 @@ func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { } func (c *Client) GetDelegationRoles() ([]data.Role, error) { - roleListResp, err := c.client.GetDelegationRoles(context.Background(), &google_protobuf.Empty{}) + roleListResp, err := c.client.GetDelegationRoles(context.Background(), &GunMessage{c.gun.String()}) if err != nil { return nil, err } @@ -293,6 +295,7 @@ func (c *Client) AddDelegation(name data.RoleName, delegationKeys []data.PublicK Name: name.String(), DelegationKeys: currDelegationKeys, Paths: paths, + Gun: c.gun.String(), } _, err := c.client.AddDelegation(context.Background(), addDelegationMessage) @@ -312,6 +315,7 @@ func (c *Client) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []d addDelegationRoleAndKeysMessage := &AddDelegationRoleAndKeysMessage{ Name: name.String(), DelegationKeys: pubKeys, + Gun: c.gun.String(), } _, err := c.client.AddDelegationRoleAndKeys(context.Background(), addDelegationRoleAndKeysMessage) @@ -322,6 +326,7 @@ func (c *Client) AddDelegationPaths(name data.RoleName, paths []string) error { addDelegationPathsMessage := &AddDelegationPathsMessage{ Name: name.String(), Paths: paths, + Gun: c.gun.String(), } _, err := c.client.AddDelegationPaths(context.Background(), addDelegationPathsMessage) @@ -333,6 +338,7 @@ func (c *Client) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths Name: name.String(), KeyIDs: keyIDs, Paths: paths, + Gun: c.gun.String(), } _, err := c.client.RemoveDelegationKeysAndPaths(context.Background(), r) @@ -342,6 +348,7 @@ func (c *Client) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths func (c *Client) RemoveDelegationRole(name data.RoleName) error { r := &RemoveDelegationRoleMessage{ Name: name.String(), + Gun: c.gun.String(), } _, err := c.client.RemoveDelegationRole(context.Background(), r) @@ -352,6 +359,7 @@ func (c *Client) RemoveDelegationPaths(name data.RoleName, paths []string) error r := &RemoveDelegationPathsMessage{ Name: name.String(), Paths: paths, + Gun: c.gun.String(), } _, err := c.client.RemoveDelegationPaths(context.Background(), r) @@ -362,6 +370,7 @@ func (c *Client) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error r := &RemoveDelegationKeysMessage{ Name: name.String(), KeyIDs: keyIDs, + Gun: c.gun.String(), } _, err := c.client.RemoveDelegationKeys(context.Background(), r) @@ -371,6 +380,7 @@ func (c *Client) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error func (c *Client) ClearDelegationPaths(name data.RoleName) error { r := &RoleNameMessage{ Role: name.String(), + Gun: c.gun.String(), } _, err := c.client.ClearDelegationPaths(context.Background(), r) @@ -383,8 +393,9 @@ func (c *Client) Witness(roles ...data.RoleName) ([]data.RoleName, error) { roleNames[index] = roleName.String() } - roleNameList := &RoleNameList{ + roleNameList := &RoleNameListMessage{ Roles: roleNames, + Gun: c.gun.String(), } roleNameListResponse, err := c.client.Witness(context.Background(), roleNameList) @@ -407,6 +418,7 @@ func (c *Client) RotateKey(role data.RoleName, serverManagesKey bool, keyList [] Role: role.String(), ServerManagesKey: serverManagesKey, KeyList: keyList, + Gun: c.gun.String(), } _, err := c.client.RotateKey(context.Background(), rotateKeyMessage) return err @@ -475,15 +487,6 @@ func (cs *CryptoService) ListKeys(role data.RoleName) []string { // ListAllKeys returns a map of all available signing key IDs to role, or // an empty map or nil if there are no keys. func (cs *CryptoService) ListAllKeys() map[string]data.RoleName { - keyIDsToRoles, err := cs.client.CryptoServiceListAllKeys(context.Background(), &google_protobuf.Empty{}) - if err != nil { - return nil - } - - res := make(map[string]data.RoleName, len(keyIDsToRoles.KeyIDs)) - for key, role := range keyIDsToRoles.KeyIDs { - res[key] = data.RoleName(role) - } - - return res + keyIDsToRoles := cs.ListAllKeys() + return keyIDsToRoles } From 158c9454ca0a935e1ff522cabb015863d2848072 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 14 Mar 2017 17:10:06 +0100 Subject: [PATCH 30/62] Implement cient api server-side Init and Publish Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 270 ++++++++++++++++++--------------------- client_api/api/api.proto | 3 - client_api/api/server.go | 77 ++++++++++- 3 files changed, 195 insertions(+), 155 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index d335afa48..3f78f041e 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -533,7 +533,6 @@ type Target struct { Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` Length int64 `protobuf:"varint,3,opt,name=length" json:"length,omitempty"` Hashes map[string][]byte `protobuf:"bytes,4,rep,name=hashes" json:"hashes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"` - Custom []byte `protobuf:"bytes,5,opt,name=custom,proto3" json:"custom,omitempty"` } func (m *Target) Reset() { *m = Target{} } @@ -569,13 +568,6 @@ func (m *Target) GetHashes() map[string][]byte { return nil } -func (m *Target) GetCustom() []byte { - if m != nil { - return m.Custom - } - return nil -} - // TargetWithRole represents a Target that exists in a particular role type TargetWithRole struct { Target *Target `protobuf:"bytes,1,opt,name=target" json:"target,omitempty"` @@ -652,7 +644,6 @@ func (m *TargetWithRoleNameList) GetTargets() []*TargetWithRole { type TargetWithRoleNameListResponse struct { TargetWithRoleNameList *TargetWithRoleNameList `protobuf:"bytes,1,opt,name=targetWithRoleNameList" json:"targetWithRoleNameList,omitempty"` Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` } func (m *TargetWithRoleNameListResponse) Reset() { *m = TargetWithRoleNameListResponse{} } @@ -674,13 +665,6 @@ func (m *TargetWithRoleNameListResponse) GetSuccess() bool { return false } -func (m *TargetWithRoleNameListResponse) GetMessage() string { - if m != nil { - return m.Message - } - return "" -} - type TargetByNameAction struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Roles *RoleNameList `protobuf:"bytes,2,opt,name=roles" json:"roles,omitempty"` @@ -788,7 +772,6 @@ func (m *PublicKey) GetPublic() []byte { type PublicKeyResponse struct { Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` } func (m *PublicKeyResponse) Reset() { *m = PublicKeyResponse{} } @@ -810,13 +793,6 @@ func (m *PublicKeyResponse) GetSuccess() bool { return false } -func (m *PublicKeyResponse) GetMessage() string { - if m != nil { - return m.Message - } - return "" -} - type DelegationRole struct { Keys map[string]*PublicKey `protobuf:"bytes,1,rep,name=keys" json:"keys,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` @@ -2611,127 +2587,127 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1947 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0x5b, 0x73, 0xdb, 0xc6, - 0x15, 0x0e, 0x48, 0x89, 0x32, 0x0f, 0x29, 0x59, 0x5a, 0xcb, 0x14, 0x4d, 0xdf, 0x64, 0xd8, 0x6d, - 0x94, 0x66, 0x42, 0x35, 0x4a, 0x9b, 0x26, 0x4d, 0xd3, 0x9a, 0xa6, 0x3d, 0x8c, 0x22, 0x5b, 0xa3, - 0x42, 0xa9, 0x3d, 0xd3, 0xcc, 0x74, 0x0a, 0x13, 0x5b, 0x12, 0x23, 0x10, 0x60, 0x80, 0xa5, 0xa6, - 0xe8, 0x43, 0x3b, 0xed, 0x5b, 0x3b, 0x7d, 0xc9, 0x63, 0x7f, 0x42, 0x7f, 0x46, 0x5f, 0xfb, 0xdc, - 0x1f, 0xd4, 0xd9, 0x0b, 0x16, 0xbb, 0xc0, 0x82, 0x52, 0x39, 0xcd, 0x1b, 0x77, 0x71, 0xce, 0x77, - 0x2e, 0x7b, 0x6e, 0xbb, 0x84, 0xa6, 0x3b, 0xf7, 0xfb, 0xf3, 0x38, 0x22, 0x11, 0xaa, 0xbb, 0x73, - 0xbf, 0x77, 0x77, 0x12, 0x45, 0x93, 0x00, 0x1f, 0xb2, 0xad, 0xb7, 0x8b, 0xdf, 0x1d, 0xbe, 0x98, - 0xcd, 0x49, 0xca, 0x29, 0xec, 0x07, 0x00, 0xa3, 0x45, 0xf8, 0x0a, 0x27, 0x89, 0x3b, 0xc1, 0x68, - 0x1b, 0xea, 0x93, 0x45, 0xd8, 0xb5, 0xf6, 0xad, 0x83, 0xa6, 0x43, 0x7f, 0xda, 0x7f, 0xb3, 0x60, - 0x77, 0xe0, 0x79, 0xcf, 0x71, 0x80, 0x27, 0x2e, 0xf1, 0x23, 0x49, 0x8a, 0x60, 0x2d, 0x74, 0x67, - 0x58, 0xd0, 0xb2, 0xdf, 0xe8, 0x63, 0xd8, 0xf2, 0x24, 0xe1, 0x09, 0x4e, 0x93, 0x6e, 0x6d, 0xbf, - 0x7e, 0xd0, 0x3a, 0xda, 0xea, 0x53, 0x95, 0xce, 0x16, 0x6f, 0x03, 0x7f, 0x7c, 0x82, 0x53, 0xa7, - 0x40, 0x85, 0x76, 0x61, 0x7d, 0xee, 0x92, 0x69, 0xd2, 0xad, 0xef, 0xd7, 0x0f, 0x9a, 0x0e, 0x5f, - 0x64, 0xca, 0xac, 0xe5, 0xca, 0xfc, 0x09, 0x1e, 0x6a, 0xba, 0x38, 0x51, 0x80, 0x07, 0xa1, 0x47, - 0x31, 0xbe, 0x0b, 0xb5, 0x84, 0x02, 0xf5, 0x5c, 0x81, 0x37, 0x70, 0x47, 0x53, 0xe0, 0x8c, 0x2a, - 0xba, 0x4c, 0xb4, 0xb4, 0xac, 0x66, 0xb0, 0x4c, 0x01, 0x4e, 0xe1, 0xb1, 0x83, 0x67, 0xd1, 0x25, - 0x7e, 0xae, 0xa9, 0x30, 0x08, 0xbd, 0x2b, 0x45, 0x74, 0xa0, 0x71, 0x81, 0xd3, 0xe3, 0xe7, 0x99, - 0x0c, 0xb1, 0xba, 0xb6, 0x53, 0x87, 0x70, 0xb7, 0x28, 0x9a, 0xfa, 0x75, 0x99, 0x48, 0x01, 0x52, - 0xcb, 0x41, 0x7e, 0x0d, 0xf7, 0x8a, 0x20, 0xff, 0x37, 0xdf, 0x7c, 0x5d, 0x56, 0xf0, 0xaa, 0x13, - 0xaf, 0xf2, 0x49, 0x19, 0xfc, 0x27, 0x70, 0x93, 0x5a, 0x7b, 0xea, 0xce, 0x54, 0x8b, 0xe3, 0x28, - 0x90, 0x80, 0xf4, 0xb7, 0xc1, 0xe2, 0x3f, 0xc2, 0xb6, 0x13, 0x11, 0x97, 0xe0, 0x13, 0x9c, 0x2e, - 0xe3, 0xfc, 0x01, 0x6c, 0x27, 0x38, 0xbe, 0xc4, 0xf1, 0x2b, 0x37, 0x74, 0x27, 0x38, 0x39, 0xc1, - 0x29, 0x83, 0xb9, 0xe1, 0x94, 0xf6, 0x51, 0x17, 0x36, 0x2e, 0x70, 0xfa, 0xd2, 0x4f, 0x88, 0x38, - 0xb4, 0x6c, 0x69, 0x38, 0xb6, 0xbf, 0x58, 0xd0, 0x3a, 0x0e, 0x7d, 0x92, 0xc9, 0x7e, 0x00, 0x10, - 0x47, 0x11, 0x39, 0xe1, 0x66, 0x5b, 0x8c, 0x5d, 0xd9, 0x41, 0x03, 0x40, 0xaa, 0x3c, 0x8f, 0x5a, - 0x9d, 0x30, 0x4d, 0x5a, 0x47, 0x3b, 0x2c, 0x11, 0x32, 0x3f, 0x50, 0x81, 0x8e, 0x81, 0xd8, 0xe0, - 0xbd, 0x27, 0xd0, 0x56, 0xb9, 0xe8, 0x91, 0xc6, 0x0c, 0x97, 0xcb, 0xe7, 0x0b, 0xfb, 0x73, 0xb8, - 0xa5, 0x52, 0x65, 0x1a, 0x1b, 0x89, 0x0d, 0x9e, 0xfe, 0xb3, 0x05, 0xbb, 0x9a, 0x6e, 0x38, 0x99, - 0x47, 0x61, 0x82, 0xd1, 0x8f, 0xa1, 0x1d, 0x2b, 0xfb, 0xcc, 0xed, 0x46, 0x63, 0x34, 0x32, 0xea, - 0xe5, 0x64, 0x31, 0x1e, 0xe3, 0x24, 0x11, 0x07, 0x91, 0x2d, 0xe9, 0x97, 0x19, 0x57, 0x4e, 0x18, - 0x99, 0x2d, 0xed, 0x4f, 0x61, 0xe7, 0x2b, 0x37, 0x9e, 0x60, 0x52, 0x08, 0x94, 0x6b, 0xa4, 0xc6, - 0xbf, 0x2d, 0x68, 0x70, 0xde, 0x72, 0x79, 0x95, 0x10, 0x35, 0x3d, 0x78, 0x03, 0x1c, 0x4e, 0xc8, - 0x94, 0x29, 0x51, 0x77, 0xc4, 0x0a, 0x1d, 0x42, 0x63, 0xea, 0x26, 0x53, 0x9c, 0x74, 0xd7, 0x58, - 0xf9, 0xda, 0x63, 0x86, 0x72, 0xe8, 0xfe, 0x17, 0xec, 0xcb, 0x8b, 0x90, 0xc4, 0xa9, 0x23, 0xc8, - 0x28, 0xd0, 0x78, 0x91, 0x90, 0x68, 0xd6, 0x5d, 0xdf, 0xb7, 0x0e, 0xda, 0x8e, 0x58, 0xf5, 0x3e, - 0x85, 0x96, 0x42, 0x4e, 0xb5, 0xba, 0xc0, 0x69, 0xa6, 0xd5, 0x05, 0x4e, 0xe9, 0xc9, 0x5c, 0xba, - 0xc1, 0x82, 0xab, 0xd5, 0x76, 0xf8, 0xe2, 0xa7, 0xb5, 0x4f, 0x2c, 0xfb, 0x18, 0xb6, 0xb8, 0xc0, - 0x37, 0x3e, 0x99, 0x52, 0x1f, 0xa3, 0xc7, 0xd0, 0x20, 0x6c, 0x47, 0xb8, 0xbf, 0xa5, 0x68, 0xe5, - 0x88, 0x4f, 0x32, 0x31, 0x6a, 0x79, 0x62, 0xd8, 0x7f, 0xb5, 0xa0, 0xa3, 0x63, 0xc9, 0x83, 0xfd, - 0x0c, 0xb6, 0x88, 0xf6, 0x45, 0x60, 0xdf, 0x52, 0xb0, 0x25, 0x53, 0x81, 0x74, 0xa5, 0xe3, 0x1d, - 0x15, 0x55, 0x91, 0xc1, 0xf2, 0x01, 0x6c, 0x70, 0x7c, 0x1e, 0xa6, 0x15, 0x3a, 0x64, 0x34, 0xf6, - 0x3f, 0x2d, 0x78, 0x60, 0x46, 0x92, 0xc6, 0x9d, 0x43, 0x87, 0x18, 0x29, 0x84, 0x91, 0x77, 0x0d, - 0x02, 0x24, 0x48, 0x05, 0xeb, 0x4a, 0x46, 0x8f, 0x01, 0x71, 0x29, 0xcf, 0x52, 0x8a, 0x33, 0x18, - 0xd3, 0xca, 0x6a, 0x0c, 0xea, 0x77, 0xb3, 0x4c, 0xad, 0x2c, 0x17, 0x7a, 0xf2, 0x2a, 0x15, 0xe2, - 0x1b, 0x68, 0x9e, 0xfb, 0x93, 0xd0, 0x25, 0x8b, 0x98, 0x65, 0x3c, 0x2b, 0xc4, 0x02, 0x9c, 0x2f, - 0x68, 0x98, 0xce, 0x30, 0x99, 0x46, 0x9e, 0x08, 0x0f, 0xb1, 0x42, 0xf7, 0xa0, 0x99, 0x64, 0xac, - 0x0c, 0xb2, 0xed, 0xe4, 0x1b, 0xd4, 0x2e, 0x3f, 0x79, 0xed, 0x06, 0xbe, 0xc7, 0xaa, 0xe2, 0x0d, - 0x27, 0x5b, 0xda, 0xbf, 0x84, 0xa6, 0xec, 0xe9, 0x68, 0x0b, 0x6a, 0xbe, 0x27, 0xe4, 0xd5, 0x7c, - 0x06, 0xea, 0x06, 0x93, 0x28, 0xf6, 0xc9, 0x74, 0x26, 0xe4, 0xe5, 0x1b, 0x54, 0x95, 0x39, 0x63, - 0x15, 0xf2, 0xc4, 0xca, 0x8e, 0x60, 0x27, 0x1f, 0x13, 0xb2, 0x83, 0xfc, 0x3e, 0x23, 0xce, 0x52, - 0xa7, 0x3c, 0x4e, 0x88, 0xaf, 0x2b, 0x9d, 0xcd, 0x7f, 0x2c, 0xd8, 0xd2, 0xfb, 0x31, 0xfa, 0x10, - 0xd6, 0x2e, 0xe8, 0xec, 0xc2, 0xc3, 0xf0, 0x3e, 0x13, 0xa6, 0x93, 0xf4, 0x69, 0x5b, 0xe4, 0x25, - 0x80, 0x91, 0x1a, 0xab, 0xcb, 0x3d, 0x68, 0x92, 0x69, 0x8c, 0x93, 0x69, 0x14, 0x78, 0x4c, 0xea, - 0xba, 0x93, 0x6f, 0xe4, 0x3d, 0x79, 0x4d, 0xe9, 0xc9, 0xbd, 0x11, 0x34, 0x25, 0xb4, 0xa1, 0x5c, - 0x3c, 0x51, 0xcb, 0x45, 0xd9, 0x0f, 0x4a, 0xf9, 0xf8, 0xbb, 0x05, 0x6d, 0x1e, 0x73, 0x34, 0x28, - 0xb0, 0x87, 0xde, 0x55, 0x3a, 0x66, 0x96, 0x5b, 0xba, 0x51, 0xa2, 0x8d, 0xe6, 0x65, 0xa6, 0x56, - 0x5d, 0x66, 0xfa, 0x00, 0x32, 0x40, 0xf8, 0xdc, 0x93, 0x69, 0x23, 0x63, 0xd0, 0x51, 0x28, 0xec, - 0x5f, 0xc0, 0xb6, 0xaa, 0x0d, 0xcb, 0xa4, 0xf7, 0x8b, 0x09, 0xbf, 0xa3, 0x48, 0xe2, 0x74, 0x79, - 0xba, 0x7f, 0x6b, 0x41, 0xb7, 0x88, 0x20, 0xe3, 0x63, 0x00, 0xdb, 0xa4, 0xf0, 0x4d, 0xd8, 0x79, - 0xbb, 0x04, 0xc9, 0x18, 0x4b, 0xe4, 0x2b, 0x85, 0xce, 0x10, 0x36, 0x9f, 0xb9, 0x89, 0x3f, 0x96, - 0x7a, 0x28, 0x20, 0x56, 0x25, 0x48, 0x4d, 0x07, 0xf9, 0x3d, 0x34, 0x86, 0x53, 0x37, 0x9c, 0xb0, - 0x6e, 0xe4, 0xb2, 0xca, 0x20, 0x4e, 0x5c, 0xac, 0x68, 0xa4, 0x24, 0xe3, 0x68, 0x9e, 0x71, 0xf2, - 0x05, 0x8d, 0x38, 0x92, 0xce, 0x33, 0x9d, 0xd8, 0x6f, 0xba, 0x47, 0xc3, 0x48, 0x0c, 0x2f, 0xec, - 0x37, 0x95, 0x3c, 0x8e, 0x42, 0x82, 0x43, 0x22, 0x7a, 0x53, 0xb6, 0xb4, 0x3f, 0x02, 0xe0, 0x92, - 0x99, 0x03, 0xbe, 0x07, 0x1b, 0x63, 0xb6, 0xca, 0x4e, 0x83, 0x9f, 0x3b, 0xa7, 0x70, 0xb2, 0x6f, - 0x76, 0x0a, 0x28, 0x67, 0x92, 0x86, 0x1f, 0x02, 0x70, 0x82, 0x20, 0x77, 0xfd, 0x4d, 0x85, 0x9f, - 0x11, 0x2b, 0x24, 0x2b, 0xb9, 0xfb, 0x29, 0xdc, 0x70, 0xa2, 0x88, 0xb0, 0x14, 0xcd, 0xc7, 0x4e, - 0x4b, 0x1b, 0x3b, 0xb5, 0x9c, 0xab, 0x15, 0x72, 0xce, 0xfe, 0x1a, 0xd6, 0x18, 0xf7, 0x7b, 0x70, - 0x23, 0x16, 0x48, 0x42, 0xd9, 0x4d, 0x51, 0x68, 0xf9, 0xa6, 0x23, 0x3f, 0x1b, 0x13, 0xdb, 0x38, - 0xef, 0xdb, 0xef, 0x53, 0xf5, 0x02, 0xee, 0xcc, 0x87, 0xea, 0xc0, 0xd5, 0x3a, 0x6a, 0xca, 0x32, - 0x9e, 0x0d, 0x6a, 0xdf, 0xd0, 0x99, 0x36, 0xd0, 0x9d, 0xc8, 0xb4, 0x0a, 0xd4, 0x06, 0xb5, 0x29, - 0xf9, 0x18, 0xa1, 0xfc, 0xbc, 0x6a, 0x13, 0xa2, 0x48, 0xb4, 0xa1, 0xc9, 0x1c, 0x4d, 0x0a, 0x89, - 0x6c, 0x5d, 0x95, 0xc8, 0xe8, 0xbe, 0x32, 0x5f, 0x68, 0x86, 0xf1, 0x51, 0xc3, 0x85, 0x4e, 0x59, - 0x08, 0x53, 0x79, 0x04, 0x28, 0x2e, 0x7d, 0x11, 0x02, 0xf7, 0x24, 0x8c, 0xfe, 0xd9, 0x31, 0xb0, - 0xb0, 0xc6, 0x6f, 0x96, 0xa1, 0x36, 0xfe, 0xd8, 0x48, 0xa1, 0x35, 0xfe, 0x0a, 0x90, 0x0a, 0xd6, - 0x95, 0x7c, 0xde, 0x81, 0xdd, 0x61, 0x9c, 0xce, 0x49, 0x74, 0x8e, 0xe3, 0x4b, 0x7f, 0x9c, 0xcd, - 0xb3, 0xf6, 0x14, 0x7a, 0xda, 0xfe, 0x30, 0xc6, 0x2e, 0x91, 0xd3, 0x6e, 0x8f, 0x07, 0xc2, 0x69, - 0x3e, 0x1c, 0xc8, 0x75, 0x79, 0xea, 0xd5, 0xfb, 0x6c, 0xbd, 0xd0, 0x67, 0xed, 0x53, 0x68, 0xb0, - 0x2a, 0x17, 0x5f, 0xbb, 0x89, 0x6a, 0xc3, 0x80, 0xe8, 0xdb, 0x72, 0xc3, 0xfe, 0x97, 0x05, 0x70, - 0x16, 0xfb, 0x97, 0xfc, 0x3a, 0xb6, 0x3a, 0x68, 0x71, 0xc2, 0x98, 0xc7, 0xfe, 0x25, 0x85, 0xe1, - 0xd3, 0x40, 0xb6, 0x44, 0x87, 0xd0, 0x1e, 0x73, 0x47, 0x31, 0x23, 0x58, 0x65, 0xcb, 0x4a, 0x13, - 0xdf, 0x72, 0x34, 0x02, 0x64, 0x43, 0x3b, 0xf1, 0x27, 0x03, 0xe9, 0x90, 0x75, 0x66, 0x80, 0xb6, - 0x67, 0xcf, 0x0a, 0xde, 0x1f, 0x78, 0x9e, 0x72, 0xb5, 0xfc, 0xdf, 0xbc, 0xff, 0x88, 0xf7, 0xe8, - 0xba, 0x52, 0xf2, 0x72, 0xf7, 0xb0, 0xa6, 0x6d, 0xff, 0xc3, 0x02, 0xa4, 0xec, 0x65, 0x41, 0x7a, - 0xad, 0xcb, 0x2f, 0x7a, 0x4f, 0x77, 0x8d, 0x41, 0x86, 0xf4, 0x95, 0x12, 0xa0, 0x6b, 0x95, 0x01, - 0xba, 0xae, 0x07, 0xe8, 0xc7, 0xd0, 0x66, 0xb7, 0x56, 0xe5, 0xa6, 0x68, 0x98, 0x1b, 0xcb, 0x57, - 0xad, 0xdf, 0x02, 0xe2, 0xb7, 0x5d, 0x2d, 0xef, 0xaa, 0xaa, 0xf2, 0x8a, 0x73, 0xd9, 0x3d, 0x7a, - 0xa6, 0x7e, 0x38, 0xe1, 0x92, 0xbe, 0x8a, 0xd8, 0xdd, 0x58, 0x0a, 0x7b, 0xa1, 0x09, 0x6b, 0x1d, - 0x7d, 0x20, 0x83, 0xa2, 0x8a, 0xa5, 0xcf, 0x77, 0xc5, 0xd5, 0x6d, 0x75, 0xdd, 0xe8, 0xb5, 0x4e, - 0x81, 0xba, 0xea, 0x5a, 0xd7, 0x54, 0xe7, 0xb2, 0x9f, 0xc1, 0xd6, 0x6b, 0x1c, 0x27, 0xca, 0xf3, - 0x5e, 0x17, 0x36, 0x2e, 0xf9, 0x0e, 0x43, 0x58, 0x77, 0xb2, 0x65, 0xd9, 0xed, 0x47, 0xdf, 0x6e, - 0x43, 0xe3, 0x34, 0x22, 0x6e, 0x9c, 0xa2, 0x1f, 0x01, 0x1c, 0x87, 0x3e, 0xf1, 0xdd, 0xc0, 0xff, - 0x03, 0x46, 0xdb, 0xcc, 0x78, 0xe5, 0x95, 0xa2, 0x87, 0xd8, 0x8e, 0x36, 0x9f, 0xd8, 0xef, 0xa0, - 0x1f, 0xc2, 0x06, 0x4b, 0xce, 0x64, 0x8a, 0x78, 0x20, 0xe5, 0x4f, 0x92, 0x15, 0x1c, 0x7d, 0x68, - 0x0e, 0x3c, 0x4f, 0x5c, 0xab, 0xd5, 0x59, 0xb0, 0x82, 0xfe, 0x43, 0x68, 0xf3, 0x37, 0xa4, 0xeb, - 0xb3, 0x9c, 0x42, 0x8b, 0x86, 0x11, 0xa7, 0x49, 0x50, 0xb7, 0x74, 0xe9, 0xc9, 0x34, 0x7c, 0xbc, - 0xec, 0xc2, 0x96, 0xe3, 0x1d, 0xc3, 0xcd, 0x11, 0x26, 0xea, 0x8d, 0x0b, 0xa9, 0x37, 0x78, 0xf5, - 0x12, 0xd6, 0x33, 0xdd, 0x01, 0x15, 0xa8, 0x5f, 0x41, 0x6f, 0x84, 0xc9, 0x20, 0x08, 0x38, 0xc5, - 0x2b, 0x4c, 0x5c, 0xcf, 0x25, 0xae, 0x40, 0xed, 0x28, 0xcc, 0xca, 0x73, 0x45, 0xef, 0xbe, 0x79, - 0xea, 0xcc, 0x61, 0x3f, 0x83, 0xcd, 0x11, 0x26, 0xc3, 0x7c, 0x1e, 0x2a, 0x1d, 0xc6, 0x5e, 0x71, - 0x7a, 0xca, 0x99, 0x87, 0xd0, 0x64, 0x3b, 0xec, 0x1e, 0x58, 0x62, 0x7c, 0xbc, 0xac, 0xb7, 0xe5, - 0x20, 0x3f, 0x07, 0x34, 0xc2, 0x44, 0xbf, 0x00, 0x18, 0xd0, 0x6e, 0xeb, 0x13, 0x48, 0xce, 0xff, - 0x14, 0x36, 0xb5, 0xf7, 0x59, 0x74, 0x87, 0x51, 0x9a, 0x1e, 0xb0, 0x2b, 0x4e, 0xfd, 0x35, 0x74, - 0xab, 0x9e, 0x98, 0xd1, 0x93, 0x32, 0x58, 0xf9, 0x05, 0xba, 0x02, 0xf7, 0x4b, 0x40, 0xe5, 0x97, - 0x63, 0xf4, 0xa0, 0x8c, 0xa8, 0x3e, 0x9b, 0x56, 0x60, 0xfd, 0xa6, 0xfc, 0xd8, 0xaa, 0x3e, 0x16, - 0xa3, 0x03, 0xee, 0x9e, 0xab, 0xdf, 0x93, 0x2b, 0x23, 0x7f, 0xd7, 0xf4, 0x22, 0x8c, 0xf6, 0x8d, - 0xb8, 0xca, 0x63, 0x71, 0x05, 0xde, 0x19, 0xdc, 0x36, 0x3e, 0x0e, 0xa3, 0x47, 0x46, 0xc0, 0xd5, - 0x34, 0x64, 0x27, 0xb4, 0x5f, 0x69, 0xf9, 0x72, 0xbc, 0x67, 0xb0, 0x3b, 0x0c, 0xb0, 0x1b, 0x17, - 0x15, 0xdc, 0xd5, 0x92, 0x7e, 0x39, 0xc6, 0x53, 0xd8, 0x78, 0xe3, 0x93, 0x90, 0xd5, 0xe8, 0xca, - 0x5a, 0x71, 0xa7, 0xfc, 0x74, 0x92, 0x23, 0x7c, 0x02, 0x4d, 0xf9, 0xa4, 0x8c, 0xb2, 0x18, 0xd7, - 0x9f, 0x98, 0x2b, 0x64, 0x7f, 0x0e, 0x9b, 0xda, 0xec, 0x50, 0x4e, 0x19, 0x2e, 0xd8, 0x38, 0xf6, - 0xd1, 0x03, 0xba, 0x65, 0x18, 0xfc, 0xd0, 0xc3, 0x32, 0x8f, 0x36, 0x12, 0xf6, 0x3a, 0x85, 0xb9, - 0x2a, 0x57, 0xe8, 0x65, 0x01, 0x91, 0x0f, 0x33, 0x26, 0x44, 0x6d, 0xcc, 0xa9, 0x3c, 0x1e, 0x1d, - 0x6d, 0x84, 0x09, 0x45, 0xe3, 0x37, 0x73, 0x75, 0x52, 0x58, 0xa2, 0xd1, 0x97, 0x85, 0xf1, 0x6a, - 0x84, 0x89, 0x32, 0x31, 0x1a, 0xa0, 0xf6, 0x8a, 0x23, 0x4d, 0x8e, 0x35, 0x80, 0x8e, 0x86, 0xc5, - 0x03, 0xae, 0x02, 0xc7, 0x6c, 0xd2, 0x17, 0x70, 0x5b, 0x83, 0xa0, 0xa1, 0xc0, 0xff, 0x0b, 0x33, - 0x86, 0xdc, 0x5e, 0x8e, 0x5b, 0xac, 0x99, 0x67, 0xd0, 0x2d, 0x21, 0x0d, 0x82, 0x80, 0x81, 0x95, - 0xc2, 0xe0, 0xd1, 0x95, 0xe3, 0x08, 0x73, 0xf7, 0xce, 0x39, 0x26, 0x2f, 0xf1, 0xc4, 0x1d, 0xa7, - 0x62, 0x2c, 0x48, 0x10, 0x7f, 0x9b, 0xd1, 0xa7, 0x84, 0x5e, 0xa7, 0xcf, 0xff, 0x5b, 0xec, 0x67, - 0xff, 0x2d, 0xf6, 0xd9, 0x7f, 0x8b, 0xf6, 0x3b, 0x6f, 0x1b, 0x6c, 0xe7, 0xa3, 0xff, 0x06, 0x00, - 0x00, 0xff, 0xff, 0xa4, 0x5e, 0xd4, 0xbc, 0x8d, 0x1c, 0x00, 0x00, + // 1943 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0x5f, 0x73, 0xdb, 0xc6, + 0x11, 0x0f, 0x48, 0x89, 0x32, 0x97, 0x94, 0x2c, 0x9d, 0x65, 0x8a, 0xa6, 0x6d, 0x59, 0x86, 0xdd, + 0x46, 0x69, 0x26, 0x54, 0xa3, 0xb4, 0x69, 0xd2, 0x34, 0xad, 0x69, 0xda, 0xc3, 0x28, 0xb2, 0x35, + 0x2a, 0x94, 0xd8, 0x33, 0xcd, 0x4c, 0xa7, 0x30, 0x71, 0x25, 0x31, 0x02, 0x01, 0x06, 0x38, 0x69, + 0x8a, 0x3e, 0xb4, 0xd3, 0xbe, 0xb5, 0xd3, 0x99, 0x4e, 0x1e, 0xfb, 0x11, 0xfa, 0xda, 0x6f, 0xd0, + 0xef, 0xe0, 0x0f, 0xd4, 0xb9, 0x3f, 0x38, 0xdc, 0x01, 0x07, 0x4a, 0xe5, 0xb4, 0x6f, 0xbc, 0xc3, + 0xee, 0x6f, 0xff, 0xdc, 0xee, 0xed, 0xde, 0x12, 0x9a, 0xee, 0xdc, 0xef, 0xcf, 0xe3, 0x88, 0x44, + 0xa8, 0xee, 0xce, 0xfd, 0xde, 0xdd, 0x49, 0x14, 0x4d, 0x02, 0x7c, 0xc0, 0xb6, 0xde, 0x5c, 0xfc, + 0xf6, 0xe0, 0xf9, 0x6c, 0x4e, 0x52, 0x4e, 0x61, 0xef, 0x02, 0x8c, 0x2e, 0xc2, 0x97, 0x38, 0x49, + 0xdc, 0x09, 0x46, 0x9b, 0x50, 0x9f, 0x5c, 0x84, 0x5d, 0x6b, 0xcf, 0xda, 0x6f, 0x3a, 0xf4, 0xa7, + 0xfd, 0x57, 0x0b, 0xb6, 0x07, 0x9e, 0xf7, 0x0c, 0x07, 0x78, 0xe2, 0x12, 0x3f, 0x92, 0xa4, 0x08, + 0x56, 0x42, 0x77, 0x86, 0x05, 0x2d, 0xfb, 0x8d, 0x3e, 0x86, 0x0d, 0x4f, 0x12, 0x1e, 0xe3, 0x34, + 0xe9, 0xd6, 0xf6, 0xea, 0xfb, 0xad, 0xc3, 0x8d, 0x3e, 0x55, 0xe9, 0xf4, 0xe2, 0x4d, 0xe0, 0x8f, + 0x8f, 0x71, 0xea, 0x14, 0xa8, 0xd0, 0x36, 0xac, 0xce, 0x5d, 0x32, 0x4d, 0xba, 0xf5, 0xbd, 0xfa, + 0x7e, 0xd3, 0xe1, 0x8b, 0x4c, 0x99, 0x95, 0x5c, 0x99, 0x3f, 0xc2, 0x03, 0x4d, 0x17, 0x27, 0x0a, + 0xf0, 0x20, 0xf4, 0x28, 0xc6, 0xff, 0x43, 0x2d, 0xa1, 0x40, 0x3d, 0x57, 0xe0, 0x35, 0xdc, 0xd1, + 0x14, 0x38, 0xa5, 0x8a, 0x2e, 0x12, 0x2d, 0x2d, 0xab, 0x19, 0x2c, 0x53, 0x80, 0x53, 0x78, 0xe4, + 0xe0, 0x59, 0x74, 0x89, 0x9f, 0x69, 0x2a, 0x0c, 0x42, 0xef, 0x4a, 0x11, 0x1d, 0x68, 0x9c, 0xe3, + 0xf4, 0xe8, 0x59, 0x26, 0x43, 0xac, 0xae, 0xed, 0xd4, 0x21, 0xdc, 0x2d, 0x8a, 0xa6, 0x7e, 0x5d, + 0x24, 0x52, 0x80, 0xd4, 0x72, 0x90, 0x5f, 0xc1, 0xbd, 0x22, 0xc8, 0xff, 0xcc, 0x37, 0xdf, 0x94, + 0x15, 0xbc, 0xea, 0xc4, 0xab, 0x7c, 0x52, 0x06, 0xff, 0x09, 0xdc, 0xa4, 0xd6, 0x9e, 0xb8, 0x33, + 0xd5, 0xe2, 0x38, 0x0a, 0x24, 0x20, 0xfd, 0x6d, 0xb0, 0xf8, 0x0f, 0xb0, 0xe9, 0x44, 0xc4, 0x25, + 0xf8, 0x18, 0xa7, 0x8b, 0x38, 0x7f, 0x00, 0x9b, 0x09, 0x8e, 0x2f, 0x71, 0xfc, 0xd2, 0x0d, 0xdd, + 0x09, 0x4e, 0x8e, 0x71, 0xca, 0x60, 0x6e, 0x38, 0xa5, 0x7d, 0xd4, 0x85, 0xb5, 0x73, 0x9c, 0xbe, + 0xf0, 0x13, 0x22, 0x0e, 0x2d, 0x5b, 0x1a, 0x8e, 0xed, 0xcf, 0x16, 0xb4, 0x8e, 0x42, 0x9f, 0x64, + 0xb2, 0x77, 0x01, 0xe2, 0x28, 0x22, 0xc7, 0xdc, 0x6c, 0x8b, 0xb1, 0x2b, 0x3b, 0x68, 0x00, 0x48, + 0x95, 0xe7, 0x51, 0xab, 0x13, 0xa6, 0x49, 0xeb, 0x70, 0x8b, 0x25, 0x42, 0xe6, 0x07, 0x2a, 0xd0, + 0x31, 0x10, 0x1b, 0xbc, 0xf7, 0x18, 0xda, 0x2a, 0x17, 0x3d, 0xd2, 0x98, 0xe1, 0x72, 0xf9, 0x7c, + 0x61, 0x7f, 0x0e, 0xb7, 0x54, 0xaa, 0x4c, 0x63, 0x23, 0xb1, 0xc1, 0xd3, 0x7f, 0xb2, 0x60, 0x5b, + 0xd3, 0x0d, 0x27, 0xf3, 0x28, 0x4c, 0x30, 0xfa, 0x31, 0xb4, 0x63, 0x65, 0x9f, 0xb9, 0xdd, 0x68, + 0x8c, 0x46, 0x46, 0xbd, 0x9c, 0x5c, 0x8c, 0xc7, 0x38, 0x49, 0xc4, 0x41, 0x64, 0x4b, 0xfa, 0x65, + 0xc6, 0x95, 0x13, 0x46, 0x66, 0x4b, 0xfb, 0x53, 0xd8, 0xfa, 0xca, 0x8d, 0x27, 0x98, 0x14, 0x02, + 0xe5, 0x1a, 0xa9, 0xf1, 0x2f, 0x0b, 0x1a, 0x9c, 0xb7, 0x7c, 0xbd, 0x4a, 0x88, 0x9a, 0x1e, 0xbc, + 0x01, 0x0e, 0x27, 0x64, 0xca, 0x94, 0xa8, 0x3b, 0x62, 0x85, 0x0e, 0xa0, 0x31, 0x75, 0x93, 0x29, + 0x4e, 0xba, 0x2b, 0xec, 0xfa, 0xda, 0x61, 0x86, 0x72, 0xe8, 0xfe, 0x17, 0xec, 0xcb, 0xf3, 0x90, + 0xc4, 0xa9, 0x23, 0xc8, 0x7a, 0x9f, 0x42, 0x4b, 0xd9, 0xa6, 0xd2, 0xcf, 0x71, 0x9a, 0x49, 0x3f, + 0xc7, 0x29, 0x3d, 0x81, 0x4b, 0x37, 0xb8, 0xe0, 0xe2, 0xdb, 0x0e, 0x5f, 0xfc, 0xb4, 0xf6, 0x89, + 0x65, 0x1f, 0xc1, 0x06, 0x07, 0x7e, 0xed, 0x93, 0x29, 0xf5, 0x25, 0x7a, 0x04, 0x0d, 0xc2, 0x76, + 0x84, 0x9b, 0x5b, 0x8a, 0x74, 0x47, 0x7c, 0x92, 0x09, 0x50, 0xcb, 0x13, 0xc0, 0xfe, 0x8b, 0x05, + 0x1d, 0x1d, 0x4b, 0x1e, 0xe0, 0x67, 0xb0, 0x41, 0xb4, 0x2f, 0x02, 0xfb, 0x96, 0x82, 0x2d, 0x99, + 0x0a, 0xa4, 0x4b, 0x1d, 0xe3, 0xa8, 0xa8, 0x8a, 0x0c, 0x8a, 0x0f, 0x60, 0x8d, 0xe3, 0xf3, 0x70, + 0xac, 0xd0, 0x21, 0xa3, 0xb1, 0xff, 0x6e, 0xc1, 0xae, 0x19, 0x49, 0x1a, 0x77, 0x06, 0x1d, 0x62, + 0xa4, 0x10, 0x46, 0xde, 0x35, 0x08, 0x90, 0x20, 0x15, 0xac, 0xd5, 0x46, 0xdb, 0x63, 0x40, 0x1c, + 0xeb, 0x69, 0x4a, 0xa9, 0x07, 0x63, 0x7a, 0x4f, 0x1a, 0x43, 0xf4, 0xdd, 0x2c, 0xef, 0x2a, 0x93, + 0x5f, 0x4f, 0x45, 0x25, 0xdf, 0xbf, 0x85, 0xe6, 0x99, 0x3f, 0x09, 0x5d, 0x72, 0x11, 0xb3, 0xfc, + 0x65, 0xd7, 0xaa, 0x00, 0xe7, 0x0b, 0x1a, 0xbd, 0x33, 0x4c, 0xa6, 0x91, 0x27, 0x82, 0x40, 0xac, + 0xd0, 0x3d, 0x68, 0x26, 0x19, 0x2b, 0x83, 0x6c, 0x3b, 0xf9, 0x06, 0xb5, 0xcb, 0x4f, 0x5e, 0xb9, + 0x81, 0xef, 0xb1, 0x3b, 0xee, 0x86, 0x93, 0x2d, 0xed, 0x5f, 0x42, 0x53, 0x56, 0x68, 0xb4, 0x01, + 0x35, 0xdf, 0x13, 0xf2, 0x6a, 0x3e, 0x03, 0x75, 0x83, 0x49, 0x14, 0xfb, 0x64, 0x3a, 0x13, 0xf2, + 0xf2, 0x0d, 0xaa, 0xca, 0x9c, 0xb1, 0x0a, 0x79, 0x62, 0x65, 0x7f, 0x0d, 0x5b, 0x79, 0xd1, 0xcf, + 0x8e, 0xeb, 0xfb, 0x8c, 0x38, 0x4b, 0x90, 0x72, 0x73, 0x20, 0xbe, 0x2e, 0x38, 0x81, 0xb7, 0x16, + 0x6c, 0xe8, 0x35, 0x14, 0x7d, 0x08, 0x2b, 0xe7, 0xb4, 0xdf, 0xe0, 0x21, 0x75, 0x9f, 0x41, 0xea, + 0x24, 0x7d, 0x5a, 0xca, 0x78, 0xda, 0x32, 0x52, 0xe3, 0x8d, 0x70, 0x0f, 0x9a, 0x64, 0x1a, 0xe3, + 0x64, 0x1a, 0x05, 0x1e, 0xb3, 0x65, 0xd5, 0xc9, 0x37, 0xf2, 0x3a, 0xba, 0xa2, 0xd4, 0xd1, 0xde, + 0x08, 0x9a, 0x12, 0xda, 0x90, 0xfa, 0x8f, 0xd5, 0xd4, 0x2f, 0x5b, 0xab, 0x5c, 0x05, 0x7f, 0xb3, + 0xa0, 0xcd, 0x23, 0x8b, 0x1e, 0x3d, 0xf6, 0xd0, 0xbb, 0x4a, 0x95, 0xcb, 0xf2, 0x44, 0x37, 0x4a, + 0x94, 0xbe, 0xfc, 0xca, 0xa8, 0x55, 0x5f, 0x19, 0x7d, 0x00, 0x19, 0x06, 0xbc, 0x57, 0xc9, 0xb4, + 0x91, 0x91, 0xe6, 0x28, 0x14, 0xf6, 0x2f, 0x60, 0x53, 0xd5, 0x86, 0x65, 0xc5, 0xfb, 0xc5, 0xe4, + 0xdd, 0x52, 0x24, 0x71, 0xba, 0x3c, 0x75, 0xbf, 0xb3, 0xa0, 0x5b, 0x44, 0x90, 0x51, 0x30, 0x80, + 0x4d, 0x52, 0xf8, 0x26, 0xec, 0xbc, 0x5d, 0x82, 0x64, 0x8c, 0x25, 0xf2, 0xa5, 0xee, 0xa5, 0x21, + 0xac, 0x3f, 0x75, 0x13, 0x7f, 0x2c, 0xf5, 0x50, 0x40, 0xac, 0x4a, 0x90, 0x9a, 0x0e, 0xf2, 0x3b, + 0x68, 0x0c, 0xa7, 0x6e, 0x38, 0x61, 0x15, 0xc4, 0x65, 0xf9, 0x2f, 0x4e, 0x5c, 0xac, 0x68, 0xa4, + 0x24, 0xe3, 0x68, 0x9e, 0x71, 0xf2, 0x05, 0x8d, 0x38, 0x92, 0xce, 0x33, 0x9d, 0xd8, 0x6f, 0xba, + 0x47, 0xc3, 0x48, 0x34, 0x1c, 0xec, 0x37, 0x95, 0x3c, 0x8e, 0x42, 0x82, 0x43, 0xd2, 0x5d, 0x65, + 0xf9, 0x94, 0x2d, 0xed, 0x8f, 0x00, 0xb8, 0x64, 0xe6, 0x80, 0xef, 0xc1, 0xda, 0x98, 0xad, 0xb2, + 0xd3, 0xe0, 0xe7, 0xce, 0x29, 0x9c, 0xec, 0x9b, 0x9d, 0x02, 0xca, 0x99, 0xa4, 0xe1, 0x07, 0x00, + 0x9c, 0x20, 0xc8, 0x5d, 0x7f, 0x53, 0xe1, 0x67, 0xc4, 0x0a, 0xc9, 0x52, 0xee, 0x7e, 0x02, 0x37, + 0x9c, 0x28, 0x22, 0x2c, 0x45, 0xf3, 0x56, 0xd1, 0xd2, 0x5a, 0x45, 0x2d, 0xe7, 0x6a, 0x85, 0x9c, + 0xb3, 0xbf, 0x81, 0x15, 0xc6, 0xfd, 0x1e, 0xdc, 0x88, 0x05, 0x92, 0x50, 0x76, 0x5d, 0x5c, 0xa7, + 0x7c, 0xd3, 0x91, 0x9f, 0x8d, 0x89, 0x6d, 0xec, 0xd1, 0xed, 0xf7, 0xa9, 0x7a, 0x01, 0x77, 0xe6, + 0x03, 0xb5, 0x49, 0x6a, 0x1d, 0x36, 0xe5, 0x65, 0x9d, 0x35, 0x57, 0xdf, 0xd2, 0x3e, 0x34, 0xd0, + 0x9d, 0xc8, 0xb4, 0x0a, 0xd4, 0x62, 0xb3, 0x2e, 0xf9, 0x18, 0xa1, 0xfc, 0xbc, 0x94, 0xfb, 0xc6, + 0x80, 0x28, 0x12, 0x2d, 0x4e, 0x32, 0x47, 0x93, 0x42, 0x22, 0x5b, 0x57, 0x25, 0x32, 0xba, 0xaf, + 0xf4, 0x0a, 0x9a, 0x61, 0xbc, 0x6d, 0x70, 0xa1, 0x53, 0x16, 0xc2, 0x54, 0x1e, 0x01, 0x8a, 0x4b, + 0x5f, 0x84, 0xc0, 0x1d, 0x09, 0xa3, 0x7f, 0x76, 0x0c, 0x2c, 0xf6, 0x3f, 0x2d, 0xd8, 0x35, 0xcb, + 0x50, 0x8b, 0x78, 0x6c, 0xa4, 0xd0, 0x8a, 0x78, 0x05, 0x48, 0x05, 0xeb, 0x52, 0x3e, 0xef, 0xc0, + 0xf6, 0x30, 0x4e, 0xe7, 0x24, 0x3a, 0xc3, 0xf1, 0xa5, 0x3f, 0xce, 0x7a, 0x50, 0x7b, 0x0a, 0x3d, + 0x6d, 0x7f, 0x18, 0x63, 0x97, 0xc8, 0x0e, 0xb5, 0xc7, 0x03, 0xe1, 0x24, 0x6f, 0x01, 0xe4, 0xba, + 0xdc, 0xa9, 0xea, 0xd5, 0xb4, 0x5e, 0xa8, 0xa6, 0xf6, 0x09, 0x34, 0xd8, 0x2d, 0x17, 0x5f, 0xbb, + 0x54, 0x6a, 0x25, 0x5f, 0x54, 0x67, 0xb9, 0x61, 0xff, 0xdb, 0x02, 0x38, 0x8d, 0xfd, 0x4b, 0xfe, + 0x84, 0x5a, 0x1e, 0xb4, 0xd8, 0x47, 0xcc, 0x63, 0xff, 0x92, 0xc2, 0xf0, 0x9a, 0x9f, 0x2d, 0xd1, + 0x01, 0xb4, 0xc7, 0xdc, 0x51, 0xcc, 0x08, 0x76, 0xb3, 0x65, 0x57, 0x13, 0xdf, 0x72, 0x34, 0x02, + 0x64, 0x43, 0x3b, 0xf1, 0x27, 0x03, 0xe9, 0x90, 0x55, 0x66, 0x80, 0xb6, 0x67, 0xcf, 0x0a, 0xde, + 0x1f, 0x78, 0x9e, 0xf2, 0x1c, 0xfc, 0xef, 0xbc, 0xff, 0x90, 0xd7, 0xe8, 0xba, 0x72, 0xe5, 0xe5, + 0xee, 0x61, 0x45, 0xdb, 0xfe, 0x87, 0x05, 0x48, 0xd9, 0xcb, 0x82, 0xf4, 0x5a, 0x0f, 0x56, 0xf4, + 0x9e, 0xee, 0x1a, 0x83, 0x0c, 0xe9, 0x2b, 0x25, 0x40, 0x57, 0x2a, 0x03, 0x74, 0x55, 0x0f, 0xd0, + 0x8f, 0xa1, 0xcd, 0x5e, 0x9a, 0xca, 0xeb, 0xce, 0xd0, 0x1d, 0x96, 0x9f, 0x47, 0xbf, 0x01, 0xc4, + 0x5f, 0xa8, 0x5a, 0xde, 0x55, 0xdd, 0xca, 0xcb, 0xa4, 0xce, 0x5b, 0x0b, 0xee, 0xd1, 0x33, 0xf5, + 0xc3, 0x09, 0x97, 0xf4, 0x55, 0xc4, 0xde, 0xb3, 0x52, 0xd8, 0x73, 0x4d, 0x58, 0xeb, 0xf0, 0x03, + 0x19, 0x14, 0x55, 0x2c, 0x7d, 0xbe, 0x2b, 0x9e, 0x5b, 0xcb, 0xeb, 0x46, 0x9f, 0x68, 0x0a, 0xd4, + 0x55, 0x4f, 0xb4, 0xa6, 0xda, 0x97, 0xfd, 0x0c, 0x36, 0x5e, 0xe1, 0x38, 0x51, 0x46, 0x72, 0x5d, + 0x58, 0xbb, 0xe4, 0x3b, 0x0c, 0x61, 0xd5, 0xc9, 0x96, 0x65, 0xb7, 0x1f, 0x7e, 0xb7, 0x09, 0x8d, + 0x93, 0x88, 0xb8, 0x71, 0x8a, 0x7e, 0x04, 0x70, 0x14, 0xfa, 0xc4, 0x77, 0x03, 0xff, 0xf7, 0x18, + 0x6d, 0x32, 0xe3, 0x95, 0xc9, 0x42, 0x0f, 0xb1, 0x1d, 0xad, 0x3f, 0xb1, 0xdf, 0x41, 0x3f, 0x84, + 0x35, 0x96, 0x9c, 0xc9, 0x14, 0xf1, 0x40, 0xca, 0xc7, 0x88, 0x15, 0x1c, 0x7d, 0x68, 0x0e, 0x3c, + 0x4f, 0x3c, 0x85, 0xd5, 0x5e, 0xb0, 0x82, 0xfe, 0x43, 0x68, 0xf3, 0xb9, 0xcf, 0xf5, 0x59, 0x4e, + 0xa0, 0x45, 0xc3, 0x88, 0xd3, 0x24, 0xa8, 0x5b, 0x7a, 0xda, 0x64, 0x1a, 0x3e, 0x5a, 0xf4, 0xf8, + 0xca, 0xf1, 0x8e, 0xe0, 0xe6, 0x08, 0x13, 0xf5, 0x5d, 0x85, 0xd4, 0x57, 0xb7, 0xfa, 0xd4, 0xea, + 0x99, 0xde, 0x73, 0x0a, 0xd4, 0xd7, 0xd0, 0x1b, 0x61, 0x32, 0x08, 0x02, 0x4e, 0xf1, 0x12, 0x13, + 0xd7, 0x73, 0x89, 0x2b, 0x50, 0x3b, 0x0a, 0xb3, 0x32, 0x62, 0xe8, 0xdd, 0x37, 0x77, 0x9d, 0x39, + 0xec, 0x67, 0xb0, 0x3e, 0xc2, 0x64, 0x98, 0xf7, 0x43, 0xa5, 0xc3, 0xd8, 0x29, 0x76, 0x4f, 0x39, + 0xf3, 0x10, 0x9a, 0x6c, 0x87, 0xbd, 0xf6, 0x4a, 0x8c, 0x8f, 0x16, 0xd5, 0xb6, 0x1c, 0xe4, 0xe7, + 0x80, 0x46, 0x98, 0xe8, 0x0f, 0x00, 0x03, 0xda, 0x6d, 0xbd, 0x03, 0xc9, 0xf9, 0x9f, 0xc0, 0xba, + 0x36, 0x53, 0x45, 0x77, 0x18, 0xa5, 0x69, 0xe8, 0x5c, 0x71, 0xea, 0xaf, 0xa0, 0x5b, 0x35, 0x16, + 0x46, 0x8f, 0xcb, 0x60, 0xe5, 0xa9, 0x71, 0x05, 0xee, 0x97, 0x80, 0xca, 0xd3, 0x5e, 0xb4, 0x5b, + 0x46, 0x54, 0x47, 0x9d, 0x15, 0x58, 0xbf, 0x2e, 0x0f, 0x48, 0xd5, 0x01, 0x2f, 0xda, 0xe7, 0xee, + 0xb9, 0x7a, 0x06, 0x5c, 0x19, 0xf9, 0xdb, 0xa6, 0x29, 0x2e, 0xda, 0x33, 0xe2, 0x2a, 0x03, 0xde, + 0x0a, 0xbc, 0x53, 0xb8, 0x6d, 0x1c, 0xe8, 0xa2, 0x87, 0x46, 0xc0, 0xe5, 0x34, 0x64, 0x27, 0xb4, + 0x57, 0x69, 0xf9, 0x62, 0xbc, 0xa7, 0xb0, 0x3d, 0x0c, 0xb0, 0x1b, 0x17, 0x15, 0xdc, 0xd6, 0x92, + 0x7e, 0x31, 0xc6, 0x13, 0x58, 0x7b, 0xed, 0x93, 0x90, 0xdd, 0xd1, 0x95, 0x77, 0xc5, 0x9d, 0xf2, + 0x80, 0x24, 0x47, 0xf8, 0x04, 0x9a, 0x72, 0x0c, 0x8c, 0xb2, 0x18, 0xd7, 0xc7, 0xc2, 0x15, 0xb2, + 0x3f, 0x87, 0x75, 0xad, 0x77, 0x28, 0xa7, 0x0c, 0x17, 0x6c, 0x6c, 0xfb, 0xe8, 0x01, 0xdd, 0x32, + 0x34, 0x7e, 0xe8, 0x41, 0x99, 0x47, 0x6b, 0x09, 0x7b, 0x9d, 0x42, 0x5f, 0x95, 0x2b, 0xf4, 0xa2, + 0x80, 0xc8, 0x9b, 0x19, 0x13, 0xa2, 0xd6, 0xe6, 0x54, 0x1e, 0x8f, 0x8e, 0x36, 0xc2, 0x84, 0xa2, + 0xf1, 0x97, 0xb9, 0xda, 0x29, 0x2c, 0xd0, 0xe8, 0xcb, 0x42, 0x7b, 0x35, 0xc2, 0x44, 0xe9, 0x18, + 0x0d, 0x50, 0x3b, 0xc5, 0x96, 0x26, 0xc7, 0x1a, 0x40, 0x47, 0xc3, 0xe2, 0x01, 0x57, 0x81, 0x63, + 0x36, 0xe9, 0x0b, 0xb8, 0xad, 0x41, 0xd0, 0x50, 0xe0, 0xff, 0x5f, 0x19, 0x43, 0x6e, 0x27, 0xc7, + 0x2d, 0xde, 0x99, 0xa7, 0xd0, 0x2d, 0x21, 0x0d, 0x82, 0x80, 0x81, 0x95, 0xc2, 0xe0, 0xe1, 0x95, + 0xed, 0x08, 0x73, 0xf7, 0xd6, 0x19, 0x26, 0x2f, 0xf0, 0xc4, 0x1d, 0xa7, 0xa2, 0x2d, 0x48, 0x10, + 0x9f, 0xcd, 0xe8, 0x5d, 0x42, 0xaf, 0xd3, 0xe7, 0xff, 0x07, 0xf6, 0xb3, 0xff, 0x03, 0xfb, 0xec, + 0xff, 0x40, 0xfb, 0x9d, 0x37, 0x0d, 0xb6, 0xf3, 0xd1, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x7b, + 0xf1, 0xa4, 0xe4, 0x41, 0x1c, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index 8baea3cf0..cdce14b85 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -146,7 +146,6 @@ message Target { string name = 2; int64 length = 3; map hashes = 4; - bytes custom = 5; } // TargetWithRole represents a Target that exists in a particular role @@ -168,7 +167,6 @@ message TargetWithRoleNameList { message TargetWithRoleNameListResponse { TargetWithRoleNameList targetWithRoleNameList = 1; bool success = 2; - string message = 3; } message TargetByNameAction { @@ -193,7 +191,6 @@ message PublicKey { message PublicKeyResponse { PublicKey pubkey = 1; bool success = 2; - string message = 3; } message DelegationRole { diff --git a/client_api/api/server.go b/client_api/api/server.go index 9a520e8eb..55df3bec8 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -36,11 +36,40 @@ type Server struct { } func (srv *Server) Initialize(ctx context.Context, initMessage *InitMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented + r, err := srv.initRepo(data.GUN(initMessage.Gun)) + if err != nil { + return nil, err + } + + roles := make([]data.RoleName, len(initMessage.ServerManagedRoles.Roles)) + for index, role := range initMessage.ServerManagedRoles.Roles { + roles[index] = data.RoleName(role) + } + + err = r.Initialize(initMessage.RootKeyIDs, roles...) + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } -func (srv *Server) Publish(ctx context.Context, empty *google_protobuf.Empty) (*BasicResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) Publish(ctx context.Context, gun *GunMessage) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(gun.Gun)) + if err != nil { + return nil, err + } + + err = r.Publish() + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } func (srv *Server) AddTarget(ctx context.Context, t *Target) (*BasicResponse, error) { @@ -85,7 +114,45 @@ func (srv *Server) RemoveTarget(ctx context.Context, t *Target) (*BasicResponse, }, nil } -func (srv *Server) ListTargets(context.Context, *RoleNameList) (*TargetWithRoleNameListResponse, error) { +func (srv *Server) ListTargets(ctx context.Context, message *RoleNameListMessage) (*TargetWithRoleNameListResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + roles := make([]data.RoleName, len(message.Roles)) + for index, role := range message.Roles { + roles[index] = data.RoleName(role) + } + + targets, err := r.ListTargets(roles...) + if err != nil { + return nil, err + } + + res := make([]*TargetWithRole, len(targets)) + for index, target := range targets { + res[index] = &TargetWithRole{ + Target: &Target{ + Gun: message.Gun, + Name: target.Name, + Length: target.Length, + Hashes: target.Hashes, + + }, + Role: target.Role.String() + } + } + + return &TargetWithRoleNameListResponse{ + TargetWithRoleNameList: &TargetWithRoleNameList{ + Targets: targets, + }, + Success: true, + }, nil + + + return nil, ErrNotImplemented } @@ -95,7 +162,7 @@ func (srv *Server) GetTargetByName(context.Context, *TargetByNameAction) (*Targe } // GetAllTargetMetadataByName -func (srv *Server) GetAllTargetMetadataByName(context.Context, *TargetName) (*TargetSignedListResponse, error) { +func (srv *Server) GetAllTargetMetadataByName(context.Context, *TargetNameMessage) (*TargetSignedListResponse, error) { return nil, ErrNotImplemented } From 8e3faf6b1bd9010f579ffb44d80eefbeab153268 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Wed, 15 Mar 2017 14:30:14 +0100 Subject: [PATCH 31/62] Implement more cient api server-side - part 2 Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/server.go | 131 ++++++++++++++++++++++++++++++++++----- 1 file changed, 115 insertions(+), 16 deletions(-) diff --git a/client_api/api/server.go b/client_api/api/server.go index 55df3bec8..397205c01 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -130,45 +130,144 @@ func (srv *Server) ListTargets(ctx context.Context, message *RoleNameListMessage return nil, err } - res := make([]*TargetWithRole, len(targets)) + resTargets := make([]*TargetWithRole, len(targets)) for index, target := range targets { - res[index] = &TargetWithRole{ + resTargets[index] = &TargetWithRole{ Target: &Target{ - Gun: message.Gun, - Name: target.Name, + Gun: message.Gun, + Name: target.Name, Length: target.Length, Hashes: target.Hashes, - }, - Role: target.Role.String() + Role: target.Role.String(), } } return &TargetWithRoleNameListResponse{ TargetWithRoleNameList: &TargetWithRoleNameList{ - Targets: targets, + Targets: resTargets, }, Success: true, }, nil +} +// GetTargetByName returns a target by the given name. +func (srv *Server) GetTargetByName(ctx context.Context, message *TargetByNameAction) (*TargetWithRoleResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + roles := make([]data.RoleName, len(message.Roles.Roles)) + for index, role := range message.Roles.Roles { + roles[index] = data.RoleName(role) + } - return nil, ErrNotImplemented -} + target, err := r.GetTargetByName(message.Name, roles...) + if err != nil { + return nil, err + } -// GetTargetByName returns a target by the given name. -func (srv *Server) GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRoleResponse, error) { - return nil, ErrNotImplemented + return &TargetWithRoleResponse{ + TargetWithRole: &TargetWithRole{ + Target: &Target{ + Gun: message.Gun, + Name: target.Name, + Length: target.Length, + Hashes: target.Hashes, + }, + Role: target.Role.String(), + }, + Success: true, + }, nil } // GetAllTargetMetadataByName -func (srv *Server) GetAllTargetMetadataByName(context.Context, *TargetNameMessage) (*TargetSignedListResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) GetAllTargetMetadataByName(ctx context.Context, message *TargetNameMessage) (*TargetSignedListResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + targets, err := r.GetAllTargetMetadataByName(message.Name) + if err != nil { + return nil, err + } + + resTargets := make([]*TargetSigned, len(targets)) + for indexTarget, target := range targets { + + resSignatures := make([]*Signature, len(target.Signatures)) + for indexSig, signature := range target.Signatures { + resSignatures[indexSig] = &Signature{ + KeyID: signature.KeyID, + Method: signature.Method.String(), + } + } + + resKeys := make(map[string]*PublicKey, len(target.Role.Keys)) + for keyName, keyPubkey := range target.Role.Keys { + resKeys[keyName] = &PublicKey{ + Id: keyPubkey.ID(), + Algorithm: keyPubkey.Algorithm(), + Public: keyPubkey.Public(), + } + } + + resTargets[indexTarget] = &TargetSigned{ + Role: &DelegationRole{ + Keys: resKeys, + Name: target.Role.Name.String(), + Threshold: int32(target.Role.Threshold), // FIXME + Paths: target.Role.Paths, + }, + Target: &Target{ + Gun: message.Gun, + Name: target.Target.Name, + Length: target.Target.Length, + Hashes: target.Target.Hashes, + }, + Signatures: resSignatures, + } + } + + return &TargetSignedListResponse{ + TargetSignedList: &TargetSignedList{ + Targets: resTargets, + }, + Success: true, + }, nil } // GetChangelist returns the list of the repository's unpublished changes -func (srv *Server) GetChangelist(context.Context, *google_protobuf.Empty) (*ChangeListResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) GetChangelist(ctx context.Context, message *GunMessage) (*ChangeListResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + changelist, err := r.GetChangelist() + if err != nil { + return nil, err + } + + resChangelist := make([]*Change, len(changelist.List())) + for index, change := range changelist.List() { + resChangelist[index] = &Change{ + Action: change.Action(), + Scope: change.Scope().String(), + Type: change.Type(), + Path: change.Path(), + Content: change.Content(), + } + } + + return &ChangeListResponse{ + Changelist: &ChangeList{ + Changes: resChangelist, + }, + Success: true, + }, nil } func (srv *Server) ListRoles(context.Context, *google_protobuf.Empty) (*RoleWithSignaturesListResponse, error) { From ac1b1317b5b9e525f79dfe8147a64ba13886780c Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Wed, 15 Mar 2017 15:12:55 +0100 Subject: [PATCH 32/62] Implement more cient api server-side - part 3 Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/server.go | 251 ++++++++++++++++++++++++++++++++++----- 1 file changed, 219 insertions(+), 32 deletions(-) diff --git a/client_api/api/server.go b/client_api/api/server.go index 397205c01..9b2fd5329 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -270,88 +270,275 @@ func (srv *Server) GetChangelist(ctx context.Context, message *GunMessage) (*Cha }, nil } -func (srv *Server) ListRoles(context.Context, *google_protobuf.Empty) (*RoleWithSignaturesListResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) ListRoles(ctx context.Context, message *GunMessage) (*RoleWithSignaturesListResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + roles, err := r.ListRoles() + if err != nil { + return nil, err + } + + resRoles := make([]*RoleWithSignatures, len(roles)) + for index, role := range roles { + + resSignatures := make([]*Signature, len(role.Signatures)) + for indexSig, signature := range role.Signatures { + resSignatures[indexSig] = &Signature{ + KeyID: signature.KeyID, + Method: signature.Method.String(), + } + } + + resRoles[index] = &RoleWithSignatures{ + Signatures: resSignatures, + Role: &Role{ + RootRole: &RootRole{ + KeyIDs: role.KeyIDs, + Threshold: int32(role.Threshold), // FIXME + }, + Name: role.Name.String(), + Paths: role.Paths, + }, + } + } + + return &RoleWithSignaturesListResponse{ + RoleWithSignaturesList: &RoleWithSignaturesList{ + RoleWithSignatures: resRoles, + }, + Success: true, + }, nil } -func (srv *Server) GetDelegationRoles(context.Context, *google_protobuf.Empty) (*RoleListResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) GetDelegationRoles(ctx context.Context, message *GunMessage) (*RoleListResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + roles, err := r.GetDelegationRoles() + if err != nil { + return nil, err + } + + resRoles := make([]*Role, len(roles)) + for index, role := range roles { + resRoles[index] = &Role{ + RootRole: &RootRole{ + KeyIDs: role.KeyIDs, + Threshold: int32(role.Threshold), // FIXME + }, + Name: role.Name.String(), + Paths: role.Paths, + } + } + + return &RoleListResponse{ + RoleList: &RoleList{ + Roles: resRoles, + }, + Success: true, + }, nil } -func (srv *Server) AddDelegation(context.Context, *AddDelegationMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) AddDelegation(ctx context.Context, message *AddDelegationMessage) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + delegationKeys := make([]data.PublicKey, len(message.DelegationKeys)) + for index, key := range message.DelegationKeys { + delegationKeys[index] = data.NewPublicKey(key.Algorithm, key.Public) + } + + err = r.AddDelegation(data.RoleName(message.Name), delegationKeys, message.Paths) + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } -func (srv *Server) AddDelegationRoleAndKeys(context.Context, *AddDelegationRoleAndKeysMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) AddDelegationRoleAndKeys(ctx context.Context, message *AddDelegationRoleAndKeysMessage) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + delegationKeys := make([]data.PublicKey, len(message.DelegationKeys)) + for index, key := range message.DelegationKeys { + delegationKeys[index] = data.NewPublicKey(key.Algorithm, key.Public) + } + + err = r.AddDelegationRoleAndKeys(data.RoleName(message.Name), delegationKeys) + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } -func (srv *Server) AddDelegationPaths(context.Context, *AddDelegationPathsMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) AddDelegationPaths(ctx context.Context, message *AddDelegationPathsMessage) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + err = r.AddDelegationPaths(data.RoleName(message.Name), message.Paths) + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } -func (srv *Server) RemoveDelegationKeysAndPaths(context.Context, *RemoveDelegationKeysAndPathsMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) RemoveDelegationKeysAndPaths(ctx context.Context, message *RemoveDelegationKeysAndPathsMessage) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + err = r.RemoveDelegationKeysAndPaths(data.RoleName(message.Name), message.KeyIDs, message.Paths) + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } -func (srv *Server) RemoveDelegationRole(context.Context, *RemoveDelegationRoleMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) RemoveDelegationRole(ctx context.Context, message *RemoveDelegationRoleMessage) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + err = r.RemoveDelegationRole() + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } -func (srv *Server) RemoveDelegationPaths(context.Context, *RemoveDelegationPathsMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) RemoveDelegationPaths(ctx context.Context, message *RemoveDelegationPathsMessage) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + err = r.RemoveDelegationPaths() + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } -func (srv *Server) RemoveDelegationKeys(context.Context, *RemoveDelegationKeysMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) RemoveDelegationKeys(ctx context.Context, message *RemoveDelegationKeysMessage) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + err = r.RemoveDelegationKeys() + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } -func (srv *Server) ClearDelegationPaths(context.Context, *RoleNameMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) ClearDelegationPaths(ctx context.Context, message *RoleNameMessage) (*BasicResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + err = r.ClearDelegationPaths() + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } -func (srv *Server) Witness(context.Context, *RoleNameList) (*RoleNameListResponse, error) { - return nil, ErrNotImplemented +func (srv *Server) Witness(ctx context.Context, message *RoleNameListMessage) (*RoleNameListResponse, error) { + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + roles, err := r.Witness() + if err != nil { + return nil, err + } + + return &RoleNameListResponse{ + RoleNameList: &RoleNameList{ + Roles + }, + Success: true, + }, nil } -func (srv *Server) RotateKey(context.Context, *RotateKeyMessage) (*BasicResponse, error) { +func (srv *Server) RotateKey(ctx context.Context, message *RotateKeyMessage) (*BasicResponse, error) { return nil, ErrNotImplemented } // CryptoService implementation -func (srv *Server) CryptoService(context.Context, *google_protobuf.Empty) (*CryptoServiceMessage, error) { +func (srv *Server) CryptoService(ctx context.Context, message *GunMessage) (*CryptoServiceMessage, error) { return nil, ErrNotImplemented } -func (srv *Server) CryptoServiceCreate(context.Context, *CryptoServiceCreateMessage) (*PublicKeyResponse, error) { +func (srv *Server) CryptoServiceCreate(ctx context.Context, message *CryptoServiceCreateMessage) (*PublicKeyResponse, error) { return nil, ErrNotImplemented } -func (srv *Server) CryptoServiceAddKey(context.Context, *CryptoServiceAddKeyMessage) (*BasicResponse, error) { +func (srv *Server) CryptoServiceAddKey(ctx context.Context, message *CryptoServiceAddKeyMessage) (*BasicResponse, error) { return nil, ErrNotImplemented } -func (srv *Server) CryptoServiceGetKey(context.Context, *KeyIDMessage) (*PublicKeyResponse, error) { +func (srv *Server) CryptoServiceGetKey(ctx context.Context, message *KeyIDMessage) (*PublicKeyResponse, error) { return nil, ErrNotImplemented } -func (srv *Server) CryptoServiceGetPrivateKey(context.Context, *KeyIDMessage) (*PrivateKeyResponse, error) { +func (srv *Server) CryptoServiceGetPrivateKey(ctx context.Context, message *KeyIDMessage) (*PrivateKeyResponse, error) { return nil, ErrNotImplemented } -func (srv *Server) CryptoServiceRemoveKey(context.Context, *KeyIDMessage) (*BasicResponse, error) { +func (srv *Server) CryptoServiceRemoveKey(ctx context.Context, message *KeyIDMessage) (*BasicResponse, error) { return nil, ErrNotImplemented } -func (srv *Server) CryptoServiceListKeys(context.Context, *RoleNameMessage) (*KeyIDsListResponse, error) { +func (srv *Server) CryptoServiceListKeys(ctx context.Context, message *RoleNameMessage) (*KeyIDsListResponse, error) { return nil, ErrNotImplemented } -func (srv *Server) CryptoServiceListAllKeys(context.Context, *google_protobuf.Empty) (*SigningKeyIDsToRolesResponse, error) { +func (srv *Server) CryptoServiceListAllKeys(ctx context.Context, message *GunMessage) (*SigningKeyIDsToRolesResponse, error) { return nil, ErrNotImplemented } -func (srv *Server) SetLegacyVersions(context.Context, *VersionMessage) (*google_protobuf.Empty, error) { +func (srv *Server) SetLegacyVersions(ctx context.Context, message *VersionMessage) (*google_protobuf.Empty, error) { return nil, ErrNotImplemented } From bb89cff2ddb521fece9b33d318fefadf239b205f Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Wed, 15 Mar 2017 19:52:54 +0100 Subject: [PATCH 33/62] Finish cient api server-side implementation Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/api.pb.go | 387 ++++++++++++++++++++++++--------------- client_api/api/api.proto | 22 ++- client_api/api/client.go | 26 +-- client_api/api/server.go | 218 +++++++++++++++++++--- 4 files changed, 469 insertions(+), 184 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index 3f78f041e..354d5d1eb 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -56,6 +56,8 @@ It has these top-level messages: PrivateKeyResponse KeyIDMessage KeyIDsListResponse + CryptoServicePrivateKeySignMessage + SignatureResponse SigningKeyIDsToRolesResponse VersionMessage */ @@ -1257,8 +1259,7 @@ func (m *CryptoServiceCreateMessage) GetAlgorithm() string { } type Signer struct { - Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` - Signature string `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"` + Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` } func (m *Signer) Reset() { *m = Signer{} } @@ -1273,19 +1274,11 @@ func (m *Signer) GetPubkey() *PublicKey { return nil } -func (m *Signer) GetSignature() string { - if m != nil { - return m.Signature - } - return "" -} - type PrivateKey struct { Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` - Privkey []byte `protobuf:"bytes,3,opt,name=privkey,proto3" json:"privkey,omitempty"` - CryptoSigner *Signer `protobuf:"bytes,4,opt,name=cryptoSigner" json:"cryptoSigner,omitempty"` - SigAlgorithm string `protobuf:"bytes,5,opt,name=sigAlgorithm" json:"sigAlgorithm,omitempty"` + Privkey []byte `protobuf:"bytes,2,opt,name=privkey,proto3" json:"privkey,omitempty"` + CryptoSigner *Signer `protobuf:"bytes,3,opt,name=cryptoSigner" json:"cryptoSigner,omitempty"` + SigAlgorithm string `protobuf:"bytes,4,opt,name=sigAlgorithm" json:"sigAlgorithm,omitempty"` } func (m *PrivateKey) Reset() { *m = PrivateKey{} } @@ -1300,13 +1293,6 @@ func (m *PrivateKey) GetPubkey() *PublicKey { return nil } -func (m *PrivateKey) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - func (m *PrivateKey) GetPrivkey() []byte { if m != nil { return m.Privkey @@ -1464,6 +1450,80 @@ func (m *KeyIDsListResponse) GetMessage() string { return "" } +type CryptoServicePrivateKeySignMessage struct { + Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` + Digest []byte `protobuf:"bytes,2,opt,name=digest,proto3" json:"digest,omitempty"` + Privkey []byte `protobuf:"bytes,3,opt,name=privkey,proto3" json:"privkey,omitempty"` + Gun string `protobuf:"bytes,4,opt,name=gun" json:"gun,omitempty"` +} + +func (m *CryptoServicePrivateKeySignMessage) Reset() { *m = CryptoServicePrivateKeySignMessage{} } +func (m *CryptoServicePrivateKeySignMessage) String() string { return proto.CompactTextString(m) } +func (*CryptoServicePrivateKeySignMessage) ProtoMessage() {} +func (*CryptoServicePrivateKeySignMessage) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{47} +} + +func (m *CryptoServicePrivateKeySignMessage) GetPubkey() *PublicKey { + if m != nil { + return m.Pubkey + } + return nil +} + +func (m *CryptoServicePrivateKeySignMessage) GetDigest() []byte { + if m != nil { + return m.Digest + } + return nil +} + +func (m *CryptoServicePrivateKeySignMessage) GetPrivkey() []byte { + if m != nil { + return m.Privkey + } + return nil +} + +func (m *CryptoServicePrivateKeySignMessage) GetGun() string { + if m != nil { + return m.Gun + } + return "" +} + +type SignatureResponse struct { + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` +} + +func (m *SignatureResponse) Reset() { *m = SignatureResponse{} } +func (m *SignatureResponse) String() string { return proto.CompactTextString(m) } +func (*SignatureResponse) ProtoMessage() {} +func (*SignatureResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{48} } + +func (m *SignatureResponse) GetSignature() []byte { + if m != nil { + return m.Signature + } + return nil +} + +func (m *SignatureResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +func (m *SignatureResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + type SigningKeyIDsToRolesResponse struct { KeyIDs map[string]string `protobuf:"bytes,1,rep,name=keyIDs" json:"keyIDs,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` @@ -1473,7 +1533,7 @@ type SigningKeyIDsToRolesResponse struct { func (m *SigningKeyIDsToRolesResponse) Reset() { *m = SigningKeyIDsToRolesResponse{} } func (m *SigningKeyIDsToRolesResponse) String() string { return proto.CompactTextString(m) } func (*SigningKeyIDsToRolesResponse) ProtoMessage() {} -func (*SigningKeyIDsToRolesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{47} } +func (*SigningKeyIDsToRolesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{49} } func (m *SigningKeyIDsToRolesResponse) GetKeyIDs() map[string]string { if m != nil { @@ -1504,7 +1564,7 @@ type VersionMessage struct { func (m *VersionMessage) Reset() { *m = VersionMessage{} } func (m *VersionMessage) String() string { return proto.CompactTextString(m) } func (*VersionMessage) ProtoMessage() {} -func (*VersionMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{48} } +func (*VersionMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{50} } func (m *VersionMessage) GetVersion() int32 { if m != nil { @@ -1568,6 +1628,8 @@ func init() { proto.RegisterType((*PrivateKeyResponse)(nil), "api.PrivateKeyResponse") proto.RegisterType((*KeyIDMessage)(nil), "api.KeyIDMessage") proto.RegisterType((*KeyIDsListResponse)(nil), "api.KeyIDsListResponse") + proto.RegisterType((*CryptoServicePrivateKeySignMessage)(nil), "api.CryptoServicePrivateKeySignMessage") + proto.RegisterType((*SignatureResponse)(nil), "api.SignatureResponse") proto.RegisterType((*SigningKeyIDsToRolesResponse)(nil), "api.SigningKeyIDsToRolesResponse") proto.RegisterType((*VersionMessage)(nil), "api.VersionMessage") } @@ -1613,6 +1675,7 @@ type NotaryClient interface { // CryptoService implementation CryptoService(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*CryptoServiceMessage, error) CryptoServiceCreate(ctx context.Context, in *CryptoServiceCreateMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) + CryptoServicePrivateKeySign(ctx context.Context, in *CryptoServicePrivateKeySignMessage, opts ...grpc.CallOption) (*SignatureResponse, error) CryptoServiceAddKey(ctx context.Context, in *CryptoServiceAddKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) CryptoServiceGetKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) CryptoServiceGetPrivateKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PrivateKeyResponse, error) @@ -1828,6 +1891,15 @@ func (c *notaryClient) CryptoServiceCreate(ctx context.Context, in *CryptoServic return out, nil } +func (c *notaryClient) CryptoServicePrivateKeySign(ctx context.Context, in *CryptoServicePrivateKeySignMessage, opts ...grpc.CallOption) (*SignatureResponse, error) { + out := new(SignatureResponse) + err := grpc.Invoke(ctx, "/api.Notary/CryptoServicePrivateKeySign", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *notaryClient) CryptoServiceAddKey(ctx context.Context, in *CryptoServiceAddKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) { out := new(BasicResponse) err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceAddKey", in, out, c.cc, opts...) @@ -1924,6 +1996,7 @@ type NotaryServer interface { // CryptoService implementation CryptoService(context.Context, *GunMessage) (*CryptoServiceMessage, error) CryptoServiceCreate(context.Context, *CryptoServiceCreateMessage) (*PublicKeyResponse, error) + CryptoServicePrivateKeySign(context.Context, *CryptoServicePrivateKeySignMessage) (*SignatureResponse, error) CryptoServiceAddKey(context.Context, *CryptoServiceAddKeyMessage) (*BasicResponse, error) CryptoServiceGetKey(context.Context, *KeyIDMessage) (*PublicKeyResponse, error) CryptoServiceGetPrivateKey(context.Context, *KeyIDMessage) (*PrivateKeyResponse, error) @@ -2333,6 +2406,24 @@ func _Notary_CryptoServiceCreate_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } +func _Notary_CryptoServicePrivateKeySign_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CryptoServicePrivateKeySignMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NotaryServer).CryptoServicePrivateKeySign(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/api.Notary/CryptoServicePrivateKeySign", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NotaryServer).CryptoServicePrivateKeySign(ctx, req.(*CryptoServicePrivateKeySignMessage)) + } + return interceptor(ctx, in, info, handler) +} + func _Notary_CryptoServiceAddKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CryptoServiceAddKeyMessage) if err := dec(in); err != nil { @@ -2551,6 +2642,10 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "CryptoServiceCreate", Handler: _Notary_CryptoServiceCreate_Handler, }, + { + MethodName: "CryptoServicePrivateKeySign", + Handler: _Notary_CryptoServicePrivateKeySign_Handler, + }, { MethodName: "CryptoServiceAddKey", Handler: _Notary_CryptoServiceAddKey_Handler, @@ -2587,127 +2682,131 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1943 bytes of a gzipped FileDescriptorProto + // 2003 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0x5f, 0x73, 0xdb, 0xc6, - 0x11, 0x0f, 0x48, 0x89, 0x32, 0x97, 0x94, 0x2c, 0x9d, 0x65, 0x8a, 0xa6, 0x6d, 0x59, 0x86, 0xdd, - 0x46, 0x69, 0x26, 0x54, 0xa3, 0xb4, 0x69, 0xd2, 0x34, 0xad, 0x69, 0xda, 0xc3, 0x28, 0xb2, 0x35, - 0x2a, 0x94, 0xd8, 0x33, 0xcd, 0x4c, 0xa7, 0x30, 0x71, 0x25, 0x31, 0x02, 0x01, 0x06, 0x38, 0x69, - 0x8a, 0x3e, 0xb4, 0xd3, 0xbe, 0xb5, 0xd3, 0x99, 0x4e, 0x1e, 0xfb, 0x11, 0xfa, 0xda, 0x6f, 0xd0, - 0xef, 0xe0, 0x0f, 0xd4, 0xb9, 0x3f, 0x38, 0xdc, 0x01, 0x07, 0x4a, 0xe5, 0xb4, 0x6f, 0xbc, 0xc3, - 0xee, 0x6f, 0xff, 0xdc, 0xee, 0xed, 0xde, 0x12, 0x9a, 0xee, 0xdc, 0xef, 0xcf, 0xe3, 0x88, 0x44, - 0xa8, 0xee, 0xce, 0xfd, 0xde, 0xdd, 0x49, 0x14, 0x4d, 0x02, 0x7c, 0xc0, 0xb6, 0xde, 0x5c, 0xfc, - 0xf6, 0xe0, 0xf9, 0x6c, 0x4e, 0x52, 0x4e, 0x61, 0xef, 0x02, 0x8c, 0x2e, 0xc2, 0x97, 0x38, 0x49, - 0xdc, 0x09, 0x46, 0x9b, 0x50, 0x9f, 0x5c, 0x84, 0x5d, 0x6b, 0xcf, 0xda, 0x6f, 0x3a, 0xf4, 0xa7, - 0xfd, 0x57, 0x0b, 0xb6, 0x07, 0x9e, 0xf7, 0x0c, 0x07, 0x78, 0xe2, 0x12, 0x3f, 0x92, 0xa4, 0x08, - 0x56, 0x42, 0x77, 0x86, 0x05, 0x2d, 0xfb, 0x8d, 0x3e, 0x86, 0x0d, 0x4f, 0x12, 0x1e, 0xe3, 0x34, - 0xe9, 0xd6, 0xf6, 0xea, 0xfb, 0xad, 0xc3, 0x8d, 0x3e, 0x55, 0xe9, 0xf4, 0xe2, 0x4d, 0xe0, 0x8f, - 0x8f, 0x71, 0xea, 0x14, 0xa8, 0xd0, 0x36, 0xac, 0xce, 0x5d, 0x32, 0x4d, 0xba, 0xf5, 0xbd, 0xfa, - 0x7e, 0xd3, 0xe1, 0x8b, 0x4c, 0x99, 0x95, 0x5c, 0x99, 0x3f, 0xc2, 0x03, 0x4d, 0x17, 0x27, 0x0a, - 0xf0, 0x20, 0xf4, 0x28, 0xc6, 0xff, 0x43, 0x2d, 0xa1, 0x40, 0x3d, 0x57, 0xe0, 0x35, 0xdc, 0xd1, - 0x14, 0x38, 0xa5, 0x8a, 0x2e, 0x12, 0x2d, 0x2d, 0xab, 0x19, 0x2c, 0x53, 0x80, 0x53, 0x78, 0xe4, - 0xe0, 0x59, 0x74, 0x89, 0x9f, 0x69, 0x2a, 0x0c, 0x42, 0xef, 0x4a, 0x11, 0x1d, 0x68, 0x9c, 0xe3, - 0xf4, 0xe8, 0x59, 0x26, 0x43, 0xac, 0xae, 0xed, 0xd4, 0x21, 0xdc, 0x2d, 0x8a, 0xa6, 0x7e, 0x5d, - 0x24, 0x52, 0x80, 0xd4, 0x72, 0x90, 0x5f, 0xc1, 0xbd, 0x22, 0xc8, 0xff, 0xcc, 0x37, 0xdf, 0x94, - 0x15, 0xbc, 0xea, 0xc4, 0xab, 0x7c, 0x52, 0x06, 0xff, 0x09, 0xdc, 0xa4, 0xd6, 0x9e, 0xb8, 0x33, - 0xd5, 0xe2, 0x38, 0x0a, 0x24, 0x20, 0xfd, 0x6d, 0xb0, 0xf8, 0x0f, 0xb0, 0xe9, 0x44, 0xc4, 0x25, - 0xf8, 0x18, 0xa7, 0x8b, 0x38, 0x7f, 0x00, 0x9b, 0x09, 0x8e, 0x2f, 0x71, 0xfc, 0xd2, 0x0d, 0xdd, - 0x09, 0x4e, 0x8e, 0x71, 0xca, 0x60, 0x6e, 0x38, 0xa5, 0x7d, 0xd4, 0x85, 0xb5, 0x73, 0x9c, 0xbe, - 0xf0, 0x13, 0x22, 0x0e, 0x2d, 0x5b, 0x1a, 0x8e, 0xed, 0xcf, 0x16, 0xb4, 0x8e, 0x42, 0x9f, 0x64, - 0xb2, 0x77, 0x01, 0xe2, 0x28, 0x22, 0xc7, 0xdc, 0x6c, 0x8b, 0xb1, 0x2b, 0x3b, 0x68, 0x00, 0x48, - 0x95, 0xe7, 0x51, 0xab, 0x13, 0xa6, 0x49, 0xeb, 0x70, 0x8b, 0x25, 0x42, 0xe6, 0x07, 0x2a, 0xd0, - 0x31, 0x10, 0x1b, 0xbc, 0xf7, 0x18, 0xda, 0x2a, 0x17, 0x3d, 0xd2, 0x98, 0xe1, 0x72, 0xf9, 0x7c, - 0x61, 0x7f, 0x0e, 0xb7, 0x54, 0xaa, 0x4c, 0x63, 0x23, 0xb1, 0xc1, 0xd3, 0x7f, 0xb2, 0x60, 0x5b, - 0xd3, 0x0d, 0x27, 0xf3, 0x28, 0x4c, 0x30, 0xfa, 0x31, 0xb4, 0x63, 0x65, 0x9f, 0xb9, 0xdd, 0x68, - 0x8c, 0x46, 0x46, 0xbd, 0x9c, 0x5c, 0x8c, 0xc7, 0x38, 0x49, 0xc4, 0x41, 0x64, 0x4b, 0xfa, 0x65, - 0xc6, 0x95, 0x13, 0x46, 0x66, 0x4b, 0xfb, 0x53, 0xd8, 0xfa, 0xca, 0x8d, 0x27, 0x98, 0x14, 0x02, - 0xe5, 0x1a, 0xa9, 0xf1, 0x2f, 0x0b, 0x1a, 0x9c, 0xb7, 0x7c, 0xbd, 0x4a, 0x88, 0x9a, 0x1e, 0xbc, - 0x01, 0x0e, 0x27, 0x64, 0xca, 0x94, 0xa8, 0x3b, 0x62, 0x85, 0x0e, 0xa0, 0x31, 0x75, 0x93, 0x29, - 0x4e, 0xba, 0x2b, 0xec, 0xfa, 0xda, 0x61, 0x86, 0x72, 0xe8, 0xfe, 0x17, 0xec, 0xcb, 0xf3, 0x90, - 0xc4, 0xa9, 0x23, 0xc8, 0x7a, 0x9f, 0x42, 0x4b, 0xd9, 0xa6, 0xd2, 0xcf, 0x71, 0x9a, 0x49, 0x3f, - 0xc7, 0x29, 0x3d, 0x81, 0x4b, 0x37, 0xb8, 0xe0, 0xe2, 0xdb, 0x0e, 0x5f, 0xfc, 0xb4, 0xf6, 0x89, - 0x65, 0x1f, 0xc1, 0x06, 0x07, 0x7e, 0xed, 0x93, 0x29, 0xf5, 0x25, 0x7a, 0x04, 0x0d, 0xc2, 0x76, - 0x84, 0x9b, 0x5b, 0x8a, 0x74, 0x47, 0x7c, 0x92, 0x09, 0x50, 0xcb, 0x13, 0xc0, 0xfe, 0x8b, 0x05, - 0x1d, 0x1d, 0x4b, 0x1e, 0xe0, 0x67, 0xb0, 0x41, 0xb4, 0x2f, 0x02, 0xfb, 0x96, 0x82, 0x2d, 0x99, - 0x0a, 0xa4, 0x4b, 0x1d, 0xe3, 0xa8, 0xa8, 0x8a, 0x0c, 0x8a, 0x0f, 0x60, 0x8d, 0xe3, 0xf3, 0x70, - 0xac, 0xd0, 0x21, 0xa3, 0xb1, 0xff, 0x6e, 0xc1, 0xae, 0x19, 0x49, 0x1a, 0x77, 0x06, 0x1d, 0x62, - 0xa4, 0x10, 0x46, 0xde, 0x35, 0x08, 0x90, 0x20, 0x15, 0xac, 0xd5, 0x46, 0xdb, 0x63, 0x40, 0x1c, - 0xeb, 0x69, 0x4a, 0xa9, 0x07, 0x63, 0x7a, 0x4f, 0x1a, 0x43, 0xf4, 0xdd, 0x2c, 0xef, 0x2a, 0x93, - 0x5f, 0x4f, 0x45, 0x25, 0xdf, 0xbf, 0x85, 0xe6, 0x99, 0x3f, 0x09, 0x5d, 0x72, 0x11, 0xb3, 0xfc, - 0x65, 0xd7, 0xaa, 0x00, 0xe7, 0x0b, 0x1a, 0xbd, 0x33, 0x4c, 0xa6, 0x91, 0x27, 0x82, 0x40, 0xac, - 0xd0, 0x3d, 0x68, 0x26, 0x19, 0x2b, 0x83, 0x6c, 0x3b, 0xf9, 0x06, 0xb5, 0xcb, 0x4f, 0x5e, 0xb9, - 0x81, 0xef, 0xb1, 0x3b, 0xee, 0x86, 0x93, 0x2d, 0xed, 0x5f, 0x42, 0x53, 0x56, 0x68, 0xb4, 0x01, - 0x35, 0xdf, 0x13, 0xf2, 0x6a, 0x3e, 0x03, 0x75, 0x83, 0x49, 0x14, 0xfb, 0x64, 0x3a, 0x13, 0xf2, - 0xf2, 0x0d, 0xaa, 0xca, 0x9c, 0xb1, 0x0a, 0x79, 0x62, 0x65, 0x7f, 0x0d, 0x5b, 0x79, 0xd1, 0xcf, - 0x8e, 0xeb, 0xfb, 0x8c, 0x38, 0x4b, 0x90, 0x72, 0x73, 0x20, 0xbe, 0x2e, 0x38, 0x81, 0xb7, 0x16, - 0x6c, 0xe8, 0x35, 0x14, 0x7d, 0x08, 0x2b, 0xe7, 0xb4, 0xdf, 0xe0, 0x21, 0x75, 0x9f, 0x41, 0xea, - 0x24, 0x7d, 0x5a, 0xca, 0x78, 0xda, 0x32, 0x52, 0xe3, 0x8d, 0x70, 0x0f, 0x9a, 0x64, 0x1a, 0xe3, - 0x64, 0x1a, 0x05, 0x1e, 0xb3, 0x65, 0xd5, 0xc9, 0x37, 0xf2, 0x3a, 0xba, 0xa2, 0xd4, 0xd1, 0xde, - 0x08, 0x9a, 0x12, 0xda, 0x90, 0xfa, 0x8f, 0xd5, 0xd4, 0x2f, 0x5b, 0xab, 0x5c, 0x05, 0x7f, 0xb3, - 0xa0, 0xcd, 0x23, 0x8b, 0x1e, 0x3d, 0xf6, 0xd0, 0xbb, 0x4a, 0x95, 0xcb, 0xf2, 0x44, 0x37, 0x4a, - 0x94, 0xbe, 0xfc, 0xca, 0xa8, 0x55, 0x5f, 0x19, 0x7d, 0x00, 0x19, 0x06, 0xbc, 0x57, 0xc9, 0xb4, - 0x91, 0x91, 0xe6, 0x28, 0x14, 0xf6, 0x2f, 0x60, 0x53, 0xd5, 0x86, 0x65, 0xc5, 0xfb, 0xc5, 0xe4, - 0xdd, 0x52, 0x24, 0x71, 0xba, 0x3c, 0x75, 0xbf, 0xb3, 0xa0, 0x5b, 0x44, 0x90, 0x51, 0x30, 0x80, - 0x4d, 0x52, 0xf8, 0x26, 0xec, 0xbc, 0x5d, 0x82, 0x64, 0x8c, 0x25, 0xf2, 0xa5, 0xee, 0xa5, 0x21, - 0xac, 0x3f, 0x75, 0x13, 0x7f, 0x2c, 0xf5, 0x50, 0x40, 0xac, 0x4a, 0x90, 0x9a, 0x0e, 0xf2, 0x3b, - 0x68, 0x0c, 0xa7, 0x6e, 0x38, 0x61, 0x15, 0xc4, 0x65, 0xf9, 0x2f, 0x4e, 0x5c, 0xac, 0x68, 0xa4, - 0x24, 0xe3, 0x68, 0x9e, 0x71, 0xf2, 0x05, 0x8d, 0x38, 0x92, 0xce, 0x33, 0x9d, 0xd8, 0x6f, 0xba, - 0x47, 0xc3, 0x48, 0x34, 0x1c, 0xec, 0x37, 0x95, 0x3c, 0x8e, 0x42, 0x82, 0x43, 0xd2, 0x5d, 0x65, - 0xf9, 0x94, 0x2d, 0xed, 0x8f, 0x00, 0xb8, 0x64, 0xe6, 0x80, 0xef, 0xc1, 0xda, 0x98, 0xad, 0xb2, - 0xd3, 0xe0, 0xe7, 0xce, 0x29, 0x9c, 0xec, 0x9b, 0x9d, 0x02, 0xca, 0x99, 0xa4, 0xe1, 0x07, 0x00, - 0x9c, 0x20, 0xc8, 0x5d, 0x7f, 0x53, 0xe1, 0x67, 0xc4, 0x0a, 0xc9, 0x52, 0xee, 0x7e, 0x02, 0x37, - 0x9c, 0x28, 0x22, 0x2c, 0x45, 0xf3, 0x56, 0xd1, 0xd2, 0x5a, 0x45, 0x2d, 0xe7, 0x6a, 0x85, 0x9c, - 0xb3, 0xbf, 0x81, 0x15, 0xc6, 0xfd, 0x1e, 0xdc, 0x88, 0x05, 0x92, 0x50, 0x76, 0x5d, 0x5c, 0xa7, - 0x7c, 0xd3, 0x91, 0x9f, 0x8d, 0x89, 0x6d, 0xec, 0xd1, 0xed, 0xf7, 0xa9, 0x7a, 0x01, 0x77, 0xe6, - 0x03, 0xb5, 0x49, 0x6a, 0x1d, 0x36, 0xe5, 0x65, 0x9d, 0x35, 0x57, 0xdf, 0xd2, 0x3e, 0x34, 0xd0, - 0x9d, 0xc8, 0xb4, 0x0a, 0xd4, 0x62, 0xb3, 0x2e, 0xf9, 0x18, 0xa1, 0xfc, 0xbc, 0x94, 0xfb, 0xc6, - 0x80, 0x28, 0x12, 0x2d, 0x4e, 0x32, 0x47, 0x93, 0x42, 0x22, 0x5b, 0x57, 0x25, 0x32, 0xba, 0xaf, - 0xf4, 0x0a, 0x9a, 0x61, 0xbc, 0x6d, 0x70, 0xa1, 0x53, 0x16, 0xc2, 0x54, 0x1e, 0x01, 0x8a, 0x4b, - 0x5f, 0x84, 0xc0, 0x1d, 0x09, 0xa3, 0x7f, 0x76, 0x0c, 0x2c, 0xf6, 0x3f, 0x2d, 0xd8, 0x35, 0xcb, - 0x50, 0x8b, 0x78, 0x6c, 0xa4, 0xd0, 0x8a, 0x78, 0x05, 0x48, 0x05, 0xeb, 0x52, 0x3e, 0xef, 0xc0, - 0xf6, 0x30, 0x4e, 0xe7, 0x24, 0x3a, 0xc3, 0xf1, 0xa5, 0x3f, 0xce, 0x7a, 0x50, 0x7b, 0x0a, 0x3d, - 0x6d, 0x7f, 0x18, 0x63, 0x97, 0xc8, 0x0e, 0xb5, 0xc7, 0x03, 0xe1, 0x24, 0x6f, 0x01, 0xe4, 0xba, - 0xdc, 0xa9, 0xea, 0xd5, 0xb4, 0x5e, 0xa8, 0xa6, 0xf6, 0x09, 0x34, 0xd8, 0x2d, 0x17, 0x5f, 0xbb, - 0x54, 0x6a, 0x25, 0x5f, 0x54, 0x67, 0xb9, 0x61, 0xff, 0xdb, 0x02, 0x38, 0x8d, 0xfd, 0x4b, 0xfe, - 0x84, 0x5a, 0x1e, 0xb4, 0xd8, 0x47, 0xcc, 0x63, 0xff, 0x92, 0xc2, 0xf0, 0x9a, 0x9f, 0x2d, 0xd1, - 0x01, 0xb4, 0xc7, 0xdc, 0x51, 0xcc, 0x08, 0x76, 0xb3, 0x65, 0x57, 0x13, 0xdf, 0x72, 0x34, 0x02, - 0x64, 0x43, 0x3b, 0xf1, 0x27, 0x03, 0xe9, 0x90, 0x55, 0x66, 0x80, 0xb6, 0x67, 0xcf, 0x0a, 0xde, - 0x1f, 0x78, 0x9e, 0xf2, 0x1c, 0xfc, 0xef, 0xbc, 0xff, 0x90, 0xd7, 0xe8, 0xba, 0x72, 0xe5, 0xe5, - 0xee, 0x61, 0x45, 0xdb, 0xfe, 0x87, 0x05, 0x48, 0xd9, 0xcb, 0x82, 0xf4, 0x5a, 0x0f, 0x56, 0xf4, - 0x9e, 0xee, 0x1a, 0x83, 0x0c, 0xe9, 0x2b, 0x25, 0x40, 0x57, 0x2a, 0x03, 0x74, 0x55, 0x0f, 0xd0, - 0x8f, 0xa1, 0xcd, 0x5e, 0x9a, 0xca, 0xeb, 0xce, 0xd0, 0x1d, 0x96, 0x9f, 0x47, 0xbf, 0x01, 0xc4, - 0x5f, 0xa8, 0x5a, 0xde, 0x55, 0xdd, 0xca, 0xcb, 0xa4, 0xce, 0x5b, 0x0b, 0xee, 0xd1, 0x33, 0xf5, - 0xc3, 0x09, 0x97, 0xf4, 0x55, 0xc4, 0xde, 0xb3, 0x52, 0xd8, 0x73, 0x4d, 0x58, 0xeb, 0xf0, 0x03, - 0x19, 0x14, 0x55, 0x2c, 0x7d, 0xbe, 0x2b, 0x9e, 0x5b, 0xcb, 0xeb, 0x46, 0x9f, 0x68, 0x0a, 0xd4, - 0x55, 0x4f, 0xb4, 0xa6, 0xda, 0x97, 0xfd, 0x0c, 0x36, 0x5e, 0xe1, 0x38, 0x51, 0x46, 0x72, 0x5d, - 0x58, 0xbb, 0xe4, 0x3b, 0x0c, 0x61, 0xd5, 0xc9, 0x96, 0x65, 0xb7, 0x1f, 0x7e, 0xb7, 0x09, 0x8d, - 0x93, 0x88, 0xb8, 0x71, 0x8a, 0x7e, 0x04, 0x70, 0x14, 0xfa, 0xc4, 0x77, 0x03, 0xff, 0xf7, 0x18, - 0x6d, 0x32, 0xe3, 0x95, 0xc9, 0x42, 0x0f, 0xb1, 0x1d, 0xad, 0x3f, 0xb1, 0xdf, 0x41, 0x3f, 0x84, - 0x35, 0x96, 0x9c, 0xc9, 0x14, 0xf1, 0x40, 0xca, 0xc7, 0x88, 0x15, 0x1c, 0x7d, 0x68, 0x0e, 0x3c, - 0x4f, 0x3c, 0x85, 0xd5, 0x5e, 0xb0, 0x82, 0xfe, 0x43, 0x68, 0xf3, 0xb9, 0xcf, 0xf5, 0x59, 0x4e, - 0xa0, 0x45, 0xc3, 0x88, 0xd3, 0x24, 0xa8, 0x5b, 0x7a, 0xda, 0x64, 0x1a, 0x3e, 0x5a, 0xf4, 0xf8, - 0xca, 0xf1, 0x8e, 0xe0, 0xe6, 0x08, 0x13, 0xf5, 0x5d, 0x85, 0xd4, 0x57, 0xb7, 0xfa, 0xd4, 0xea, - 0x99, 0xde, 0x73, 0x0a, 0xd4, 0xd7, 0xd0, 0x1b, 0x61, 0x32, 0x08, 0x02, 0x4e, 0xf1, 0x12, 0x13, - 0xd7, 0x73, 0x89, 0x2b, 0x50, 0x3b, 0x0a, 0xb3, 0x32, 0x62, 0xe8, 0xdd, 0x37, 0x77, 0x9d, 0x39, - 0xec, 0x67, 0xb0, 0x3e, 0xc2, 0x64, 0x98, 0xf7, 0x43, 0xa5, 0xc3, 0xd8, 0x29, 0x76, 0x4f, 0x39, - 0xf3, 0x10, 0x9a, 0x6c, 0x87, 0xbd, 0xf6, 0x4a, 0x8c, 0x8f, 0x16, 0xd5, 0xb6, 0x1c, 0xe4, 0xe7, - 0x80, 0x46, 0x98, 0xe8, 0x0f, 0x00, 0x03, 0xda, 0x6d, 0xbd, 0x03, 0xc9, 0xf9, 0x9f, 0xc0, 0xba, - 0x36, 0x53, 0x45, 0x77, 0x18, 0xa5, 0x69, 0xe8, 0x5c, 0x71, 0xea, 0xaf, 0xa0, 0x5b, 0x35, 0x16, - 0x46, 0x8f, 0xcb, 0x60, 0xe5, 0xa9, 0x71, 0x05, 0xee, 0x97, 0x80, 0xca, 0xd3, 0x5e, 0xb4, 0x5b, - 0x46, 0x54, 0x47, 0x9d, 0x15, 0x58, 0xbf, 0x2e, 0x0f, 0x48, 0xd5, 0x01, 0x2f, 0xda, 0xe7, 0xee, - 0xb9, 0x7a, 0x06, 0x5c, 0x19, 0xf9, 0xdb, 0xa6, 0x29, 0x2e, 0xda, 0x33, 0xe2, 0x2a, 0x03, 0xde, - 0x0a, 0xbc, 0x53, 0xb8, 0x6d, 0x1c, 0xe8, 0xa2, 0x87, 0x46, 0xc0, 0xe5, 0x34, 0x64, 0x27, 0xb4, - 0x57, 0x69, 0xf9, 0x62, 0xbc, 0xa7, 0xb0, 0x3d, 0x0c, 0xb0, 0x1b, 0x17, 0x15, 0xdc, 0xd6, 0x92, - 0x7e, 0x31, 0xc6, 0x13, 0x58, 0x7b, 0xed, 0x93, 0x90, 0xdd, 0xd1, 0x95, 0x77, 0xc5, 0x9d, 0xf2, - 0x80, 0x24, 0x47, 0xf8, 0x04, 0x9a, 0x72, 0x0c, 0x8c, 0xb2, 0x18, 0xd7, 0xc7, 0xc2, 0x15, 0xb2, - 0x3f, 0x87, 0x75, 0xad, 0x77, 0x28, 0xa7, 0x0c, 0x17, 0x6c, 0x6c, 0xfb, 0xe8, 0x01, 0xdd, 0x32, - 0x34, 0x7e, 0xe8, 0x41, 0x99, 0x47, 0x6b, 0x09, 0x7b, 0x9d, 0x42, 0x5f, 0x95, 0x2b, 0xf4, 0xa2, - 0x80, 0xc8, 0x9b, 0x19, 0x13, 0xa2, 0xd6, 0xe6, 0x54, 0x1e, 0x8f, 0x8e, 0x36, 0xc2, 0x84, 0xa2, - 0xf1, 0x97, 0xb9, 0xda, 0x29, 0x2c, 0xd0, 0xe8, 0xcb, 0x42, 0x7b, 0x35, 0xc2, 0x44, 0xe9, 0x18, - 0x0d, 0x50, 0x3b, 0xc5, 0x96, 0x26, 0xc7, 0x1a, 0x40, 0x47, 0xc3, 0xe2, 0x01, 0x57, 0x81, 0x63, - 0x36, 0xe9, 0x0b, 0xb8, 0xad, 0x41, 0xd0, 0x50, 0xe0, 0xff, 0x5f, 0x19, 0x43, 0x6e, 0x27, 0xc7, - 0x2d, 0xde, 0x99, 0xa7, 0xd0, 0x2d, 0x21, 0x0d, 0x82, 0x80, 0x81, 0x95, 0xc2, 0xe0, 0xe1, 0x95, - 0xed, 0x08, 0x73, 0xf7, 0xd6, 0x19, 0x26, 0x2f, 0xf0, 0xc4, 0x1d, 0xa7, 0xa2, 0x2d, 0x48, 0x10, - 0x9f, 0xcd, 0xe8, 0x5d, 0x42, 0xaf, 0xd3, 0xe7, 0xff, 0x07, 0xf6, 0xb3, 0xff, 0x03, 0xfb, 0xec, - 0xff, 0x40, 0xfb, 0x9d, 0x37, 0x0d, 0xb6, 0xf3, 0xd1, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x7b, - 0xf1, 0xa4, 0xe4, 0x41, 0x1c, 0x00, 0x00, + 0x11, 0x37, 0x48, 0x89, 0x32, 0x97, 0x94, 0x2c, 0x9d, 0x65, 0x8a, 0xa6, 0x6d, 0x59, 0x86, 0xdd, + 0xda, 0x69, 0x26, 0x54, 0xa2, 0xb4, 0x69, 0xd2, 0x34, 0xad, 0x69, 0xda, 0xc3, 0x28, 0xb2, 0x3d, + 0x2a, 0x94, 0xd8, 0x33, 0xcd, 0x4c, 0x27, 0x30, 0x71, 0x25, 0x31, 0x02, 0x01, 0x06, 0x38, 0x69, + 0x8a, 0x3e, 0xb4, 0xd3, 0xbe, 0xb5, 0xd3, 0x99, 0xb6, 0x8f, 0x7d, 0xee, 0x53, 0x5f, 0xfb, 0x59, + 0xf2, 0x4d, 0xfa, 0x05, 0x3a, 0xf7, 0x0f, 0xb8, 0x03, 0x0e, 0x94, 0xcc, 0x69, 0xdf, 0x78, 0x87, + 0xdd, 0xdf, 0xfe, 0xb9, 0xdd, 0xdb, 0xbd, 0x25, 0x34, 0xdd, 0xb9, 0xdf, 0x9f, 0xc7, 0x11, 0x89, + 0x50, 0xdd, 0x9d, 0xfb, 0xbd, 0x5b, 0x93, 0x28, 0x9a, 0x04, 0x78, 0x9f, 0x6d, 0xbd, 0x39, 0xfb, + 0xf5, 0xfe, 0xb3, 0xd9, 0x9c, 0xa4, 0x9c, 0xc2, 0xde, 0x05, 0x18, 0x9d, 0x85, 0x2f, 0x70, 0x92, + 0xb8, 0x13, 0x8c, 0x36, 0xa1, 0x3e, 0x39, 0x0b, 0xbb, 0xd6, 0x9e, 0xf5, 0xa8, 0xe9, 0xd0, 0x9f, + 0xf6, 0x9f, 0x2d, 0xd8, 0x1e, 0x78, 0xde, 0x53, 0x1c, 0xe0, 0x89, 0x4b, 0xfc, 0x28, 0x23, 0x45, + 0xb0, 0x12, 0xba, 0x33, 0x2c, 0x68, 0xd9, 0x6f, 0xf4, 0x11, 0x6c, 0x78, 0x19, 0xe1, 0x11, 0x4e, + 0x93, 0x6e, 0x6d, 0xaf, 0xfe, 0xa8, 0x75, 0xb0, 0xd1, 0xa7, 0x2a, 0x1d, 0x9f, 0xbd, 0x09, 0xfc, + 0xf1, 0x11, 0x4e, 0x9d, 0x02, 0x15, 0xda, 0x86, 0xd5, 0xb9, 0x4b, 0xa6, 0x49, 0xb7, 0xbe, 0x57, + 0x7f, 0xd4, 0x74, 0xf8, 0x42, 0x2a, 0xb3, 0x92, 0x2b, 0xf3, 0x7b, 0xb8, 0xab, 0xe9, 0xe2, 0x44, + 0x01, 0x1e, 0x84, 0x1e, 0xc5, 0xf8, 0x7f, 0xa8, 0x25, 0x14, 0xa8, 0xe7, 0x0a, 0xbc, 0x86, 0x9b, + 0x9a, 0x02, 0xc7, 0x54, 0xd1, 0x45, 0xa2, 0x33, 0xcb, 0x6a, 0x06, 0xcb, 0x14, 0xe0, 0x14, 0xee, + 0x3b, 0x78, 0x16, 0x9d, 0xe3, 0xa7, 0x9a, 0x0a, 0x83, 0xd0, 0xbb, 0x50, 0x44, 0x07, 0x1a, 0xa7, + 0x38, 0x3d, 0x7c, 0x2a, 0x65, 0x88, 0xd5, 0xa5, 0x9d, 0x3a, 0x84, 0x5b, 0x45, 0xd1, 0xd4, 0xaf, + 0x8b, 0x44, 0x0a, 0x90, 0x5a, 0x0e, 0xf2, 0x4b, 0xb8, 0x5d, 0x04, 0xf9, 0x9f, 0xf9, 0xe6, 0xeb, + 0xb2, 0x82, 0x17, 0x9d, 0x78, 0x95, 0x4f, 0xca, 0xe0, 0x3f, 0x86, 0x6b, 0xd4, 0xda, 0x97, 0xee, + 0x4c, 0xb5, 0x38, 0x8e, 0x82, 0x0c, 0x90, 0xfe, 0x36, 0x58, 0xfc, 0x3b, 0xd8, 0x74, 0x22, 0xe2, + 0x12, 0x7c, 0x84, 0xd3, 0x45, 0x9c, 0x3f, 0x80, 0xcd, 0x04, 0xc7, 0xe7, 0x38, 0x7e, 0xe1, 0x86, + 0xee, 0x04, 0x27, 0x47, 0x38, 0x65, 0x30, 0x57, 0x9d, 0xd2, 0x3e, 0xea, 0xc2, 0xda, 0x29, 0x4e, + 0x9f, 0xfb, 0x09, 0x11, 0x87, 0x26, 0x97, 0x86, 0x63, 0xfb, 0xa3, 0x05, 0xad, 0xc3, 0xd0, 0x27, + 0x52, 0xf6, 0x2e, 0x40, 0x1c, 0x45, 0xe4, 0x88, 0x9b, 0x6d, 0x31, 0x76, 0x65, 0x07, 0x0d, 0x00, + 0xa9, 0xf2, 0x3c, 0x6a, 0x75, 0xc2, 0x34, 0x69, 0x1d, 0x6c, 0xb1, 0x44, 0x90, 0x7e, 0xa0, 0x02, + 0x1d, 0x03, 0xb1, 0xc1, 0x7b, 0x0f, 0xa0, 0xad, 0x72, 0xd1, 0x23, 0x8d, 0x19, 0x2e, 0x97, 0xcf, + 0x17, 0xf6, 0x67, 0x70, 0x5d, 0xa5, 0x92, 0x1a, 0x1b, 0x89, 0x0d, 0x9e, 0xfe, 0x83, 0x05, 0xdb, + 0x9a, 0x6e, 0x38, 0x99, 0x47, 0x61, 0x82, 0xd1, 0x8f, 0xa0, 0x1d, 0x2b, 0xfb, 0xcc, 0xed, 0x46, + 0x63, 0x34, 0x32, 0xea, 0xe5, 0xe4, 0x6c, 0x3c, 0xc6, 0x49, 0x22, 0x0e, 0x42, 0x2e, 0xe9, 0x97, + 0x19, 0x57, 0x4e, 0x18, 0x29, 0x97, 0xf6, 0x27, 0xb0, 0xf5, 0xa5, 0x1b, 0x4f, 0x30, 0x29, 0x04, + 0xca, 0x25, 0x52, 0xe3, 0xdf, 0x16, 0x34, 0x38, 0x6f, 0xf9, 0x7a, 0xcd, 0x20, 0x6a, 0x7a, 0xf0, + 0x06, 0x38, 0x9c, 0x90, 0x29, 0x53, 0xa2, 0xee, 0x88, 0x15, 0xda, 0x87, 0xc6, 0xd4, 0x4d, 0xa6, + 0x38, 0xe9, 0xae, 0xb0, 0xeb, 0x6b, 0x87, 0x19, 0xca, 0xa1, 0xfb, 0x9f, 0xb3, 0x2f, 0xcf, 0x42, + 0x12, 0xa7, 0x8e, 0x20, 0xeb, 0x7d, 0x02, 0x2d, 0x65, 0x9b, 0x4a, 0x3f, 0xc5, 0xa9, 0x94, 0x7e, + 0x8a, 0x53, 0x7a, 0x02, 0xe7, 0x6e, 0x70, 0xc6, 0xc5, 0xb7, 0x1d, 0xbe, 0xf8, 0x49, 0xed, 0x63, + 0xcb, 0x3e, 0x84, 0x0d, 0x0e, 0xfc, 0xda, 0x27, 0x53, 0xea, 0x4b, 0x74, 0x1f, 0x1a, 0x84, 0xed, + 0x08, 0x37, 0xb7, 0x14, 0xe9, 0x8e, 0xf8, 0x94, 0x25, 0x40, 0x2d, 0x4f, 0x00, 0xfb, 0x4f, 0x16, + 0x74, 0x74, 0xac, 0xec, 0x00, 0x3f, 0x85, 0x0d, 0xa2, 0x7d, 0x11, 0xd8, 0xd7, 0x15, 0xec, 0x8c, + 0xa9, 0x40, 0xba, 0xd4, 0x31, 0x8e, 0x8a, 0xaa, 0x64, 0x41, 0xf1, 0x1e, 0xac, 0x71, 0x7c, 0x1e, + 0x8e, 0x15, 0x3a, 0x48, 0x1a, 0xfb, 0xaf, 0x16, 0xec, 0x9a, 0x91, 0x32, 0xe3, 0x4e, 0xa0, 0x43, + 0x8c, 0x14, 0xc2, 0xc8, 0x5b, 0x06, 0x01, 0x19, 0x48, 0x05, 0x6b, 0xb5, 0xd1, 0xf6, 0x18, 0x10, + 0xc7, 0x7a, 0x92, 0x52, 0xea, 0xc1, 0x98, 0xde, 0x93, 0xc6, 0x10, 0x7d, 0x28, 0xf3, 0xae, 0x32, + 0xf9, 0xf5, 0x54, 0x54, 0xf2, 0xfd, 0x5b, 0x68, 0x9e, 0xf8, 0x93, 0xd0, 0x25, 0x67, 0x31, 0xcb, + 0x5f, 0x76, 0xad, 0x0a, 0x70, 0xbe, 0xa0, 0xd1, 0x3b, 0xc3, 0x64, 0x1a, 0x79, 0x22, 0x08, 0xc4, + 0x0a, 0xdd, 0x86, 0x66, 0x22, 0x59, 0x19, 0x64, 0xdb, 0xc9, 0x37, 0xa8, 0x5d, 0x7e, 0xf2, 0xca, + 0x0d, 0x7c, 0x8f, 0xdd, 0x71, 0x57, 0x1d, 0xb9, 0xb4, 0x7f, 0x01, 0xcd, 0xac, 0x42, 0xa3, 0x0d, + 0xa8, 0xf9, 0x9e, 0x90, 0x57, 0xf3, 0x19, 0xa8, 0x1b, 0x4c, 0xa2, 0xd8, 0x27, 0xd3, 0x99, 0x90, + 0x97, 0x6f, 0x50, 0x55, 0xe6, 0x8c, 0x55, 0xc8, 0x13, 0x2b, 0xfb, 0x2b, 0xd8, 0xca, 0x8b, 0xbe, + 0x3c, 0xae, 0xef, 0x33, 0x62, 0x99, 0x20, 0xe5, 0xe6, 0x40, 0x7c, 0x5d, 0x70, 0x02, 0xdf, 0x59, + 0xb0, 0xa1, 0xd7, 0x50, 0xf4, 0x01, 0xac, 0x9c, 0xd2, 0x7e, 0x83, 0x87, 0xd4, 0x1d, 0x06, 0xa9, + 0x93, 0xf4, 0x69, 0x29, 0xe3, 0x69, 0xcb, 0x48, 0x8d, 0x37, 0xc2, 0x6d, 0x68, 0x92, 0x69, 0x8c, + 0x93, 0x69, 0x14, 0x78, 0xcc, 0x96, 0x55, 0x27, 0xdf, 0xc8, 0xeb, 0xe8, 0x8a, 0x52, 0x47, 0x7b, + 0x23, 0x68, 0x66, 0xd0, 0x86, 0xd4, 0x7f, 0xa0, 0xa6, 0x7e, 0xd9, 0x5a, 0xe5, 0x2a, 0xf8, 0x8b, + 0x05, 0x6d, 0x1e, 0x59, 0xf4, 0xe8, 0xb1, 0x87, 0x1e, 0x2a, 0x55, 0x4e, 0xe6, 0x89, 0x6e, 0x94, + 0x28, 0x7d, 0xf9, 0x95, 0x51, 0xab, 0xbe, 0x32, 0xfa, 0x00, 0x59, 0x18, 0xf0, 0x5e, 0x45, 0x6a, + 0x93, 0x45, 0x9a, 0xa3, 0x50, 0xd8, 0x3f, 0x87, 0x4d, 0x55, 0x1b, 0x96, 0x15, 0xef, 0x16, 0x93, + 0x77, 0x4b, 0x91, 0xc4, 0xe9, 0xf2, 0xd4, 0xfd, 0xbb, 0x05, 0xdd, 0x22, 0x42, 0x16, 0x05, 0x03, + 0xd8, 0x24, 0x85, 0x6f, 0xc2, 0xce, 0x1b, 0x25, 0x48, 0xc6, 0x58, 0x22, 0x5f, 0xea, 0x5e, 0x1a, + 0xc2, 0xfa, 0x13, 0x37, 0xf1, 0xc7, 0x99, 0x1e, 0x0a, 0x88, 0x55, 0x09, 0x52, 0xd3, 0x41, 0x7e, + 0x03, 0x8d, 0xe1, 0xd4, 0x0d, 0x27, 0xac, 0x82, 0xb8, 0x2c, 0xff, 0xc5, 0x89, 0x8b, 0x15, 0x8d, + 0x94, 0x64, 0x1c, 0xcd, 0x25, 0x27, 0x5f, 0xd0, 0x88, 0x23, 0xe9, 0x5c, 0xea, 0xc4, 0x7e, 0xd3, + 0x3d, 0x1a, 0x46, 0xa2, 0xe1, 0x60, 0xbf, 0xa9, 0xe4, 0x71, 0x14, 0x12, 0x1c, 0x92, 0xee, 0x2a, + 0xcb, 0x27, 0xb9, 0xb4, 0x3f, 0x04, 0xe0, 0x92, 0x99, 0x03, 0xbe, 0x07, 0x6b, 0x63, 0xb6, 0x92, + 0xa7, 0xc1, 0xcf, 0x9d, 0x53, 0x38, 0xf2, 0x9b, 0x9d, 0x02, 0xca, 0x99, 0x32, 0xc3, 0xf7, 0x01, + 0x38, 0x41, 0x90, 0xbb, 0xfe, 0x9a, 0xc2, 0xcf, 0x88, 0x15, 0x92, 0xa5, 0xdc, 0xfd, 0x18, 0xae, + 0x3a, 0x51, 0x44, 0x58, 0x8a, 0xe6, 0xad, 0xa2, 0xa5, 0xb5, 0x8a, 0x5a, 0xce, 0xd5, 0x0a, 0x39, + 0x67, 0x7f, 0x0d, 0x2b, 0x8c, 0xfb, 0x1d, 0xb8, 0x1a, 0x0b, 0x24, 0xa1, 0xec, 0xba, 0xb8, 0x4e, + 0xf9, 0xa6, 0x93, 0x7d, 0x36, 0x26, 0xb6, 0xb1, 0x47, 0xb7, 0xdf, 0xa5, 0xea, 0x05, 0xdc, 0x99, + 0x77, 0xd5, 0x26, 0xa9, 0x75, 0xd0, 0xcc, 0x2e, 0x6b, 0xd9, 0x5c, 0x7d, 0x4b, 0xfb, 0xd0, 0x40, + 0x77, 0x22, 0xd3, 0x2a, 0x50, 0x8b, 0xcd, 0x7a, 0xc6, 0xc7, 0x08, 0xb3, 0xcf, 0x4b, 0xb9, 0x6f, + 0x0c, 0x88, 0x22, 0xd1, 0xe2, 0x94, 0xe5, 0x68, 0x52, 0x48, 0x64, 0xeb, 0xa2, 0x44, 0x46, 0x77, + 0x94, 0x5e, 0x41, 0x33, 0x8c, 0xb7, 0x0d, 0x2e, 0x74, 0xca, 0x42, 0x98, 0xca, 0x23, 0x40, 0x71, + 0xe9, 0x8b, 0x10, 0xb8, 0x93, 0xc1, 0xe8, 0x9f, 0x1d, 0x03, 0x8b, 0xfd, 0x2f, 0x0b, 0x76, 0xcd, + 0x32, 0xd4, 0x22, 0x1e, 0x1b, 0x29, 0xb4, 0x22, 0x5e, 0x01, 0x52, 0xc1, 0xba, 0x94, 0xcf, 0x3b, + 0xb0, 0x3d, 0x8c, 0xd3, 0x39, 0x89, 0x4e, 0x70, 0x7c, 0xee, 0x8f, 0x65, 0x0f, 0x6a, 0x4f, 0xa1, + 0xa7, 0xed, 0x0f, 0x63, 0xec, 0x92, 0xac, 0x43, 0xed, 0xf1, 0x40, 0x78, 0x99, 0xb7, 0x00, 0xd9, + 0xba, 0xdc, 0xa9, 0xea, 0xd5, 0xb4, 0x5e, 0xa8, 0xa6, 0xf6, 0xfb, 0xd0, 0x60, 0xb7, 0x5c, 0x7c, + 0xd9, 0x52, 0x69, 0xff, 0xd3, 0x02, 0x38, 0x8e, 0xfd, 0x73, 0xfe, 0x48, 0x7a, 0x9b, 0x0a, 0x3b, + 0x8f, 0xfd, 0xf3, 0x53, 0xf1, 0x50, 0x6a, 0x3b, 0x72, 0x89, 0xf6, 0xa1, 0x3d, 0xe6, 0xc6, 0x32, + 0x45, 0x98, 0x8e, 0xf2, 0x7a, 0xe1, 0x5b, 0x8e, 0x46, 0x80, 0x6c, 0x68, 0x27, 0xfe, 0x64, 0x90, + 0x19, 0xc5, 0xaf, 0x33, 0x6d, 0xcf, 0x9e, 0x15, 0x3c, 0x38, 0xf0, 0x3c, 0xe5, 0x49, 0xf7, 0x76, + 0x1e, 0xbc, 0xc7, 0xeb, 0x6c, 0x5d, 0xb9, 0xb6, 0x72, 0x07, 0xb0, 0xc2, 0x6b, 0xff, 0xc3, 0x02, + 0xa4, 0xec, 0xc9, 0x40, 0xbb, 0xd4, 0xa3, 0x13, 0xbd, 0x93, 0xbb, 0xa6, 0x42, 0x46, 0xe6, 0x2b, + 0x25, 0xc8, 0x56, 0x2a, 0x83, 0x6c, 0x55, 0x0f, 0xb2, 0x8f, 0xa0, 0xcd, 0x5e, 0x8b, 0xca, 0x0b, + 0xcd, 0xd0, 0xe1, 0x95, 0x9f, 0x38, 0xdf, 0x00, 0xe2, 0xaf, 0x4c, 0x2d, 0x77, 0xaa, 0x6e, 0xd6, + 0x65, 0xc2, 0xff, 0x6f, 0x16, 0xd8, 0xda, 0x29, 0xe5, 0x26, 0xd3, 0xa3, 0x96, 0x0a, 0x5f, 0x36, + 0xc4, 0x3a, 0xd0, 0xf0, 0xfc, 0x09, 0x4e, 0x88, 0x88, 0x30, 0xb1, 0x52, 0x43, 0xaf, 0xae, 0x87, + 0x5e, 0xf9, 0x01, 0x8e, 0x61, 0x2b, 0xbf, 0xd8, 0xa4, 0xcd, 0x5a, 0x97, 0x6b, 0x19, 0xba, 0xdc, + 0xb7, 0xb6, 0xfc, 0x3b, 0x0b, 0x6e, 0x53, 0x39, 0x7e, 0x38, 0xe1, 0x3e, 0xfe, 0x32, 0x62, 0xaf, + 0xf1, 0x4c, 0xe4, 0x33, 0xcd, 0xcd, 0xad, 0x83, 0xf7, 0xb2, 0x74, 0xa8, 0x62, 0xe9, 0xf3, 0x5d, + 0xf1, 0x58, 0x5c, 0xfe, 0x54, 0xe8, 0x03, 0x53, 0x81, 0xba, 0xe8, 0x81, 0xd9, 0x54, 0xbb, 0xca, + 0x9f, 0xc2, 0xc6, 0x2b, 0x1c, 0x27, 0xca, 0x40, 0xb1, 0x0b, 0x6b, 0xe7, 0x7c, 0x87, 0x21, 0xac, + 0x3a, 0x72, 0x59, 0x0e, 0xb8, 0x83, 0xff, 0x6c, 0x42, 0xe3, 0x65, 0x44, 0xdc, 0x38, 0x45, 0x3f, + 0x04, 0x38, 0x0c, 0x7d, 0xe2, 0xbb, 0x81, 0xff, 0x5b, 0x8c, 0x36, 0x99, 0xf1, 0xca, 0x5c, 0xa4, + 0x87, 0xd8, 0x8e, 0xd6, 0x5d, 0xd9, 0x57, 0xd0, 0xfb, 0xb0, 0xc6, 0xa2, 0x22, 0x99, 0x22, 0x9e, + 0x42, 0xf9, 0x10, 0xb4, 0x82, 0xa3, 0x0f, 0xcd, 0x81, 0xe7, 0x89, 0x87, 0xbc, 0xda, 0xc9, 0x56, + 0xd0, 0x7f, 0x00, 0x6d, 0x3e, 0xb5, 0xba, 0x3c, 0xcb, 0x4b, 0x68, 0xd1, 0x04, 0xe2, 0x34, 0x09, + 0xea, 0x96, 0x1e, 0x66, 0x52, 0xc3, 0xfb, 0x8b, 0x9e, 0x8e, 0x39, 0xde, 0x21, 0x5c, 0x1b, 0x61, + 0xa2, 0xbe, 0x0a, 0x91, 0x3a, 0x33, 0x50, 0x1f, 0x8a, 0x3d, 0xd3, 0x6b, 0x54, 0x81, 0xfa, 0x0a, + 0x7a, 0x23, 0x4c, 0x06, 0x41, 0xc0, 0x29, 0x5e, 0x60, 0xe2, 0x7a, 0x2e, 0x71, 0x05, 0x6a, 0x47, + 0x61, 0x56, 0x06, 0x24, 0xbd, 0x3b, 0xe6, 0x9e, 0x39, 0x87, 0xfd, 0x14, 0xd6, 0x47, 0x98, 0x0c, + 0xf3, 0x6e, 0xae, 0x74, 0x18, 0x3b, 0xc5, 0xde, 0x2f, 0x67, 0x1e, 0x42, 0x93, 0xed, 0xb0, 0xb7, + 0x6a, 0x89, 0xf1, 0xfe, 0xa2, 0xca, 0x9c, 0x83, 0xfc, 0x0c, 0xd0, 0x08, 0x13, 0xfd, 0xf9, 0x62, + 0x40, 0xbb, 0xa1, 0xf7, 0x4f, 0x39, 0xff, 0x63, 0x58, 0xd7, 0x26, 0xc2, 0xe8, 0x26, 0xa3, 0x34, + 0x8d, 0xcc, 0x2b, 0x4e, 0xfd, 0x15, 0x74, 0xab, 0x86, 0xda, 0xe8, 0x41, 0x19, 0xac, 0x3c, 0xf3, + 0xae, 0xc0, 0xfd, 0x02, 0x50, 0x79, 0x56, 0x8d, 0x76, 0xcb, 0x88, 0xea, 0xa0, 0xb6, 0x02, 0xeb, + 0x57, 0xe5, 0xf1, 0xae, 0x3a, 0x9e, 0x46, 0x8f, 0xb8, 0x7b, 0x2e, 0x9e, 0x60, 0x57, 0x46, 0xfe, + 0xb6, 0x69, 0x06, 0x8d, 0xf6, 0x8c, 0xb8, 0xca, 0x78, 0xba, 0x02, 0xef, 0x18, 0x6e, 0x18, 0xc7, + 0xd1, 0xe8, 0x9e, 0x11, 0x70, 0x39, 0x0d, 0xd9, 0x09, 0xed, 0x55, 0x5a, 0xbe, 0x18, 0xef, 0x09, + 0x6c, 0x0f, 0x03, 0xec, 0xc6, 0x45, 0x05, 0xb7, 0xb5, 0xa4, 0x5f, 0x8c, 0xf1, 0x18, 0xd6, 0x5e, + 0xfb, 0x24, 0x64, 0x77, 0x74, 0xe5, 0x5d, 0x71, 0xb3, 0x3c, 0xde, 0xc9, 0x11, 0x3e, 0x86, 0x66, + 0x36, 0xc4, 0x46, 0x32, 0xc6, 0xf5, 0xa1, 0x76, 0x85, 0xec, 0xcf, 0x60, 0x5d, 0xab, 0xc7, 0xe5, + 0x94, 0xe1, 0x82, 0x8d, 0x4d, 0x2b, 0x3d, 0xa0, 0xeb, 0x86, 0xb6, 0x15, 0xdd, 0x2d, 0xf3, 0x68, + 0x0d, 0x6d, 0xaf, 0x53, 0x28, 0xe8, 0xb9, 0x42, 0xdf, 0xc0, 0xad, 0x05, 0x0d, 0x02, 0x7a, 0x58, + 0x46, 0x36, 0xb6, 0x10, 0x42, 0x42, 0xa9, 0xb2, 0xdb, 0x57, 0xd0, 0xf3, 0x82, 0xce, 0xbc, 0x51, + 0x34, 0xe9, 0xac, 0xb5, 0x90, 0x95, 0x01, 0xa0, 0xa3, 0x8d, 0x30, 0xa1, 0x68, 0x7c, 0x72, 0xa1, + 0x76, 0x61, 0x0b, 0x6c, 0xfe, 0xa2, 0xd0, 0xba, 0x8e, 0x30, 0x51, 0xfa, 0x6d, 0x03, 0xd4, 0x4e, + 0xb1, 0x5d, 0xcc, 0xb1, 0x06, 0xd0, 0xd1, 0xb0, 0x78, 0x48, 0x57, 0xe0, 0x98, 0x4d, 0xfa, 0x1c, + 0x6e, 0x68, 0x10, 0x34, 0xd8, 0xf8, 0xff, 0x7b, 0xc6, 0xa0, 0xde, 0xc9, 0x71, 0x8b, 0xb7, 0xf2, + 0x31, 0x74, 0x4b, 0x48, 0x83, 0x20, 0x60, 0x60, 0xa5, 0x40, 0xbb, 0x77, 0x61, 0xc3, 0xc3, 0xdc, + 0xbd, 0x75, 0x82, 0xc9, 0x73, 0x3c, 0x71, 0xc7, 0xa9, 0x68, 0x3c, 0x12, 0xc4, 0x67, 0x57, 0x7a, + 0x1f, 0xd2, 0xeb, 0xf4, 0xf9, 0xff, 0xa5, 0x7d, 0xf9, 0x7f, 0x69, 0x9f, 0xfd, 0x5f, 0x6a, 0x5f, + 0x79, 0xd3, 0x60, 0x3b, 0x1f, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0x1d, 0xd1, 0xf4, 0x21, 0x61, + 0x1d, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index cdce14b85..3c4cb5da8 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -42,6 +42,7 @@ service Notary { // CryptoService implementation rpc CryptoService(GunMessage) returns (CryptoServiceMessage) {} rpc CryptoServiceCreate(CryptoServiceCreateMessage) returns (PublicKeyResponse) {} + rpc CryptoServicePrivateKeySign(CryptoServicePrivateKeySignMessage) returns (SignatureResponse) {} rpc CryptoServiceAddKey(CryptoServiceAddKeyMessage) returns (BasicResponse) {} rpc CryptoServiceGetKey(KeyIDMessage) returns (PublicKeyResponse) {} rpc CryptoServiceGetPrivateKey(KeyIDMessage) returns (PrivateKeyResponse) {} @@ -293,15 +294,13 @@ message CryptoServiceCreateMessage { message Signer { PublicKey pubkey = 1; - string signature = 2; } message PrivateKey { PublicKey pubkey = 1; - bytes signature = 2; - bytes privkey = 3; - Signer cryptoSigner = 4; - string sigAlgorithm = 5; + bytes privkey = 2; + Signer cryptoSigner = 3; + string sigAlgorithm = 4; } message CryptoServiceAddKeyMessage { @@ -329,6 +328,19 @@ message KeyIDsListResponse { string message = 3; } +message CryptoServicePrivateKeySignMessage { + PublicKey pubkey = 1; + bytes digest = 2; + bytes privkey = 3; + string gun = 4; +} + +message SignatureResponse { + bytes signature = 1; + bool success = 2; + string message = 3; +} + message SigningKeyIDsToRolesResponse { map keyIDs = 1; bool success = 2; diff --git a/client_api/api/client.go b/client_api/api/client.go index c5af197a7..4b8349675 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -32,7 +32,7 @@ func (c *Client) Initialize(rootKeyIDs []string, serverManagedRoles ...data.Role initMsg := &InitMessage{ RootKeyIDs: rootKeyIDs, ServerManagedRoles: &RoleNameList{Roles: roles}, - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.Initialize(context.Background(), initMsg) return err @@ -113,7 +113,7 @@ func (c *Client) GetTargetByName(name string, roles ...data.RoleName) (*client.T targetByNameAction := &TargetByNameAction{ Name: name, Roles: &RoleNameList{Roles: rolesList}, - Gun: c.gun.String(), + Gun: c.gun.String(), } targetWithRole, err := c.client.GetTargetByName(context.Background(), targetByNameAction) @@ -139,7 +139,7 @@ func (c *Client) GetTargetByName(name string, roles ...data.RoleName) (*client.T func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) { targetName := &TargetNameMessage{ Name: name, - Gun: c.gun.String(), + Gun: c.gun.String(), } targetSignedListResponse, err := c.client.GetAllTargetMetadataByName(context.Background(), targetName) @@ -295,7 +295,7 @@ func (c *Client) AddDelegation(name data.RoleName, delegationKeys []data.PublicK Name: name.String(), DelegationKeys: currDelegationKeys, Paths: paths, - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.AddDelegation(context.Background(), addDelegationMessage) @@ -315,7 +315,7 @@ func (c *Client) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []d addDelegationRoleAndKeysMessage := &AddDelegationRoleAndKeysMessage{ Name: name.String(), DelegationKeys: pubKeys, - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.AddDelegationRoleAndKeys(context.Background(), addDelegationRoleAndKeysMessage) @@ -326,7 +326,7 @@ func (c *Client) AddDelegationPaths(name data.RoleName, paths []string) error { addDelegationPathsMessage := &AddDelegationPathsMessage{ Name: name.String(), Paths: paths, - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.AddDelegationPaths(context.Background(), addDelegationPathsMessage) @@ -338,7 +338,7 @@ func (c *Client) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths Name: name.String(), KeyIDs: keyIDs, Paths: paths, - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.RemoveDelegationKeysAndPaths(context.Background(), r) @@ -348,7 +348,7 @@ func (c *Client) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths func (c *Client) RemoveDelegationRole(name data.RoleName) error { r := &RemoveDelegationRoleMessage{ Name: name.String(), - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.RemoveDelegationRole(context.Background(), r) @@ -359,7 +359,7 @@ func (c *Client) RemoveDelegationPaths(name data.RoleName, paths []string) error r := &RemoveDelegationPathsMessage{ Name: name.String(), Paths: paths, - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.RemoveDelegationPaths(context.Background(), r) @@ -370,7 +370,7 @@ func (c *Client) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error r := &RemoveDelegationKeysMessage{ Name: name.String(), KeyIDs: keyIDs, - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.RemoveDelegationKeys(context.Background(), r) @@ -380,7 +380,7 @@ func (c *Client) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error func (c *Client) ClearDelegationPaths(name data.RoleName) error { r := &RoleNameMessage{ Role: name.String(), - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.ClearDelegationPaths(context.Background(), r) @@ -395,7 +395,7 @@ func (c *Client) Witness(roles ...data.RoleName) ([]data.RoleName, error) { roleNameList := &RoleNameListMessage{ Roles: roleNames, - Gun: c.gun.String(), + Gun: c.gun.String(), } roleNameListResponse, err := c.client.Witness(context.Background(), roleNameList) @@ -418,7 +418,7 @@ func (c *Client) RotateKey(role data.RoleName, serverManagesKey bool, keyList [] Role: role.String(), ServerManagesKey: serverManagesKey, KeyList: keyList, - Gun: c.gun.String(), + Gun: c.gun.String(), } _, err := c.client.RotateKey(context.Background(), rotateKeyMessage) return err diff --git a/client_api/api/server.go b/client_api/api/server.go index 9b2fd5329..de7d6e585 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -8,6 +8,7 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc" + "crypto/rand" "github.com/docker/notary" "github.com/docker/notary/client" "github.com/docker/notary/client/changelist" @@ -296,10 +297,10 @@ func (srv *Server) ListRoles(ctx context.Context, message *GunMessage) (*RoleWit Signatures: resSignatures, Role: &Role{ RootRole: &RootRole{ - KeyIDs: role.KeyIDs, + KeyIDs: role.KeyIDs, Threshold: int32(role.Threshold), // FIXME }, - Name: role.Name.String(), + Name: role.Name.String(), Paths: role.Paths, }, } @@ -327,12 +328,12 @@ func (srv *Server) GetDelegationRoles(ctx context.Context, message *GunMessage) resRoles := make([]*Role, len(roles)) for index, role := range roles { resRoles[index] = &Role{ - RootRole: &RootRole{ - KeyIDs: role.KeyIDs, - Threshold: int32(role.Threshold), // FIXME - }, - Name: role.Name.String(), - Paths: role.Paths, + RootRole: &RootRole{ + KeyIDs: role.KeyIDs, + Threshold: int32(role.Threshold), // FIXME + }, + Name: role.Name.String(), + Paths: role.Paths, } } @@ -424,7 +425,7 @@ func (srv *Server) RemoveDelegationRole(ctx context.Context, message *RemoveDele return nil, err } - err = r.RemoveDelegationRole() + err = r.RemoveDelegationRole(data.RoleName(message.Name)) if err != nil { return nil, err } @@ -440,7 +441,7 @@ func (srv *Server) RemoveDelegationPaths(ctx context.Context, message *RemoveDel return nil, err } - err = r.RemoveDelegationPaths() + err = r.RemoveDelegationPaths(data.RoleName(message.Name), message.Paths) if err != nil { return nil, err } @@ -456,7 +457,7 @@ func (srv *Server) RemoveDelegationKeys(ctx context.Context, message *RemoveDele return nil, err } - err = r.RemoveDelegationKeys() + err = r.RemoveDelegationKeys(data.RoleName(message.Name), message.KeyIDs) if err != nil { return nil, err } @@ -472,7 +473,7 @@ func (srv *Server) ClearDelegationPaths(ctx context.Context, message *RoleNameMe return nil, err } - err = r.ClearDelegationPaths() + err = r.ClearDelegationPaths(data.RoleName(message.Role)) if err != nil { return nil, err } @@ -488,21 +489,43 @@ func (srv *Server) Witness(ctx context.Context, message *RoleNameListMessage) (* return nil, err } - roles, err := r.Witness() + roles := make([]data.RoleName, len(message.Roles)) + for index, role := range message.Roles { + roles[index] = data.RoleName(role) + } + + currRoles, err := r.Witness(roles...) if err != nil { return nil, err } + resRoles := make([]string, len(currRoles)) + for index, role := range currRoles { + resRoles[index] = role.String() + } + return &RoleNameListResponse{ RoleNameList: &RoleNameList{ - Roles + Roles: resRoles, }, Success: true, }, nil } func (srv *Server) RotateKey(ctx context.Context, message *RotateKeyMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + err = r.RotateKey(data.RoleName(message.Role), message.ServerManagesKey, message.KeyList) + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } // CryptoService implementation @@ -511,31 +534,182 @@ func (srv *Server) CryptoService(ctx context.Context, message *GunMessage) (*Cry } func (srv *Server) CryptoServiceCreate(ctx context.Context, message *CryptoServiceCreateMessage) (*PublicKeyResponse, error) { - return nil, ErrNotImplemented + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + cs := r.CryptoService() + + pubkey, err := cs.Create(data.RoleName(message.RoleName), data.GUN(message.Gun), message.Algorithm) + if err != nil { + return nil, err + } + + return &PublicKeyResponse{ + Pubkey: &PublicKey{ + Id: pubkey.ID(), + Algorithm: pubkey.Algorithm(), + Public: pubkey.Public(), + }, + Success: true, + }, nil +} + +func (srv *Server) CryptoServicePrivateKeySign(ctx context.Context, message *CryptoServicePrivateKeySignMessage) (*SignatureResponse, error) { + pubkey := data.NewPublicKey(message.Pubkey.Algorithm, message.Pubkey.Public) + privkey, err := data.NewPrivateKey(pubkey, message.Privkey) + if err != nil { + return nil, err + } + + sig, err := privkey.Sign(rand.Reader, message.Digest, nil) + if err != nil { + return nil, err + } + + return &SignatureResponse{ + Signature: sig, + Success: true, + }, nil } func (srv *Server) CryptoServiceAddKey(ctx context.Context, message *CryptoServiceAddKeyMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + cs := r.CryptoService() + + pubKey := data.NewPublicKey(message.Key.Pubkey.Algorithm, message.Key.Pubkey.Public) + + privKey, err := data.NewPrivateKey(pubKey, message.Key.Privkey) + if err != nil { + return nil, err + } + + err = cs.AddKey(data.RoleName(message.RoleName), data.GUN(message.Gun), privKey) + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } func (srv *Server) CryptoServiceGetKey(ctx context.Context, message *KeyIDMessage) (*PublicKeyResponse, error) { - return nil, ErrNotImplemented + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + cs := r.CryptoService() + + pubkey := cs.GetKey(message.KeyID) + + return &PublicKeyResponse{ + Pubkey: &PublicKey{ + Id: pubkey.ID(), + Algorithm: pubkey.Algorithm(), + Public: pubkey.Public(), + }, + Success: true, + }, nil } func (srv *Server) CryptoServiceGetPrivateKey(ctx context.Context, message *KeyIDMessage) (*PrivateKeyResponse, error) { - return nil, ErrNotImplemented + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + cs := r.CryptoService() + + privkey, rolename, err := cs.GetPrivateKey(message.KeyID) + if err != nil { + return nil, err + } + + resPrivkey := &PrivateKey{ + Pubkey: &PublicKey{ + Id: privkey.ID(), + Algorithm: privkey.Algorithm(), + Public: privkey.Public(), + }, + Privkey: privkey.Private(), + CryptoSigner: &Signer{ + Pubkey: &PublicKey{ + Id: data.PublicKey(privkey.CryptoSigner().Public()).ID(), + Algorithm: data.PublicKey(privkey.CryptoSigner().Public()).Algorithm(), + Public: data.PublicKey(privkey.CryptoSigner().Public()).Public(), + }, + }, + SigAlgorithm: privkey.SignatureAlgorithm().String(), + } + + return &PrivateKeyResponse{ + Role: rolename.String(), + Gun: message.Gun, + Privkey: resPrivkey, + Success: true, + }, nil } func (srv *Server) CryptoServiceRemoveKey(ctx context.Context, message *KeyIDMessage) (*BasicResponse, error) { - return nil, ErrNotImplemented + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + cs := r.CryptoService() + + err = cs.RemoveKey(message.KeyID) + if err != nil { + return nil, err + } + + return &BasicResponse{ + Success: true, + }, nil } func (srv *Server) CryptoServiceListKeys(ctx context.Context, message *RoleNameMessage) (*KeyIDsListResponse, error) { - return nil, ErrNotImplemented + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + cs := r.CryptoService() + + keys := cs.ListKeys(data.RoleName(message.Role)) + + return &KeyIDsListResponse{ + KeyIDs: keys, + Success: true, + }, nil } func (srv *Server) CryptoServiceListAllKeys(ctx context.Context, message *GunMessage) (*SigningKeyIDsToRolesResponse, error) { - return nil, ErrNotImplemented + r, err := srv.initRepo(data.GUN(message.Gun)) + if err != nil { + return nil, err + } + + cs := r.CryptoService() + + keys := cs.ListAllKeys() + + resKeys := make(map[string]string, len(keys)) + for keyID, role := range keys { + resKeys[keyID] = role.String() + } + + return &SigningKeyIDsToRolesResponse{ + KeyIDs: resKeys, + Success: true, + }, nil } func (srv *Server) SetLegacyVersions(ctx context.Context, message *VersionMessage) (*google_protobuf.Empty, error) { From c82dadead2ad47e224d888c2f3deeacef699dc7b Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Thu, 16 Mar 2017 19:59:33 +0100 Subject: [PATCH 34/62] Fix cherry-pick conflicts Signed-off-by: Nassim 'Nass' Eddequiouaq --- client_api/api/server.go | 12 ++++++------ cmd/notary/config.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/client_api/api/server.go b/client_api/api/server.go index de7d6e585..d7f817f1f 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -247,13 +247,13 @@ func (srv *Server) GetChangelist(ctx context.Context, message *GunMessage) (*Cha return nil, err } - changelist, err := r.GetChangelist() + cl, err := r.GetChangelist() if err != nil { return nil, err } - resChangelist := make([]*Change, len(changelist.List())) - for index, change := range changelist.List() { + resChangelist := make([]*Change, len(cl.List())) + for index, change := range cl.List() { resChangelist[index] = &Change{ Action: change.Action(), Scope: change.Scope().String(), @@ -641,9 +641,9 @@ func (srv *Server) CryptoServiceGetPrivateKey(ctx context.Context, message *KeyI Privkey: privkey.Private(), CryptoSigner: &Signer{ Pubkey: &PublicKey{ - Id: data.PublicKey(privkey.CryptoSigner().Public()).ID(), - Algorithm: data.PublicKey(privkey.CryptoSigner().Public()).Algorithm(), - Public: data.PublicKey(privkey.CryptoSigner().Public()).Public(), + Id: privkey.ID(), + Algorithm: privkey.Algorithm(), + Public: privkey.Public(), }, }, SigAlgorithm: privkey.SignatureAlgorithm().String(), diff --git a/cmd/notary/config.json b/cmd/notary/config.json index 2ae55d235..805b4de17 100644 --- a/cmd/notary/config.json +++ b/cmd/notary/config.json @@ -5,7 +5,7 @@ }, "api": { "addr": "clientapi-server:4449", - "tls_ca_file": "/Users/david/go/src/github.com/docker/notary/fixtures/root-ca.crt" + "tls_ca_file": "/Users/nass/work/src/github.com/docker/notary/fixtures/root-ca.crt" } } From e21831c5482a753ba29dd7585e2e3258965b09dd Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Fri, 17 Mar 2017 11:23:33 -0700 Subject: [PATCH 35/62] moving around some of the auth stuff to collect it better in one place. Wrapping up configuration of auth Signed-off-by: David Lawrence (github: endophage) --- .../client}/authchallenge.go | 2 +- {client/auth => auth/client}/session.go | 2 +- {utils/grpcauth => auth/grpc}/auth.go | 11 ++- {utils/grpcauth => auth/grpc}/auth_test.go | 2 +- {utils => auth}/token/accesscontroller.go | 0 {utils => auth}/token/stringset.go | 0 {utils => auth}/token/token.go | 0 {utils => auth}/token/util.go | 0 client_api/api/server.go | 4 +- cmd/clientapi/main.go | 11 ++- cmd/clientapi/setup/config.go | 73 ++++++++++++++++++- const.go | 11 +++ 12 files changed, 99 insertions(+), 17 deletions(-) rename {client/auth/challenge => auth/client}/authchallenge.go (99%) rename {client/auth => auth/client}/session.go (99%) rename {utils/grpcauth => auth/grpc}/auth.go (94%) rename {utils/grpcauth => auth/grpc}/auth_test.go (96%) rename {utils => auth}/token/accesscontroller.go (100%) rename {utils => auth}/token/stringset.go (100%) rename {utils => auth}/token/token.go (100%) rename {utils => auth}/token/util.go (100%) diff --git a/client/auth/challenge/authchallenge.go b/auth/client/authchallenge.go similarity index 99% rename from client/auth/challenge/authchallenge.go rename to auth/client/authchallenge.go index 38b9b7994..ec19e0e6c 100644 --- a/client/auth/challenge/authchallenge.go +++ b/auth/client/authchallenge.go @@ -1,4 +1,4 @@ -package challenge +package client import ( "net/http" diff --git a/client/auth/session.go b/auth/client/session.go similarity index 99% rename from client/auth/session.go rename to auth/client/session.go index 248cceb80..51ddcadc6 100644 --- a/client/auth/session.go +++ b/auth/client/session.go @@ -1,4 +1,4 @@ -package auth +package client import ( "encoding/json" diff --git a/utils/grpcauth/auth.go b/auth/grpc/auth.go similarity index 94% rename from utils/grpcauth/auth.go rename to auth/grpc/auth.go index e1201a658..4c01647fa 100644 --- a/utils/grpcauth/auth.go +++ b/auth/grpc/auth.go @@ -1,11 +1,11 @@ package grpcauth import ( + "errors" "fmt" "github.com/Sirupsen/logrus" - "github.com/docker/notary/client/auth" - "github.com/docker/notary/client/auth/challenge" - "github.com/docker/notary/utils/token" + auth "github.com/docker/notary/auth/client" + "github.com/docker/notary/auth/token" google_protobuf "github.com/golang/protobuf/ptypes/empty" "golang.org/x/net/context" "google.golang.org/grpc" @@ -134,7 +134,10 @@ func (c *ClientAuthorizer) Interceptor(ctx context.Context, method string, req, } func (c *ClientAuthorizer) getToken(challengeHeader []string) (string, error) { - challenges := challenge.ParseAuthHeader(challengeHeader) + challenges := auth.ParseAuthHeader(challengeHeader) + if len(challenges) == 0 { + return "", errors.New("no challenge header could be parsed from the response") + } logrus.Infof("received challenge for following token: %s", challenges[0]) return c.authHandler.AuthorizeRequest(challenges[0].Parameters, challenges[0].Parameters["scope"]) } diff --git a/utils/grpcauth/auth_test.go b/auth/grpc/auth_test.go similarity index 96% rename from utils/grpcauth/auth_test.go rename to auth/grpc/auth_test.go index 186acf074..faee622ab 100644 --- a/utils/grpcauth/auth_test.go +++ b/auth/grpc/auth_test.go @@ -1,9 +1,9 @@ package grpcauth import ( + "github.com/docker/notary/auth/token" "github.com/docker/notary/client" "github.com/docker/notary/client_api/api" - "github.com/docker/notary/utils/token" "github.com/stretchr/testify/require" "google.golang.org/grpc" "net" diff --git a/utils/token/accesscontroller.go b/auth/token/accesscontroller.go similarity index 100% rename from utils/token/accesscontroller.go rename to auth/token/accesscontroller.go diff --git a/utils/token/stringset.go b/auth/token/stringset.go similarity index 100% rename from utils/token/stringset.go rename to auth/token/stringset.go diff --git a/utils/token/token.go b/auth/token/token.go similarity index 100% rename from utils/token/token.go rename to auth/token/token.go diff --git a/utils/token/util.go b/auth/token/util.go similarity index 100% rename from utils/token/util.go rename to auth/token/util.go diff --git a/client_api/api/server.go b/client_api/api/server.go index d7f817f1f..8da1676b0 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -22,13 +22,13 @@ import ( // NewServer creates a new instance of a Client API server with a configured // upstream Notary Server. -func NewServer(upstream string, upstreamCAPath string, grpcSrv *grpc.Server) (*grpc.Server, error) { +func NewServer(upstream string, upstreamCAPath string, grpcSrv *grpc.Server) error { srv := &Server{ upstream: upstream, upstreamCAPath: upstreamCAPath, } RegisterNotaryServer(grpcSrv, srv) - return grpcSrv, nil + return nil } type Server struct { diff --git a/cmd/clientapi/main.go b/cmd/clientapi/main.go index 950aaa70f..d57e850bb 100644 --- a/cmd/clientapi/main.go +++ b/cmd/clientapi/main.go @@ -50,7 +50,9 @@ func main() { opts := []grpc.ServerOption{ grpc.Creds(creds), - grpc.UnaryInterceptor(auth), + } + if auth != nil { + opts = append(opts, grpc.UnaryInterceptor(auth)) } srv, lis, err := setup.NewGRPCServer(grpcAddr, opts) @@ -58,15 +60,16 @@ func main() { logrus.Fatal("grpc server failed to start on %s: %v", grpcAddr, err) } - s, err := api.NewServer(upstreamAddr, upstreamCAPath, srv) + err = api.NewServer(upstreamAddr, upstreamCAPath, srv) if err != nil { logrus.Fatal(err) } - // grpcServer, lis, err := setup.SetupGRPCServer(serverConfig) + srv.GetServiceInfo() logrus.Infof("serving on %s", grpcAddr) - if err := s.Serve(lis); err != nil { + if err := srv.Serve(lis); err != nil { + logrus.Error("server stopped with an error: %v", err) } logrus.Info("server shutting down") } diff --git a/cmd/clientapi/setup/config.go b/cmd/clientapi/setup/config.go index 0dc762cf4..f81e18f7c 100644 --- a/cmd/clientapi/setup/config.go +++ b/cmd/clientapi/setup/config.go @@ -2,18 +2,26 @@ package setup import ( "crypto/tls" + "errors" "fmt" "github.com/Sirupsen/logrus" + "github.com/docker/notary" + grpcauth "github.com/docker/notary/auth/grpc" + "github.com/docker/notary/auth/token" + "github.com/docker/notary/client_api/api" "github.com/docker/notary/utils" "github.com/spf13/viper" - "net" - - "github.com/docker/notary/utils/grpcauth" "google.golang.org/grpc" ghealth "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" + "net" ) +// the client api will always require push and pull permissions against +// the upstream notary server so at a minimum, all endpoints will request +// these permissions. +var requiredPermissions = []string{"push", "pull"} + func ViperConfig(path string) (*viper.Viper, error) { vc := viper.New() vc.SetConfigFile(path) @@ -56,5 +64,62 @@ func GetAddrAndTLSConfig(vc *viper.Viper) (string, *tls.Config, error) { } func Authorization(vc *viper.Viper) (grpc.UnaryServerInterceptor, error) { - return grpcauth.NewServerAuthorizer("", nil) + authType := vc.GetString("auth.type") + switch authType { + case notary.AuthTypeToken: + var ( + realm = vc.GetString("auth.options.realm") + service = vc.GetString("auth.options.service") + issuer = vc.GetString("auth.options.issuer") + rootCAPath = vc.GetString("auth.options.rootcertbundle") + permissions = vc.GetStringMap("auth.options.permissions") + tokenAuth, err = token.NewAuth(realm, issuer, service, rootCAPath) + ) + if err != nil { + return nil, err + } + basePerms, err := buildBasePermissionList("push", "pull") + if err != nil { + return nil, err + } + basePerms, err = mergePermissions(basePerms, permissions) + if err != nil { + return nil, err + } + return grpcauth.NewServerAuthorizer(tokenAuth, basePerms) + + case "": + // no auth configured + return nil, nil + } + return nil, fmt.Errorf("unrecognized authorization type: %s", authType) +} + +func buildBasePermissionList(requiredPerms ...string) (map[string][]string, error) { + srv := grpc.Server{} + apiSrv := api.Server{} + api.RegisterNotaryServer(&srv, &apiSrv) + srvInfo := srv.GetServiceInfo() + svc, ok := srvInfo["api.Notary"] + if !ok { + return nil, errors.New("could not find api.Notary service") + } + permissions := make(map[string][]string) + for _, method := range svc.Methods { + permissions[method.Name] = requiredPerms + } + return permissions, nil +} + +func mergePermissions(basePerms map[string][]string, additional map[string]interface{}) (map[string][]string, error) { + for k, v := range basePerms { + if more, ok := additional[k]; ok { + add, ok := more.([]string) + if !ok { + return basePerms, fmt.Errorf("additional permissions for %s could not be parsed as a list of strings", k) + } + basePerms[k] = append(v, add...) + } + } + return basePerms, nil } diff --git a/const.go b/const.go index a1bf3588c..33410ee95 100644 --- a/const.go +++ b/const.go @@ -75,6 +75,17 @@ const ( // DefaultPageSize is the default number of records to return from the changefeed DefaultPageSize = 100 + + // Supported auth types that will be found in a config's auth.type field + + // AuthTypeToken indicates JWT based token auth. The following fields will be + // additionally required under auth.options: + // - realm: the url to the token issuing service at which tokens may be requested. + // - service: the name of the service requesting the token. + // - issuer: the name of the issuing service. + // - rootcertbundle: the absolute or relative (to the config file) path to a root ca + // that will sign the public cert associated with the token signer. + AuthTypeToken = "token" ) // enum to use for setting and retrieving values from contexts From e6e7e88656a6d360e8ce8861f3e2f33b481db7dc Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Mon, 20 Mar 2017 13:39:58 -0700 Subject: [PATCH 36/62] use relative path for API CA in cmd/notary/config.json so it works for everyone Signed-off-by: David Lawrence (github: endophage) --- cmd/notary/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/notary/config.json b/cmd/notary/config.json index 805b4de17..deeba0b8b 100644 --- a/cmd/notary/config.json +++ b/cmd/notary/config.json @@ -5,7 +5,7 @@ }, "api": { "addr": "clientapi-server:4449", - "tls_ca_file": "/Users/nass/work/src/github.com/docker/notary/fixtures/root-ca.crt" + "tls_ca_file": "../../fixtures/root-ca.crt" } } From cdfd8dfb51c6b82797bff93ee79ecf63c55a58da Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Mon, 20 Mar 2017 16:06:43 -0700 Subject: [PATCH 37/62] removing test that was intentionally failing. I was just using it to exercise some of the code while I had a debugger running Signed-off-by: David Lawrence (github: endophage) --- auth/grpc/auth_test.go | 43 ------------------------------------------ 1 file changed, 43 deletions(-) diff --git a/auth/grpc/auth_test.go b/auth/grpc/auth_test.go index faee622ab..303c8bc32 100644 --- a/auth/grpc/auth_test.go +++ b/auth/grpc/auth_test.go @@ -1,44 +1 @@ package grpcauth - -import ( - "github.com/docker/notary/auth/token" - "github.com/docker/notary/client" - "github.com/docker/notary/client_api/api" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - "net" - "testing" -) - -func TestServerAuthorizer(t *testing.T) { - tok, err := token.NewAuth("https://auth.docker.io/token", "auth.docker.io", "registry.docker.io", "../../fixtures/root-ca.crt") - require.NoError(t, err) - auth, err := NewServerAuthorizer( - tok, - map[string][]string{ - "/api.Notary/AddTarget": {"push"}, - }, - ) - require.NoError(t, err) - srv := grpc.NewServer( - grpc.UnaryInterceptor(auth), - ) - lis, err := net.Listen("tcp", "localhost:6789") - require.NoError(t, err) - - api.NewServer("", "", srv) - go srv.Serve(lis) - - conn, err := grpc.Dial( - "localhost:6789", - grpc.WithInsecure(), - grpc.WithUnaryInterceptor(NewClientAuthorizer()), - ) - require.NoError(t, err) - c := api.NewClient(conn, "endophage/carrot") - err = c.AddTarget( - &client.Target{}, - "targets", - ) - require.NoError(t, err) -} From bcc3abeeff23d500b85b5744598e9ff49993d310 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 30 Mar 2017 10:39:20 -0700 Subject: [PATCH 38/62] forward tokens from ClientAPI to notary server Signed-off-by: David Lawrence (github: endophage) --- client_api/api/server.go | 20 ++++++++++++-------- utils/transport.go | 18 +++++++++++++++++- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/client_api/api/server.go b/client_api/api/server.go index 8da1676b0..68274ce0d 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -9,6 +9,7 @@ import ( "google.golang.org/grpc" "crypto/rand" + "errors" "github.com/docker/notary" "github.com/docker/notary/client" "github.com/docker/notary/client/changelist" @@ -18,6 +19,7 @@ import ( "github.com/docker/notary/trustpinning" "github.com/docker/notary/tuf/data" "github.com/docker/notary/utils" + "google.golang.org/grpc/metadata" ) // NewServer creates a new instance of a Client API server with a configured @@ -37,7 +39,7 @@ type Server struct { } func (srv *Server) Initialize(ctx context.Context, initMessage *InitMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(initMessage.Gun)) + r, err := srv.initRepo(ctx, data.GUN(initMessage.Gun)) if err != nil { return nil, err } @@ -58,7 +60,7 @@ func (srv *Server) Initialize(ctx context.Context, initMessage *InitMessage) (*B } func (srv *Server) Publish(ctx context.Context, gun *GunMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(gun.Gun)) + r, err := srv.initRepo(ctx, data.GUN(gun.Gun)) if err != nil { return nil, err } @@ -746,15 +748,17 @@ func initializeRepo(r *client.NotaryRepository) error { return r.Initialize([]string{rootKeyID}) } -func (srv *Server) initRepo(gun data.GUN) (*client.NotaryRepository, error) { +func (srv *Server) initRepo(ctx context.Context, gun data.GUN) (*client.NotaryRepository, error) { logrus.Errorf("initializing with upstream ca file %s", srv.upstreamCAPath) baseDir := "var/lib/clientapi" - rt, err := utils.GetReadOnlyAuthTransport( - srv.upstream, - []string{gun.String()}, - "", - "", + md, ok := metadata.FromContext(ctx) + if !ok { + return nil, errors.New("initRepo may only be used with GRPC contexts") + } + tokens := md["Authorization"] + rt, err := utils.GetForwardingAuthTransport( srv.upstreamCAPath, + tokens, ) if err != nil { return nil, err diff --git a/utils/transport.go b/utils/transport.go index 53a6eb99e..53ff260f9 100644 --- a/utils/transport.go +++ b/utils/transport.go @@ -13,6 +13,7 @@ import ( "github.com/docker/distribution/registry/client/auth/challenge" "github.com/docker/distribution/registry/client/transport" "io/ioutil" + "strings" ) // Stolen from a mix of UCP + nautilus signer, some might be able to be cleaned up / streamlined @@ -86,6 +87,22 @@ func GetReadOnlyAuthTransport(server string, scopes []string, username, password return authedTransport, nil } +// GetForwardingAuthTransport returns an http.RoundTripper that fowards the provided token +// to the end service. It is assumed the token already carries the necessary authorization +// scope to perform the action required of that end service. +// It is presumed tokens is simply taken directly from the http.Header on an incoming request +// to the intermediate service and requires no additional formatting. +func GetForwardingAuthTransport(rootCAPath string, tokens []string) (http.RoundTripper, error) { + httpsTransport, err := httpsTransport(rootCAPath, "", "") + if err != nil { + return nil, err + } + tokenHeader := http.Header{ + "Authorization": tokens, + } + return transport.NewTransport(httpsTransport, transport.NewHeaderRequestModifier(tokenHeader)), nil +} + func httpsTransport(caFile, clientCertFile, clientKeyFile string) (*http.Transport, error) { tlsConfig := &tls.Config{} transport := http.Transport{ @@ -98,7 +115,6 @@ func httpsTransport(caFile, clientCertFile, clientKeyFile string) (*http.Transpo TLSClientConfig: tlsConfig, } // Override with the system cert pool if the caFile was empty - // TODO(riyazdf): update this code when go-connections updates to use the system cert pool if caFile == "" { systemCertPool, err := x509.SystemCertPool() if err != nil { From 297656cb39a06c9b8c1a48ce09527dea7840f1fd Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 30 Mar 2017 12:07:11 -0700 Subject: [PATCH 39/62] configure key storage for clientapi Signed-off-by: David Lawrence (github: endophage) --- client_api/api/server.go | 72 ++++++++++++++++------------------- cmd/clientapi/main.go | 14 ++++--- cmd/clientapi/setup/config.go | 51 +++++++++++++++++++++++++ utils/configuration.go | 33 +++++++++++++--- 4 files changed, 120 insertions(+), 50 deletions(-) diff --git a/client_api/api/server.go b/client_api/api/server.go index 68274ce0d..218652123 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -1,8 +1,6 @@ package api import ( - "path/filepath" - "github.com/Sirupsen/logrus" google_protobuf "github.com/golang/protobuf/ptypes/empty" "golang.org/x/net/context" @@ -10,7 +8,6 @@ import ( "crypto/rand" "errors" - "github.com/docker/notary" "github.com/docker/notary/client" "github.com/docker/notary/client/changelist" "github.com/docker/notary/cryptoservice" @@ -22,12 +19,16 @@ import ( "google.golang.org/grpc/metadata" ) +const baseDir = "var/lib/docker/clientapi" + // NewServer creates a new instance of a Client API server with a configured // upstream Notary Server. -func NewServer(upstream string, upstreamCAPath string, grpcSrv *grpc.Server) error { +func NewServer(upstream string, upstreamCAPath string, grpcSrv *grpc.Server, keyStores []trustmanager.KeyStore) error { + srv := &Server{ upstream: upstream, upstreamCAPath: upstreamCAPath, + keyStores: keyStores, } RegisterNotaryServer(grpcSrv, srv) return nil @@ -36,6 +37,7 @@ func NewServer(upstream string, upstreamCAPath string, grpcSrv *grpc.Server) err type Server struct { upstream string upstreamCAPath string + keyStores []trustmanager.KeyStore } func (srv *Server) Initialize(ctx context.Context, initMessage *InitMessage) (*BasicResponse, error) { @@ -76,7 +78,7 @@ func (srv *Server) Publish(ctx context.Context, gun *GunMessage) (*BasicResponse } func (srv *Server) AddTarget(ctx context.Context, t *Target) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(t.GetGun())) + r, err := srv.initRepo(ctx, data.GUN(t.GetGun())) if err != nil { return nil, err } @@ -99,7 +101,7 @@ func (srv *Server) AddTarget(ctx context.Context, t *Target) (*BasicResponse, er } func (srv *Server) RemoveTarget(ctx context.Context, t *Target) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(t.GetGun())) + r, err := srv.initRepo(ctx, data.GUN(t.GetGun())) if err != nil { return nil, err } @@ -118,7 +120,7 @@ func (srv *Server) RemoveTarget(ctx context.Context, t *Target) (*BasicResponse, } func (srv *Server) ListTargets(ctx context.Context, message *RoleNameListMessage) (*TargetWithRoleNameListResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -156,7 +158,7 @@ func (srv *Server) ListTargets(ctx context.Context, message *RoleNameListMessage // GetTargetByName returns a target by the given name. func (srv *Server) GetTargetByName(ctx context.Context, message *TargetByNameAction) (*TargetWithRoleResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -187,7 +189,7 @@ func (srv *Server) GetTargetByName(ctx context.Context, message *TargetByNameAct // GetAllTargetMetadataByName func (srv *Server) GetAllTargetMetadataByName(ctx context.Context, message *TargetNameMessage) (*TargetSignedListResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -244,7 +246,7 @@ func (srv *Server) GetAllTargetMetadataByName(ctx context.Context, message *Targ // GetChangelist returns the list of the repository's unpublished changes func (srv *Server) GetChangelist(ctx context.Context, message *GunMessage) (*ChangeListResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -274,7 +276,7 @@ func (srv *Server) GetChangelist(ctx context.Context, message *GunMessage) (*Cha } func (srv *Server) ListRoles(ctx context.Context, message *GunMessage) (*RoleWithSignaturesListResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -317,7 +319,7 @@ func (srv *Server) ListRoles(ctx context.Context, message *GunMessage) (*RoleWit } func (srv *Server) GetDelegationRoles(ctx context.Context, message *GunMessage) (*RoleListResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -348,7 +350,7 @@ func (srv *Server) GetDelegationRoles(ctx context.Context, message *GunMessage) } func (srv *Server) AddDelegation(ctx context.Context, message *AddDelegationMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -369,7 +371,7 @@ func (srv *Server) AddDelegation(ctx context.Context, message *AddDelegationMess } func (srv *Server) AddDelegationRoleAndKeys(ctx context.Context, message *AddDelegationRoleAndKeysMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -390,7 +392,7 @@ func (srv *Server) AddDelegationRoleAndKeys(ctx context.Context, message *AddDel } func (srv *Server) AddDelegationPaths(ctx context.Context, message *AddDelegationPathsMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -406,7 +408,7 @@ func (srv *Server) AddDelegationPaths(ctx context.Context, message *AddDelegatio } func (srv *Server) RemoveDelegationKeysAndPaths(ctx context.Context, message *RemoveDelegationKeysAndPathsMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -422,7 +424,7 @@ func (srv *Server) RemoveDelegationKeysAndPaths(ctx context.Context, message *Re } func (srv *Server) RemoveDelegationRole(ctx context.Context, message *RemoveDelegationRoleMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -438,7 +440,7 @@ func (srv *Server) RemoveDelegationRole(ctx context.Context, message *RemoveDele } func (srv *Server) RemoveDelegationPaths(ctx context.Context, message *RemoveDelegationPathsMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -454,7 +456,7 @@ func (srv *Server) RemoveDelegationPaths(ctx context.Context, message *RemoveDel } func (srv *Server) RemoveDelegationKeys(ctx context.Context, message *RemoveDelegationKeysMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -470,7 +472,7 @@ func (srv *Server) RemoveDelegationKeys(ctx context.Context, message *RemoveDele } func (srv *Server) ClearDelegationPaths(ctx context.Context, message *RoleNameMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -486,7 +488,7 @@ func (srv *Server) ClearDelegationPaths(ctx context.Context, message *RoleNameMe } func (srv *Server) Witness(ctx context.Context, message *RoleNameListMessage) (*RoleNameListResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -515,7 +517,7 @@ func (srv *Server) Witness(ctx context.Context, message *RoleNameListMessage) (* } func (srv *Server) RotateKey(ctx context.Context, message *RotateKeyMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -536,7 +538,7 @@ func (srv *Server) CryptoService(ctx context.Context, message *GunMessage) (*Cry } func (srv *Server) CryptoServiceCreate(ctx context.Context, message *CryptoServiceCreateMessage) (*PublicKeyResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -577,7 +579,7 @@ func (srv *Server) CryptoServicePrivateKeySign(ctx context.Context, message *Cry } func (srv *Server) CryptoServiceAddKey(ctx context.Context, message *CryptoServiceAddKeyMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -602,7 +604,7 @@ func (srv *Server) CryptoServiceAddKey(ctx context.Context, message *CryptoServi } func (srv *Server) CryptoServiceGetKey(ctx context.Context, message *KeyIDMessage) (*PublicKeyResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -622,7 +624,7 @@ func (srv *Server) CryptoServiceGetKey(ctx context.Context, message *KeyIDMessag } func (srv *Server) CryptoServiceGetPrivateKey(ctx context.Context, message *KeyIDMessage) (*PrivateKeyResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -660,7 +662,7 @@ func (srv *Server) CryptoServiceGetPrivateKey(ctx context.Context, message *KeyI } func (srv *Server) CryptoServiceRemoveKey(ctx context.Context, message *KeyIDMessage) (*BasicResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -678,7 +680,7 @@ func (srv *Server) CryptoServiceRemoveKey(ctx context.Context, message *KeyIDMes } func (srv *Server) CryptoServiceListKeys(ctx context.Context, message *RoleNameMessage) (*KeyIDsListResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -694,7 +696,7 @@ func (srv *Server) CryptoServiceListKeys(ctx context.Context, message *RoleNameM } func (srv *Server) CryptoServiceListAllKeys(ctx context.Context, message *GunMessage) (*SigningKeyIDsToRolesResponse, error) { - r, err := srv.initRepo(data.GUN(message.Gun)) + r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { return nil, err } @@ -750,7 +752,6 @@ func initializeRepo(r *client.NotaryRepository) error { func (srv *Server) initRepo(ctx context.Context, gun data.GUN) (*client.NotaryRepository, error) { logrus.Errorf("initializing with upstream ca file %s", srv.upstreamCAPath) - baseDir := "var/lib/clientapi" md, ok := metadata.FromContext(ctx) if !ok { return nil, errors.New("initRepo may only be used with GRPC contexts") @@ -764,12 +765,7 @@ func (srv *Server) initRepo(ctx context.Context, gun data.GUN) (*client.NotaryRe return nil, err } - keyStore, err := trustmanager.NewKeyFileStore(filepath.Join(baseDir, notary.PrivDir), retriever) - if err != nil { - return nil, err - } - - cryptoService := cryptoservice.NewCryptoService(keyStore) + cryptoService := cryptoservice.NewCryptoService(srv.keyStores...) remoteStore, err := storage.NewHTTPStore( srv.upstream+"/v2/"+gun.String()+"/_trust/tuf/", @@ -791,10 +787,6 @@ func (srv *Server) initRepo(ctx context.Context, gun data.GUN) (*client.NotaryRe ) } -func retriever(keyName, alias string, createNew bool, attempts int) (string, bool, error) { - return "password", false, nil -} - func DefaultPermissions() map[string][]string { return map[string][]string{ "/api.Notary/AddTarget": {"push", "pull"}, diff --git a/cmd/clientapi/main.go b/cmd/clientapi/main.go index d57e850bb..f6acb9eda 100644 --- a/cmd/clientapi/main.go +++ b/cmd/clientapi/main.go @@ -36,7 +36,7 @@ func main() { // and setupGRPCServer() grpcAddr, tlsConfig, err := setup.GetAddrAndTLSConfig(vc) if err != nil { - logrus.Fatal("unable to set up TLS: %s", err.Error()) + logrus.Fatalf("unable to set up TLS: %s", err.Error()) } upstreamAddr := vc.GetString("upstream.addr") @@ -45,7 +45,7 @@ func main() { creds := credentials.NewTLS(tlsConfig) auth, err := setup.Authorization(vc) if err != nil { - logrus.Fatal("unable to configure authorization: %s", err.Error()) + logrus.Fatalf("unable to configure authorization: %s", err.Error()) } opts := []grpc.ServerOption{ @@ -57,10 +57,14 @@ func main() { srv, lis, err := setup.NewGRPCServer(grpcAddr, opts) if err != nil { - logrus.Fatal("grpc server failed to start on %s: %v", + logrus.Fatalf("grpc server failed to start on %s: %v", grpcAddr, err) } - err = api.NewServer(upstreamAddr, upstreamCAPath, srv) + keyStorage, err := setup.KeyStorage(vc) + if err != nil { + logrus.Fatalf("failed to configure key storage: %s", err.Error()) + } + err = api.NewServer(upstreamAddr, upstreamCAPath, srv, keyStorage) if err != nil { logrus.Fatal(err) } @@ -69,7 +73,7 @@ func main() { logrus.Infof("serving on %s", grpcAddr) if err := srv.Serve(lis); err != nil { - logrus.Error("server stopped with an error: %v", err) + logrus.Errorf("server stopped with an error: %v", err) } logrus.Info("server shutting down") } diff --git a/cmd/clientapi/setup/config.go b/cmd/clientapi/setup/config.go index f81e18f7c..814e445d3 100644 --- a/cmd/clientapi/setup/config.go +++ b/cmd/clientapi/setup/config.go @@ -5,16 +5,21 @@ import ( "errors" "fmt" "github.com/Sirupsen/logrus" + "github.com/docker/go-connections/tlsconfig" "github.com/docker/notary" grpcauth "github.com/docker/notary/auth/grpc" "github.com/docker/notary/auth/token" "github.com/docker/notary/client_api/api" + "github.com/docker/notary/passphrase" + "github.com/docker/notary/trustmanager" + "github.com/docker/notary/trustmanager/remoteks" "github.com/docker/notary/utils" "github.com/spf13/viper" "google.golang.org/grpc" ghealth "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" "net" + "path/filepath" ) // the client api will always require push and pull permissions against @@ -95,6 +100,52 @@ func Authorization(vc *viper.Viper) (grpc.UnaryServerInterceptor, error) { return nil, fmt.Errorf("unrecognized authorization type: %s", authType) } +func KeyStorage(vc *viper.Viper) ([]trustmanager.KeyStore, error) { + var ( + keyStore trustmanager.KeyStore + err error + location = vc.GetString("key_storage.type") + secret = vc.GetString("key_storage.secret") + ) + if secret == "" { + return nil, errors.New("must set a key_storage.secret") + } + switch location { + case "local": + baseDir := vc.GetString("key_storage.directory") + if baseDir == "" { + return nil, errors.New("local key storage selected but no key_storage.directory included in configuration") + } + keyStore, err = trustmanager.NewKeyFileStore(filepath.Join(baseDir, notary.PrivDir), passphrase.ConstantRetriever(secret)) + if err != nil { + return nil, err + } + case "memory": + keyStore = trustmanager.NewKeyMemoryStore(passphrase.ConstantRetriever(secret)) + case "remote": + tlsOpts, err := utils.ParseTLS(vc, "key_storage", true) + if err != nil { + return nil, err + } + tlsConfig, err := tlsconfig.Client(tlsOpts) + if err != nil { + return nil, err + } + store, err := remoteks.NewRemoteStore( + vc.GetString("key_storage.addr"), + tlsConfig, + vc.GetDuration("key_storage.timeout"), + ) + if err != nil { + return nil, err + } + keyStore = trustmanager.NewGenericKeyStore(store, passphrase.ConstantRetriever(secret)) + default: + return nil, errors.New("no key storage configured") + } + return []trustmanager.KeyStore{keyStore}, nil +} + func buildBasePermissionList(requiredPerms ...string) (map[string][]string, error) { srv := grpc.Server{} apiSrv := api.Server{} diff --git a/utils/configuration.go b/utils/configuration.go index 057995ec5..1d091a0ec 100644 --- a/utils/configuration.go +++ b/utils/configuration.go @@ -52,11 +52,34 @@ func GetPathRelativeToConfig(configuration *viper.Viper, key string) string { // The cert/key files are relative to the config file used to populate the instance // of viper. func ParseServerTLS(configuration *viper.Viper, tlsRequired bool) (*tls.Config, error) { - // unmarshalling into objects does not seem to pick up env vars + tlsOpts, err := ParseTLS(configuration, "server", tlsRequired) + if err != nil { + return nil, err + } + return tlsconfig.Server(tlsOpts) +} + +// ParseTLS tries to parse out valid server TLS options from a Viper. +// The cert/key files are relative to the config file used to populate the instance +// of viper. +func ParseTLS(configuration *viper.Viper, prefix string, tlsRequired bool) (tlsconfig.Options, error) { + rootCA := GetPathRelativeToConfig( + configuration, + strings.Join([]string{prefix, "tls_ca_file"}, "."), + ) + clientCert := GetPathRelativeToConfig( + configuration, + strings.Join([]string{prefix, "tls_client_cert"}, "."), + ) + clientKey := GetPathRelativeToConfig( + configuration, + strings.Join([]string{prefix, "tls_client_key"}, "."), + ) + tlsOpts := tlsconfig.Options{ - CertFile: GetPathRelativeToConfig(configuration, "server.tls_cert_file"), - KeyFile: GetPathRelativeToConfig(configuration, "server.tls_key_file"), - CAFile: GetPathRelativeToConfig(configuration, "server.client_ca_file"), + CertFile: clientCert, + KeyFile: clientKey, + CAFile: rootCA, } if tlsOpts.CAFile != "" { tlsOpts.ClientAuth = tls.RequireAndVerifyClientCert @@ -74,7 +97,7 @@ func ParseServerTLS(configuration *viper.Viper, tlsRequired bool) (*tls.Config, } } - return tlsconfig.Server(tlsOpts) + return &tlsOpts, nil } // ParseLogLevel tries to parse out a log level from a Viper. If there is no From 1841e0ce38d8eef5cd754be1b11db8241229f150 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 29 Mar 2017 17:07:42 -0700 Subject: [PATCH 40/62] wildcarded trustpinning for cert ids Signed-off-by: David Lawrence (github: endophage) --- trustpinning/certs_test.go | 20 ++++++++++++++++++++ trustpinning/trustpin.go | 25 +++++++++++++++++++++++++ trustpinning/trustpin_test.go | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 trustpinning/trustpin_test.go diff --git a/trustpinning/certs_test.go b/trustpinning/certs_test.go index 328de7c1e..cfed8dcb3 100644 --- a/trustpinning/certs_test.go +++ b/trustpinning/certs_test.go @@ -363,6 +363,26 @@ func TestValidateRootWithPinnedCertAndIntermediates(t *testing.T) { } } require.Equal(t, typedSignedRoot, validatedRoot) + + // test is also works with a wildcarded gun in certs + validatedRoot, err = trustpinning.ValidateRoot( + nil, + signedRoot, + "docker.io/notary/test", + trustpinning.TrustPinConfig{ + Certs: map[string][]string{ + "docker.io/notar*": {ecdsax509Key.ID()}, + }, + DisableTOFU: true, + }, + ) + require.NoError(t, err, "failed to validate certID with intermediate") + for idx, sig := range typedSignedRoot.Signatures { + if sig.KeyID == ecdsax509Key.ID() { + typedSignedRoot.Signatures[idx].IsValid = true + } + } + require.Equal(t, typedSignedRoot, validatedRoot) } func TestValidateRootFailuresWithPinnedCert(t *testing.T) { diff --git a/trustpinning/trustpin.go b/trustpinning/trustpin.go index c102051f3..990d7ebf9 100644 --- a/trustpinning/trustpin.go +++ b/trustpinning/trustpin.go @@ -37,6 +37,11 @@ func NewTrustPinChecker(trustPinConfig TrustPinConfig, gun data.GUN, firstBootst t.pinnedCertIDs = pinnedCerts return t.certsCheck, nil } + var ok bool + t.pinnedCertIDs, ok = wildcardMatch(gun, trustPinConfig.Certs) + if ok { + return t.certsCheck, nil + } if caFilepath, err := getPinnedCAFilepathByPrefix(gun, trustPinConfig); err == nil { logrus.Debugf("trust-pinning using root CA bundle at: %s", caFilepath) @@ -121,3 +126,23 @@ func getPinnedCAFilepathByPrefix(gun data.GUN, t TrustPinConfig) (string, error) } return specificCAFilepath, nil } + +// wildcardMatch will attempt to match the most specific (longest prefix) wildcarded +// trustpinning option for key IDs. Given the simple globbing and the use of maps, +// it is impossible to have two different prefixes of equal length. +// This logic also solves the issue of Go's randomization of map iteration. +func wildcardMatch(gun data.GUN, certs map[string][]string) ([]string, bool) { + var ( + longest = "" + ids []string + ) + for k, v := range certs { + if strings.HasSuffix(k, "*") { + if strings.HasPrefix(gun.String(), k[:len(k)-1]) && len(k) > len(longest) { + longest = k + ids = v + } + } + } + return ids, ids != nil +} diff --git a/trustpinning/trustpin_test.go b/trustpinning/trustpin_test.go new file mode 100644 index 000000000..daee80d7a --- /dev/null +++ b/trustpinning/trustpin_test.go @@ -0,0 +1,33 @@ +package trustpinning + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestWildcardMatch(t *testing.T) { + testCerts := map[string][]string{ + "docker.io/library/ubuntu": {"abc"}, + "docker.io/endophage/b*": {"def"}, + "docker.io/endophage/*": {"xyz"}, + } + + // wildcardMatch should ONLY match wildcarded names even if a specific + // match is present + res, ok := wildcardMatch("docker.io/library/ubuntu", testCerts) + require.Nil(t, res) + require.False(t, ok) + + // wildcard match should match on segment boundaries + res, ok = wildcardMatch("docker.io/endophage/foo", testCerts) + require.Len(t, res, 1) + require.Equal(t, "xyz", res[0]) + require.True(t, ok) + + // wildcardMatch should also match between segment boundaries, and take + // the first match is finds as the ONLY match. + res, ok = wildcardMatch("docker.io/endophage/bar", testCerts) + require.Len(t, res, 1) + require.Equal(t, "def", res[0]) + require.True(t, ok) +} From 894c9605baa8f39fdf09765bdb02fc10c5c0413f Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Mon, 3 Apr 2017 21:21:15 -0700 Subject: [PATCH 41/62] update gorm to reduce size of #1110 Signed-off-by: David Lawrence (github: endophage) --- cmd/notary-server/main_test.go | 2 +- fixtures/server-config.sqlite.json | 23 + server/storage/sql_models.go | 4 +- server/storage/sqldb.go | 2 +- signer/keydbstore/sql_keydbstore.go | 2 +- vendor.conf | 4 +- vendor/github.com/jinzhu/gorm/association.go | 446 ++++-- vendor/github.com/jinzhu/gorm/callback.go | 264 ++-- .../github.com/jinzhu/gorm/callback_create.go | 159 ++- .../github.com/jinzhu/gorm/callback_delete.go | 75 +- .../github.com/jinzhu/gorm/callback_query.go | 115 +- .../jinzhu/gorm/callback_query_preload.go | 346 +++++ .../jinzhu/gorm/callback_row_query.go | 30 + .../github.com/jinzhu/gorm/callback_save.go | 99 ++ .../github.com/jinzhu/gorm/callback_shared.go | 76 -- .../github.com/jinzhu/gorm/callback_update.go | 115 +- .../github.com/jinzhu/gorm/common_dialect.go | 101 -- vendor/github.com/jinzhu/gorm/dialect.go | 130 +- .../github.com/jinzhu/gorm/dialect_common.go | 152 +++ .../github.com/jinzhu/gorm/dialect_mysql.go | 146 ++ .../jinzhu/gorm/dialect_postgres.go | 134 ++ .../github.com/jinzhu/gorm/dialect_sqlite3.go | 108 ++ vendor/github.com/jinzhu/gorm/errors.go | 57 +- vendor/github.com/jinzhu/gorm/field.go | 78 +- vendor/github.com/jinzhu/gorm/foundation.go | 78 -- .../jinzhu/gorm/join_table_handler.go | 138 +- vendor/github.com/jinzhu/gorm/logger.go | 98 +- vendor/github.com/jinzhu/gorm/main.go | 519 +++++-- vendor/github.com/jinzhu/gorm/main_private.go | 50 - vendor/github.com/jinzhu/gorm/model.go | 6 +- vendor/github.com/jinzhu/gorm/model_struct.go | 680 +++++---- vendor/github.com/jinzhu/gorm/mssql.go | 81 -- vendor/github.com/jinzhu/gorm/mysql.go | 65 - vendor/github.com/jinzhu/gorm/postgres.go | 131 -- vendor/github.com/jinzhu/gorm/preload.go | 242 ---- vendor/github.com/jinzhu/gorm/scope.go | 1214 ++++++++++++++--- .../github.com/jinzhu/gorm/scope_private.go | 596 -------- vendor/github.com/jinzhu/gorm/search.go | 76 +- vendor/github.com/jinzhu/gorm/sqlite3.go | 63 - vendor/github.com/jinzhu/gorm/utils.go | 252 +++- .../github.com/jinzhu/gorm/utils_private.go | 73 - vendor/github.com/jinzhu/inflection/LICENSE | 21 + .../jinzhu/inflection/inflections.go | 273 ++++ vendor/github.com/lib/pq/hstore/hstore.go | 118 -- 44 files changed, 4567 insertions(+), 2875 deletions(-) create mode 100644 fixtures/server-config.sqlite.json create mode 100644 vendor/github.com/jinzhu/gorm/callback_query_preload.go create mode 100644 vendor/github.com/jinzhu/gorm/callback_row_query.go create mode 100644 vendor/github.com/jinzhu/gorm/callback_save.go delete mode 100644 vendor/github.com/jinzhu/gorm/callback_shared.go delete mode 100644 vendor/github.com/jinzhu/gorm/common_dialect.go create mode 100644 vendor/github.com/jinzhu/gorm/dialect_common.go create mode 100644 vendor/github.com/jinzhu/gorm/dialect_mysql.go create mode 100644 vendor/github.com/jinzhu/gorm/dialect_postgres.go create mode 100644 vendor/github.com/jinzhu/gorm/dialect_sqlite3.go delete mode 100644 vendor/github.com/jinzhu/gorm/foundation.go delete mode 100644 vendor/github.com/jinzhu/gorm/main_private.go delete mode 100644 vendor/github.com/jinzhu/gorm/mssql.go delete mode 100644 vendor/github.com/jinzhu/gorm/mysql.go delete mode 100644 vendor/github.com/jinzhu/gorm/postgres.go delete mode 100644 vendor/github.com/jinzhu/gorm/preload.go delete mode 100644 vendor/github.com/jinzhu/gorm/scope_private.go delete mode 100644 vendor/github.com/jinzhu/gorm/sqlite3.go delete mode 100644 vendor/github.com/jinzhu/gorm/utils_private.go create mode 100644 vendor/github.com/jinzhu/inflection/LICENSE create mode 100644 vendor/github.com/jinzhu/inflection/inflections.go delete mode 100644 vendor/github.com/lib/pq/hstore/hstore.go diff --git a/cmd/notary-server/main_test.go b/cmd/notary-server/main_test.go index cf58fd9c5..55c6a0b1a 100644 --- a/cmd/notary-server/main_test.go +++ b/cmd/notary-server/main_test.go @@ -407,7 +407,7 @@ func TestGetGUNPRefixes(t *testing.T) { // For sanity, make sure we can always parse the sample config func TestSampleConfig(t *testing.T) { var registerCalled = 0 - _, _, err := parseServerConfig("../../fixtures/server-config.json", fakeRegisterer(®isterCalled), false) + _, _, err := parseServerConfig("../../fixtures/server-config.sqlite.json", fakeRegisterer(®isterCalled), false) require.NoError(t, err) // once for the DB, once for the trust service diff --git a/fixtures/server-config.sqlite.json b/fixtures/server-config.sqlite.json new file mode 100644 index 000000000..b52938875 --- /dev/null +++ b/fixtures/server-config.sqlite.json @@ -0,0 +1,23 @@ +{ + "server": { + "http_addr": ":4443", + "tls_key_file": "./notary-server.key", + "tls_cert_file": "./notary-server.crt" + }, + "trust_service": { + "type": "remote", + "hostname": "notarysigner", + "port": "7899", + "tls_ca_file": "./root-ca.crt", + "key_algorithm": "ecdsa", + "tls_client_cert": "./notary-server.crt", + "tls_client_key": "./notary-server.key" + }, + "logging": { + "level": "debug" + }, + "storage": { + "backend": "sqlite3", + "db_url": "/tmp/notary-server.db" + } +} diff --git a/server/storage/sql_models.go b/server/storage/sql_models.go index 5dfb62e9c..12ff97691 100644 --- a/server/storage/sql_models.go +++ b/server/storage/sql_models.go @@ -50,7 +50,7 @@ func (c Change) TableName() string { // CreateTUFTable creates the DB table for TUFFile func CreateTUFTable(db gorm.DB) error { // TODO: gorm - query := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&TUFFile{}) + query := db.AutoMigrate(&TUFFile{}) if query.Error != nil { return query.Error } @@ -61,6 +61,6 @@ func CreateTUFTable(db gorm.DB) error { // CreateChangefeedTable creates the DB table for Changefeed func CreateChangefeedTable(db gorm.DB) error { - query := db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8").CreateTable(&Change{}) + query := db.AutoMigrate(&Change{}) return query.Error } diff --git a/server/storage/sqldb.go b/server/storage/sqldb.go index adc86a44a..b8ee7a307 100644 --- a/server/storage/sqldb.go +++ b/server/storage/sqldb.go @@ -26,7 +26,7 @@ func NewSQLStorage(dialect string, args ...interface{}) (*SQLStorage, error) { return nil, err } return &SQLStorage{ - DB: gormDB, + DB: *gormDB, }, nil } diff --git a/signer/keydbstore/sql_keydbstore.go b/signer/keydbstore/sql_keydbstore.go index f381be3f9..c94946b95 100644 --- a/signer/keydbstore/sql_keydbstore.go +++ b/signer/keydbstore/sql_keydbstore.go @@ -56,7 +56,7 @@ func NewSQLKeyDBStore(passphraseRetriever notary.PassRetriever, defaultPassAlias } return &SQLKeyDBStore{ - db: db, + db: *db, dbType: dbDialect, defaultPassAlias: defaultPassAlias, retriever: passphraseRetriever, diff --git a/vendor.conf b/vendor.conf index f949db07e..ce4e1e6fc 100644 --- a/vendor.conf +++ b/vendor.conf @@ -8,9 +8,9 @@ github.com/docker/go-connections f549a9393d05688dff0992ef3efd8bbe6c628aeb github.com/docker/go/canonical d30aec9fd63c35133f8f79c3412ad91a3b08be06 github.com/dvsekhvalnov/jose2go v1.2 github.com/go-sql-driver/mysql 0cc29e9fe8e25c2c58cf47bcab566e029bbaa88b -github.com/golang/protobuf c3cefd437628a0b7d31b34fe44b3a7a540e98527 github.com/gorilla/mux e444e69cbd2e2e3e0749a2f3c717cec491552bbf -github.com/jinzhu/gorm 82d726bbfd8cefbe2dcdc7f7f0484551c0d40433 +github.com/jinzhu/gorm 5409931a1bb87e484d68d649af9367c207713ea2 +github.com/jinzhu/inflection 1c35d901db3da928c72a72d8458480cc9ade058f github.com/lib/pq 0dad96c0b94f8dee039aa40467f767467392a0af github.com/mattn/go-sqlite3 v1.0.0 github.com/miekg/pkcs11 ba39b9c6300b7e0be41b115330145ef8afdff7d6 diff --git a/vendor/github.com/jinzhu/gorm/association.go b/vendor/github.com/jinzhu/gorm/association.go index e34a10bd9..14fd1c356 100644 --- a/vendor/github.com/jinzhu/gorm/association.go +++ b/vendor/github.com/jinzhu/gorm/association.go @@ -6,180 +6,368 @@ import ( "reflect" ) +// Association Mode contains some helper methods to handle relationship things easily. type Association struct { - Scope *Scope - PrimaryKey interface{} - Column string - Error error - Field *Field -} - -func (association *Association) setErr(err error) *Association { - if err != nil { - association.Error = err - } - return association + Error error + scope *Scope + column string + field *Field } +// Find find out all related associations func (association *Association) Find(value interface{}) *Association { - association.Scope.related(value, association.Column) - return association.setErr(association.Scope.db.Error) + association.scope.related(value, association.column) + return association.setErr(association.scope.db.Error) } +// Append append new associations for many2many, has_many, replace current association for has_one, belongs_to func (association *Association) Append(values ...interface{}) *Association { - scope := association.Scope - field := association.Field + if association.Error != nil { + return association + } - for _, value := range values { - reflectvalue := reflect.Indirect(reflect.ValueOf(value)) - if reflectvalue.Kind() == reflect.Struct { - field.Set(reflect.Append(field.Field, reflectvalue)) - } else if reflectvalue.Kind() == reflect.Slice { - field.Set(reflect.AppendSlice(field.Field, reflectvalue)) - } else { - association.setErr(errors.New("invalid association type")) - } + if relationship := association.field.Relationship; relationship.Kind == "has_one" { + return association.Replace(values...) } - scope.Search.Select(association.Column) - scope.callCallbacks(scope.db.parent.callback.updates) - return association.setErr(scope.db.Error) + return association.saveAssociations(values...) } -func (association *Association) getPrimaryKeys(values ...interface{}) []interface{} { - primaryKeys := []interface{}{} - scope := association.Scope +// Replace replace current associations with new one +func (association *Association) Replace(values ...interface{}) *Association { + if association.Error != nil { + return association + } - for _, value := range values { - reflectValue := reflect.Indirect(reflect.ValueOf(value)) - if reflectValue.Kind() == reflect.Slice { - for i := 0; i < reflectValue.Len(); i++ { - if primaryField := scope.New(reflectValue.Index(i).Interface()).PrimaryField(); !primaryField.IsBlank { - primaryKeys = append(primaryKeys, primaryField.Field.Interface()) + var ( + relationship = association.field.Relationship + scope = association.scope + field = association.field.Field + newDB = scope.NewDB() + ) + + // Append new values + association.field.Set(reflect.Zero(association.field.Field.Type())) + association.saveAssociations(values...) + + // Belongs To + if relationship.Kind == "belongs_to" { + // Set foreign key to be null when clearing value (length equals 0) + if len(values) == 0 { + // Set foreign key to be nil + var foreignKeyMap = map[string]interface{}{} + for _, foreignKey := range relationship.ForeignDBNames { + foreignKeyMap[foreignKey] = nil + } + association.setErr(newDB.Model(scope.Value).UpdateColumn(foreignKeyMap).Error) + } + } else { + // Polymorphic Relations + if relationship.PolymorphicDBName != "" { + newDB = newDB.Where(fmt.Sprintf("%v = ?", scope.Quote(relationship.PolymorphicDBName)), relationship.PolymorphicValue) + } + + // Delete Relations except new created + if len(values) > 0 { + var associationForeignFieldNames, associationForeignDBNames []string + if relationship.Kind == "many_to_many" { + // if many to many relations, get association fields name from association foreign keys + associationScope := scope.New(reflect.New(field.Type()).Interface()) + for idx, dbName := range relationship.AssociationForeignFieldNames { + if field, ok := associationScope.FieldByName(dbName); ok { + associationForeignFieldNames = append(associationForeignFieldNames, field.Name) + associationForeignDBNames = append(associationForeignDBNames, relationship.AssociationForeignDBNames[idx]) + } + } + } else { + // If has one/many relations, use primary keys + for _, field := range scope.New(reflect.New(field.Type()).Interface()).PrimaryFields() { + associationForeignFieldNames = append(associationForeignFieldNames, field.Name) + associationForeignDBNames = append(associationForeignDBNames, field.DBName) } } - } else if reflectValue.Kind() == reflect.Struct { - if primaryField := scope.New(value).PrimaryField(); !primaryField.IsBlank { - primaryKeys = append(primaryKeys, primaryField.Field.Interface()) + + newPrimaryKeys := scope.getColumnAsArray(associationForeignFieldNames, field.Interface()) + + if len(newPrimaryKeys) > 0 { + sql := fmt.Sprintf("%v NOT IN (%v)", toQueryCondition(scope, associationForeignDBNames), toQueryMarks(newPrimaryKeys)) + newDB = newDB.Where(sql, toQueryValues(newPrimaryKeys)...) } } - } - return primaryKeys -} -func (association *Association) Delete(values ...interface{}) *Association { - primaryKeys := association.getPrimaryKeys(values...) - - if len(primaryKeys) == 0 { - association.setErr(errors.New("no primary key found")) - } else { - scope := association.Scope - relationship := association.Field.Relationship - // many to many if relationship.Kind == "many_to_many" { - sql := fmt.Sprintf("%v = ? AND %v IN (?)", scope.Quote(relationship.ForeignDBName), scope.Quote(relationship.AssociationForeignDBName)) - query := scope.NewDB().Where(sql, association.PrimaryKey, primaryKeys) - if err := relationship.JoinTableHandler.Delete(relationship.JoinTableHandler, query, relationship); err == nil { - leftValues := reflect.Zero(association.Field.Field.Type()) - for i := 0; i < association.Field.Field.Len(); i++ { - value := association.Field.Field.Index(i) - if primaryField := association.Scope.New(value.Interface()).PrimaryField(); primaryField != nil { - var included = false - for _, primaryKey := range primaryKeys { - if equalAsString(primaryKey, primaryField.Field.Interface()) { - included = true - } - } - if !included { - leftValues = reflect.Append(leftValues, value) - } - } + // if many to many relations, delete related relations from join table + var sourceForeignFieldNames []string + + for _, dbName := range relationship.ForeignFieldNames { + if field, ok := scope.FieldByName(dbName); ok { + sourceForeignFieldNames = append(sourceForeignFieldNames, field.Name) } - association.Field.Set(leftValues) } - } else { - association.setErr(errors.New("delete only support many to many")) + + if sourcePrimaryKeys := scope.getColumnAsArray(sourceForeignFieldNames, scope.Value); len(sourcePrimaryKeys) > 0 { + newDB = newDB.Where(fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relationship.ForeignDBNames), toQueryMarks(sourcePrimaryKeys)), toQueryValues(sourcePrimaryKeys)...) + + association.setErr(relationship.JoinTableHandler.Delete(relationship.JoinTableHandler, newDB, relationship)) + } + } else if relationship.Kind == "has_one" || relationship.Kind == "has_many" { + // has_one or has_many relations, set foreign key to be nil (TODO or delete them?) + var foreignKeyMap = map[string]interface{}{} + for idx, foreignKey := range relationship.ForeignDBNames { + foreignKeyMap[foreignKey] = nil + if field, ok := scope.FieldByName(relationship.AssociationForeignFieldNames[idx]); ok { + newDB = newDB.Where(fmt.Sprintf("%v = ?", scope.Quote(foreignKey)), field.Field.Interface()) + } + } + + fieldValue := reflect.New(association.field.Field.Type()).Interface() + association.setErr(newDB.Model(fieldValue).UpdateColumn(foreignKeyMap).Error) } } return association } -func (association *Association) Replace(values ...interface{}) *Association { - relationship := association.Field.Relationship - scope := association.Scope +// Delete remove relationship between source & passed arguments, but won't delete those arguments +func (association *Association) Delete(values ...interface{}) *Association { + if association.Error != nil { + return association + } + + var ( + relationship = association.field.Relationship + scope = association.scope + field = association.field.Field + newDB = scope.NewDB() + ) + + if len(values) == 0 { + return association + } + + var deletingResourcePrimaryFieldNames, deletingResourcePrimaryDBNames []string + for _, field := range scope.New(reflect.New(field.Type()).Interface()).PrimaryFields() { + deletingResourcePrimaryFieldNames = append(deletingResourcePrimaryFieldNames, field.Name) + deletingResourcePrimaryDBNames = append(deletingResourcePrimaryDBNames, field.DBName) + } + + deletingPrimaryKeys := scope.getColumnAsArray(deletingResourcePrimaryFieldNames, values...) + if relationship.Kind == "many_to_many" { - field := association.Field.Field - - oldPrimaryKeys := association.getPrimaryKeys(field.Interface()) - association.Field.Set(reflect.Zero(association.Field.Field.Type())) - association.Append(values...) - newPrimaryKeys := association.getPrimaryKeys(field.Interface()) - - var addedPrimaryKeys = []interface{}{} - for _, newKey := range newPrimaryKeys { - hasEqual := false - for _, oldKey := range oldPrimaryKeys { - if reflect.DeepEqual(newKey, oldKey) { - hasEqual = true - break - } + // source value's foreign keys + for idx, foreignKey := range relationship.ForeignDBNames { + if field, ok := scope.FieldByName(relationship.ForeignFieldNames[idx]); ok { + newDB = newDB.Where(fmt.Sprintf("%v = ?", scope.Quote(foreignKey)), field.Field.Interface()) } - if !hasEqual { - addedPrimaryKeys = append(addedPrimaryKeys, newKey) + } + + // get association's foreign fields name + var associationScope = scope.New(reflect.New(field.Type()).Interface()) + var associationForeignFieldNames []string + for _, associationDBName := range relationship.AssociationForeignFieldNames { + if field, ok := associationScope.FieldByName(associationDBName); ok { + associationForeignFieldNames = append(associationForeignFieldNames, field.Name) } } - for _, primaryKey := range association.getPrimaryKeys(values...) { - addedPrimaryKeys = append(addedPrimaryKeys, primaryKey) + + // association value's foreign keys + deletingPrimaryKeys := scope.getColumnAsArray(associationForeignFieldNames, values...) + sql := fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relationship.AssociationForeignDBNames), toQueryMarks(deletingPrimaryKeys)) + newDB = newDB.Where(sql, toQueryValues(deletingPrimaryKeys)...) + + association.setErr(relationship.JoinTableHandler.Delete(relationship.JoinTableHandler, newDB, relationship)) + } else { + var foreignKeyMap = map[string]interface{}{} + for _, foreignKey := range relationship.ForeignDBNames { + foreignKeyMap[foreignKey] = nil } - if len(addedPrimaryKeys) > 0 { - sql := fmt.Sprintf("%v = ? AND %v NOT IN (?)", scope.Quote(relationship.ForeignDBName), scope.Quote(relationship.AssociationForeignDBName)) - query := scope.NewDB().Where(sql, association.PrimaryKey, addedPrimaryKeys) - association.setErr(relationship.JoinTableHandler.Delete(relationship.JoinTableHandler, query, relationship)) + if relationship.Kind == "belongs_to" { + // find with deleting relation's foreign keys + primaryKeys := scope.getColumnAsArray(relationship.AssociationForeignFieldNames, values...) + newDB = newDB.Where( + fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relationship.ForeignDBNames), toQueryMarks(primaryKeys)), + toQueryValues(primaryKeys)..., + ) + + // set foreign key to be null if there are some records affected + modelValue := reflect.New(scope.GetModelStruct().ModelType).Interface() + if results := newDB.Model(modelValue).UpdateColumn(foreignKeyMap); results.Error == nil { + if results.RowsAffected > 0 { + scope.updatedAttrsWithValues(foreignKeyMap) + } + } else { + association.setErr(results.Error) + } + } else if relationship.Kind == "has_one" || relationship.Kind == "has_many" { + // find all relations + primaryKeys := scope.getColumnAsArray(relationship.AssociationForeignFieldNames, scope.Value) + newDB = newDB.Where( + fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relationship.ForeignDBNames), toQueryMarks(primaryKeys)), + toQueryValues(primaryKeys)..., + ) + + // only include those deleting relations + newDB = newDB.Where( + fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, deletingResourcePrimaryDBNames), toQueryMarks(deletingPrimaryKeys)), + toQueryValues(deletingPrimaryKeys)..., + ) + + // set matched relation's foreign key to be null + fieldValue := reflect.New(association.field.Field.Type()).Interface() + association.setErr(newDB.Model(fieldValue).UpdateColumn(foreignKeyMap).Error) } - } else { - association.setErr(errors.New("replace only support many to many")) } - return association -} -func (association *Association) Clear() *Association { - relationship := association.Field.Relationship - scope := association.Scope - if relationship.Kind == "many_to_many" { - sql := fmt.Sprintf("%v = ?", scope.Quote(relationship.ForeignDBName)) - query := scope.NewDB().Where(sql, association.PrimaryKey) - if err := relationship.JoinTableHandler.Delete(relationship.JoinTableHandler, query, relationship); err == nil { - association.Field.Set(reflect.Zero(association.Field.Field.Type())) - } else { - association.setErr(err) + // Remove deleted records from source's field + if association.Error == nil { + if field.Kind() == reflect.Slice { + leftValues := reflect.Zero(field.Type()) + + for i := 0; i < field.Len(); i++ { + reflectValue := field.Index(i) + primaryKey := scope.getColumnAsArray(deletingResourcePrimaryFieldNames, reflectValue.Interface())[0] + var isDeleted = false + for _, pk := range deletingPrimaryKeys { + if equalAsString(primaryKey, pk) { + isDeleted = true + break + } + } + if !isDeleted { + leftValues = reflect.Append(leftValues, reflectValue) + } + } + + association.field.Set(leftValues) + } else if field.Kind() == reflect.Struct { + primaryKey := scope.getColumnAsArray(deletingResourcePrimaryFieldNames, field.Interface())[0] + for _, pk := range deletingPrimaryKeys { + if equalAsString(primaryKey, pk) { + association.field.Set(reflect.Zero(field.Type())) + break + } + } } - } else { - association.setErr(errors.New("clear only support many to many")) } + return association } +// Clear remove relationship between source & current associations, won't delete those associations +func (association *Association) Clear() *Association { + return association.Replace() +} + +// Count return the count of current associations func (association *Association) Count() int { - count := -1 - relationship := association.Field.Relationship - scope := association.Scope - newScope := scope.New(association.Field.Field.Interface()) + var ( + count = 0 + relationship = association.field.Relationship + scope = association.scope + fieldValue = association.field.Field.Interface() + query = scope.DB() + ) if relationship.Kind == "many_to_many" { - relationship.JoinTableHandler.JoinWith(relationship.JoinTableHandler, scope.NewDB(), association.Scope.Value).Table(newScope.TableName()).Count(&count) + query = relationship.JoinTableHandler.JoinWith(relationship.JoinTableHandler, query, scope.Value) } else if relationship.Kind == "has_many" || relationship.Kind == "has_one" { - whereSql := fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.ForeignDBName)) - countScope := scope.DB().Table(newScope.TableName()).Where(whereSql, association.PrimaryKey) - if relationship.PolymorphicType != "" { - countScope = countScope.Where(fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.PolymorphicDBName)), scope.TableName()) - } - countScope.Count(&count) + primaryKeys := scope.getColumnAsArray(relationship.AssociationForeignFieldNames, scope.Value) + query = query.Where( + fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relationship.ForeignDBNames), toQueryMarks(primaryKeys)), + toQueryValues(primaryKeys)..., + ) } else if relationship.Kind == "belongs_to" { - if v, ok := scope.FieldByName(association.Column); ok { - whereSql := fmt.Sprintf("%v.%v = ?", newScope.QuotedTableName(), newScope.Quote(relationship.ForeignDBName)) - scope.DB().Table(newScope.TableName()).Where(whereSql, v).Count(&count) - } + primaryKeys := scope.getColumnAsArray(relationship.ForeignFieldNames, scope.Value) + query = query.Where( + fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relationship.AssociationForeignDBNames), toQueryMarks(primaryKeys)), + toQueryValues(primaryKeys)..., + ) + } + + if relationship.PolymorphicType != "" { + query = query.Where( + fmt.Sprintf("%v.%v = ?", scope.New(fieldValue).QuotedTableName(), scope.Quote(relationship.PolymorphicDBName)), + relationship.PolymorphicValue, + ) } + query.Model(fieldValue).Count(&count) return count } + +// saveAssociations save passed values as associations +func (association *Association) saveAssociations(values ...interface{}) *Association { + var ( + scope = association.scope + field = association.field + relationship = field.Relationship + ) + + saveAssociation := func(reflectValue reflect.Value) { + // value has to been pointer + if reflectValue.Kind() != reflect.Ptr { + reflectPtr := reflect.New(reflectValue.Type()) + reflectPtr.Elem().Set(reflectValue) + reflectValue = reflectPtr + } + + // value has to been saved for many2many + if relationship.Kind == "many_to_many" { + if scope.New(reflectValue.Interface()).PrimaryKeyZero() { + association.setErr(scope.NewDB().Save(reflectValue.Interface()).Error) + } + } + + // Assign Fields + var fieldType = field.Field.Type() + var setFieldBackToValue, setSliceFieldBackToValue bool + if reflectValue.Type().AssignableTo(fieldType) { + field.Set(reflectValue) + } else if reflectValue.Type().Elem().AssignableTo(fieldType) { + // if field's type is struct, then need to set value back to argument after save + setFieldBackToValue = true + field.Set(reflectValue.Elem()) + } else if fieldType.Kind() == reflect.Slice { + if reflectValue.Type().AssignableTo(fieldType.Elem()) { + field.Set(reflect.Append(field.Field, reflectValue)) + } else if reflectValue.Type().Elem().AssignableTo(fieldType.Elem()) { + // if field's type is slice of struct, then need to set value back to argument after save + setSliceFieldBackToValue = true + field.Set(reflect.Append(field.Field, reflectValue.Elem())) + } + } + + if relationship.Kind == "many_to_many" { + association.setErr(relationship.JoinTableHandler.Add(relationship.JoinTableHandler, scope.NewDB(), scope.Value, reflectValue.Interface())) + } else { + association.setErr(scope.NewDB().Select(field.Name).Save(scope.Value).Error) + + if setFieldBackToValue { + reflectValue.Elem().Set(field.Field) + } else if setSliceFieldBackToValue { + reflectValue.Elem().Set(field.Field.Index(field.Field.Len() - 1)) + } + } + } + + for _, value := range values { + reflectValue := reflect.ValueOf(value) + indirectReflectValue := reflect.Indirect(reflectValue) + if indirectReflectValue.Kind() == reflect.Struct { + saveAssociation(reflectValue) + } else if indirectReflectValue.Kind() == reflect.Slice { + for i := 0; i < indirectReflectValue.Len(); i++ { + saveAssociation(indirectReflectValue.Index(i)) + } + } else { + association.setErr(errors.New("invalid value type")) + } + } + return association +} + +func (association *Association) setErr(err error) *Association { + if err != nil { + association.Error = err + } + return association +} diff --git a/vendor/github.com/jinzhu/gorm/callback.go b/vendor/github.com/jinzhu/gorm/callback.go index 603e5111e..17f754519 100644 --- a/vendor/github.com/jinzhu/gorm/callback.go +++ b/vendor/github.com/jinzhu/gorm/callback.go @@ -4,93 +4,144 @@ import ( "fmt" ) -type callback struct { +// DefaultCallback default callbacks defined by gorm +var DefaultCallback = &Callback{} + +// Callback is a struct that contains all CRUD callbacks +// Field `creates` contains callbacks will be call when creating object +// Field `updates` contains callbacks will be call when updating object +// Field `deletes` contains callbacks will be call when deleting object +// Field `queries` contains callbacks will be call when querying object with query methods like Find, First, Related, Association... +// Field `rowQueries` contains callbacks will be call when querying object with Row, Rows... +// Field `processors` contains all callback processors, will be used to generate above callbacks in order +type Callback struct { creates []*func(scope *Scope) updates []*func(scope *Scope) deletes []*func(scope *Scope) queries []*func(scope *Scope) rowQueries []*func(scope *Scope) - processors []*callbackProcessor + processors []*CallbackProcessor } -type callbackProcessor struct { - name string - before string - after string - replace bool - remove bool - typ string - processor *func(scope *Scope) - callback *callback +// CallbackProcessor contains callback informations +type CallbackProcessor struct { + name string // current callback's name + before string // register current callback before a callback + after string // register current callback after a callback + replace bool // replace callbacks with same name + remove bool // delete callbacks with same name + kind string // callback type: create, update, delete, query, row_query + processor *func(scope *Scope) // callback handler + parent *Callback } -func (c *callback) addProcessor(typ string) *callbackProcessor { - cp := &callbackProcessor{typ: typ, callback: c} - c.processors = append(c.processors, cp) - return cp -} - -func (c *callback) clone() *callback { - return &callback{ +func (c *Callback) clone() *Callback { + return &Callback{ creates: c.creates, updates: c.updates, deletes: c.deletes, queries: c.queries, + rowQueries: c.rowQueries, processors: c.processors, } } -func (c *callback) Create() *callbackProcessor { - return c.addProcessor("create") +// Create could be used to register callbacks for creating object +// db.Callback().Create().After("gorm:create").Register("plugin:run_after_create", func(*Scope) { +// // business logic +// ... +// +// // set error if some thing wrong happened, will rollback the creating +// scope.Err(errors.New("error")) +// }) +func (c *Callback) Create() *CallbackProcessor { + return &CallbackProcessor{kind: "create", parent: c} } -func (c *callback) Update() *callbackProcessor { - return c.addProcessor("update") +// Update could be used to register callbacks for updating object, refer `Create` for usage +func (c *Callback) Update() *CallbackProcessor { + return &CallbackProcessor{kind: "update", parent: c} } -func (c *callback) Delete() *callbackProcessor { - return c.addProcessor("delete") +// Delete could be used to register callbacks for deleting object, refer `Create` for usage +func (c *Callback) Delete() *CallbackProcessor { + return &CallbackProcessor{kind: "delete", parent: c} } -func (c *callback) Query() *callbackProcessor { - return c.addProcessor("query") +// Query could be used to register callbacks for querying objects with query methods like `Find`, `First`, `Related`, `Association`... +// Refer `Create` for usage +func (c *Callback) Query() *CallbackProcessor { + return &CallbackProcessor{kind: "query", parent: c} } -func (c *callback) RowQuery() *callbackProcessor { - return c.addProcessor("row_query") +// RowQuery could be used to register callbacks for querying objects with `Row`, `Rows`, refer `Create` for usage +func (c *Callback) RowQuery() *CallbackProcessor { + return &CallbackProcessor{kind: "row_query", parent: c} } -func (cp *callbackProcessor) Before(name string) *callbackProcessor { - cp.before = name +// After insert a new callback after callback `callbackName`, refer `Callbacks.Create` +func (cp *CallbackProcessor) After(callbackName string) *CallbackProcessor { + cp.after = callbackName return cp } -func (cp *callbackProcessor) After(name string) *callbackProcessor { - cp.after = name +// Before insert a new callback before callback `callbackName`, refer `Callbacks.Create` +func (cp *CallbackProcessor) Before(callbackName string) *CallbackProcessor { + cp.before = callbackName return cp } -func (cp *callbackProcessor) Register(name string, fc func(scope *Scope)) { - cp.name = name - cp.processor = &fc - cp.callback.sort() +// Register a new callback, refer `Callbacks.Create` +func (cp *CallbackProcessor) Register(callbackName string, callback func(scope *Scope)) { + if cp.kind == "row_query" { + if cp.before == "" && cp.after == "" && callbackName != "gorm:row_query" { + fmt.Printf("Registing RowQuery callback %v without specify order with Before(), After(), applying Before('gorm:row_query') by default for compatibility...\n", callbackName) + cp.before = "gorm:row_query" + } + } + + cp.name = callbackName + cp.processor = &callback + cp.parent.processors = append(cp.parent.processors, cp) + cp.parent.reorder() } -func (cp *callbackProcessor) Remove(name string) { - fmt.Printf("[info] removing callback `%v` from %v\n", name, fileWithLineNum()) - cp.name = name +// Remove a registered callback +// db.Callback().Create().Remove("gorm:update_time_stamp_when_create") +func (cp *CallbackProcessor) Remove(callbackName string) { + fmt.Printf("[info] removing callback `%v` from %v\n", callbackName, fileWithLineNum()) + cp.name = callbackName cp.remove = true - cp.callback.sort() + cp.parent.processors = append(cp.parent.processors, cp) + cp.parent.reorder() +} + +// Replace a registered callback with new callback +// db.Callback().Create().Replace("gorm:update_time_stamp_when_create", func(*Scope) { +// scope.SetColumn("Created", now) +// scope.SetColumn("Updated", now) +// }) +func (cp *CallbackProcessor) Replace(callbackName string, callback func(scope *Scope)) { + fmt.Printf("[info] replacing callback `%v` from %v\n", callbackName, fileWithLineNum()) + cp.name = callbackName + cp.processor = &callback + cp.replace = true + cp.parent.processors = append(cp.parent.processors, cp) + cp.parent.reorder() } -func (cp *callbackProcessor) Replace(name string, fc func(scope *Scope)) { - fmt.Printf("[info] replacing callback `%v` from %v\n", name, fileWithLineNum()) - cp.name = name - cp.processor = &fc - cp.replace = true - cp.callback.sort() +// Get registered callback +// db.Callback().Create().Get("gorm:create") +func (cp *CallbackProcessor) Get(callbackName string) (callback func(scope *Scope)) { + for _, p := range cp.parent.processors { + if p.name == callbackName && p.kind == cp.kind && !cp.remove { + return *p.processor + } + } + return nil } +// getRIndex get right index from string slice func getRIndex(strs []string, str string) int { for i := len(strs) - 1; i >= 0; i-- { if strs[i] == str { @@ -100,51 +151,53 @@ func getRIndex(strs []string, str string) int { return -1 } -func sortProcessors(cps []*callbackProcessor) []*func(scope *Scope) { - var sortCallbackProcessor func(c *callbackProcessor) - var names, sortedNames = []string{}, []string{} +// sortProcessors sort callback processors based on its before, after, remove, replace +func sortProcessors(cps []*CallbackProcessor) []*func(scope *Scope) { + var ( + allNames, sortedNames []string + sortCallbackProcessor func(c *CallbackProcessor) + ) for _, cp := range cps { - if index := getRIndex(names, cp.name); index > -1 { - if !cp.replace && !cp.remove { - fmt.Printf("[warning] duplicated callback `%v` from %v\n", cp.name, fileWithLineNum()) - } + // show warning message the callback name already exists + if index := getRIndex(allNames, cp.name); index > -1 && !cp.replace && !cp.remove { + fmt.Printf("[warning] duplicated callback `%v` from %v\n", cp.name, fileWithLineNum()) } - names = append(names, cp.name) + allNames = append(allNames, cp.name) } - sortCallbackProcessor = func(c *callbackProcessor) { - if getRIndex(sortedNames, c.name) > -1 { - return - } - - if len(c.before) > 0 { - if index := getRIndex(sortedNames, c.before); index > -1 { - sortedNames = append(sortedNames[:index], append([]string{c.name}, sortedNames[index:]...)...) - } else if index := getRIndex(names, c.before); index > -1 { - sortedNames = append(sortedNames, c.name) - sortCallbackProcessor(cps[index]) - } else { - sortedNames = append(sortedNames, c.name) + sortCallbackProcessor = func(c *CallbackProcessor) { + if getRIndex(sortedNames, c.name) == -1 { // if not sorted + if c.before != "" { // if defined before callback + if index := getRIndex(sortedNames, c.before); index != -1 { + // if before callback already sorted, append current callback just after it + sortedNames = append(sortedNames[:index], append([]string{c.name}, sortedNames[index:]...)...) + } else if index := getRIndex(allNames, c.before); index != -1 { + // if before callback exists but haven't sorted, append current callback to last + sortedNames = append(sortedNames, c.name) + sortCallbackProcessor(cps[index]) + } } - } - if len(c.after) > 0 { - if index := getRIndex(sortedNames, c.after); index > -1 { - sortedNames = append(sortedNames[:index+1], append([]string{c.name}, sortedNames[index+1:]...)...) - } else if index := getRIndex(names, c.after); index > -1 { - cp := cps[index] - if len(cp.before) == 0 { - cp.before = c.name + if c.after != "" { // if defined after callback + if index := getRIndex(sortedNames, c.after); index != -1 { + // if after callback already sorted, append current callback just before it + sortedNames = append(sortedNames[:index+1], append([]string{c.name}, sortedNames[index+1:]...)...) + } else if index := getRIndex(allNames, c.after); index != -1 { + // if after callback exists but haven't sorted + cp := cps[index] + // set after callback's before callback to current callback + if cp.before == "" { + cp.before = c.name + } + sortCallbackProcessor(cp) } - sortCallbackProcessor(cp) - } else { - sortedNames = append(sortedNames, c.name) } - } - if getRIndex(sortedNames, c.name) == -1 { - sortedNames = append(sortedNames, c.name) + // if current callback haven't been sorted, append it to last + if getRIndex(sortedNames, c.name) == -1 { + sortedNames = append(sortedNames, c.name) + } } } @@ -152,41 +205,34 @@ func sortProcessors(cps []*callbackProcessor) []*func(scope *Scope) { sortCallbackProcessor(cp) } - var funcs = []*func(scope *Scope){} - var sortedFuncs = []*func(scope *Scope){} + var sortedFuncs []*func(scope *Scope) for _, name := range sortedNames { - index := getRIndex(names, name) - if !cps[index].remove { + if index := getRIndex(allNames, name); !cps[index].remove { sortedFuncs = append(sortedFuncs, cps[index].processor) } } - for _, cp := range cps { - if sindex := getRIndex(sortedNames, cp.name); sindex == -1 { - if !cp.remove { - funcs = append(funcs, cp.processor) - } - } - } - - return append(sortedFuncs, funcs...) + return sortedFuncs } -func (c *callback) sort() { - var creates, updates, deletes, queries, rowQueries []*callbackProcessor +// reorder all registered processors, and reset CRUD callbacks +func (c *Callback) reorder() { + var creates, updates, deletes, queries, rowQueries []*CallbackProcessor for _, processor := range c.processors { - switch processor.typ { - case "create": - creates = append(creates, processor) - case "update": - updates = append(updates, processor) - case "delete": - deletes = append(deletes, processor) - case "query": - queries = append(queries, processor) - case "row_query": - rowQueries = append(rowQueries, processor) + if processor.name != "" { + switch processor.kind { + case "create": + creates = append(creates, processor) + case "update": + updates = append(updates, processor) + case "delete": + deletes = append(deletes, processor) + case "query": + queries = append(queries, processor) + case "row_query": + rowQueries = append(rowQueries, processor) + } } } @@ -196,5 +242,3 @@ func (c *callback) sort() { c.queries = sortProcessors(queries) c.rowQueries = sortProcessors(rowQueries) } - -var DefaultCallback = &callback{processors: []*callbackProcessor{}} diff --git a/vendor/github.com/jinzhu/gorm/callback_create.go b/vendor/github.com/jinzhu/gorm/callback_create.go index 7f21ed6a5..f07098801 100644 --- a/vendor/github.com/jinzhu/gorm/callback_create.go +++ b/vendor/github.com/jinzhu/gorm/callback_create.go @@ -5,12 +5,31 @@ import ( "strings" ) -func BeforeCreate(scope *Scope) { - scope.CallMethodWithErrorCheck("BeforeSave") - scope.CallMethodWithErrorCheck("BeforeCreate") +// Define callbacks for creating +func init() { + DefaultCallback.Create().Register("gorm:begin_transaction", beginTransactionCallback) + DefaultCallback.Create().Register("gorm:before_create", beforeCreateCallback) + DefaultCallback.Create().Register("gorm:save_before_associations", saveBeforeAssociationsCallback) + DefaultCallback.Create().Register("gorm:update_time_stamp", updateTimeStampForCreateCallback) + DefaultCallback.Create().Register("gorm:create", createCallback) + DefaultCallback.Create().Register("gorm:force_reload_after_create", forceReloadAfterCreateCallback) + DefaultCallback.Create().Register("gorm:save_after_associations", saveAfterAssociationsCallback) + DefaultCallback.Create().Register("gorm:after_create", afterCreateCallback) + DefaultCallback.Create().Register("gorm:commit_or_rollback_transaction", commitOrRollbackTransactionCallback) +} + +// beforeCreateCallback will invoke `BeforeSave`, `BeforeCreate` method before creating +func beforeCreateCallback(scope *Scope) { + if !scope.HasError() { + scope.CallMethod("BeforeSave") + } + if !scope.HasError() { + scope.CallMethod("BeforeCreate") + } } -func UpdateTimeStampWhenCreate(scope *Scope) { +// updateTimeStampForCreateCallback will set `CreatedAt`, `UpdatedAt` when creating +func updateTimeStampForCreateCallback(scope *Scope) { if !scope.HasError() { now := NowFunc() scope.SetColumn("CreatedAt", now) @@ -18,93 +37,117 @@ func UpdateTimeStampWhenCreate(scope *Scope) { } } -func Create(scope *Scope) { - defer scope.Trace(NowFunc()) - +// createCallback the callback used to insert data into database +func createCallback(scope *Scope) { if !scope.HasError() { - // set create sql - var sqls, columns []string - fields := scope.Fields() - for _, field := range fields { + defer scope.trace(NowFunc()) + + var ( + columns, placeholders []string + blankColumnsWithDefaultValue []string + ) + + for _, field := range scope.Fields() { if scope.changeableField(field) { if field.IsNormal { - if !field.IsPrimaryKey || (field.IsPrimaryKey && !field.IsBlank) { - if !field.IsBlank || !field.HasDefaultValue { - columns = append(columns, scope.Quote(field.DBName)) - sqls = append(sqls, scope.AddToVars(field.Field.Interface())) - } + if field.IsBlank && field.HasDefaultValue { + blankColumnsWithDefaultValue = append(blankColumnsWithDefaultValue, scope.Quote(field.DBName)) + scope.InstanceSet("gorm:blank_columns_with_default_value", blankColumnsWithDefaultValue) + } else if !field.IsPrimaryKey || !field.IsBlank { + columns = append(columns, scope.Quote(field.DBName)) + placeholders = append(placeholders, scope.AddToVars(field.Field.Interface())) } - } else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" { - if relationField := fields[relationship.ForeignDBName]; !scope.changeableField(relationField) { - columns = append(columns, scope.Quote(relationField.DBName)) - sqls = append(sqls, scope.AddToVars(relationField.Field.Interface())) + } else if field.Relationship != nil && field.Relationship.Kind == "belongs_to" { + for _, foreignKey := range field.Relationship.ForeignDBNames { + if foreignField, ok := scope.FieldByName(foreignKey); ok && !scope.changeableField(foreignField) { + columns = append(columns, scope.Quote(foreignField.DBName)) + placeholders = append(placeholders, scope.AddToVars(foreignField.Field.Interface())) + } } } } } - returningKey := "*" - primaryField := scope.PrimaryField() + var ( + returningColumn = "*" + quotedTableName = scope.QuotedTableName() + primaryField = scope.PrimaryField() + extraOption string + ) + + if str, ok := scope.Get("gorm:insert_option"); ok { + extraOption = fmt.Sprint(str) + } + if primaryField != nil { - returningKey = scope.Quote(primaryField.DBName) + returningColumn = scope.Quote(primaryField.DBName) } + lastInsertIDReturningSuffix := scope.Dialect().LastInsertIDReturningSuffix(quotedTableName, returningColumn) + if len(columns) == 0 { - scope.Raw(fmt.Sprintf("INSERT INTO %v DEFAULT VALUES %v", - scope.QuotedTableName(), - scope.Dialect().ReturningStr(scope.TableName(), returningKey), + scope.Raw(fmt.Sprintf( + "INSERT INTO %v DEFAULT VALUES%v%v", + quotedTableName, + addExtraSpaceIfExist(extraOption), + addExtraSpaceIfExist(lastInsertIDReturningSuffix), )) } else { scope.Raw(fmt.Sprintf( - "INSERT INTO %v (%v) VALUES (%v) %v", + "INSERT INTO %v (%v) VALUES (%v)%v%v", scope.QuotedTableName(), strings.Join(columns, ","), - strings.Join(sqls, ","), - scope.Dialect().ReturningStr(scope.TableName(), returningKey), + strings.Join(placeholders, ","), + addExtraSpaceIfExist(extraOption), + addExtraSpaceIfExist(lastInsertIDReturningSuffix), )) } // execute create sql - if scope.Dialect().SupportLastInsertId() { - if result, err := scope.SqlDB().Exec(scope.Sql, scope.SqlVars...); scope.Err(err) == nil { - id, err := result.LastInsertId() - if scope.Err(err) == nil { - scope.db.RowsAffected, _ = result.RowsAffected() - if primaryField != nil && primaryField.IsBlank { - scope.Err(scope.SetColumn(primaryField, id)) + if lastInsertIDReturningSuffix == "" || primaryField == nil { + if result, err := scope.SQLDB().Exec(scope.SQL, scope.SQLVars...); scope.Err(err) == nil { + // set rows affected count + scope.db.RowsAffected, _ = result.RowsAffected() + + // set primary value to primary field + if primaryField != nil && primaryField.IsBlank { + if primaryValue, err := result.LastInsertId(); scope.Err(err) == nil { + scope.Err(primaryField.Set(primaryValue)) } } } } else { - if primaryField == nil { - if results, err := scope.SqlDB().Exec(scope.Sql, scope.SqlVars...); err == nil { - scope.db.RowsAffected, _ = results.RowsAffected() - } else { - scope.Err(err) - } - } else { - if err := scope.Err(scope.SqlDB().QueryRow(scope.Sql, scope.SqlVars...).Scan(primaryField.Field.Addr().Interface())); err == nil { + if primaryField.Field.CanAddr() { + if err := scope.SQLDB().QueryRow(scope.SQL, scope.SQLVars...).Scan(primaryField.Field.Addr().Interface()); scope.Err(err) == nil { + primaryField.IsBlank = false scope.db.RowsAffected = 1 - } else { - scope.Err(err) } + } else { + scope.Err(ErrUnaddressable) } } } } -func AfterCreate(scope *Scope) { - scope.CallMethodWithErrorCheck("AfterCreate") - scope.CallMethodWithErrorCheck("AfterSave") +// forceReloadAfterCreateCallback will reload columns that having default value, and set it back to current object +func forceReloadAfterCreateCallback(scope *Scope) { + if blankColumnsWithDefaultValue, ok := scope.InstanceGet("gorm:blank_columns_with_default_value"); ok { + db := scope.DB().New().Table(scope.TableName()).Select(blankColumnsWithDefaultValue.([]string)) + for _, field := range scope.Fields() { + if field.IsPrimaryKey && !field.IsBlank { + db = db.Where(fmt.Sprintf("%v = ?", field.DBName), field.Field.Interface()) + } + } + db.Scan(scope.Value) + } } -func init() { - DefaultCallback.Create().Register("gorm:begin_transaction", BeginTransaction) - DefaultCallback.Create().Register("gorm:before_create", BeforeCreate) - DefaultCallback.Create().Register("gorm:save_before_associations", SaveBeforeAssociations) - DefaultCallback.Create().Register("gorm:update_time_stamp_when_create", UpdateTimeStampWhenCreate) - DefaultCallback.Create().Register("gorm:create", Create) - DefaultCallback.Create().Register("gorm:save_after_associations", SaveAfterAssociations) - DefaultCallback.Create().Register("gorm:after_create", AfterCreate) - DefaultCallback.Create().Register("gorm:commit_or_rollback_transaction", CommitOrRollbackTransaction) +// afterCreateCallback will invoke `AfterCreate`, `AfterSave` method after creating +func afterCreateCallback(scope *Scope) { + if !scope.HasError() { + scope.CallMethod("AfterCreate") + } + if !scope.HasError() { + scope.CallMethod("AfterSave") + } } diff --git a/vendor/github.com/jinzhu/gorm/callback_delete.go b/vendor/github.com/jinzhu/gorm/callback_delete.go index 72236659a..73d908806 100644 --- a/vendor/github.com/jinzhu/gorm/callback_delete.go +++ b/vendor/github.com/jinzhu/gorm/callback_delete.go @@ -1,36 +1,63 @@ package gorm -import "fmt" +import ( + "errors" + "fmt" +) -func BeforeDelete(scope *Scope) { - scope.CallMethodWithErrorCheck("BeforeDelete") +// Define callbacks for deleting +func init() { + DefaultCallback.Delete().Register("gorm:begin_transaction", beginTransactionCallback) + DefaultCallback.Delete().Register("gorm:before_delete", beforeDeleteCallback) + DefaultCallback.Delete().Register("gorm:delete", deleteCallback) + DefaultCallback.Delete().Register("gorm:after_delete", afterDeleteCallback) + DefaultCallback.Delete().Register("gorm:commit_or_rollback_transaction", commitOrRollbackTransactionCallback) } -func Delete(scope *Scope) { +// beforeDeleteCallback will invoke `BeforeDelete` method before deleting +func beforeDeleteCallback(scope *Scope) { + if scope.DB().HasBlockGlobalUpdate() && !scope.hasConditions() { + scope.Err(errors.New("Missing WHERE clause while deleting")) + return + } if !scope.HasError() { - if !scope.Search.Unscoped && scope.HasColumn("DeletedAt") { - scope.Raw( - fmt.Sprintf("UPDATE %v SET deleted_at=%v %v", - scope.QuotedTableName(), - scope.AddToVars(NowFunc()), - scope.CombinedConditionSql(), - )) - } else { - scope.Raw(fmt.Sprintf("DELETE FROM %v %v", scope.QuotedTableName(), scope.CombinedConditionSql())) - } - - scope.Exec() + scope.CallMethod("BeforeDelete") } } -func AfterDelete(scope *Scope) { - scope.CallMethodWithErrorCheck("AfterDelete") +// deleteCallback used to delete data from database or set deleted_at to current time (when using with soft delete) +func deleteCallback(scope *Scope) { + if !scope.HasError() { + var extraOption string + if str, ok := scope.Get("gorm:delete_option"); ok { + extraOption = fmt.Sprint(str) + } + + deletedAtField, hasDeletedAtField := scope.FieldByName("DeletedAt") + + if !scope.Search.Unscoped && hasDeletedAtField { + scope.Raw(fmt.Sprintf( + "UPDATE %v SET %v=%v%v%v", + scope.QuotedTableName(), + scope.Quote(deletedAtField.DBName), + scope.AddToVars(NowFunc()), + addExtraSpaceIfExist(scope.CombinedConditionSql()), + addExtraSpaceIfExist(extraOption), + )).Exec() + } else { + scope.Raw(fmt.Sprintf( + "DELETE FROM %v%v%v", + scope.QuotedTableName(), + addExtraSpaceIfExist(scope.CombinedConditionSql()), + addExtraSpaceIfExist(extraOption), + )).Exec() + } + } } -func init() { - DefaultCallback.Delete().Register("gorm:begin_transaction", BeginTransaction) - DefaultCallback.Delete().Register("gorm:before_delete", BeforeDelete) - DefaultCallback.Delete().Register("gorm:delete", Delete) - DefaultCallback.Delete().Register("gorm:after_delete", AfterDelete) - DefaultCallback.Delete().Register("gorm:commit_or_rollback_transaction", CommitOrRollbackTransaction) +// afterDeleteCallback will invoke `AfterDelete` method after deleting +func afterDeleteCallback(scope *Scope) { + if !scope.HasError() { + scope.CallMethod("AfterDelete") + } } diff --git a/vendor/github.com/jinzhu/gorm/callback_query.go b/vendor/github.com/jinzhu/gorm/callback_query.go index 4de911e81..4ed1705ee 100644 --- a/vendor/github.com/jinzhu/gorm/callback_query.go +++ b/vendor/github.com/jinzhu/gorm/callback_query.go @@ -6,113 +6,92 @@ import ( "reflect" ) -func Query(scope *Scope) { - defer scope.Trace(NowFunc()) +// Define callbacks for querying +func init() { + DefaultCallback.Query().Register("gorm:query", queryCallback) + DefaultCallback.Query().Register("gorm:preload", preloadCallback) + DefaultCallback.Query().Register("gorm:after_query", afterQueryCallback) +} + +// queryCallback used to query data from database +func queryCallback(scope *Scope) { + defer scope.trace(NowFunc()) var ( - isSlice bool - isPtr bool - anyRecordFound bool - destType reflect.Type + isSlice, isPtr bool + resultType reflect.Type + results = scope.IndirectValue() ) if orderBy, ok := scope.Get("gorm:order_by_primary_key"); ok { - if primaryKey := scope.PrimaryKey(); primaryKey != "" { - scope.Search.Order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), scope.Quote(primaryKey), orderBy)) + if primaryField := scope.PrimaryField(); primaryField != nil { + scope.Search.Order(fmt.Sprintf("%v.%v %v", scope.QuotedTableName(), scope.Quote(primaryField.DBName), orderBy)) } } - var dest = scope.IndirectValue() if value, ok := scope.Get("gorm:query_destination"); ok { - dest = reflect.Indirect(reflect.ValueOf(value)) + results = indirect(reflect.ValueOf(value)) } - if kind := dest.Kind(); kind == reflect.Slice { + if kind := results.Kind(); kind == reflect.Slice { isSlice = true - destType = dest.Type().Elem() - dest.Set(reflect.Indirect(reflect.New(reflect.SliceOf(destType)))) + resultType = results.Type().Elem() + results.Set(reflect.MakeSlice(results.Type(), 0, 0)) - if destType.Kind() == reflect.Ptr { + if resultType.Kind() == reflect.Ptr { isPtr = true - destType = destType.Elem() + resultType = resultType.Elem() } } else if kind != reflect.Struct { scope.Err(errors.New("unsupported destination, should be slice or struct")) return } - scope.prepareQuerySql() + scope.prepareQuerySQL() if !scope.HasError() { - rows, err := scope.SqlDB().Query(scope.Sql, scope.SqlVars...) scope.db.RowsAffected = 0 - - if scope.Err(err) != nil { - return + if str, ok := scope.Get("gorm:query_option"); ok { + scope.SQL += addExtraSpaceIfExist(fmt.Sprint(str)) } - defer rows.Close() - columns, _ := rows.Columns() - for rows.Next() { - scope.db.RowsAffected++ + if rows, err := scope.SQLDB().Query(scope.SQL, scope.SQLVars...); scope.Err(err) == nil { + defer rows.Close() - anyRecordFound = true - elem := dest - if isSlice { - elem = reflect.New(destType).Elem() - } + columns, _ := rows.Columns() + for rows.Next() { + scope.db.RowsAffected++ - var values = make([]interface{}, len(columns)) + elem := results + if isSlice { + elem = reflect.New(resultType).Elem() + } - fields := scope.New(elem.Addr().Interface()).Fields() + scope.scan(rows, columns, scope.New(elem.Addr().Interface()).Fields()) - for index, column := range columns { - if field, ok := fields[column]; ok { - if field.Field.Kind() == reflect.Ptr { - values[index] = field.Field.Addr().Interface() + if isSlice { + if isPtr { + results.Set(reflect.Append(results, elem.Addr())) } else { - values[index] = reflect.New(reflect.PtrTo(field.Field.Type())).Interface() + results.Set(reflect.Append(results, elem)) } - } else { - var value interface{} - values[index] = &value } } - scope.Err(rows.Scan(values...)) - - for index, column := range columns { - value := values[index] - if field, ok := fields[column]; ok { - if field.Field.Kind() == reflect.Ptr { - field.Field.Set(reflect.ValueOf(value).Elem()) - } else if v := reflect.ValueOf(value).Elem().Elem(); v.IsValid() { - field.Field.Set(v) - } - } + if err := rows.Err(); err != nil { + scope.Err(err) } - if isSlice { - if isPtr { - dest.Set(reflect.Append(dest, elem.Addr())) - } else { - dest.Set(reflect.Append(dest, elem)) - } + if scope.db.RowsAffected == 0 && !isSlice { + scope.Err(ErrRecordNotFound) } } - - if !anyRecordFound && !isSlice { - scope.Err(RecordNotFound) - } } } -func AfterQuery(scope *Scope) { - scope.CallMethodWithErrorCheck("AfterFind") -} - -func init() { - DefaultCallback.Query().Register("gorm:query", Query) - DefaultCallback.Query().Register("gorm:after_query", AfterQuery) - DefaultCallback.Query().Register("gorm:preload", Preload) +// afterQueryCallback will invoke `AfterFind` method after querying +func afterQueryCallback(scope *Scope) { + if !scope.HasError() { + scope.CallMethod("AfterFind") + } } diff --git a/vendor/github.com/jinzhu/gorm/callback_query_preload.go b/vendor/github.com/jinzhu/gorm/callback_query_preload.go new file mode 100644 index 000000000..b3fd4fb42 --- /dev/null +++ b/vendor/github.com/jinzhu/gorm/callback_query_preload.go @@ -0,0 +1,346 @@ +package gorm + +import ( + "errors" + "fmt" + "reflect" + "strings" +) + +// preloadCallback used to preload associations +func preloadCallback(scope *Scope) { + if scope.Search.preload == nil || scope.HasError() { + return + } + + var ( + preloadedMap = map[string]bool{} + fields = scope.Fields() + ) + + for _, preload := range scope.Search.preload { + var ( + preloadFields = strings.Split(preload.schema, ".") + currentScope = scope + currentFields = fields + ) + + for idx, preloadField := range preloadFields { + var currentPreloadConditions []interface{} + + if currentScope == nil { + continue + } + + // if not preloaded + if preloadKey := strings.Join(preloadFields[:idx+1], "."); !preloadedMap[preloadKey] { + + // assign search conditions to last preload + if idx == len(preloadFields)-1 { + currentPreloadConditions = preload.conditions + } + + for _, field := range currentFields { + if field.Name != preloadField || field.Relationship == nil { + continue + } + + switch field.Relationship.Kind { + case "has_one": + currentScope.handleHasOnePreload(field, currentPreloadConditions) + case "has_many": + currentScope.handleHasManyPreload(field, currentPreloadConditions) + case "belongs_to": + currentScope.handleBelongsToPreload(field, currentPreloadConditions) + case "many_to_many": + currentScope.handleManyToManyPreload(field, currentPreloadConditions) + default: + scope.Err(errors.New("unsupported relation")) + } + + preloadedMap[preloadKey] = true + break + } + + if !preloadedMap[preloadKey] { + scope.Err(fmt.Errorf("can't preload field %s for %s", preloadField, currentScope.GetModelStruct().ModelType)) + return + } + } + + // preload next level + if idx < len(preloadFields)-1 { + currentScope = currentScope.getColumnAsScope(preloadField) + if currentScope != nil { + currentFields = currentScope.Fields() + } + } + } + } +} + +func (scope *Scope) generatePreloadDBWithConditions(conditions []interface{}) (*DB, []interface{}) { + var ( + preloadDB = scope.NewDB() + preloadConditions []interface{} + ) + + for _, condition := range conditions { + if scopes, ok := condition.(func(*DB) *DB); ok { + preloadDB = scopes(preloadDB) + } else { + preloadConditions = append(preloadConditions, condition) + } + } + + return preloadDB, preloadConditions +} + +// handleHasOnePreload used to preload has one associations +func (scope *Scope) handleHasOnePreload(field *Field, conditions []interface{}) { + relation := field.Relationship + + // get relations's primary keys + primaryKeys := scope.getColumnAsArray(relation.AssociationForeignFieldNames, scope.Value) + if len(primaryKeys) == 0 { + return + } + + // preload conditions + preloadDB, preloadConditions := scope.generatePreloadDBWithConditions(conditions) + + // find relations + query := fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relation.ForeignDBNames), toQueryMarks(primaryKeys)) + values := toQueryValues(primaryKeys) + if relation.PolymorphicType != "" { + query += fmt.Sprintf(" AND %v = ?", scope.Quote(relation.PolymorphicDBName)) + values = append(values, relation.PolymorphicValue) + } + + results := makeSlice(field.Struct.Type) + scope.Err(preloadDB.Where(query, values...).Find(results, preloadConditions...).Error) + + // assign find results + var ( + resultsValue = indirect(reflect.ValueOf(results)) + indirectScopeValue = scope.IndirectValue() + ) + + if indirectScopeValue.Kind() == reflect.Slice { + for j := 0; j < indirectScopeValue.Len(); j++ { + for i := 0; i < resultsValue.Len(); i++ { + result := resultsValue.Index(i) + foreignValues := getValueFromFields(result, relation.ForeignFieldNames) + if indirectValue := indirect(indirectScopeValue.Index(j)); equalAsString(getValueFromFields(indirectValue, relation.AssociationForeignFieldNames), foreignValues) { + indirectValue.FieldByName(field.Name).Set(result) + break + } + } + } + } else { + for i := 0; i < resultsValue.Len(); i++ { + result := resultsValue.Index(i) + scope.Err(field.Set(result)) + } + } +} + +// handleHasManyPreload used to preload has many associations +func (scope *Scope) handleHasManyPreload(field *Field, conditions []interface{}) { + relation := field.Relationship + + // get relations's primary keys + primaryKeys := scope.getColumnAsArray(relation.AssociationForeignFieldNames, scope.Value) + if len(primaryKeys) == 0 { + return + } + + // preload conditions + preloadDB, preloadConditions := scope.generatePreloadDBWithConditions(conditions) + + // find relations + query := fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relation.ForeignDBNames), toQueryMarks(primaryKeys)) + values := toQueryValues(primaryKeys) + if relation.PolymorphicType != "" { + query += fmt.Sprintf(" AND %v = ?", scope.Quote(relation.PolymorphicDBName)) + values = append(values, relation.PolymorphicValue) + } + + results := makeSlice(field.Struct.Type) + scope.Err(preloadDB.Where(query, values...).Find(results, preloadConditions...).Error) + + // assign find results + var ( + resultsValue = indirect(reflect.ValueOf(results)) + indirectScopeValue = scope.IndirectValue() + ) + + if indirectScopeValue.Kind() == reflect.Slice { + preloadMap := make(map[string][]reflect.Value) + for i := 0; i < resultsValue.Len(); i++ { + result := resultsValue.Index(i) + foreignValues := getValueFromFields(result, relation.ForeignFieldNames) + preloadMap[toString(foreignValues)] = append(preloadMap[toString(foreignValues)], result) + } + + for j := 0; j < indirectScopeValue.Len(); j++ { + object := indirect(indirectScopeValue.Index(j)) + objectRealValue := getValueFromFields(object, relation.AssociationForeignFieldNames) + f := object.FieldByName(field.Name) + if results, ok := preloadMap[toString(objectRealValue)]; ok { + f.Set(reflect.Append(f, results...)) + } else { + f.Set(reflect.MakeSlice(f.Type(), 0, 0)) + } + } + } else { + scope.Err(field.Set(resultsValue)) + } +} + +// handleBelongsToPreload used to preload belongs to associations +func (scope *Scope) handleBelongsToPreload(field *Field, conditions []interface{}) { + relation := field.Relationship + + // preload conditions + preloadDB, preloadConditions := scope.generatePreloadDBWithConditions(conditions) + + // get relations's primary keys + primaryKeys := scope.getColumnAsArray(relation.ForeignFieldNames, scope.Value) + if len(primaryKeys) == 0 { + return + } + + // find relations + results := makeSlice(field.Struct.Type) + scope.Err(preloadDB.Where(fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relation.AssociationForeignDBNames), toQueryMarks(primaryKeys)), toQueryValues(primaryKeys)...).Find(results, preloadConditions...).Error) + + // assign find results + var ( + resultsValue = indirect(reflect.ValueOf(results)) + indirectScopeValue = scope.IndirectValue() + ) + + for i := 0; i < resultsValue.Len(); i++ { + result := resultsValue.Index(i) + if indirectScopeValue.Kind() == reflect.Slice { + value := getValueFromFields(result, relation.AssociationForeignFieldNames) + for j := 0; j < indirectScopeValue.Len(); j++ { + object := indirect(indirectScopeValue.Index(j)) + if equalAsString(getValueFromFields(object, relation.ForeignFieldNames), value) { + object.FieldByName(field.Name).Set(result) + } + } + } else { + scope.Err(field.Set(result)) + } + } +} + +// handleManyToManyPreload used to preload many to many associations +func (scope *Scope) handleManyToManyPreload(field *Field, conditions []interface{}) { + var ( + relation = field.Relationship + joinTableHandler = relation.JoinTableHandler + fieldType = field.Struct.Type.Elem() + foreignKeyValue interface{} + foreignKeyType = reflect.ValueOf(&foreignKeyValue).Type() + linkHash = map[string][]reflect.Value{} + isPtr bool + ) + + if fieldType.Kind() == reflect.Ptr { + isPtr = true + fieldType = fieldType.Elem() + } + + var sourceKeys = []string{} + for _, key := range joinTableHandler.SourceForeignKeys() { + sourceKeys = append(sourceKeys, key.DBName) + } + + // preload conditions + preloadDB, preloadConditions := scope.generatePreloadDBWithConditions(conditions) + + // generate query with join table + newScope := scope.New(reflect.New(fieldType).Interface()) + preloadDB = preloadDB.Table(newScope.TableName()).Model(newScope.Value).Select("*") + preloadDB = joinTableHandler.JoinWith(joinTableHandler, preloadDB, scope.Value) + + // preload inline conditions + if len(preloadConditions) > 0 { + preloadDB = preloadDB.Where(preloadConditions[0], preloadConditions[1:]...) + } + + rows, err := preloadDB.Rows() + + if scope.Err(err) != nil { + return + } + defer rows.Close() + + columns, _ := rows.Columns() + for rows.Next() { + var ( + elem = reflect.New(fieldType).Elem() + fields = scope.New(elem.Addr().Interface()).Fields() + ) + + // register foreign keys in join tables + var joinTableFields []*Field + for _, sourceKey := range sourceKeys { + joinTableFields = append(joinTableFields, &Field{StructField: &StructField{DBName: sourceKey, IsNormal: true}, Field: reflect.New(foreignKeyType).Elem()}) + } + + scope.scan(rows, columns, append(fields, joinTableFields...)) + + var foreignKeys = make([]interface{}, len(sourceKeys)) + // generate hashed forkey keys in join table + for idx, joinTableField := range joinTableFields { + if !joinTableField.Field.IsNil() { + foreignKeys[idx] = joinTableField.Field.Elem().Interface() + } + } + hashedSourceKeys := toString(foreignKeys) + + if isPtr { + linkHash[hashedSourceKeys] = append(linkHash[hashedSourceKeys], elem.Addr()) + } else { + linkHash[hashedSourceKeys] = append(linkHash[hashedSourceKeys], elem) + } + } + + // assign find results + var ( + indirectScopeValue = scope.IndirectValue() + fieldsSourceMap = map[string][]reflect.Value{} + foreignFieldNames = []string{} + ) + + for _, dbName := range relation.ForeignFieldNames { + if field, ok := scope.FieldByName(dbName); ok { + foreignFieldNames = append(foreignFieldNames, field.Name) + } + } + + if indirectScopeValue.Kind() == reflect.Slice { + for j := 0; j < indirectScopeValue.Len(); j++ { + object := indirect(indirectScopeValue.Index(j)) + key := toString(getValueFromFields(object, foreignFieldNames)) + fieldsSourceMap[key] = append(fieldsSourceMap[key], object.FieldByName(field.Name)) + } + } else if indirectScopeValue.IsValid() { + key := toString(getValueFromFields(indirectScopeValue, foreignFieldNames)) + fieldsSourceMap[key] = append(fieldsSourceMap[key], indirectScopeValue.FieldByName(field.Name)) + } + for source, link := range linkHash { + for i, field := range fieldsSourceMap[source] { + //If not 0 this means Value is a pointer and we already added preloaded models to it + if fieldsSourceMap[source][i].Len() != 0 { + continue + } + field.Set(reflect.Append(fieldsSourceMap[source][i], link...)) + } + + } +} diff --git a/vendor/github.com/jinzhu/gorm/callback_row_query.go b/vendor/github.com/jinzhu/gorm/callback_row_query.go new file mode 100644 index 000000000..c2ff4a083 --- /dev/null +++ b/vendor/github.com/jinzhu/gorm/callback_row_query.go @@ -0,0 +1,30 @@ +package gorm + +import "database/sql" + +// Define callbacks for row query +func init() { + DefaultCallback.RowQuery().Register("gorm:row_query", rowQueryCallback) +} + +type RowQueryResult struct { + Row *sql.Row +} + +type RowsQueryResult struct { + Rows *sql.Rows + Error error +} + +// queryCallback used to query data from database +func rowQueryCallback(scope *Scope) { + if result, ok := scope.InstanceGet("row_query_result"); ok { + scope.prepareQuerySQL() + + if rowResult, ok := result.(*RowQueryResult); ok { + rowResult.Row = scope.SQLDB().QueryRow(scope.SQL, scope.SQLVars...) + } else if rowsResult, ok := result.(*RowsQueryResult); ok { + rowsResult.Rows, rowsResult.Error = scope.SQLDB().Query(scope.SQL, scope.SQLVars...) + } + } +} diff --git a/vendor/github.com/jinzhu/gorm/callback_save.go b/vendor/github.com/jinzhu/gorm/callback_save.go new file mode 100644 index 000000000..f4bc918e7 --- /dev/null +++ b/vendor/github.com/jinzhu/gorm/callback_save.go @@ -0,0 +1,99 @@ +package gorm + +import "reflect" + +func beginTransactionCallback(scope *Scope) { + scope.Begin() +} + +func commitOrRollbackTransactionCallback(scope *Scope) { + scope.CommitOrRollback() +} + +func saveFieldAsAssociation(scope *Scope, field *Field) (bool, *Relationship) { + if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored { + if value, ok := field.TagSettings["SAVE_ASSOCIATIONS"]; !ok || (value != "false" && value != "skip") { + if relationship := field.Relationship; relationship != nil { + return true, relationship + } + } + } + return false, nil +} + +func saveBeforeAssociationsCallback(scope *Scope) { + if !scope.shouldSaveAssociations() { + return + } + for _, field := range scope.Fields() { + if ok, relationship := saveFieldAsAssociation(scope, field); ok && relationship.Kind == "belongs_to" { + fieldValue := field.Field.Addr().Interface() + scope.Err(scope.NewDB().Save(fieldValue).Error) + if len(relationship.ForeignFieldNames) != 0 { + // set value's foreign key + for idx, fieldName := range relationship.ForeignFieldNames { + associationForeignName := relationship.AssociationForeignDBNames[idx] + if foreignField, ok := scope.New(fieldValue).FieldByName(associationForeignName); ok { + scope.Err(scope.SetColumn(fieldName, foreignField.Field.Interface())) + } + } + } + } + } +} + +func saveAfterAssociationsCallback(scope *Scope) { + if !scope.shouldSaveAssociations() { + return + } + for _, field := range scope.Fields() { + if ok, relationship := saveFieldAsAssociation(scope, field); ok && + (relationship.Kind == "has_one" || relationship.Kind == "has_many" || relationship.Kind == "many_to_many") { + value := field.Field + + switch value.Kind() { + case reflect.Slice: + for i := 0; i < value.Len(); i++ { + newDB := scope.NewDB() + elem := value.Index(i).Addr().Interface() + newScope := newDB.NewScope(elem) + + if relationship.JoinTableHandler == nil && len(relationship.ForeignFieldNames) != 0 { + for idx, fieldName := range relationship.ForeignFieldNames { + associationForeignName := relationship.AssociationForeignDBNames[idx] + if f, ok := scope.FieldByName(associationForeignName); ok { + scope.Err(newScope.SetColumn(fieldName, f.Field.Interface())) + } + } + } + + if relationship.PolymorphicType != "" { + scope.Err(newScope.SetColumn(relationship.PolymorphicType, relationship.PolymorphicValue)) + } + + scope.Err(newDB.Save(elem).Error) + + if joinTableHandler := relationship.JoinTableHandler; joinTableHandler != nil { + scope.Err(joinTableHandler.Add(joinTableHandler, newDB, scope.Value, newScope.Value)) + } + } + default: + elem := value.Addr().Interface() + newScope := scope.New(elem) + if len(relationship.ForeignFieldNames) != 0 { + for idx, fieldName := range relationship.ForeignFieldNames { + associationForeignName := relationship.AssociationForeignDBNames[idx] + if f, ok := scope.FieldByName(associationForeignName); ok { + scope.Err(newScope.SetColumn(fieldName, f.Field.Interface())) + } + } + } + + if relationship.PolymorphicType != "" { + scope.Err(newScope.SetColumn(relationship.PolymorphicType, relationship.PolymorphicValue)) + } + scope.Err(scope.NewDB().Save(elem).Error) + } + } + } +} diff --git a/vendor/github.com/jinzhu/gorm/callback_shared.go b/vendor/github.com/jinzhu/gorm/callback_shared.go deleted file mode 100644 index c1b9bd008..000000000 --- a/vendor/github.com/jinzhu/gorm/callback_shared.go +++ /dev/null @@ -1,76 +0,0 @@ -package gorm - -import "reflect" - -func BeginTransaction(scope *Scope) { - scope.Begin() -} - -func CommitOrRollbackTransaction(scope *Scope) { - scope.CommitOrRollback() -} - -func SaveBeforeAssociations(scope *Scope) { - if !scope.shouldSaveAssociations() { - return - } - for _, field := range scope.Fields() { - if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored { - if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" { - value := field.Field - scope.Err(scope.NewDB().Save(value.Addr().Interface()).Error) - if relationship.ForeignFieldName != "" { - scope.Err(scope.SetColumn(relationship.ForeignFieldName, scope.New(value.Addr().Interface()).PrimaryKeyValue())) - } - } - } - } -} - -func SaveAfterAssociations(scope *Scope) { - if !scope.shouldSaveAssociations() { - return - } - for _, field := range scope.Fields() { - if scope.changeableField(field) && !field.IsBlank && !field.IsIgnored { - if relationship := field.Relationship; relationship != nil && - (relationship.Kind == "has_one" || relationship.Kind == "has_many" || relationship.Kind == "many_to_many") { - value := field.Field - - switch value.Kind() { - case reflect.Slice: - for i := 0; i < value.Len(); i++ { - newDB := scope.NewDB() - elem := value.Index(i).Addr().Interface() - newScope := newDB.NewScope(elem) - - if relationship.JoinTableHandler == nil && relationship.ForeignFieldName != "" { - scope.Err(newScope.SetColumn(relationship.ForeignFieldName, scope.PrimaryKeyValue())) - } - - if relationship.PolymorphicType != "" { - scope.Err(newScope.SetColumn(relationship.PolymorphicType, scope.TableName())) - } - - scope.Err(newDB.Save(elem).Error) - - if joinTableHandler := relationship.JoinTableHandler; joinTableHandler != nil { - scope.Err(joinTableHandler.Add(joinTableHandler, scope.NewDB(), scope.Value, newScope.Value)) - } - } - default: - elem := value.Addr().Interface() - newScope := scope.New(elem) - if relationship.ForeignFieldName != "" { - scope.Err(newScope.SetColumn(relationship.ForeignFieldName, scope.PrimaryKeyValue())) - } - - if relationship.PolymorphicType != "" { - scope.Err(newScope.SetColumn(relationship.PolymorphicType, scope.TableName())) - } - scope.Err(scope.NewDB().Save(elem).Error) - } - } - } - } -} diff --git a/vendor/github.com/jinzhu/gorm/callback_update.go b/vendor/github.com/jinzhu/gorm/callback_update.go index c3f7b4b62..6948439fb 100644 --- a/vendor/github.com/jinzhu/gorm/callback_update.go +++ b/vendor/github.com/jinzhu/gorm/callback_update.go @@ -1,96 +1,109 @@ package gorm import ( + "errors" "fmt" "strings" ) -func AssignUpdateAttributes(scope *Scope) { - if attrs, ok := scope.InstanceGet("gorm:update_interface"); ok { - if maps := convertInterfaceToMap(attrs); len(maps) > 0 { - protected, ok := scope.Get("gorm:ignore_protected_attrs") - _, updateColumn := scope.Get("gorm:update_column") - updateAttrs, hasUpdate := scope.updatedAttrsWithValues(maps, ok && protected.(bool)) +// Define callbacks for updating +func init() { + DefaultCallback.Update().Register("gorm:assign_updating_attributes", assignUpdatingAttributesCallback) + DefaultCallback.Update().Register("gorm:begin_transaction", beginTransactionCallback) + DefaultCallback.Update().Register("gorm:before_update", beforeUpdateCallback) + DefaultCallback.Update().Register("gorm:save_before_associations", saveBeforeAssociationsCallback) + DefaultCallback.Update().Register("gorm:update_time_stamp", updateTimeStampForUpdateCallback) + DefaultCallback.Update().Register("gorm:update", updateCallback) + DefaultCallback.Update().Register("gorm:save_after_associations", saveAfterAssociationsCallback) + DefaultCallback.Update().Register("gorm:after_update", afterUpdateCallback) + DefaultCallback.Update().Register("gorm:commit_or_rollback_transaction", commitOrRollbackTransactionCallback) +} - if updateColumn { - scope.InstanceSet("gorm:update_attrs", maps) - } else if len(updateAttrs) > 0 { - scope.InstanceSet("gorm:update_attrs", updateAttrs) - } else if !hasUpdate { - scope.SkipLeft() - return - } +// assignUpdatingAttributesCallback assign updating attributes to model +func assignUpdatingAttributesCallback(scope *Scope) { + if attrs, ok := scope.InstanceGet("gorm:update_interface"); ok { + if updateMaps, hasUpdate := scope.updatedAttrsWithValues(attrs); hasUpdate { + scope.InstanceSet("gorm:update_attrs", updateMaps) + } else { + scope.SkipLeft() } } } -func BeforeUpdate(scope *Scope) { +// beforeUpdateCallback will invoke `BeforeSave`, `BeforeUpdate` method before updating +func beforeUpdateCallback(scope *Scope) { + if scope.DB().HasBlockGlobalUpdate() && !scope.hasConditions() { + scope.Err(errors.New("Missing WHERE clause while updating")) + return + } if _, ok := scope.Get("gorm:update_column"); !ok { - scope.CallMethodWithErrorCheck("BeforeSave") - scope.CallMethodWithErrorCheck("BeforeUpdate") + if !scope.HasError() { + scope.CallMethod("BeforeSave") + } + if !scope.HasError() { + scope.CallMethod("BeforeUpdate") + } } } -func UpdateTimeStampWhenUpdate(scope *Scope) { +// updateTimeStampForUpdateCallback will set `UpdatedAt` when updating +func updateTimeStampForUpdateCallback(scope *Scope) { if _, ok := scope.Get("gorm:update_column"); !ok { scope.SetColumn("UpdatedAt", NowFunc()) } } -func Update(scope *Scope) { +// updateCallback the callback used to update data to database +func updateCallback(scope *Scope) { if !scope.HasError() { var sqls []string if updateAttrs, ok := scope.InstanceGet("gorm:update_attrs"); ok { - for key, value := range updateAttrs.(map[string]interface{}) { - if scope.changeableDBColumn(key) { - sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(key), scope.AddToVars(value))) - } + for column, value := range updateAttrs.(map[string]interface{}) { + sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(column), scope.AddToVars(value))) } } else { - fields := scope.Fields() - for _, field := range fields { - if scope.changeableField(field) && !field.IsPrimaryKey && field.IsNormal { - if !field.IsBlank || !field.HasDefaultValue { + for _, field := range scope.Fields() { + if scope.changeableField(field) { + if !field.IsPrimaryKey && field.IsNormal { sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface()))) - } - } else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" { - if relationField := fields[relationship.ForeignDBName]; !scope.changeableField(relationField) { - if !relationField.IsBlank { - sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(relationField.DBName), scope.AddToVars(relationField.Field.Interface()))) + } else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" { + for _, foreignKey := range relationship.ForeignDBNames { + if foreignField, ok := scope.FieldByName(foreignKey); ok && !scope.changeableField(foreignField) { + sqls = append(sqls, + fmt.Sprintf("%v = %v", scope.Quote(foreignField.DBName), scope.AddToVars(foreignField.Field.Interface()))) + } } } } } } + var extraOption string + if str, ok := scope.Get("gorm:update_option"); ok { + extraOption = fmt.Sprint(str) + } + if len(sqls) > 0 { scope.Raw(fmt.Sprintf( - "UPDATE %v SET %v %v", + "UPDATE %v SET %v%v%v", scope.QuotedTableName(), strings.Join(sqls, ", "), - scope.CombinedConditionSql(), - )) - scope.Exec() + addExtraSpaceIfExist(scope.CombinedConditionSql()), + addExtraSpaceIfExist(extraOption), + )).Exec() } } } -func AfterUpdate(scope *Scope) { +// afterUpdateCallback will invoke `AfterUpdate`, `AfterSave` method after updating +func afterUpdateCallback(scope *Scope) { if _, ok := scope.Get("gorm:update_column"); !ok { - scope.CallMethodWithErrorCheck("AfterUpdate") - scope.CallMethodWithErrorCheck("AfterSave") + if !scope.HasError() { + scope.CallMethod("AfterUpdate") + } + if !scope.HasError() { + scope.CallMethod("AfterSave") + } } } - -func init() { - DefaultCallback.Update().Register("gorm:assign_update_attributes", AssignUpdateAttributes) - DefaultCallback.Update().Register("gorm:begin_transaction", BeginTransaction) - DefaultCallback.Update().Register("gorm:before_update", BeforeUpdate) - DefaultCallback.Update().Register("gorm:save_before_associations", SaveBeforeAssociations) - DefaultCallback.Update().Register("gorm:update_time_stamp_when_update", UpdateTimeStampWhenUpdate) - DefaultCallback.Update().Register("gorm:update", Update) - DefaultCallback.Update().Register("gorm:save_after_associations", SaveAfterAssociations) - DefaultCallback.Update().Register("gorm:after_update", AfterUpdate) - DefaultCallback.Update().Register("gorm:commit_or_rollback_transaction", CommitOrRollbackTransaction) -} diff --git a/vendor/github.com/jinzhu/gorm/common_dialect.go b/vendor/github.com/jinzhu/gorm/common_dialect.go deleted file mode 100644 index 281df8a71..000000000 --- a/vendor/github.com/jinzhu/gorm/common_dialect.go +++ /dev/null @@ -1,101 +0,0 @@ -package gorm - -import ( - "fmt" - "reflect" - "strings" - "time" -) - -type commonDialect struct{} - -func (commonDialect) BinVar(i int) string { - return "$$" // ? -} - -func (commonDialect) SupportLastInsertId() bool { - return true -} - -func (commonDialect) HasTop() bool { - return false -} - -func (commonDialect) SqlTag(value reflect.Value, size int, autoIncrease bool) string { - switch value.Kind() { - case reflect.Bool: - return "BOOLEAN" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: - if autoIncrease { - return "INTEGER AUTO_INCREMENT" - } - return "INTEGER" - case reflect.Int64, reflect.Uint64: - if autoIncrease { - return "BIGINT AUTO_INCREMENT" - } - return "BIGINT" - case reflect.Float32, reflect.Float64: - return "FLOAT" - case reflect.String: - if size > 0 && size < 65532 { - return fmt.Sprintf("VARCHAR(%d)", size) - } - return "VARCHAR(65532)" - case reflect.Struct: - if _, ok := value.Interface().(time.Time); ok { - return "TIMESTAMP" - } - default: - if _, ok := value.Interface().([]byte); ok { - if size > 0 && size < 65532 { - return fmt.Sprintf("BINARY(%d)", size) - } - return "BINARY(65532)" - } - } - panic(fmt.Sprintf("invalid sql type %s (%s) for commonDialect", value.Type().Name(), value.Kind().String())) -} - -func (commonDialect) ReturningStr(tableName, key string) string { - return "" -} - -func (commonDialect) SelectFromDummyTable() string { - return "" -} - -func (commonDialect) Quote(key string) string { - return fmt.Sprintf(`"%s"`, key) -} - -func (commonDialect) databaseName(scope *Scope) string { - from := strings.Index(scope.db.parent.source, "/") + 1 - to := strings.Index(scope.db.parent.source, "?") - if to == -1 { - to = len(scope.db.parent.source) - } - return scope.db.parent.source[from:to] -} - -func (c commonDialect) HasTable(scope *Scope, tableName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_name = ? AND table_schema = ?", tableName, c.databaseName(scope)).Row().Scan(&count) - return count > 0 -} - -func (c commonDialect) HasColumn(scope *Scope, tableName string, columnName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = ? AND table_name = ? AND column_name = ?", c.databaseName(scope), tableName, columnName).Row().Scan(&count) - return count > 0 -} - -func (commonDialect) HasIndex(scope *Scope, tableName string, indexName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM INFORMATION_SCHEMA.STATISTICS where table_name = ? AND index_name = ?", tableName, indexName).Row().Scan(&count) - return count > 0 -} - -func (commonDialect) RemoveIndex(scope *Scope, indexName string) { - scope.NewDB().Exec(fmt.Sprintf("DROP INDEX %v ON %v", indexName, scope.QuotedTableName())) -} diff --git a/vendor/github.com/jinzhu/gorm/dialect.go b/vendor/github.com/jinzhu/gorm/dialect.go index f32210757..de72b79a9 100644 --- a/vendor/github.com/jinzhu/gorm/dialect.go +++ b/vendor/github.com/jinzhu/gorm/dialect.go @@ -1,40 +1,116 @@ package gorm import ( + "database/sql" "fmt" "reflect" + "strconv" + "strings" ) +// Dialect interface contains behaviors that differ across SQL database type Dialect interface { - BinVar(i int) string - SupportLastInsertId() bool - HasTop() bool - SqlTag(value reflect.Value, size int, autoIncrease bool) string - ReturningStr(tableName, key string) string - SelectFromDummyTable() string + // GetName get dialect's name + GetName() string + + // SetDB set db for dialect + SetDB(db *sql.DB) + + // BindVar return the placeholder for actual values in SQL statements, in many dbs it is "?", Postgres using $1 + BindVar(i int) string + // Quote quotes field name to avoid SQL parsing exceptions by using a reserved word as a field name Quote(key string) string - HasTable(scope *Scope, tableName string) bool - HasColumn(scope *Scope, tableName string, columnName string) bool - HasIndex(scope *Scope, tableName string, indexName string) bool - RemoveIndex(scope *Scope, indexName string) + // DataTypeOf return data's sql type + DataTypeOf(field *StructField) string + + // HasIndex check has index or not + HasIndex(tableName string, indexName string) bool + // HasForeignKey check has foreign key or not + HasForeignKey(tableName string, foreignKeyName string) bool + // RemoveIndex remove index + RemoveIndex(tableName string, indexName string) error + // HasTable check has table or not + HasTable(tableName string) bool + // HasColumn check has column or not + HasColumn(tableName string, columnName string) bool + + // LimitAndOffsetSQL return generated SQL with Limit and Offset, as mssql has special case + LimitAndOffsetSQL(limit, offset interface{}) string + // SelectFromDummyTable return select values, for most dbs, `SELECT values` just works, mysql needs `SELECT value FROM DUAL` + SelectFromDummyTable() string + // LastInsertIdReturningSuffix most dbs support LastInsertId, but postgres needs to use `RETURNING` + LastInsertIDReturningSuffix(tableName, columnName string) string + + // BuildForeignKeyName returns a foreign key name for the given table, field and reference + BuildForeignKeyName(tableName, field, dest string) string + + // CurrentDatabase return current database name + CurrentDatabase() string +} + +var dialectsMap = map[string]Dialect{} + +func newDialect(name string, db *sql.DB) Dialect { + if value, ok := dialectsMap[name]; ok { + dialect := reflect.New(reflect.TypeOf(value).Elem()).Interface().(Dialect) + dialect.SetDB(db) + return dialect + } + + fmt.Printf("`%v` is not officially supported, running under compatibility mode.\n", name) + commontDialect := &commonDialect{} + commontDialect.SetDB(db) + return commontDialect } -func NewDialect(driver string) Dialect { - var d Dialect - switch driver { - case "postgres": - d = &postgres{} - case "foundation": - d = &foundation{} - case "mysql": - d = &mysql{} - case "sqlite3": - d = &sqlite3{} - case "mssql": - d = &mssql{} - default: - fmt.Printf("`%v` is not officially supported, running under compatibility mode.\n", driver) - d = &commonDialect{} +// RegisterDialect register new dialect +func RegisterDialect(name string, dialect Dialect) { + dialectsMap[name] = dialect +} + +// ParseFieldStructForDialect get field's sql data type +var ParseFieldStructForDialect = func(field *StructField, dialect Dialect) (fieldValue reflect.Value, sqlType string, size int, additionalType string) { + // Get redirected field type + var ( + reflectType = field.Struct.Type + dataType = field.TagSettings["TYPE"] + ) + + for reflectType.Kind() == reflect.Ptr { + reflectType = reflectType.Elem() } - return d + + // Get redirected field value + fieldValue = reflect.Indirect(reflect.New(reflectType)) + + if gormDataType, ok := fieldValue.Interface().(interface { + GormDataType(Dialect) string + }); ok { + dataType = gormDataType.GormDataType(dialect) + } + + // Get scanner's real value + var getScannerValue func(reflect.Value) + getScannerValue = func(value reflect.Value) { + fieldValue = value + if _, isScanner := reflect.New(fieldValue.Type()).Interface().(sql.Scanner); isScanner && fieldValue.Kind() == reflect.Struct { + getScannerValue(fieldValue.Field(0)) + } + } + getScannerValue(fieldValue) + + // Default Size + if num, ok := field.TagSettings["SIZE"]; ok { + size, _ = strconv.Atoi(num) + } else { + size = 255 + } + + // Default type from tag setting + additionalType = field.TagSettings["NOT NULL"] + " " + field.TagSettings["UNIQUE"] + if value, ok := field.TagSettings["DEFAULT"]; ok { + additionalType = additionalType + " DEFAULT " + value + } + + return fieldValue, dataType, size, strings.TrimSpace(additionalType) } diff --git a/vendor/github.com/jinzhu/gorm/dialect_common.go b/vendor/github.com/jinzhu/gorm/dialect_common.go new file mode 100644 index 000000000..601afd4cf --- /dev/null +++ b/vendor/github.com/jinzhu/gorm/dialect_common.go @@ -0,0 +1,152 @@ +package gorm + +import ( + "database/sql" + "fmt" + "reflect" + "regexp" + "strconv" + "strings" + "time" +) + +// DefaultForeignKeyNamer contains the default foreign key name generator method +type DefaultForeignKeyNamer struct { +} + +type commonDialect struct { + db *sql.DB + DefaultForeignKeyNamer +} + +func init() { + RegisterDialect("common", &commonDialect{}) +} + +func (commonDialect) GetName() string { + return "common" +} + +func (s *commonDialect) SetDB(db *sql.DB) { + s.db = db +} + +func (commonDialect) BindVar(i int) string { + return "$$" // ? +} + +func (commonDialect) Quote(key string) string { + return fmt.Sprintf(`"%s"`, key) +} + +func (s *commonDialect) DataTypeOf(field *StructField) string { + var dataValue, sqlType, size, additionalType = ParseFieldStructForDialect(field, s) + + if sqlType == "" { + switch dataValue.Kind() { + case reflect.Bool: + sqlType = "BOOLEAN" + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok { + sqlType = "INTEGER AUTO_INCREMENT" + } else { + sqlType = "INTEGER" + } + case reflect.Int64, reflect.Uint64: + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok { + sqlType = "BIGINT AUTO_INCREMENT" + } else { + sqlType = "BIGINT" + } + case reflect.Float32, reflect.Float64: + sqlType = "FLOAT" + case reflect.String: + if size > 0 && size < 65532 { + sqlType = fmt.Sprintf("VARCHAR(%d)", size) + } else { + sqlType = "VARCHAR(65532)" + } + case reflect.Struct: + if _, ok := dataValue.Interface().(time.Time); ok { + sqlType = "TIMESTAMP" + } + default: + if _, ok := dataValue.Interface().([]byte); ok { + if size > 0 && size < 65532 { + sqlType = fmt.Sprintf("BINARY(%d)", size) + } else { + sqlType = "BINARY(65532)" + } + } + } + } + + if sqlType == "" { + panic(fmt.Sprintf("invalid sql type %s (%s) for commonDialect", dataValue.Type().Name(), dataValue.Kind().String())) + } + + if strings.TrimSpace(additionalType) == "" { + return sqlType + } + return fmt.Sprintf("%v %v", sqlType, additionalType) +} + +func (s commonDialect) HasIndex(tableName string, indexName string) bool { + var count int + s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema = ? AND table_name = ? AND index_name = ?", s.CurrentDatabase(), tableName, indexName).Scan(&count) + return count > 0 +} + +func (s commonDialect) RemoveIndex(tableName string, indexName string) error { + _, err := s.db.Exec(fmt.Sprintf("DROP INDEX %v", indexName)) + return err +} + +func (s commonDialect) HasForeignKey(tableName string, foreignKeyName string) bool { + return false +} + +func (s commonDialect) HasTable(tableName string) bool { + var count int + s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = ? AND table_name = ?", s.CurrentDatabase(), tableName).Scan(&count) + return count > 0 +} + +func (s commonDialect) HasColumn(tableName string, columnName string) bool { + var count int + s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = ? AND table_name = ? AND column_name = ?", s.CurrentDatabase(), tableName, columnName).Scan(&count) + return count > 0 +} + +func (s commonDialect) CurrentDatabase() (name string) { + s.db.QueryRow("SELECT DATABASE()").Scan(&name) + return +} + +func (commonDialect) LimitAndOffsetSQL(limit, offset interface{}) (sql string) { + if limit != nil { + if parsedLimit, err := strconv.ParseInt(fmt.Sprint(limit), 0, 0); err == nil && parsedLimit > 0 { + sql += fmt.Sprintf(" LIMIT %d", parsedLimit) + } + } + if offset != nil { + if parsedOffset, err := strconv.ParseInt(fmt.Sprint(offset), 0, 0); err == nil && parsedOffset > 0 { + sql += fmt.Sprintf(" OFFSET %d", parsedOffset) + } + } + return +} + +func (commonDialect) SelectFromDummyTable() string { + return "" +} + +func (commonDialect) LastInsertIDReturningSuffix(tableName, columnName string) string { + return "" +} + +func (DefaultForeignKeyNamer) BuildForeignKeyName(tableName, field, dest string) string { + keyName := fmt.Sprintf("%s_%s_%s_foreign", tableName, field, dest) + keyName = regexp.MustCompile("(_*[^a-zA-Z]+_*|_+)").ReplaceAllString(keyName, "_") + return keyName +} diff --git a/vendor/github.com/jinzhu/gorm/dialect_mysql.go b/vendor/github.com/jinzhu/gorm/dialect_mysql.go new file mode 100644 index 000000000..b471a1624 --- /dev/null +++ b/vendor/github.com/jinzhu/gorm/dialect_mysql.go @@ -0,0 +1,146 @@ +package gorm + +import ( + "crypto/sha1" + "fmt" + "reflect" + "regexp" + "strings" + "time" + "unicode/utf8" +) + +type mysql struct { + commonDialect +} + +func init() { + RegisterDialect("mysql", &mysql{}) +} + +func (mysql) GetName() string { + return "mysql" +} + +func (mysql) Quote(key string) string { + return fmt.Sprintf("`%s`", key) +} + +// Get Data Type for MySQL Dialect +func (s *mysql) DataTypeOf(field *StructField) string { + var dataValue, sqlType, size, additionalType = ParseFieldStructForDialect(field, s) + + // MySQL allows only one auto increment column per table, and it must + // be a KEY column. + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok { + if _, ok = field.TagSettings["INDEX"]; !ok && !field.IsPrimaryKey { + delete(field.TagSettings, "AUTO_INCREMENT") + } + } + + if sqlType == "" { + switch dataValue.Kind() { + case reflect.Bool: + sqlType = "boolean" + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok || field.IsPrimaryKey { + field.TagSettings["AUTO_INCREMENT"] = "AUTO_INCREMENT" + sqlType = "int AUTO_INCREMENT" + } else { + sqlType = "int" + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok || field.IsPrimaryKey { + field.TagSettings["AUTO_INCREMENT"] = "AUTO_INCREMENT" + sqlType = "int unsigned AUTO_INCREMENT" + } else { + sqlType = "int unsigned" + } + case reflect.Int64: + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok || field.IsPrimaryKey { + field.TagSettings["AUTO_INCREMENT"] = "AUTO_INCREMENT" + sqlType = "bigint AUTO_INCREMENT" + } else { + sqlType = "bigint" + } + case reflect.Uint64: + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok || field.IsPrimaryKey { + field.TagSettings["AUTO_INCREMENT"] = "AUTO_INCREMENT" + sqlType = "bigint unsigned AUTO_INCREMENT" + } else { + sqlType = "bigint unsigned" + } + case reflect.Float32, reflect.Float64: + sqlType = "double" + case reflect.String: + if size > 0 && size < 65532 { + sqlType = fmt.Sprintf("varchar(%d)", size) + } else { + sqlType = "longtext" + } + case reflect.Struct: + if _, ok := dataValue.Interface().(time.Time); ok { + if _, ok := field.TagSettings["NOT NULL"]; ok { + sqlType = "timestamp" + } else { + sqlType = "timestamp NULL" + } + } + default: + if _, ok := dataValue.Interface().([]byte); ok { + if size > 0 && size < 65532 { + sqlType = fmt.Sprintf("varbinary(%d)", size) + } else { + sqlType = "longblob" + } + } + } + } + + if sqlType == "" { + panic(fmt.Sprintf("invalid sql type %s (%s) for mysql", dataValue.Type().Name(), dataValue.Kind().String())) + } + + if strings.TrimSpace(additionalType) == "" { + return sqlType + } + return fmt.Sprintf("%v %v", sqlType, additionalType) +} + +func (s mysql) RemoveIndex(tableName string, indexName string) error { + _, err := s.db.Exec(fmt.Sprintf("DROP INDEX %v ON %v", indexName, s.Quote(tableName))) + return err +} + +func (s mysql) HasForeignKey(tableName string, foreignKeyName string) bool { + var count int + s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA=? AND TABLE_NAME=? AND CONSTRAINT_NAME=? AND CONSTRAINT_TYPE='FOREIGN KEY'", s.CurrentDatabase(), tableName, foreignKeyName).Scan(&count) + return count > 0 +} + +func (s mysql) CurrentDatabase() (name string) { + s.db.QueryRow("SELECT DATABASE()").Scan(&name) + return +} + +func (mysql) SelectFromDummyTable() string { + return "FROM DUAL" +} + +func (s mysql) BuildForeignKeyName(tableName, field, dest string) string { + keyName := s.commonDialect.BuildForeignKeyName(tableName, field, dest) + if utf8.RuneCountInString(keyName) <= 64 { + return keyName + } + h := sha1.New() + h.Write([]byte(keyName)) + bs := h.Sum(nil) + + // sha1 is 40 digits, keep first 24 characters of destination + destRunes := []rune(regexp.MustCompile("(_*[^a-zA-Z]+_*|_+)").ReplaceAllString(dest, "_")) + if len(destRunes) > 24 { + destRunes = destRunes[:24] + } + + return fmt.Sprintf("%s%x", string(destRunes), bs) +} diff --git a/vendor/github.com/jinzhu/gorm/dialect_postgres.go b/vendor/github.com/jinzhu/gorm/dialect_postgres.go new file mode 100644 index 000000000..7d07a02c3 --- /dev/null +++ b/vendor/github.com/jinzhu/gorm/dialect_postgres.go @@ -0,0 +1,134 @@ +package gorm + +import ( + "fmt" + "reflect" + "strings" + "time" +) + +type postgres struct { + commonDialect +} + +func init() { + RegisterDialect("postgres", &postgres{}) +} + +func (postgres) GetName() string { + return "postgres" +} + +func (postgres) BindVar(i int) string { + return fmt.Sprintf("$%v", i) +} + +func (s *postgres) DataTypeOf(field *StructField) string { + var dataValue, sqlType, size, additionalType = ParseFieldStructForDialect(field, s) + + if sqlType == "" { + switch dataValue.Kind() { + case reflect.Bool: + sqlType = "boolean" + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok || field.IsPrimaryKey { + field.TagSettings["AUTO_INCREMENT"] = "AUTO_INCREMENT" + sqlType = "serial" + } else { + sqlType = "integer" + } + case reflect.Int64, reflect.Uint64: + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok || field.IsPrimaryKey { + field.TagSettings["AUTO_INCREMENT"] = "AUTO_INCREMENT" + sqlType = "bigserial" + } else { + sqlType = "bigint" + } + case reflect.Float32, reflect.Float64: + sqlType = "numeric" + case reflect.String: + if _, ok := field.TagSettings["SIZE"]; !ok { + size = 0 // if SIZE haven't been set, use `text` as the default type, as there are no performance different + } + + if size > 0 && size < 65532 { + sqlType = fmt.Sprintf("varchar(%d)", size) + } else { + sqlType = "text" + } + case reflect.Struct: + if _, ok := dataValue.Interface().(time.Time); ok { + sqlType = "timestamp with time zone" + } + case reflect.Map: + if dataValue.Type().Name() == "Hstore" { + sqlType = "hstore" + } + default: + if isByteArrayOrSlice(dataValue) { + sqlType = "bytea" + } else if isUUID(dataValue) { + sqlType = "uuid" + } + } + } + + if sqlType == "" { + panic(fmt.Sprintf("invalid sql type %s (%s) for postgres", dataValue.Type().Name(), dataValue.Kind().String())) + } + + if strings.TrimSpace(additionalType) == "" { + return sqlType + } + return fmt.Sprintf("%v %v", sqlType, additionalType) +} + +func (s postgres) HasIndex(tableName string, indexName string) bool { + var count int + s.db.QueryRow("SELECT count(*) FROM pg_indexes WHERE tablename = $1 AND indexname = $2", tableName, indexName).Scan(&count) + return count > 0 +} + +func (s postgres) HasForeignKey(tableName string, foreignKeyName string) bool { + var count int + s.db.QueryRow("SELECT count(con.conname) FROM pg_constraint con WHERE $1::regclass::oid = con.conrelid AND con.conname = $2 AND con.contype='f'", tableName, foreignKeyName).Scan(&count) + return count > 0 +} + +func (s postgres) HasTable(tableName string) bool { + var count int + s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.tables WHERE table_name = $1 AND table_type = 'BASE TABLE'", tableName).Scan(&count) + return count > 0 +} + +func (s postgres) HasColumn(tableName string, columnName string) bool { + var count int + s.db.QueryRow("SELECT count(*) FROM INFORMATION_SCHEMA.columns WHERE table_name = $1 AND column_name = $2", tableName, columnName).Scan(&count) + return count > 0 +} + +func (s postgres) CurrentDatabase() (name string) { + s.db.QueryRow("SELECT CURRENT_DATABASE()").Scan(&name) + return +} + +func (s postgres) LastInsertIDReturningSuffix(tableName, key string) string { + return fmt.Sprintf("RETURNING %v.%v", tableName, key) +} + +func (postgres) SupportLastInsertID() bool { + return false +} + +func isByteArrayOrSlice(value reflect.Value) bool { + return (value.Kind() == reflect.Array || value.Kind() == reflect.Slice) && value.Type().Elem() == reflect.TypeOf(uint8(0)) +} + +func isUUID(value reflect.Value) bool { + if value.Kind() != reflect.Array || value.Type().Len() != 16 { + return false + } + typename := value.Type().Name() + lower := strings.ToLower(typename) + return "uuid" == lower || "guid" == lower +} diff --git a/vendor/github.com/jinzhu/gorm/dialect_sqlite3.go b/vendor/github.com/jinzhu/gorm/dialect_sqlite3.go new file mode 100644 index 000000000..33f4aa50b --- /dev/null +++ b/vendor/github.com/jinzhu/gorm/dialect_sqlite3.go @@ -0,0 +1,108 @@ +package gorm + +import ( + "fmt" + "reflect" + "strings" + "time" +) + +type sqlite3 struct { + commonDialect +} + +func init() { + RegisterDialect("sqlite", &sqlite3{}) + RegisterDialect("sqlite3", &sqlite3{}) +} + +func (sqlite3) GetName() string { + return "sqlite3" +} + +// Get Data Type for Sqlite Dialect +func (s *sqlite3) DataTypeOf(field *StructField) string { + var dataValue, sqlType, size, additionalType = ParseFieldStructForDialect(field, s) + + if sqlType == "" { + switch dataValue.Kind() { + case reflect.Bool: + sqlType = "bool" + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: + if field.IsPrimaryKey { + field.TagSettings["AUTO_INCREMENT"] = "AUTO_INCREMENT" + sqlType = "integer primary key autoincrement" + } else { + sqlType = "integer" + } + case reflect.Int64, reflect.Uint64: + if field.IsPrimaryKey { + field.TagSettings["AUTO_INCREMENT"] = "AUTO_INCREMENT" + sqlType = "integer primary key autoincrement" + } else { + sqlType = "bigint" + } + case reflect.Float32, reflect.Float64: + sqlType = "real" + case reflect.String: + if size > 0 && size < 65532 { + sqlType = fmt.Sprintf("varchar(%d)", size) + } else { + sqlType = "text" + } + case reflect.Struct: + if _, ok := dataValue.Interface().(time.Time); ok { + sqlType = "datetime" + } + default: + if _, ok := dataValue.Interface().([]byte); ok { + sqlType = "blob" + } + } + } + + if sqlType == "" { + panic(fmt.Sprintf("invalid sql type %s (%s) for sqlite3", dataValue.Type().Name(), dataValue.Kind().String())) + } + + if strings.TrimSpace(additionalType) == "" { + return sqlType + } + return fmt.Sprintf("%v %v", sqlType, additionalType) +} + +func (s sqlite3) HasIndex(tableName string, indexName string) bool { + var count int + s.db.QueryRow(fmt.Sprintf("SELECT count(*) FROM sqlite_master WHERE tbl_name = ? AND sql LIKE '%%INDEX %v ON%%'", indexName), tableName).Scan(&count) + return count > 0 +} + +func (s sqlite3) HasTable(tableName string) bool { + var count int + s.db.QueryRow("SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?", tableName).Scan(&count) + return count > 0 +} + +func (s sqlite3) HasColumn(tableName string, columnName string) bool { + var count int + s.db.QueryRow(fmt.Sprintf("SELECT count(*) FROM sqlite_master WHERE tbl_name = ? AND (sql LIKE '%%\"%v\" %%' OR sql LIKE '%%%v %%');\n", columnName, columnName), tableName).Scan(&count) + return count > 0 +} + +func (s sqlite3) CurrentDatabase() (name string) { + var ( + ifaces = make([]interface{}, 3) + pointers = make([]*string, 3) + i int + ) + for i = 0; i < 3; i++ { + ifaces[i] = &pointers[i] + } + if err := s.db.QueryRow("PRAGMA database_list").Scan(ifaces...); err != nil { + return + } + if pointers[1] != nil { + name = *pointers[1] + } + return +} diff --git a/vendor/github.com/jinzhu/gorm/errors.go b/vendor/github.com/jinzhu/gorm/errors.go index 470c97d59..832fa9b00 100644 --- a/vendor/github.com/jinzhu/gorm/errors.go +++ b/vendor/github.com/jinzhu/gorm/errors.go @@ -1,11 +1,56 @@ package gorm -import "errors" +import ( + "errors" + "strings" +) var ( - RecordNotFound = errors.New("record not found") - InvalidSql = errors.New("invalid sql") - NoNewAttrs = errors.New("no new attributes") - NoValidTransaction = errors.New("no valid transaction") - CantStartTransaction = errors.New("can't start transaction") + // ErrRecordNotFound record not found error, happens when haven't find any matched data when looking up with a struct + ErrRecordNotFound = errors.New("record not found") + // ErrInvalidSQL invalid SQL error, happens when you passed invalid SQL + ErrInvalidSQL = errors.New("invalid SQL") + // ErrInvalidTransaction invalid transaction when you are trying to `Commit` or `Rollback` + ErrInvalidTransaction = errors.New("no valid transaction") + // ErrCantStartTransaction can't start transaction when you are trying to start one with `Begin` + ErrCantStartTransaction = errors.New("can't start transaction") + // ErrUnaddressable unaddressable value + ErrUnaddressable = errors.New("using unaddressable value") ) + +// Errors contains all happened errors +type Errors []error + +// GetErrors gets all happened errors +func (errs Errors) GetErrors() []error { + return errs +} + +// Add adds an error +func (errs Errors) Add(newErrors ...error) Errors { + for _, err := range newErrors { + if errors, ok := err.(Errors); ok { + errs = errs.Add(errors...) + } else { + ok = true + for _, e := range errs { + if err == e { + ok = false + } + } + if ok { + errs = append(errs, err) + } + } + } + return errs +} + +// Error format happened errors +func (errs Errors) Error() string { + var errors = []string{} + for _, e := range errs { + errors = append(errors, e.Error()) + } + return strings.Join(errors, "; ") +} diff --git a/vendor/github.com/jinzhu/gorm/field.go b/vendor/github.com/jinzhu/gorm/field.go index 8f5efa6de..11c410b0f 100644 --- a/vendor/github.com/jinzhu/gorm/field.go +++ b/vendor/github.com/jinzhu/gorm/field.go @@ -3,82 +3,56 @@ package gorm import ( "database/sql" "errors" + "fmt" "reflect" ) +// Field model field definition type Field struct { *StructField IsBlank bool Field reflect.Value } -func (field *Field) Set(value interface{}) error { +// Set set a value to the field +func (field *Field) Set(value interface{}) (err error) { if !field.Field.IsValid() { return errors.New("field value not valid") } if !field.Field.CanAddr() { - return errors.New("unaddressable value") + return ErrUnaddressable } - if rvalue, ok := value.(reflect.Value); ok { - value = rvalue.Interface() + reflectValue, ok := value.(reflect.Value) + if !ok { + reflectValue = reflect.ValueOf(value) } - if scanner, ok := field.Field.Addr().Interface().(sql.Scanner); ok { - if v, ok := value.(reflect.Value); ok { - if err := scanner.Scan(v.Interface()); err != nil { - return err - } + fieldValue := field.Field + if reflectValue.IsValid() { + if reflectValue.Type().ConvertibleTo(fieldValue.Type()) { + fieldValue.Set(reflectValue.Convert(fieldValue.Type())) } else { - if err := scanner.Scan(value); err != nil { - return err + if fieldValue.Kind() == reflect.Ptr { + if fieldValue.IsNil() { + fieldValue.Set(reflect.New(field.Struct.Type.Elem())) + } + fieldValue = fieldValue.Elem() } - } - } else { - reflectValue, ok := value.(reflect.Value) - if !ok { - reflectValue = reflect.ValueOf(value) - } - if reflectValue.Type().ConvertibleTo(field.Field.Type()) { - field.Field.Set(reflectValue.Convert(field.Field.Type())) - } else { - return errors.New("could not convert argument") - } - } - - field.IsBlank = isBlank(field.Field) - return nil -} - -// Fields get value's fields -func (scope *Scope) Fields() map[string]*Field { - if scope.fields == nil { - fields := map[string]*Field{} - structFields := scope.GetStructFields() - - indirectValue := scope.IndirectValue() - isStruct := indirectValue.Kind() == reflect.Struct - for _, structField := range structFields { - if isStruct { - fields[structField.DBName] = getField(indirectValue, structField) + if reflectValue.Type().ConvertibleTo(fieldValue.Type()) { + fieldValue.Set(reflectValue.Convert(fieldValue.Type())) + } else if scanner, ok := fieldValue.Addr().Interface().(sql.Scanner); ok { + err = scanner.Scan(reflectValue.Interface()) } else { - fields[structField.DBName] = &Field{StructField: structField, IsBlank: true} + err = fmt.Errorf("could not convert argument of field %s from %s to %s", field.Name, reflectValue.Type(), fieldValue.Type()) } } - - scope.fields = fields + } else { + field.Field.Set(reflect.Zero(field.Field.Type())) } - return scope.fields -} -func getField(indirectValue reflect.Value, structField *StructField) *Field { - field := &Field{StructField: structField} - for _, name := range structField.Names { - indirectValue = reflect.Indirect(indirectValue).FieldByName(name) - } - field.Field = indirectValue - field.IsBlank = isBlank(indirectValue) - return field + field.IsBlank = isBlank(field.Field) + return err } diff --git a/vendor/github.com/jinzhu/gorm/foundation.go b/vendor/github.com/jinzhu/gorm/foundation.go deleted file mode 100644 index a9c8f5000..000000000 --- a/vendor/github.com/jinzhu/gorm/foundation.go +++ /dev/null @@ -1,78 +0,0 @@ -package gorm - -import ( - "fmt" - "reflect" - "time" -) - -type foundation struct { - commonDialect -} - -func (foundation) BinVar(i int) string { - return fmt.Sprintf("$%v", i) -} - -func (foundation) SupportLastInsertId() bool { - return false -} - -func (foundation) SqlTag(value reflect.Value, size int, autoIncrease bool) string { - switch value.Kind() { - case reflect.Bool: - return "boolean" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: - if autoIncrease { - return "serial" - } - return "int" - case reflect.Int64, reflect.Uint64: - if autoIncrease { - return "bigserial" - } - return "bigint" - case reflect.Float32, reflect.Float64: - return "double" - case reflect.String: - if size > 0 && size < 65532 { - return fmt.Sprintf("varchar(%d)", size) - } - return "clob" - case reflect.Struct: - if _, ok := value.Interface().(time.Time); ok { - return "datetime" - } - default: - if _, ok := value.Interface().([]byte); ok { - return "blob" - } - } - panic(fmt.Sprintf("invalid sql type %s (%s) for foundation", value.Type().Name(), value.Kind().String())) -} - -func (f foundation) ReturningStr(tableName, key string) string { - return fmt.Sprintf("RETURNING %v.%v", f.Quote(tableName), key) -} - -func (foundation) HasTable(scope *Scope, tableName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM INFORMATION_SCHEMA.tables WHERE table_schema = current_schema AND table_type = 'TABLE' AND table_name = ?", tableName).Row().Scan(&count) - return count > 0 -} - -func (foundation) HasColumn(scope *Scope, tableName string, columnName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM INFORMATION_SCHEMA.columns WHERE table_schema = current_schema AND table_name = ? AND column_name = ?", tableName, columnName).Row().Scan(&count) - return count > 0 -} - -func (f foundation) RemoveIndex(scope *Scope, indexName string) { - scope.NewDB().Exec(fmt.Sprintf("DROP INDEX %v", f.Quote(indexName))) -} - -func (foundation) HasIndex(scope *Scope, tableName string, indexName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM INFORMATION_SCHEMA.indexes WHERE table_schema = current_schema AND table_name = ? AND index_name = ?", tableName, indexName).Row().Scan(&count) - return count > 0 -} diff --git a/vendor/github.com/jinzhu/gorm/join_table_handler.go b/vendor/github.com/jinzhu/gorm/join_table_handler.go index 07ecee2e6..18c12a859 100644 --- a/vendor/github.com/jinzhu/gorm/join_table_handler.go +++ b/vendor/github.com/jinzhu/gorm/join_table_handler.go @@ -7,88 +7,80 @@ import ( "strings" ) +// JoinTableHandlerInterface is an interface for how to handle many2many relations type JoinTableHandlerInterface interface { + // initialize join table handler Setup(relationship *Relationship, tableName string, source reflect.Type, destination reflect.Type) + // Table return join table's table name Table(db *DB) string + // Add create relationship in join table for source and destination Add(handler JoinTableHandlerInterface, db *DB, source interface{}, destination interface{}) error + // Delete delete relationship in join table for sources Delete(handler JoinTableHandlerInterface, db *DB, sources ...interface{}) error + // JoinWith query with `Join` conditions JoinWith(handler JoinTableHandlerInterface, db *DB, source interface{}) *DB + // SourceForeignKeys return source foreign keys SourceForeignKeys() []JoinTableForeignKey + // DestinationForeignKeys return destination foreign keys DestinationForeignKeys() []JoinTableForeignKey } +// JoinTableForeignKey join table foreign key struct type JoinTableForeignKey struct { DBName string AssociationDBName string } +// JoinTableSource is a struct that contains model type and foreign keys type JoinTableSource struct { ModelType reflect.Type ForeignKeys []JoinTableForeignKey } +// JoinTableHandler default join table handler type JoinTableHandler struct { TableName string `sql:"-"` Source JoinTableSource `sql:"-"` Destination JoinTableSource `sql:"-"` } +// SourceForeignKeys return source foreign keys func (s *JoinTableHandler) SourceForeignKeys() []JoinTableForeignKey { return s.Source.ForeignKeys } +// DestinationForeignKeys return destination foreign keys func (s *JoinTableHandler) DestinationForeignKeys() []JoinTableForeignKey { return s.Destination.ForeignKeys } +// Setup initialize a default join table handler func (s *JoinTableHandler) Setup(relationship *Relationship, tableName string, source reflect.Type, destination reflect.Type) { s.TableName = tableName s.Source = JoinTableSource{ModelType: source} - sourceScope := &Scope{Value: reflect.New(source).Interface()} - sourcePrimaryFields := sourceScope.GetModelStruct().PrimaryFields - for _, primaryField := range sourcePrimaryFields { - if relationship.ForeignDBName == "" { - relationship.ForeignFieldName = source.Name() + primaryField.Name - relationship.ForeignDBName = ToDBName(relationship.ForeignFieldName) - } - - var dbName string - if len(sourcePrimaryFields) == 1 || primaryField.DBName == "id" { - dbName = relationship.ForeignDBName - } else { - dbName = ToDBName(source.Name() + primaryField.Name) - } - + for idx, dbName := range relationship.ForeignFieldNames { s.Source.ForeignKeys = append(s.Source.ForeignKeys, JoinTableForeignKey{ - DBName: dbName, - AssociationDBName: primaryField.DBName, + DBName: relationship.ForeignDBNames[idx], + AssociationDBName: dbName, }) } s.Destination = JoinTableSource{ModelType: destination} - destinationScope := &Scope{Value: reflect.New(destination).Interface()} - destinationPrimaryFields := destinationScope.GetModelStruct().PrimaryFields - for _, primaryField := range destinationPrimaryFields { - var dbName string - if len(sourcePrimaryFields) == 1 || primaryField.DBName == "id" { - dbName = relationship.AssociationForeignDBName - } else { - dbName = ToDBName(destinationScope.GetModelStruct().ModelType.Name() + primaryField.Name) - } - + for idx, dbName := range relationship.AssociationForeignFieldNames { s.Destination.ForeignKeys = append(s.Destination.ForeignKeys, JoinTableForeignKey{ - DBName: dbName, - AssociationDBName: primaryField.DBName, + DBName: relationship.AssociationForeignDBNames[idx], + AssociationDBName: dbName, }) } } +// Table return join table's table name func (s JoinTableHandler) Table(db *DB) string { return s.TableName } -func (s JoinTableHandler) GetSearchMap(db *DB, sources ...interface{}) map[string]interface{} { +func (s JoinTableHandler) getSearchMap(db *DB, sources ...interface{}) map[string]interface{} { values := map[string]interface{}{} for _, source := range sources { @@ -97,25 +89,30 @@ func (s JoinTableHandler) GetSearchMap(db *DB, sources ...interface{}) map[strin if s.Source.ModelType == modelType { for _, foreignKey := range s.Source.ForeignKeys { - values[foreignKey.DBName] = scope.Fields()[foreignKey.AssociationDBName].Field.Interface() + if field, ok := scope.FieldByName(foreignKey.AssociationDBName); ok { + values[foreignKey.DBName] = field.Field.Interface() + } } } else if s.Destination.ModelType == modelType { for _, foreignKey := range s.Destination.ForeignKeys { - values[foreignKey.DBName] = scope.Fields()[foreignKey.AssociationDBName].Field.Interface() + if field, ok := scope.FieldByName(foreignKey.AssociationDBName); ok { + values[foreignKey.DBName] = field.Field.Interface() + } } } } return values } -func (s JoinTableHandler) Add(handler JoinTableHandlerInterface, db *DB, source1 interface{}, source2 interface{}) error { +// Add create relationship in join table for source and destination +func (s JoinTableHandler) Add(handler JoinTableHandlerInterface, db *DB, source interface{}, destination interface{}) error { scope := db.NewScope("") - searchMap := s.GetSearchMap(db, source1, source2) + searchMap := s.getSearchMap(db, source, destination) var assignColumns, binVars, conditions []string var values []interface{} for key, value := range searchMap { - assignColumns = append(assignColumns, key) + assignColumns = append(assignColumns, scope.Quote(key)) binVars = append(binVars, `?`) conditions = append(conditions, fmt.Sprintf("%v = ?", scope.Quote(key))) values = append(values, value) @@ -125,7 +122,7 @@ func (s JoinTableHandler) Add(handler JoinTableHandlerInterface, db *DB, source1 values = append(values, value) } - quotedTable := handler.Table(db) + quotedTable := scope.Quote(handler.Table(db)) sql := fmt.Sprintf( "INSERT INTO %v (%v) SELECT %v %v WHERE NOT EXISTS (SELECT * FROM %v WHERE %v)", quotedTable, @@ -139,40 +136,69 @@ func (s JoinTableHandler) Add(handler JoinTableHandlerInterface, db *DB, source1 return db.Exec(sql, values...).Error } +// Delete delete relationship in join table for sources func (s JoinTableHandler) Delete(handler JoinTableHandlerInterface, db *DB, sources ...interface{}) error { - var conditions []string - var values []interface{} + var ( + scope = db.NewScope(nil) + conditions []string + values []interface{} + ) - for key, value := range s.GetSearchMap(db, sources...) { - conditions = append(conditions, fmt.Sprintf("%v = ?", key)) + for key, value := range s.getSearchMap(db, sources...) { + conditions = append(conditions, fmt.Sprintf("%v = ?", scope.Quote(key))) values = append(values, value) } return db.Table(handler.Table(db)).Where(strings.Join(conditions, " AND "), values...).Delete("").Error } +// JoinWith query with `Join` conditions func (s JoinTableHandler) JoinWith(handler JoinTableHandlerInterface, db *DB, source interface{}) *DB { - quotedTable := handler.Table(db) + var ( + scope = db.NewScope(source) + tableName = handler.Table(db) + quotedTableName = scope.Quote(tableName) + joinConditions []string + values []interface{} + ) - scope := db.NewScope(source) - modelType := scope.GetModelStruct().ModelType - var joinConditions []string - var queryConditions []string - var values []interface{} - if s.Source.ModelType == modelType { + if s.Source.ModelType == scope.GetModelStruct().ModelType { + destinationTableName := db.NewScope(reflect.New(s.Destination.ModelType).Interface()).QuotedTableName() for _, foreignKey := range s.Destination.ForeignKeys { - destinationTableName := db.NewScope(reflect.New(s.Destination.ModelType).Interface()).QuotedTableName() - joinConditions = append(joinConditions, fmt.Sprintf("%v.%v = %v.%v", quotedTable, scope.Quote(foreignKey.DBName), destinationTableName, scope.Quote(foreignKey.AssociationDBName))) + joinConditions = append(joinConditions, fmt.Sprintf("%v.%v = %v.%v", quotedTableName, scope.Quote(foreignKey.DBName), destinationTableName, scope.Quote(foreignKey.AssociationDBName))) } + var foreignDBNames []string + var foreignFieldNames []string + for _, foreignKey := range s.Source.ForeignKeys { - queryConditions = append(queryConditions, fmt.Sprintf("%v.%v = ?", quotedTable, scope.Quote(foreignKey.DBName))) - values = append(values, scope.Fields()[foreignKey.AssociationDBName].Field.Interface()) + foreignDBNames = append(foreignDBNames, foreignKey.DBName) + if field, ok := scope.FieldByName(foreignKey.AssociationDBName); ok { + foreignFieldNames = append(foreignFieldNames, field.Name) + } + } + + foreignFieldValues := scope.getColumnAsArray(foreignFieldNames, scope.Value) + + var condString string + if len(foreignFieldValues) > 0 { + var quotedForeignDBNames []string + for _, dbName := range foreignDBNames { + quotedForeignDBNames = append(quotedForeignDBNames, tableName+"."+dbName) + } + + condString = fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, quotedForeignDBNames), toQueryMarks(foreignFieldValues)) + + keys := scope.getColumnAsArray(foreignFieldNames, scope.Value) + values = append(values, toQueryValues(keys)) + } else { + condString = fmt.Sprintf("1 <> 1") } - return db.Joins(fmt.Sprintf("INNER JOIN %v ON %v", quotedTable, strings.Join(joinConditions, " AND "))). - Where(strings.Join(queryConditions, " AND "), values...) - } else { - db.Error = errors.New("wrong source type for join table handler") - return db + + return db.Joins(fmt.Sprintf("INNER JOIN %v ON %v", quotedTableName, strings.Join(joinConditions, " AND "))). + Where(condString, toQueryValues(foreignFieldValues)...) } + + db.Error = errors.New("wrong source type for join table handler") + return db } diff --git a/vendor/github.com/jinzhu/gorm/logger.go b/vendor/github.com/jinzhu/gorm/logger.go index 907faa8e0..117b04031 100644 --- a/vendor/github.com/jinzhu/gorm/logger.go +++ b/vendor/github.com/jinzhu/gorm/logger.go @@ -8,60 +8,110 @@ import ( "reflect" "regexp" "time" + "unicode" ) -type logger interface { - Print(v ...interface{}) -} +var ( + defaultLogger = Logger{log.New(os.Stdout, "\r\n", 0)} + sqlRegexp = regexp.MustCompile(`\?`) + numericPlaceHolderRegexp = regexp.MustCompile(`\$\d+`) +) -type Logger struct { - *log.Logger +func isPrintable(s string) bool { + for _, r := range s { + if !unicode.IsPrint(r) { + return false + } + } + return true } -var defaultLogger = Logger{log.New(os.Stdout, "\r\n", 0)} - -// Format log -var sqlRegexp = regexp.MustCompile(`(\$\d+)|\?`) - -func (logger Logger) Print(values ...interface{}) { +var LogFormatter = func(values ...interface{}) (messages []interface{}) { if len(values) > 1 { - level := values[0] - currentTime := "\n\033[33m[" + NowFunc().Format("2006-01-02 15:04:05") + "]\033[0m" - source := fmt.Sprintf("\033[35m(%v)\033[0m", values[1]) - messages := []interface{}{source, currentTime} + var ( + sql string + formattedValues []string + level = values[0] + currentTime = "\n\033[33m[" + NowFunc().Format("2006-01-02 15:04:05") + "]\033[0m" + source = fmt.Sprintf("\033[35m(%v)\033[0m", values[1]) + ) + + messages = []interface{}{source, currentTime} if level == "sql" { // duration messages = append(messages, fmt.Sprintf(" \033[36;1m[%.2fms]\033[0m ", float64(values[2].(time.Duration).Nanoseconds()/1e4)/100.0)) // sql - var formatedValues []interface{} + for _, value := range values[4].([]interface{}) { indirectValue := reflect.Indirect(reflect.ValueOf(value)) if indirectValue.IsValid() { value = indirectValue.Interface() if t, ok := value.(time.Time); ok { - formatedValues = append(formatedValues, fmt.Sprintf("'%v'", t.Format(time.RFC3339))) + formattedValues = append(formattedValues, fmt.Sprintf("'%v'", t.Format("2006-01-02 15:04:05"))) } else if b, ok := value.([]byte); ok { - formatedValues = append(formatedValues, fmt.Sprintf("'%v'", string(b))) + if str := string(b); isPrintable(str) { + formattedValues = append(formattedValues, fmt.Sprintf("'%v'", str)) + } else { + formattedValues = append(formattedValues, "''") + } } else if r, ok := value.(driver.Valuer); ok { if value, err := r.Value(); err == nil && value != nil { - formatedValues = append(formatedValues, fmt.Sprintf("'%v'", value)) + formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value)) } else { - formatedValues = append(formatedValues, "NULL") + formattedValues = append(formattedValues, "NULL") } } else { - formatedValues = append(formatedValues, fmt.Sprintf("'%v'", value)) + formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value)) } } else { - formatedValues = append(formatedValues, fmt.Sprintf("'%v'", value)) + formattedValues = append(formattedValues, "NULL") } } - messages = append(messages, fmt.Sprintf(sqlRegexp.ReplaceAllString(values[3].(string), "%v"), formatedValues...)) + + // differentiate between $n placeholders or else treat like ? + if numericPlaceHolderRegexp.MatchString(values[3].(string)) { + sql = values[3].(string) + for index, value := range formattedValues { + placeholder := fmt.Sprintf(`\$%d([^\d]|$)`, index+1) + sql = regexp.MustCompile(placeholder).ReplaceAllString(sql, value+"$1") + } + } else { + formattedValuesLength := len(formattedValues) + for index, value := range sqlRegexp.Split(values[3].(string), -1) { + sql += value + if index < formattedValuesLength { + sql += formattedValues[index] + } + } + } + + messages = append(messages, sql) } else { messages = append(messages, "\033[31;1m") messages = append(messages, values[2:]...) messages = append(messages, "\033[0m") } - logger.Println(messages...) } + + return +} + +type logger interface { + Print(v ...interface{}) +} + +// LogWriter log writer interface +type LogWriter interface { + Println(v ...interface{}) +} + +// Logger default logger +type Logger struct { + LogWriter +} + +// Print format & print log +func (logger Logger) Print(values ...interface{}) { + logger.Println(LogFormatter(values...)...) } diff --git a/vendor/github.com/jinzhu/gorm/main.go b/vendor/github.com/jinzhu/gorm/main.go index aba51fc4d..9ea109092 100644 --- a/vendor/github.com/jinzhu/gorm/main.go +++ b/vendor/github.com/jinzhu/gorm/main.go @@ -9,83 +9,80 @@ import ( "time" ) -// NowFunc returns current time, this function is exported in order to be able -// to give the flexibility to the developer to customize it according to their -// needs -// -// e.g: return time.Now().UTC() -// -var NowFunc = func() time.Time { - return time.Now() -} - +// DB contains information for current db connection type DB struct { - Value interface{} - Error error - RowsAffected int64 - callback *callback + Value interface{} + Error error + RowsAffected int64 + + // single db db sqlCommon - parent *DB - search *search + blockGlobalUpdate bool logMode int logger logger - dialect Dialect - singularTable bool - source string + search *search values map[string]interface{} - joinTableHandlers map[string]JoinTableHandler -} -func Open(dialect string, args ...interface{}) (DB, error) { - var db DB - var err error + // global db + parent *DB + callbacks *Callback + dialect Dialect + singularTable bool +} +// Open initialize a new db connection, need to import driver first, e.g: +// +// import _ "github.com/go-sql-driver/mysql" +// func main() { +// db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local") +// } +// GORM has wrapped some drivers, for easier to remember driver's import path, so you could import the mysql driver with +// import _ "github.com/jinzhu/gorm/dialects/mysql" +// // import _ "github.com/jinzhu/gorm/dialects/postgres" +// // import _ "github.com/jinzhu/gorm/dialects/sqlite" +// // import _ "github.com/jinzhu/gorm/dialects/mssql" +func Open(dialect string, args ...interface{}) (db *DB, err error) { if len(args) == 0 { err = errors.New("invalid database source") - } else { - var source string - var dbSql sqlCommon - - switch value := args[0].(type) { - case string: - var driver = dialect - if len(args) == 1 { - source = value - } else if len(args) >= 2 { - driver = value - source = args[1].(string) - } - if driver == "foundation" { - driver = "postgres" // FoundationDB speaks a postgres-compatible protocol. - } - dbSql, err = sql.Open(driver, source) - case sqlCommon: - source = reflect.Indirect(reflect.ValueOf(value)).FieldByName("dsn").String() - dbSql = value - } - - db = DB{ - dialect: NewDialect(dialect), - logger: defaultLogger, - callback: DefaultCallback, - source: source, - values: map[string]interface{}{}, - db: dbSql, + return nil, err + } + var source string + var dbSQL *sql.DB + + switch value := args[0].(type) { + case string: + var driver = dialect + if len(args) == 1 { + source = value + } else if len(args) >= 2 { + driver = value + source = args[1].(string) } - db.parent = &db + dbSQL, err = sql.Open(driver, source) + case *sql.DB: + source = reflect.Indirect(reflect.ValueOf(value)).FieldByName("dsn").String() + dbSQL = value } - return db, err -} - -func (s *DB) Close() error { - return s.parent.db.(*sql.DB).Close() -} + db = &DB{ + db: dbSQL, + logger: defaultLogger, + values: map[string]interface{}{}, + callbacks: DefaultCallback, + dialect: newDialect(dialect, dbSQL), + } + db.parent = db -func (s *DB) DB() *sql.DB { - return s.db.(*sql.DB) + if err == nil { + // Send a ping to make sure the database connection is alive. + if err = db.DB().Ping(); err != nil { + db.DB().Close() + } + } + return } +// New clone a new db connection without search conditions func (s *DB) New() *DB { clone := s.clone() clone.search = nil @@ -93,29 +90,43 @@ func (s *DB) New() *DB { return clone } -// NewScope create scope for callbacks, including DB's search information -func (db *DB) NewScope(value interface{}) *Scope { - dbClone := db.clone() - dbClone.Value = value - return &Scope{db: dbClone, Search: dbClone.search.clone(), Value: value} +// Close close current db connection +func (s *DB) Close() error { + if db, ok := s.parent.db.(*sql.DB); ok { + return db.Close() + } + return errors.New("can't close current db") +} + +// DB get `*sql.DB` from current connection +func (s *DB) DB() *sql.DB { + return s.db.(*sql.DB) } -// CommonDB Return the underlying sql.DB or sql.Tx instance. -// Use of this method is discouraged. It's mainly intended to allow -// coexistence with legacy non-GORM code. +// CommonDB return the underlying `*sql.DB` or `*sql.Tx` instance, mainly intended to allow coexistence with legacy non-GORM code. func (s *DB) CommonDB() sqlCommon { return s.db } -func (s *DB) Callback() *callback { - s.parent.callback = s.parent.callback.clone() - return s.parent.callback +// Dialect get dialect +func (s *DB) Dialect() Dialect { + return s.parent.dialect +} + +// Callback return `Callbacks` container, you could add/change/delete callbacks with it +// db.Callback().Create().Register("update_created_at", updateCreated) +// Refer https://jinzhu.github.io/gorm/development.html#callbacks +func (s *DB) Callback() *Callback { + s.parent.callbacks = s.parent.callbacks.clone() + return s.parent.callbacks } -func (s *DB) SetLogger(l logger) { - s.parent.logger = l +// SetLogger replace default logger +func (s *DB) SetLogger(log logger) { + s.logger = log } +// LogMode set log mode, `true` for detailed logs, `false` for no log, default, will only print error logs func (s *DB) LogMode(enable bool) *DB { if enable { s.logMode = 2 @@ -125,55 +136,104 @@ func (s *DB) LogMode(enable bool) *DB { return s } +// BlockGlobalUpdate if true, generates an error on update/delete without where clause. +// This is to prevent eventual error with empty objects updates/deletions +func (s *DB) BlockGlobalUpdate(enable bool) *DB { + s.blockGlobalUpdate = enable + return s +} + +// HasBlockGlobalUpdate return state of block +func (s *DB) HasBlockGlobalUpdate() bool { + return s.blockGlobalUpdate +} + +// SingularTable use singular table by default func (s *DB) SingularTable(enable bool) { - modelStructs = map[reflect.Type]*ModelStruct{} + modelStructsMap = newModelStructsMap() s.parent.singularTable = enable } +// NewScope create a scope for current operation +func (s *DB) NewScope(value interface{}) *Scope { + dbClone := s.clone() + dbClone.Value = value + return &Scope{db: dbClone, Search: dbClone.search.clone(), Value: value} +} + +// Where return a new relation, filter records with given conditions, accepts `map`, `struct` or `string` as conditions, refer http://jinzhu.github.io/gorm/crud.html#query func (s *DB) Where(query interface{}, args ...interface{}) *DB { return s.clone().search.Where(query, args...).db } +// Or filter records that match before conditions or this one, similar to `Where` func (s *DB) Or(query interface{}, args ...interface{}) *DB { return s.clone().search.Or(query, args...).db } +// Not filter records that don't match current conditions, similar to `Where` func (s *DB) Not(query interface{}, args ...interface{}) *DB { return s.clone().search.Not(query, args...).db } -func (s *DB) Limit(value interface{}) *DB { - return s.clone().search.Limit(value).db +// Limit specify the number of records to be retrieved +func (s *DB) Limit(limit interface{}) *DB { + return s.clone().search.Limit(limit).db } -func (s *DB) Offset(value interface{}) *DB { - return s.clone().search.Offset(value).db +// Offset specify the number of records to skip before starting to return the records +func (s *DB) Offset(offset interface{}) *DB { + return s.clone().search.Offset(offset).db } -func (s *DB) Order(value string, reorder ...bool) *DB { +// Order specify order when retrieve records from database, set reorder to `true` to overwrite defined conditions +// db.Order("name DESC") +// db.Order("name DESC", true) // reorder +// db.Order(gorm.Expr("name = ? DESC", "first")) // sql expression +func (s *DB) Order(value interface{}, reorder ...bool) *DB { return s.clone().search.Order(value, reorder...).db } +// Select specify fields that you want to retrieve from database when querying, by default, will select all fields; +// When creating/updating, specify fields that you want to save to database func (s *DB) Select(query interface{}, args ...interface{}) *DB { return s.clone().search.Select(query, args...).db } +// Omit specify fields that you want to ignore when saving to database for creating, updating func (s *DB) Omit(columns ...string) *DB { return s.clone().search.Omit(columns...).db } +// Group specify the group method on the find func (s *DB) Group(query string) *DB { return s.clone().search.Group(query).db } +// Having specify HAVING conditions for GROUP BY func (s *DB) Having(query string, values ...interface{}) *DB { return s.clone().search.Having(query, values...).db } -func (s *DB) Joins(query string) *DB { - return s.clone().search.Joins(query).db +// Joins specify Joins conditions +// db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Find(&user) +func (s *DB) Joins(query string, args ...interface{}) *DB { + return s.clone().search.Joins(query, args...).db } +// Scopes pass current database connection to arguments `func(*DB) *DB`, which could be used to add conditions dynamically +// func AmountGreaterThan1000(db *gorm.DB) *gorm.DB { +// return db.Where("amount > ?", 1000) +// } +// +// func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB { +// return func (db *gorm.DB) *gorm.DB { +// return db.Scopes(AmountGreaterThan1000).Where("status in (?)", status) +// } +// } +// +// db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders) +// Refer https://jinzhu.github.io/gorm/crud.html#scopes func (s *DB) Scopes(funcs ...func(*DB) *DB) *DB { for _, f := range funcs { s = f(s) @@ -181,60 +241,91 @@ func (s *DB) Scopes(funcs ...func(*DB) *DB) *DB { return s } +// Unscoped return all record including deleted record, refer Soft Delete https://jinzhu.github.io/gorm/crud.html#soft-delete func (s *DB) Unscoped() *DB { return s.clone().search.unscoped().db } +// Attrs initialize struct with argument if record not found with `FirstOrInit` https://jinzhu.github.io/gorm/crud.html#firstorinit or `FirstOrCreate` https://jinzhu.github.io/gorm/crud.html#firstorcreate func (s *DB) Attrs(attrs ...interface{}) *DB { return s.clone().search.Attrs(attrs...).db } +// Assign assign result with argument regardless it is found or not with `FirstOrInit` https://jinzhu.github.io/gorm/crud.html#firstorinit or `FirstOrCreate` https://jinzhu.github.io/gorm/crud.html#firstorcreate func (s *DB) Assign(attrs ...interface{}) *DB { return s.clone().search.Assign(attrs...).db } +// First find first record that match given conditions, order by primary key func (s *DB) First(out interface{}, where ...interface{}) *DB { newScope := s.clone().NewScope(out) newScope.Search.Limit(1) return newScope.Set("gorm:order_by_primary_key", "ASC"). - inlineCondition(where...).callCallbacks(s.parent.callback.queries).db + inlineCondition(where...).callCallbacks(s.parent.callbacks.queries).db } +// Last find last record that match given conditions, order by primary key func (s *DB) Last(out interface{}, where ...interface{}) *DB { newScope := s.clone().NewScope(out) newScope.Search.Limit(1) return newScope.Set("gorm:order_by_primary_key", "DESC"). - inlineCondition(where...).callCallbacks(s.parent.callback.queries).db + inlineCondition(where...).callCallbacks(s.parent.callbacks.queries).db } +// Find find records that match given conditions func (s *DB) Find(out interface{}, where ...interface{}) *DB { - return s.clone().NewScope(out).inlineCondition(where...).callCallbacks(s.parent.callback.queries).db + return s.clone().NewScope(out).inlineCondition(where...).callCallbacks(s.parent.callbacks.queries).db } +// Scan scan value to a struct func (s *DB) Scan(dest interface{}) *DB { - return s.clone().NewScope(s.Value).Set("gorm:query_destination", dest).callCallbacks(s.parent.callback.queries).db + return s.clone().NewScope(s.Value).Set("gorm:query_destination", dest).callCallbacks(s.parent.callbacks.queries).db } +// Row return `*sql.Row` with given conditions func (s *DB) Row() *sql.Row { return s.NewScope(s.Value).row() } +// Rows return `*sql.Rows` with given conditions func (s *DB) Rows() (*sql.Rows, error) { return s.NewScope(s.Value).rows() } +// ScanRows scan `*sql.Rows` to give struct +func (s *DB) ScanRows(rows *sql.Rows, result interface{}) error { + var ( + clone = s.clone() + scope = clone.NewScope(result) + columns, err = rows.Columns() + ) + + if clone.AddError(err) == nil { + scope.scan(rows, columns, scope.Fields()) + } + + return clone.Error +} + +// Pluck used to query single column from a model as a map +// var ages []int64 +// db.Find(&users).Pluck("age", &ages) func (s *DB) Pluck(column string, value interface{}) *DB { return s.NewScope(s.Value).pluck(column, value).db } +// Count get how many records for a model func (s *DB) Count(value interface{}) *DB { return s.NewScope(s.Value).count(value).db } +// Related get related associations func (s *DB) Related(value interface{}, foreignKeys ...string) *DB { return s.clone().NewScope(s.Value).related(value, foreignKeys...).db } +// FirstOrInit find first matched record or initialize a new one with given conditions (only works with struct, map conditions) +// https://jinzhu.github.io/gorm/crud.html#firstorinit func (s *DB) FirstOrInit(out interface{}, where ...interface{}) *DB { c := s.clone() if result := c.First(out, where...); result.Error != nil { @@ -243,82 +334,104 @@ func (s *DB) FirstOrInit(out interface{}, where ...interface{}) *DB { } c.NewScope(out).inlineCondition(where...).initialize() } else { - c.NewScope(out).updatedAttrsWithValues(convertInterfaceToMap(s.search.assignAttrs), false) + c.NewScope(out).updatedAttrsWithValues(c.search.assignAttrs) } return c } +// FirstOrCreate find first matched record or create a new one with given conditions (only works with struct, map conditions) +// https://jinzhu.github.io/gorm/crud.html#firstorcreate func (s *DB) FirstOrCreate(out interface{}, where ...interface{}) *DB { c := s.clone() - if result := c.First(out, where...); result.Error != nil { + if result := s.First(out, where...); result.Error != nil { if !result.RecordNotFound() { return result } - c.NewScope(out).inlineCondition(where...).initialize().callCallbacks(s.parent.callback.creates) + return c.NewScope(out).inlineCondition(where...).initialize().callCallbacks(c.parent.callbacks.creates).db } else if len(c.search.assignAttrs) > 0 { - c.NewScope(out).InstanceSet("gorm:update_interface", s.search.assignAttrs).callCallbacks(s.parent.callback.updates) + return c.NewScope(out).InstanceSet("gorm:update_interface", c.search.assignAttrs).callCallbacks(c.parent.callbacks.updates).db } return c } +// Update update attributes with callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update func (s *DB) Update(attrs ...interface{}) *DB { return s.Updates(toSearchableMap(attrs...), true) } +// Updates update attributes with callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update func (s *DB) Updates(values interface{}, ignoreProtectedAttrs ...bool) *DB { return s.clone().NewScope(s.Value). Set("gorm:ignore_protected_attrs", len(ignoreProtectedAttrs) > 0). InstanceSet("gorm:update_interface", values). - callCallbacks(s.parent.callback.updates).db + callCallbacks(s.parent.callbacks.updates).db } +// UpdateColumn update attributes without callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update func (s *DB) UpdateColumn(attrs ...interface{}) *DB { return s.UpdateColumns(toSearchableMap(attrs...)) } +// UpdateColumns update attributes without callbacks, refer: https://jinzhu.github.io/gorm/crud.html#update func (s *DB) UpdateColumns(values interface{}) *DB { return s.clone().NewScope(s.Value). Set("gorm:update_column", true). Set("gorm:save_associations", false). InstanceSet("gorm:update_interface", values). - callCallbacks(s.parent.callback.updates).db + callCallbacks(s.parent.callbacks.updates).db } +// Save update value in database, if the value doesn't have primary key, will insert it func (s *DB) Save(value interface{}) *DB { scope := s.clone().NewScope(value) - if scope.PrimaryKeyZero() { - return scope.callCallbacks(s.parent.callback.creates).db + if !scope.PrimaryKeyZero() { + newDB := scope.callCallbacks(s.parent.callbacks.updates).db + if newDB.Error == nil && newDB.RowsAffected == 0 { + return s.New().FirstOrCreate(value) + } + return newDB } - return scope.callCallbacks(s.parent.callback.updates).db + return scope.callCallbacks(s.parent.callbacks.creates).db } +// Create insert the value into database func (s *DB) Create(value interface{}) *DB { scope := s.clone().NewScope(value) - return scope.callCallbacks(s.parent.callback.creates).db + return scope.callCallbacks(s.parent.callbacks.creates).db } +// Delete delete value match given conditions, if the value has primary key, then will including the primary key as condition func (s *DB) Delete(value interface{}, where ...interface{}) *DB { - return s.clone().NewScope(value).inlineCondition(where...).callCallbacks(s.parent.callback.deletes).db + return s.clone().NewScope(value).inlineCondition(where...).callCallbacks(s.parent.callbacks.deletes).db } +// Raw use raw sql as conditions, won't run it unless invoked by other methods +// db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result) func (s *DB) Raw(sql string, values ...interface{}) *DB { return s.clone().search.Raw(true).Where(sql, values...).db } +// Exec execute raw sql func (s *DB) Exec(sql string, values ...interface{}) *DB { scope := s.clone().NewScope(nil) - generatedSql := scope.buildWhereCondition(map[string]interface{}{"query": sql, "args": values}) - generatedSql = strings.TrimSuffix(strings.TrimPrefix(generatedSql, "("), ")") - scope.Raw(generatedSql) + generatedSQL := scope.buildWhereCondition(map[string]interface{}{"query": sql, "args": values}) + generatedSQL = strings.TrimSuffix(strings.TrimPrefix(generatedSQL, "("), ")") + scope.Raw(generatedSQL) return scope.Exec().db } +// Model specify the model you would like to run db operations +// // update all users's name to `hello` +// db.Model(&User{}).Update("name", "hello") +// // if user's primary key is non-blank, will use it as condition, then will only update the user's name to `hello` +// db.Model(&user).Update("name", "hello") func (s *DB) Model(value interface{}) *DB { c := s.clone() c.Value = value return c } +// Table specify the table you would like to run db operations func (s *DB) Table(name string) *DB { clone := s.clone() clone.search.Table(name) @@ -326,129 +439,175 @@ func (s *DB) Table(name string) *DB { return clone } +// Debug start debug mode func (s *DB) Debug() *DB { return s.clone().LogMode(true) } +// Begin begin a transaction func (s *DB) Begin() *DB { c := s.clone() if db, ok := c.db.(sqlDb); ok { tx, err := db.Begin() c.db = interface{}(tx).(sqlCommon) - c.err(err) + c.AddError(err) } else { - c.err(CantStartTransaction) + c.AddError(ErrCantStartTransaction) } return c } +// Commit commit a transaction func (s *DB) Commit() *DB { if db, ok := s.db.(sqlTx); ok { - s.err(db.Commit()) + s.AddError(db.Commit()) } else { - s.err(NoValidTransaction) + s.AddError(ErrInvalidTransaction) } return s } +// Rollback rollback a transaction func (s *DB) Rollback() *DB { if db, ok := s.db.(sqlTx); ok { - s.err(db.Rollback()) + s.AddError(db.Rollback()) } else { - s.err(NoValidTransaction) + s.AddError(ErrInvalidTransaction) } return s } +// NewRecord check if value's primary key is blank func (s *DB) NewRecord(value interface{}) bool { return s.clone().NewScope(value).PrimaryKeyZero() } +// RecordNotFound check if returning ErrRecordNotFound error func (s *DB) RecordNotFound() bool { - return s.Error == RecordNotFound + for _, err := range s.GetErrors() { + if err == ErrRecordNotFound { + return true + } + } + return false } -// Migrations -func (s *DB) CreateTable(value interface{}) *DB { - return s.clone().NewScope(value).createTable().db +// CreateTable create table for models +func (s *DB) CreateTable(models ...interface{}) *DB { + db := s.Unscoped() + for _, model := range models { + db = db.NewScope(model).createTable().db + } + return db } -func (s *DB) DropTable(value interface{}) *DB { - return s.clone().NewScope(value).dropTable().db +// DropTable drop table for models +func (s *DB) DropTable(values ...interface{}) *DB { + db := s.clone() + for _, value := range values { + if tableName, ok := value.(string); ok { + db = db.Table(tableName) + } + + db = db.NewScope(value).dropTable().db + } + return db } -func (s *DB) DropTableIfExists(value interface{}) *DB { - return s.clone().NewScope(value).dropTableIfExists().db +// DropTableIfExists drop table if it is exist +func (s *DB) DropTableIfExists(values ...interface{}) *DB { + db := s.clone() + for _, value := range values { + if s.HasTable(value) { + db.AddError(s.DropTable(value).Error) + } + } + return db } +// HasTable check has table or not func (s *DB) HasTable(value interface{}) bool { - scope := s.clone().NewScope(value) - tableName := scope.TableName() - return scope.Dialect().HasTable(scope, tableName) + var ( + scope = s.clone().NewScope(value) + tableName string + ) + + if name, ok := value.(string); ok { + tableName = name + } else { + tableName = scope.TableName() + } + + has := scope.Dialect().HasTable(tableName) + s.AddError(scope.db.Error) + return has } +// AutoMigrate run auto migration for given models, will only add missing fields, won't delete/change current data func (s *DB) AutoMigrate(values ...interface{}) *DB { - db := s.clone() + db := s.Unscoped() for _, value := range values { - db = db.NewScope(value).NeedPtr().autoMigrate().db + db = db.NewScope(value).autoMigrate().db } return db } +// ModifyColumn modify column to type func (s *DB) ModifyColumn(column string, typ string) *DB { scope := s.clone().NewScope(s.Value) scope.modifyColumn(column, typ) return scope.db } +// DropColumn drop a column func (s *DB) DropColumn(column string) *DB { scope := s.clone().NewScope(s.Value) scope.dropColumn(column) return scope.db } -func (s *DB) AddIndex(indexName string, column ...string) *DB { - scope := s.clone().NewScope(s.Value) - scope.addIndex(false, indexName, column...) +// AddIndex add index for columns with given name +func (s *DB) AddIndex(indexName string, columns ...string) *DB { + scope := s.Unscoped().NewScope(s.Value) + scope.addIndex(false, indexName, columns...) return scope.db } -func (s *DB) AddUniqueIndex(indexName string, column ...string) *DB { - scope := s.clone().NewScope(s.Value) - scope.addIndex(true, indexName, column...) +// AddUniqueIndex add unique index for columns with given name +func (s *DB) AddUniqueIndex(indexName string, columns ...string) *DB { + scope := s.Unscoped().NewScope(s.Value) + scope.addIndex(true, indexName, columns...) return scope.db } +// RemoveIndex remove index with name func (s *DB) RemoveIndex(indexName string) *DB { scope := s.clone().NewScope(s.Value) scope.removeIndex(indexName) return scope.db } -/* -Add foreign key to the given scope - -Example: - db.Model(&User{}).AddForeignKey("city_id", "cities(id)", "RESTRICT", "RESTRICT") -*/ +// AddForeignKey Add foreign key to the given scope, e.g: +// db.Model(&User{}).AddForeignKey("city_id", "cities(id)", "RESTRICT", "RESTRICT") func (s *DB) AddForeignKey(field string, dest string, onDelete string, onUpdate string) *DB { scope := s.clone().NewScope(s.Value) scope.addForeignKey(field, dest, onDelete, onUpdate) return scope.db } +// Association start `Association Mode` to handler relations things easir in that mode, refer: https://jinzhu.github.io/gorm/associations.html#association-mode func (s *DB) Association(column string) *Association { var err error - scope := s.clone().NewScope(s.Value) + var scope = s.Set("gorm:association:source", s.Value).NewScope(s.Value) if primaryField := scope.PrimaryField(); primaryField.IsBlank { err = errors.New("primary key can't be nil") } else { if field, ok := scope.FieldByName(column); ok { - if field.Relationship == nil || field.Relationship.ForeignFieldName == "" { + if field.Relationship == nil || len(field.Relationship.ForeignFieldNames) == 0 { err = fmt.Errorf("invalid association %v for %v", column, scope.IndirectValue().Type()) } else { - return &Association{Scope: scope, Column: column, PrimaryKey: primaryField.Field.Interface(), Field: field} + return &Association{scope: scope, column: column, field: field} } } else { err = fmt.Errorf("%v doesn't have column %v", scope.IndirectValue().Type(), column) @@ -458,39 +617,121 @@ func (s *DB) Association(column string) *Association { return &Association{Error: err} } +// Preload preload associations with given conditions +// db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users) func (s *DB) Preload(column string, conditions ...interface{}) *DB { return s.clone().search.Preload(column, conditions...).db } -// Set set value by name +// Set set setting by name, which could be used in callbacks, will clone a new db, and update its setting func (s *DB) Set(name string, value interface{}) *DB { return s.clone().InstantSet(name, value) } +// InstantSet instant set setting, will affect current db func (s *DB) InstantSet(name string, value interface{}) *DB { s.values[name] = value return s } -// Get get value by name +// Get get setting by name func (s *DB) Get(name string) (value interface{}, ok bool) { value, ok = s.values[name] return } +// SetJoinTableHandler set a model's join table handler for a relation func (s *DB) SetJoinTableHandler(source interface{}, column string, handler JoinTableHandlerInterface) { scope := s.NewScope(source) for _, field := range scope.GetModelStruct().StructFields { if field.Name == column || field.DBName == column { - if many2many := parseTagSetting(field.Tag.Get("gorm"))["MANY2MANY"]; many2many != "" { + if many2many := field.TagSettings["MANY2MANY"]; many2many != "" { source := (&Scope{Value: source}).GetModelStruct().ModelType destination := (&Scope{Value: reflect.New(field.Struct.Type).Interface()}).GetModelStruct().ModelType handler.Setup(field.Relationship, many2many, source, destination) field.Relationship.JoinTableHandler = handler - if table := handler.Table(s); scope.Dialect().HasTable(scope, table) { + if table := handler.Table(s); scope.Dialect().HasTable(table) { s.Table(table).AutoMigrate(handler) } } } } } + +// AddError add error to the db +func (s *DB) AddError(err error) error { + if err != nil { + if err != ErrRecordNotFound { + if s.logMode == 0 { + go s.print(fileWithLineNum(), err) + } else { + s.log(err) + } + + errors := Errors(s.GetErrors()) + errors = errors.Add(err) + if len(errors) > 1 { + err = errors + } + } + + s.Error = err + } + return err +} + +// GetErrors get happened errors from the db +func (s *DB) GetErrors() []error { + if errs, ok := s.Error.(Errors); ok { + return errs + } else if s.Error != nil { + return []error{s.Error} + } + return []error{} +} + +//////////////////////////////////////////////////////////////////////////////// +// Private Methods For DB +//////////////////////////////////////////////////////////////////////////////// + +func (s *DB) clone() *DB { + db := DB{ + db: s.db, + parent: s.parent, + logger: s.logger, + logMode: s.logMode, + values: map[string]interface{}{}, + Value: s.Value, + Error: s.Error, + blockGlobalUpdate: s.blockGlobalUpdate, + } + + for key, value := range s.values { + db.values[key] = value + } + + if s.search == nil { + db.search = &search{limit: -1, offset: -1} + } else { + db.search = s.search.clone() + } + + db.search.db = &db + return &db +} + +func (s *DB) print(v ...interface{}) { + s.logger.Print(v...) +} + +func (s *DB) log(v ...interface{}) { + if s != nil && s.logMode == 2 { + s.print(append([]interface{}{"log", fileWithLineNum()}, v...)...) + } +} + +func (s *DB) slog(sql string, t time.Time, vars ...interface{}) { + if s.logMode == 2 { + s.print("sql", fileWithLineNum(), NowFunc().Sub(t), sql, vars) + } +} diff --git a/vendor/github.com/jinzhu/gorm/main_private.go b/vendor/github.com/jinzhu/gorm/main_private.go deleted file mode 100644 index 914f70071..000000000 --- a/vendor/github.com/jinzhu/gorm/main_private.go +++ /dev/null @@ -1,50 +0,0 @@ -package gorm - -import "time" - -func (s *DB) clone() *DB { - db := DB{db: s.db, parent: s.parent, logMode: s.logMode, values: map[string]interface{}{}, Value: s.Value, Error: s.Error} - - for key, value := range s.values { - db.values[key] = value - } - - if s.search == nil { - db.search = &search{} - } else { - db.search = s.search.clone() - } - - db.search.db = &db - return &db -} - -func (s *DB) err(err error) error { - if err != nil { - if err != RecordNotFound { - if s.logMode == 0 { - go s.print(fileWithLineNum(), err) - } else { - s.log(err) - } - } - s.Error = err - } - return err -} - -func (s *DB) print(v ...interface{}) { - s.parent.logger.(logger).Print(v...) -} - -func (s *DB) log(v ...interface{}) { - if s != nil && s.logMode == 2 { - s.print(append([]interface{}{"log", fileWithLineNum()}, v...)...) - } -} - -func (s *DB) slog(sql string, t time.Time, vars ...interface{}) { - if s.logMode == 2 { - s.print("sql", fileWithLineNum(), NowFunc().Sub(t), sql, vars) - } -} diff --git a/vendor/github.com/jinzhu/gorm/model.go b/vendor/github.com/jinzhu/gorm/model.go index 50fa52e66..f37ff7eaa 100644 --- a/vendor/github.com/jinzhu/gorm/model.go +++ b/vendor/github.com/jinzhu/gorm/model.go @@ -2,9 +2,13 @@ package gorm import "time" +// Model base model definition, including fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`, which could be embedded in your models +// type User struct { +// gorm.Model +// } type Model struct { ID uint `gorm:"primary_key"` CreatedAt time.Time UpdatedAt time.Time - DeletedAt *time.Time + DeletedAt *time.Time `sql:"index"` } diff --git a/vendor/github.com/jinzhu/gorm/model_struct.go b/vendor/github.com/jinzhu/gorm/model_struct.go index 10423ae21..d4a467844 100644 --- a/vendor/github.com/jinzhu/gorm/model_struct.go +++ b/vendor/github.com/jinzhu/gorm/model_struct.go @@ -2,21 +2,45 @@ package gorm import ( "database/sql" - "fmt" + "errors" "go/ast" "reflect" - "regexp" - "strconv" "strings" + "sync" "time" -) -var modelStructs = map[reflect.Type]*ModelStruct{} + "github.com/jinzhu/inflection" +) +// DefaultTableNameHandler default table name handler var DefaultTableNameHandler = func(db *DB, defaultTableName string) string { return defaultTableName } +type safeModelStructsMap struct { + m map[reflect.Type]*ModelStruct + l *sync.RWMutex +} + +func (s *safeModelStructsMap) Set(key reflect.Type, value *ModelStruct) { + s.l.Lock() + defer s.l.Unlock() + s.m[key] = value +} + +func (s *safeModelStructsMap) Get(key reflect.Type) *ModelStruct { + s.l.RLock() + defer s.l.RUnlock() + return s.m[key] +} + +func newModelStructsMap() *safeModelStructsMap { + return &safeModelStructsMap{l: new(sync.RWMutex), m: make(map[reflect.Type]*ModelStruct)} +} + +var modelStructsMap = newModelStructsMap() + +// ModelStruct model definition type ModelStruct struct { PrimaryFields []*StructField StructFields []*StructField @@ -24,10 +48,25 @@ type ModelStruct struct { defaultTableName string } -func (s ModelStruct) TableName(db *DB) string { +// TableName get model's table name +func (s *ModelStruct) TableName(db *DB) string { + if s.defaultTableName == "" && db != nil && s.ModelType != nil { + // Set default table name + if tabler, ok := reflect.New(s.ModelType).Interface().(tabler); ok { + s.defaultTableName = tabler.TableName() + } else { + tableName := ToDBName(s.ModelType.Name()) + if db == nil || !db.parent.singularTable { + tableName = inflection.Plural(tableName) + } + s.defaultTableName = tableName + } + } + return DefaultTableNameHandler(db, s.defaultTableName) } +// StructField model field's struct definition type StructField struct { DBName string Name string @@ -38,13 +77,14 @@ type StructField struct { IsScanner bool HasDefaultValue bool Tag reflect.StructTag + TagSettings map[string]string Struct reflect.StructField IsForeignKey bool Relationship *Relationship } func (structField *StructField) clone() *StructField { - return &StructField{ + clone := &StructField{ DBName: structField.DBName, Name: structField.Name, Names: structField.Names, @@ -54,322 +94,490 @@ func (structField *StructField) clone() *StructField { IsScanner: structField.IsScanner, HasDefaultValue: structField.HasDefaultValue, Tag: structField.Tag, + TagSettings: map[string]string{}, Struct: structField.Struct, IsForeignKey: structField.IsForeignKey, Relationship: structField.Relationship, } + + for key, value := range structField.TagSettings { + clone.TagSettings[key] = value + } + + return clone } +// Relationship described the relationship between models type Relationship struct { - Kind string - PolymorphicType string - PolymorphicDBName string - ForeignFieldName string - ForeignDBName string - AssociationForeignFieldName string - AssociationForeignDBName string - JoinTableHandler JoinTableHandlerInterface + Kind string + PolymorphicType string + PolymorphicDBName string + PolymorphicValue string + ForeignFieldNames []string + ForeignDBNames []string + AssociationForeignFieldNames []string + AssociationForeignDBNames []string + JoinTableHandler JoinTableHandlerInterface } -var pluralMapKeys = []*regexp.Regexp{regexp.MustCompile("ch$"), regexp.MustCompile("ss$"), regexp.MustCompile("sh$"), regexp.MustCompile("day$"), regexp.MustCompile("y$"), regexp.MustCompile("x$"), regexp.MustCompile("([^s])s?$")} -var pluralMapValues = []string{"ches", "sses", "shes", "days", "ies", "xes", "${1}s"} +func getForeignField(column string, fields []*StructField) *StructField { + for _, field := range fields { + if field.Name == column || field.DBName == column || field.DBName == ToDBName(column) { + return field + } + } + return nil +} +// GetModelStruct get value's model struct, relationships based on struct and tag definition func (scope *Scope) GetModelStruct() *ModelStruct { var modelStruct ModelStruct - - reflectValue := reflect.Indirect(reflect.ValueOf(scope.Value)) - if !reflectValue.IsValid() { + // Scope value can't be nil + if scope.Value == nil { return &modelStruct } - if reflectValue.Kind() == reflect.Slice { - reflectValue = reflect.Indirect(reflect.New(reflectValue.Type().Elem())) - } - - scopeType := reflectValue.Type() - - if scopeType.Kind() == reflect.Ptr { - scopeType = scopeType.Elem() - } - - if value, ok := modelStructs[scopeType]; ok { - return value + reflectType := reflect.ValueOf(scope.Value).Type() + for reflectType.Kind() == reflect.Slice || reflectType.Kind() == reflect.Ptr { + reflectType = reflectType.Elem() } - modelStruct.ModelType = scopeType - if scopeType.Kind() != reflect.Struct { + // Scope value need to be a struct + if reflectType.Kind() != reflect.Struct { return &modelStruct } - // Set tablename - type tabler interface { - TableName() string + // Get Cached model struct + if value := modelStructsMap.Get(reflectType); value != nil { + return value } - if tabler, ok := reflect.New(scopeType).Interface().(interface { - TableName() string - }); ok { - modelStruct.defaultTableName = tabler.TableName() - } else { - name := ToDBName(scopeType.Name()) - if scope.db == nil || !scope.db.parent.singularTable { - for index, reg := range pluralMapKeys { - if reg.MatchString(name) { - name = reg.ReplaceAllString(name, pluralMapValues[index]) - } - } - } - - modelStruct.defaultTableName = name - } + modelStruct.ModelType = reflectType // Get all fields - fields := []*StructField{} - for i := 0; i < scopeType.NumField(); i++ { - if fieldStruct := scopeType.Field(i); ast.IsExported(fieldStruct.Name) { + for i := 0; i < reflectType.NumField(); i++ { + if fieldStruct := reflectType.Field(i); ast.IsExported(fieldStruct.Name) { field := &StructField{ - Struct: fieldStruct, - Name: fieldStruct.Name, - Names: []string{fieldStruct.Name}, - Tag: fieldStruct.Tag, + Struct: fieldStruct, + Name: fieldStruct.Name, + Names: []string{fieldStruct.Name}, + Tag: fieldStruct.Tag, + TagSettings: parseTagSetting(fieldStruct.Tag), } - if fieldStruct.Tag.Get("sql") == "-" { + // is ignored field + if _, ok := field.TagSettings["-"]; ok { field.IsIgnored = true } else { - sqlSettings := parseTagSetting(field.Tag.Get("sql")) - gormSettings := parseTagSetting(field.Tag.Get("gorm")) - if _, ok := gormSettings["PRIMARY_KEY"]; ok { + if _, ok := field.TagSettings["PRIMARY_KEY"]; ok { field.IsPrimaryKey = true modelStruct.PrimaryFields = append(modelStruct.PrimaryFields, field) } - if _, ok := sqlSettings["DEFAULT"]; ok { + if _, ok := field.TagSettings["DEFAULT"]; ok { field.HasDefaultValue = true } - if value, ok := gormSettings["COLUMN"]; ok { - field.DBName = value - } else { - field.DBName = ToDBName(fieldStruct.Name) + if _, ok := field.TagSettings["AUTO_INCREMENT"]; ok && !field.IsPrimaryKey { + field.HasDefaultValue = true } - } - fields = append(fields, field) - } - } - defer func() { - for _, field := range fields { - if !field.IsIgnored { - fieldStruct := field.Struct - fieldType, indirectType := fieldStruct.Type, fieldStruct.Type - if indirectType.Kind() == reflect.Ptr { + indirectType := fieldStruct.Type + for indirectType.Kind() == reflect.Ptr { indirectType = indirectType.Elem() } - if _, isScanner := reflect.New(fieldType).Interface().(sql.Scanner); isScanner { + fieldValue := reflect.New(indirectType).Interface() + if _, isScanner := fieldValue.(sql.Scanner); isScanner { + // is scanner field.IsScanner, field.IsNormal = true, true - } - - if _, isTime := reflect.New(indirectType).Interface().(*time.Time); isTime { - field.IsNormal = true - } - - if !field.IsNormal { - gormSettings := parseTagSetting(field.Tag.Get("gorm")) - toScope := scope.New(reflect.New(fieldStruct.Type).Interface()) - - getForeignField := func(column string, fields []*StructField) *StructField { - for _, field := range fields { - if field.Name == column || field.DBName == ToDBName(column) { - return field + if indirectType.Kind() == reflect.Struct { + for i := 0; i < indirectType.NumField(); i++ { + for key, value := range parseTagSetting(indirectType.Field(i).Tag) { + if _, ok := field.TagSettings[key]; !ok { + field.TagSettings[key] = value + } } } - return nil } + } else if _, isTime := fieldValue.(*time.Time); isTime { + // is time + field.IsNormal = true + } else if _, ok := field.TagSettings["EMBEDDED"]; ok || fieldStruct.Anonymous { + // is embedded struct + for _, subField := range scope.New(fieldValue).GetModelStruct().StructFields { + subField = subField.clone() + subField.Names = append([]string{fieldStruct.Name}, subField.Names...) + if prefix, ok := field.TagSettings["EMBEDDED_PREFIX"]; ok { + subField.DBName = prefix + subField.DBName + } - var relationship = &Relationship{} - - foreignKey := gormSettings["FOREIGNKEY"] - if polymorphic := gormSettings["POLYMORPHIC"]; polymorphic != "" { - if polymorphicField := getForeignField(polymorphic+"Id", toScope.GetStructFields()); polymorphicField != nil { - if polymorphicType := getForeignField(polymorphic+"Type", toScope.GetStructFields()); polymorphicType != nil { - relationship.ForeignFieldName = polymorphicField.Name - relationship.ForeignDBName = polymorphicField.DBName - relationship.PolymorphicType = polymorphicType.Name - relationship.PolymorphicDBName = polymorphicType.DBName - polymorphicType.IsForeignKey = true - polymorphicField.IsForeignKey = true + if subField.IsPrimaryKey { + if _, ok := subField.TagSettings["PRIMARY_KEY"]; ok { + modelStruct.PrimaryFields = append(modelStruct.PrimaryFields, subField) + } else { + subField.IsPrimaryKey = false } } + modelStruct.StructFields = append(modelStruct.StructFields, subField) } - + continue + } else { + // build relationships switch indirectType.Kind() { case reflect.Slice: - elemType := indirectType.Elem() - if elemType.Kind() == reflect.Ptr { - elemType = elemType.Elem() - } - - if elemType.Kind() == reflect.Struct { - if foreignKey == "" { - foreignKey = scopeType.Name() + "Id" + defer func(field *StructField) { + var ( + relationship = &Relationship{} + toScope = scope.New(reflect.New(field.Struct.Type).Interface()) + foreignKeys []string + associationForeignKeys []string + elemType = field.Struct.Type + ) + + if foreignKey := field.TagSettings["FOREIGNKEY"]; foreignKey != "" { + foreignKeys = strings.Split(field.TagSettings["FOREIGNKEY"], ",") } - if many2many := gormSettings["MANY2MANY"]; many2many != "" { - relationship.Kind = "many_to_many" - associationForeignKey := gormSettings["ASSOCIATIONFOREIGNKEY"] - if associationForeignKey == "" { - associationForeignKey = elemType.Name() + "Id" - } + if foreignKey := field.TagSettings["ASSOCIATIONFOREIGNKEY"]; foreignKey != "" { + associationForeignKeys = strings.Split(field.TagSettings["ASSOCIATIONFOREIGNKEY"], ",") + } - relationship.ForeignFieldName = foreignKey - relationship.ForeignDBName = ToDBName(foreignKey) - relationship.AssociationForeignFieldName = associationForeignKey - relationship.AssociationForeignDBName = ToDBName(associationForeignKey) + for elemType.Kind() == reflect.Slice || elemType.Kind() == reflect.Ptr { + elemType = elemType.Elem() + } - joinTableHandler := JoinTableHandler{} - joinTableHandler.Setup(relationship, many2many, scopeType, elemType) - relationship.JoinTableHandler = &joinTableHandler - field.Relationship = relationship - } else { - relationship.Kind = "has_many" - if foreignField := getForeignField(foreignKey, toScope.GetStructFields()); foreignField != nil { - relationship.ForeignFieldName = foreignField.Name - relationship.ForeignDBName = foreignField.DBName - foreignField.IsForeignKey = true - field.Relationship = relationship - } else if relationship.ForeignFieldName != "" { + if elemType.Kind() == reflect.Struct { + if many2many := field.TagSettings["MANY2MANY"]; many2many != "" { + relationship.Kind = "many_to_many" + + // if no foreign keys defined with tag + if len(foreignKeys) == 0 { + for _, field := range modelStruct.PrimaryFields { + foreignKeys = append(foreignKeys, field.DBName) + } + } + + for _, foreignKey := range foreignKeys { + if foreignField := getForeignField(foreignKey, modelStruct.StructFields); foreignField != nil { + // source foreign keys (db names) + relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.DBName) + // join table foreign keys for source + joinTableDBName := ToDBName(reflectType.Name()) + "_" + foreignField.DBName + relationship.ForeignDBNames = append(relationship.ForeignDBNames, joinTableDBName) + } + } + + // if no association foreign keys defined with tag + if len(associationForeignKeys) == 0 { + for _, field := range toScope.PrimaryFields() { + associationForeignKeys = append(associationForeignKeys, field.DBName) + } + } + + for _, name := range associationForeignKeys { + if field, ok := toScope.FieldByName(name); ok { + // association foreign keys (db names) + relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, field.DBName) + // join table foreign keys for association + joinTableDBName := ToDBName(elemType.Name()) + "_" + field.DBName + relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, joinTableDBName) + } + } + + joinTableHandler := JoinTableHandler{} + joinTableHandler.Setup(relationship, many2many, reflectType, elemType) + relationship.JoinTableHandler = &joinTableHandler field.Relationship = relationship + } else { + // User has many comments, associationType is User, comment use UserID as foreign key + var associationType = reflectType.Name() + var toFields = toScope.GetStructFields() + relationship.Kind = "has_many" + + if polymorphic := field.TagSettings["POLYMORPHIC"]; polymorphic != "" { + // Dog has many toys, tag polymorphic is Owner, then associationType is Owner + // Toy use OwnerID, OwnerType ('dogs') as foreign key + if polymorphicType := getForeignField(polymorphic+"Type", toFields); polymorphicType != nil { + associationType = polymorphic + relationship.PolymorphicType = polymorphicType.Name + relationship.PolymorphicDBName = polymorphicType.DBName + // if Dog has multiple set of toys set name of the set (instead of default 'dogs') + if value, ok := field.TagSettings["POLYMORPHIC_VALUE"]; ok { + relationship.PolymorphicValue = value + } else { + relationship.PolymorphicValue = scope.TableName() + } + polymorphicType.IsForeignKey = true + } + } + + // if no foreign keys defined with tag + if len(foreignKeys) == 0 { + // if no association foreign keys defined with tag + if len(associationForeignKeys) == 0 { + for _, field := range modelStruct.PrimaryFields { + foreignKeys = append(foreignKeys, associationType+field.Name) + associationForeignKeys = append(associationForeignKeys, field.Name) + } + } else { + // generate foreign keys from defined association foreign keys + for _, scopeFieldName := range associationForeignKeys { + if foreignField := getForeignField(scopeFieldName, modelStruct.StructFields); foreignField != nil { + foreignKeys = append(foreignKeys, associationType+foreignField.Name) + associationForeignKeys = append(associationForeignKeys, foreignField.Name) + } + } + } + } else { + // generate association foreign keys from foreign keys + if len(associationForeignKeys) == 0 { + for _, foreignKey := range foreignKeys { + if strings.HasPrefix(foreignKey, associationType) { + associationForeignKey := strings.TrimPrefix(foreignKey, associationType) + if foreignField := getForeignField(associationForeignKey, modelStruct.StructFields); foreignField != nil { + associationForeignKeys = append(associationForeignKeys, associationForeignKey) + } + } + } + if len(associationForeignKeys) == 0 && len(foreignKeys) == 1 { + associationForeignKeys = []string{scope.PrimaryKey()} + } + } else if len(foreignKeys) != len(associationForeignKeys) { + scope.Err(errors.New("invalid foreign keys, should have same length")) + return + } + } + + for idx, foreignKey := range foreignKeys { + if foreignField := getForeignField(foreignKey, toFields); foreignField != nil { + if associationField := getForeignField(associationForeignKeys[idx], modelStruct.StructFields); associationField != nil { + // source foreign keys + foreignField.IsForeignKey = true + relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, associationField.Name) + relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, associationField.DBName) + + // association foreign keys + relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.Name) + relationship.ForeignDBNames = append(relationship.ForeignDBNames, foreignField.DBName) + } + } + } + + if len(relationship.ForeignFieldNames) != 0 { + field.Relationship = relationship + } } + } else { + field.IsNormal = true } - } else { - field.IsNormal = true - } + }(field) case reflect.Struct: - if _, ok := gormSettings["EMBEDDED"]; ok || fieldStruct.Anonymous { - for _, toField := range toScope.GetStructFields() { - toField = toField.clone() - toField.Names = append([]string{fieldStruct.Name}, toField.Names...) - modelStruct.StructFields = append(modelStruct.StructFields, toField) - if toField.IsPrimaryKey { - modelStruct.PrimaryFields = append(modelStruct.PrimaryFields, toField) + defer func(field *StructField) { + var ( + // user has one profile, associationType is User, profile use UserID as foreign key + // user belongs to profile, associationType is Profile, user use ProfileID as foreign key + associationType = reflectType.Name() + relationship = &Relationship{} + toScope = scope.New(reflect.New(field.Struct.Type).Interface()) + toFields = toScope.GetStructFields() + tagForeignKeys []string + tagAssociationForeignKeys []string + ) + + if foreignKey := field.TagSettings["FOREIGNKEY"]; foreignKey != "" { + tagForeignKeys = strings.Split(field.TagSettings["FOREIGNKEY"], ",") + } + + if foreignKey := field.TagSettings["ASSOCIATIONFOREIGNKEY"]; foreignKey != "" { + tagAssociationForeignKeys = strings.Split(field.TagSettings["ASSOCIATIONFOREIGNKEY"], ",") + } + + if polymorphic := field.TagSettings["POLYMORPHIC"]; polymorphic != "" { + // Cat has one toy, tag polymorphic is Owner, then associationType is Owner + // Toy use OwnerID, OwnerType ('cats') as foreign key + if polymorphicType := getForeignField(polymorphic+"Type", toFields); polymorphicType != nil { + associationType = polymorphic + relationship.PolymorphicType = polymorphicType.Name + relationship.PolymorphicDBName = polymorphicType.DBName + // if Cat has several different types of toys set name for each (instead of default 'cats') + if value, ok := field.TagSettings["POLYMORPHIC_VALUE"]; ok { + relationship.PolymorphicValue = value + } else { + relationship.PolymorphicValue = scope.TableName() + } + polymorphicType.IsForeignKey = true } } - continue - } else { - belongsToForeignKey := foreignKey - if belongsToForeignKey == "" { - belongsToForeignKey = field.Name + "Id" + + // Has One + { + var foreignKeys = tagForeignKeys + var associationForeignKeys = tagAssociationForeignKeys + // if no foreign keys defined with tag + if len(foreignKeys) == 0 { + // if no association foreign keys defined with tag + if len(associationForeignKeys) == 0 { + for _, primaryField := range modelStruct.PrimaryFields { + foreignKeys = append(foreignKeys, associationType+primaryField.Name) + associationForeignKeys = append(associationForeignKeys, primaryField.Name) + } + } else { + // generate foreign keys form association foreign keys + for _, associationForeignKey := range tagAssociationForeignKeys { + if foreignField := getForeignField(associationForeignKey, modelStruct.StructFields); foreignField != nil { + foreignKeys = append(foreignKeys, associationType+foreignField.Name) + associationForeignKeys = append(associationForeignKeys, foreignField.Name) + } + } + } + } else { + // generate association foreign keys from foreign keys + if len(associationForeignKeys) == 0 { + for _, foreignKey := range foreignKeys { + if strings.HasPrefix(foreignKey, associationType) { + associationForeignKey := strings.TrimPrefix(foreignKey, associationType) + if foreignField := getForeignField(associationForeignKey, modelStruct.StructFields); foreignField != nil { + associationForeignKeys = append(associationForeignKeys, associationForeignKey) + } + } + } + if len(associationForeignKeys) == 0 && len(foreignKeys) == 1 { + associationForeignKeys = []string{scope.PrimaryKey()} + } + } else if len(foreignKeys) != len(associationForeignKeys) { + scope.Err(errors.New("invalid foreign keys, should have same length")) + return + } + } + + for idx, foreignKey := range foreignKeys { + if foreignField := getForeignField(foreignKey, toFields); foreignField != nil { + if scopeField := getForeignField(associationForeignKeys[idx], modelStruct.StructFields); scopeField != nil { + foreignField.IsForeignKey = true + // source foreign keys + relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, scopeField.Name) + relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, scopeField.DBName) + + // association foreign keys + relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.Name) + relationship.ForeignDBNames = append(relationship.ForeignDBNames, foreignField.DBName) + } + } + } } - if foreignField := getForeignField(belongsToForeignKey, fields); foreignField != nil { - relationship.Kind = "belongs_to" - relationship.ForeignFieldName = foreignField.Name - relationship.ForeignDBName = foreignField.DBName - foreignField.IsForeignKey = true + if len(relationship.ForeignFieldNames) != 0 { + relationship.Kind = "has_one" field.Relationship = relationship } else { - if foreignKey == "" { - foreignKey = modelStruct.ModelType.Name() + "Id" + var foreignKeys = tagForeignKeys + var associationForeignKeys = tagAssociationForeignKeys + + if len(foreignKeys) == 0 { + // generate foreign keys & association foreign keys + if len(associationForeignKeys) == 0 { + for _, primaryField := range toScope.PrimaryFields() { + foreignKeys = append(foreignKeys, field.Name+primaryField.Name) + associationForeignKeys = append(associationForeignKeys, primaryField.Name) + } + } else { + // generate foreign keys with association foreign keys + for _, associationForeignKey := range associationForeignKeys { + if foreignField := getForeignField(associationForeignKey, toFields); foreignField != nil { + foreignKeys = append(foreignKeys, field.Name+foreignField.Name) + associationForeignKeys = append(associationForeignKeys, foreignField.Name) + } + } + } + } else { + // generate foreign keys & association foreign keys + if len(associationForeignKeys) == 0 { + for _, foreignKey := range foreignKeys { + if strings.HasPrefix(foreignKey, field.Name) { + associationForeignKey := strings.TrimPrefix(foreignKey, field.Name) + if foreignField := getForeignField(associationForeignKey, toFields); foreignField != nil { + associationForeignKeys = append(associationForeignKeys, associationForeignKey) + } + } + } + if len(associationForeignKeys) == 0 && len(foreignKeys) == 1 { + associationForeignKeys = []string{toScope.PrimaryKey()} + } + } else if len(foreignKeys) != len(associationForeignKeys) { + scope.Err(errors.New("invalid foreign keys, should have same length")) + return + } } - relationship.Kind = "has_one" - if foreignField := getForeignField(foreignKey, toScope.GetStructFields()); foreignField != nil { - relationship.ForeignFieldName = foreignField.Name - relationship.ForeignDBName = foreignField.DBName - foreignField.IsForeignKey = true - field.Relationship = relationship - } else if relationship.ForeignFieldName != "" { + + for idx, foreignKey := range foreignKeys { + if foreignField := getForeignField(foreignKey, modelStruct.StructFields); foreignField != nil { + if associationField := getForeignField(associationForeignKeys[idx], toFields); associationField != nil { + foreignField.IsForeignKey = true + + // association foreign keys + relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, associationField.Name) + relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, associationField.DBName) + + // source foreign keys + relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.Name) + relationship.ForeignDBNames = append(relationship.ForeignDBNames, foreignField.DBName) + } + } + } + + if len(relationship.ForeignFieldNames) != 0 { + relationship.Kind = "belongs_to" field.Relationship = relationship } } - } + }(field) default: field.IsNormal = true } } + } - if field.IsNormal { - if len(modelStruct.PrimaryFields) == 0 && field.DBName == "id" { - field.IsPrimaryKey = true - modelStruct.PrimaryFields = append(modelStruct.PrimaryFields, field) - } - } + // Even it is ignored, also possible to decode db value into the field + if value, ok := field.TagSettings["COLUMN"]; ok { + field.DBName = value + } else { + field.DBName = ToDBName(fieldStruct.Name) } + modelStruct.StructFields = append(modelStruct.StructFields, field) } - }() - - modelStructs[scopeType] = &modelStruct - - return &modelStruct -} - -func (scope *Scope) GetStructFields() (fields []*StructField) { - return scope.GetModelStruct().StructFields -} - -func (scope *Scope) generateSqlTag(field *StructField) string { - var sqlType string - structType := field.Struct.Type - if structType.Kind() == reflect.Ptr { - structType = structType.Elem() - } - reflectValue := reflect.Indirect(reflect.New(structType)) - sqlSettings := parseTagSetting(field.Tag.Get("sql")) - - if value, ok := sqlSettings["TYPE"]; ok { - sqlType = value } - additionalType := sqlSettings["NOT NULL"] + " " + sqlSettings["UNIQUE"] - if value, ok := sqlSettings["DEFAULT"]; ok { - additionalType = additionalType + " DEFAULT " + value - } - - if field.IsScanner { - var getScannerValue func(reflect.Value) - getScannerValue = func(value reflect.Value) { - reflectValue = value - if _, isScanner := reflect.New(reflectValue.Type()).Interface().(sql.Scanner); isScanner && reflectValue.Kind() == reflect.Struct { - getScannerValue(reflectValue.Field(0)) - } + if len(modelStruct.PrimaryFields) == 0 { + if field := getForeignField("id", modelStruct.StructFields); field != nil { + field.IsPrimaryKey = true + modelStruct.PrimaryFields = append(modelStruct.PrimaryFields, field) } - getScannerValue(reflectValue) } - if sqlType == "" { - var size = 255 + modelStructsMap.Set(reflectType, &modelStruct) - if value, ok := sqlSettings["SIZE"]; ok { - size, _ = strconv.Atoi(value) - } - - _, autoIncrease := sqlSettings["AUTO_INCREMENT"] - if field.IsPrimaryKey { - autoIncrease = true - } - - sqlType = scope.Dialect().SqlTag(reflectValue, size, autoIncrease) - } + return &modelStruct +} - if strings.TrimSpace(additionalType) == "" { - return sqlType - } else { - return fmt.Sprintf("%v %v", sqlType, additionalType) - } +// GetStructFields get model's field structs +func (scope *Scope) GetStructFields() (fields []*StructField) { + return scope.GetModelStruct().StructFields } -func parseTagSetting(str string) map[string]string { - tags := strings.Split(str, ";") +func parseTagSetting(tags reflect.StructTag) map[string]string { setting := map[string]string{} - for _, value := range tags { - v := strings.Split(value, ":") - k := strings.TrimSpace(strings.ToUpper(v[0])) - if len(v) == 2 { - setting[k] = v[1] - } else { - setting[k] = k + for _, str := range []string{tags.Get("sql"), tags.Get("gorm")} { + tags := strings.Split(str, ";") + for _, value := range tags { + v := strings.Split(value, ":") + k := strings.TrimSpace(strings.ToUpper(v[0])) + if len(v) >= 2 { + setting[k] = strings.Join(v[1:], ":") + } else { + setting[k] = k + } } } return setting diff --git a/vendor/github.com/jinzhu/gorm/mssql.go b/vendor/github.com/jinzhu/gorm/mssql.go deleted file mode 100644 index c44541c7a..000000000 --- a/vendor/github.com/jinzhu/gorm/mssql.go +++ /dev/null @@ -1,81 +0,0 @@ -package gorm - -import ( - "fmt" - "reflect" - "strings" - "time" -) - -type mssql struct { - commonDialect -} - -func (mssql) HasTop() bool { - return true -} - -func (mssql) SqlTag(value reflect.Value, size int, autoIncrease bool) string { - switch value.Kind() { - case reflect.Bool: - return "bit" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: - if autoIncrease { - return "int IDENTITY(1,1)" - } - return "int" - case reflect.Int64, reflect.Uint64: - if autoIncrease { - return "bigint IDENTITY(1,1)" - } - return "bigint" - case reflect.Float32, reflect.Float64: - return "float" - case reflect.String: - if size > 0 && size < 65532 { - return fmt.Sprintf("nvarchar(%d)", size) - } - return "text" - case reflect.Struct: - if _, ok := value.Interface().(time.Time); ok { - return "datetime2" - } - default: - if _, ok := value.Interface().([]byte); ok { - if size > 0 && size < 65532 { - return fmt.Sprintf("varchar(%d)", size) - } - return "text" - } - } - panic(fmt.Sprintf("invalid sql type %s (%s) for mssql", value.Type().Name(), value.Kind().String())) -} - -func (mssql) databaseName(scope *Scope) string { - dbStr := strings.Split(scope.db.parent.source, ";") - for _, value := range dbStr { - s := strings.Split(value, "=") - if s[0] == "database" { - return s[1] - } - } - return "" -} - -func (s mssql) HasTable(scope *Scope, tableName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM INFORMATION_SCHEMA.tables WHERE table_name = ? AND table_catalog = ?", tableName, s.databaseName(scope)).Row().Scan(&count) - return count > 0 -} - -func (s mssql) HasColumn(scope *Scope, tableName string, columnName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM information_schema.columns WHERE table_catalog = ? AND table_name = ? AND column_name = ?", s.databaseName(scope), tableName, columnName).Row().Scan(&count) - return count > 0 -} - -func (mssql) HasIndex(scope *Scope, tableName string, indexName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM sys.indexes WHERE name=? AND object_id=OBJECT_ID(?)", indexName, tableName).Row().Scan(&count) - return count > 0 -} diff --git a/vendor/github.com/jinzhu/gorm/mysql.go b/vendor/github.com/jinzhu/gorm/mysql.go deleted file mode 100644 index a5e4a4595..000000000 --- a/vendor/github.com/jinzhu/gorm/mysql.go +++ /dev/null @@ -1,65 +0,0 @@ -package gorm - -import ( - "fmt" - "reflect" - "time" -) - -type mysql struct { - commonDialect -} - -func (mysql) SqlTag(value reflect.Value, size int, autoIncrease bool) string { - switch value.Kind() { - case reflect.Bool: - return "boolean" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: - if autoIncrease { - return "int AUTO_INCREMENT" - } - return "int" - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: - if autoIncrease { - return "int unsigned AUTO_INCREMENT" - } - return "int unsigned" - case reflect.Int64: - if autoIncrease { - return "bigint AUTO_INCREMENT" - } - return "bigint" - case reflect.Uint64: - if autoIncrease { - return "bigint unsigned AUTO_INCREMENT" - } - return "bigint unsigned" - case reflect.Float32, reflect.Float64: - return "double" - case reflect.String: - if size > 0 && size < 65532 { - return fmt.Sprintf("varchar(%d)", size) - } - return "longtext" - case reflect.Struct: - if _, ok := value.Interface().(time.Time); ok { - return "timestamp NULL" - } - default: - if _, ok := value.Interface().([]byte); ok { - if size > 0 && size < 65532 { - return fmt.Sprintf("varbinary(%d)", size) - } - return "longblob" - } - } - panic(fmt.Sprintf("invalid sql type %s (%s) for mysql", value.Type().Name(), value.Kind().String())) -} - -func (mysql) Quote(key string) string { - return fmt.Sprintf("`%s`", key) -} - -func (mysql) SelectFromDummyTable() string { - return "FROM DUAL" -} diff --git a/vendor/github.com/jinzhu/gorm/postgres.go b/vendor/github.com/jinzhu/gorm/postgres.go deleted file mode 100644 index 4218e1ba8..000000000 --- a/vendor/github.com/jinzhu/gorm/postgres.go +++ /dev/null @@ -1,131 +0,0 @@ -package gorm - -import ( - "database/sql" - "database/sql/driver" - "fmt" - "reflect" - "time" - - "github.com/lib/pq/hstore" -) - -type postgres struct { - commonDialect -} - -func (postgres) BinVar(i int) string { - return fmt.Sprintf("$%v", i) -} - -func (postgres) SupportLastInsertId() bool { - return false -} - -func (postgres) SqlTag(value reflect.Value, size int, autoIncrease bool) string { - switch value.Kind() { - case reflect.Bool: - return "boolean" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: - if autoIncrease { - return "serial" - } - return "integer" - case reflect.Int64, reflect.Uint64: - if autoIncrease { - return "bigserial" - } - return "bigint" - case reflect.Float32, reflect.Float64: - return "numeric" - case reflect.String: - if size > 0 && size < 65532 { - return fmt.Sprintf("varchar(%d)", size) - } - return "text" - case reflect.Struct: - if _, ok := value.Interface().(time.Time); ok { - return "timestamp with time zone" - } - case reflect.Map: - if value.Type() == hstoreType { - return "hstore" - } - default: - if _, ok := value.Interface().([]byte); ok { - return "bytea" - } - } - panic(fmt.Sprintf("invalid sql type %s (%s) for postgres", value.Type().Name(), value.Kind().String())) -} - -func (s postgres) ReturningStr(tableName, key string) string { - return fmt.Sprintf("RETURNING %v.%v", s.Quote(tableName), key) -} - -func (postgres) HasTable(scope *Scope, tableName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM INFORMATION_SCHEMA.tables WHERE table_name = ? AND table_type = 'BASE TABLE'", tableName).Row().Scan(&count) - return count > 0 -} - -func (postgres) HasColumn(scope *Scope, tableName string, columnName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM INFORMATION_SCHEMA.columns WHERE table_name = ? AND column_name = ?", tableName, columnName).Row().Scan(&count) - return count > 0 -} - -func (postgres) RemoveIndex(scope *Scope, indexName string) { - scope.NewDB().Exec(fmt.Sprintf("DROP INDEX %v", indexName)) -} - -func (postgres) HasIndex(scope *Scope, tableName string, indexName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM pg_indexes WHERE tablename = ? AND indexname = ?", tableName, indexName).Row().Scan(&count) - return count > 0 -} - -var hstoreType = reflect.TypeOf(Hstore{}) - -type Hstore map[string]*string - -func (h Hstore) Value() (driver.Value, error) { - hstore := hstore.Hstore{Map: map[string]sql.NullString{}} - if len(h) == 0 { - return nil, nil - } - - for key, value := range h { - var s sql.NullString - if value != nil { - s.String = *value - s.Valid = true - } - hstore.Map[key] = s - } - return hstore.Value() -} - -func (h *Hstore) Scan(value interface{}) error { - hstore := hstore.Hstore{} - - if err := hstore.Scan(value); err != nil { - return err - } - - if len(hstore.Map) == 0 { - return nil - } - - *h = Hstore{} - for k := range hstore.Map { - if hstore.Map[k].Valid { - s := hstore.Map[k].String - (*h)[k] = &s - } else { - (*h)[k] = nil - } - } - - return nil -} diff --git a/vendor/github.com/jinzhu/gorm/preload.go b/vendor/github.com/jinzhu/gorm/preload.go deleted file mode 100644 index 03910c445..000000000 --- a/vendor/github.com/jinzhu/gorm/preload.go +++ /dev/null @@ -1,242 +0,0 @@ -package gorm - -import ( - "database/sql/driver" - "errors" - "fmt" - "reflect" - "strings" -) - -func getRealValue(value reflect.Value, field string) interface{} { - result := reflect.Indirect(value).FieldByName(field).Interface() - if r, ok := result.(driver.Valuer); ok { - result, _ = r.Value() - } - return result -} - -func equalAsString(a interface{}, b interface{}) bool { - return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b) -} - -func Preload(scope *Scope) { - if scope.Search.preload == nil { - return - } - - preloadMap := map[string]bool{} - fields := scope.Fields() - for _, preload := range scope.Search.preload { - schema, conditions := preload.schema, preload.conditions - keys := strings.Split(schema, ".") - currentScope := scope - currentFields := fields - originalConditions := conditions - conditions = []interface{}{} - for i, key := range keys { - var found bool - if preloadMap[strings.Join(keys[:i+1], ".")] { - goto nextLoop - } - - if i == len(keys)-1 { - conditions = originalConditions - } - - for _, field := range currentFields { - if field.Name != key || field.Relationship == nil { - continue - } - - found = true - switch field.Relationship.Kind { - case "has_one": - currentScope.handleHasOnePreload(field, conditions) - case "has_many": - currentScope.handleHasManyPreload(field, conditions) - case "belongs_to": - currentScope.handleBelongsToPreload(field, conditions) - case "many_to_many": - fallthrough - default: - currentScope.Err(errors.New("not supported relation")) - } - break - } - - if !found { - value := reflect.ValueOf(currentScope.Value) - if value.Kind() == reflect.Slice && value.Type().Elem().Kind() == reflect.Interface { - value = value.Index(0).Elem() - } - scope.Err(fmt.Errorf("can't find field %s in %s", key, value.Type())) - return - } - - preloadMap[strings.Join(keys[:i+1], ".")] = true - - nextLoop: - if i < len(keys)-1 { - currentScope = currentScope.getColumnsAsScope(key) - currentFields = currentScope.Fields() - } - } - } - -} - -func makeSlice(typ reflect.Type) interface{} { - if typ.Kind() == reflect.Slice { - typ = typ.Elem() - } - sliceType := reflect.SliceOf(typ) - slice := reflect.New(sliceType) - slice.Elem().Set(reflect.MakeSlice(sliceType, 0, 0)) - return slice.Interface() -} - -func (scope *Scope) handleHasOnePreload(field *Field, conditions []interface{}) { - primaryName := scope.PrimaryField().Name - primaryKeys := scope.getColumnAsArray(primaryName) - if len(primaryKeys) == 0 { - return - } - - results := makeSlice(field.Struct.Type) - relation := field.Relationship - condition := fmt.Sprintf("%v IN (?)", scope.Quote(relation.ForeignDBName)) - - scope.Err(scope.NewDB().Where(condition, primaryKeys).Find(results, conditions...).Error) - resultValues := reflect.Indirect(reflect.ValueOf(results)) - - for i := 0; i < resultValues.Len(); i++ { - result := resultValues.Index(i) - if scope.IndirectValue().Kind() == reflect.Slice { - value := getRealValue(result, relation.ForeignFieldName) - objects := scope.IndirectValue() - for j := 0; j < objects.Len(); j++ { - if equalAsString(getRealValue(objects.Index(j), primaryName), value) { - reflect.Indirect(objects.Index(j)).FieldByName(field.Name).Set(result) - break - } - } - } else { - if err := scope.SetColumn(field, result); err != nil { - scope.Err(err) - return - } - } - } -} - -func (scope *Scope) handleHasManyPreload(field *Field, conditions []interface{}) { - primaryName := scope.PrimaryField().Name - primaryKeys := scope.getColumnAsArray(primaryName) - if len(primaryKeys) == 0 { - return - } - - results := makeSlice(field.Struct.Type) - relation := field.Relationship - condition := fmt.Sprintf("%v IN (?)", scope.Quote(relation.ForeignDBName)) - - scope.Err(scope.NewDB().Where(condition, primaryKeys).Find(results, conditions...).Error) - resultValues := reflect.Indirect(reflect.ValueOf(results)) - - if scope.IndirectValue().Kind() == reflect.Slice { - for i := 0; i < resultValues.Len(); i++ { - result := resultValues.Index(i) - value := getRealValue(result, relation.ForeignFieldName) - objects := scope.IndirectValue() - for j := 0; j < objects.Len(); j++ { - object := reflect.Indirect(objects.Index(j)) - if equalAsString(getRealValue(object, primaryName), value) { - f := object.FieldByName(field.Name) - f.Set(reflect.Append(f, result)) - break - } - } - } - } else { - scope.SetColumn(field, resultValues) - } -} - -func (scope *Scope) handleBelongsToPreload(field *Field, conditions []interface{}) { - relation := field.Relationship - primaryKeys := scope.getColumnAsArray(relation.ForeignFieldName) - if len(primaryKeys) == 0 { - return - } - - results := makeSlice(field.Struct.Type) - associationPrimaryKey := scope.New(results).PrimaryField().Name - - scope.Err(scope.NewDB().Where(primaryKeys).Find(results, conditions...).Error) - resultValues := reflect.Indirect(reflect.ValueOf(results)) - - for i := 0; i < resultValues.Len(); i++ { - result := resultValues.Index(i) - if scope.IndirectValue().Kind() == reflect.Slice { - value := getRealValue(result, associationPrimaryKey) - objects := scope.IndirectValue() - for j := 0; j < objects.Len(); j++ { - object := reflect.Indirect(objects.Index(j)) - if equalAsString(getRealValue(object, relation.ForeignFieldName), value) { - object.FieldByName(field.Name).Set(result) - } - } - } else { - scope.SetColumn(field, result) - } - } -} - -func (scope *Scope) getColumnAsArray(column string) (columns []interface{}) { - values := scope.IndirectValue() - switch values.Kind() { - case reflect.Slice: - for i := 0; i < values.Len(); i++ { - columns = append(columns, reflect.Indirect(values.Index(i)).FieldByName(column).Interface()) - } - case reflect.Struct: - return []interface{}{values.FieldByName(column).Interface()} - } - return -} - -func (scope *Scope) getColumnsAsScope(column string) *Scope { - values := scope.IndirectValue() - switch values.Kind() { - case reflect.Slice: - modelType := values.Type().Elem() - if modelType.Kind() == reflect.Ptr { - modelType = modelType.Elem() - } - fieldStruct, _ := modelType.FieldByName(column) - var columns reflect.Value - if fieldStruct.Type.Kind() == reflect.Slice || fieldStruct.Type.Kind() == reflect.Ptr { - columns = reflect.New(reflect.SliceOf(reflect.PtrTo(fieldStruct.Type.Elem()))).Elem() - } else { - columns = reflect.New(reflect.SliceOf(reflect.PtrTo(fieldStruct.Type))).Elem() - } - for i := 0; i < values.Len(); i++ { - column := reflect.Indirect(values.Index(i)).FieldByName(column) - if column.Kind() == reflect.Ptr { - column = column.Elem() - } - if column.Kind() == reflect.Slice { - for i := 0; i < column.Len(); i++ { - columns = reflect.Append(columns, column.Index(i).Addr()) - } - } else { - columns = reflect.Append(columns, column.Addr()) - } - } - return scope.New(columns.Interface()) - case reflect.Struct: - return scope.New(values.FieldByName(column).Addr().Interface()) - } - return nil -} diff --git a/vendor/github.com/jinzhu/gorm/scope.go b/vendor/github.com/jinzhu/gorm/scope.go index cd6b235d1..45f7185fd 100644 --- a/vendor/github.com/jinzhu/gorm/scope.go +++ b/vendor/github.com/jinzhu/gorm/scope.go @@ -1,47 +1,35 @@ package gorm import ( + "database/sql" + "database/sql/driver" "errors" "fmt" + "regexp" + "strconv" "strings" "time" "reflect" ) +// Scope contain current operation's information when you perform any operation on the database type Scope struct { Search *search Value interface{} - Sql string - SqlVars []interface{} + SQL string + SQLVars []interface{} db *DB - indirectValue *reflect.Value - instanceId string + instanceID string primaryKeyField *Field skipLeft bool - fields map[string]*Field + fields *[]*Field selectAttrs *[]string } +// IndirectValue return scope's reflect value's indirect value func (scope *Scope) IndirectValue() reflect.Value { - if scope.indirectValue == nil { - value := reflect.Indirect(reflect.ValueOf(scope.Value)) - if value.Kind() == reflect.Ptr { - value = value.Elem() - } - scope.indirectValue = &value - } - return *scope.indirectValue -} - -func (scope *Scope) NeedPtr() *Scope { - reflectKind := reflect.ValueOf(scope.Value).Kind() - if !((reflectKind == reflect.Invalid) || (reflectKind == reflect.Ptr)) { - err := fmt.Errorf("%v %v\n", fileWithLineNum(), "using unaddressable value") - scope.Err(err) - fmt.Printf(err.Error()) - } - return scope + return indirect(reflect.ValueOf(scope.Value)) } // New create a new Scope without search information @@ -49,6 +37,15 @@ func (scope *Scope) New(value interface{}) *Scope { return &Scope{db: scope.NewDB(), Search: &search{}, Value: value} } +//////////////////////////////////////////////////////////////////////////////// +// Scope DB +//////////////////////////////////////////////////////////////////////////////// + +// DB return scope's DB connection +func (scope *Scope) DB() *DB { + return scope.db +} + // NewDB create a new DB without search information func (scope *Scope) NewDB() *DB { if scope.db != nil { @@ -60,21 +57,17 @@ func (scope *Scope) NewDB() *DB { return nil } -func (scope *Scope) DB() *DB { - return scope.db -} - -// SqlDB return *sql.DB -func (scope *Scope) SqlDB() sqlCommon { +// SQLDB return *sql.DB +func (scope *Scope) SQLDB() sqlCommon { return scope.db.db } -// SkipLeft skip remaining callbacks -func (scope *Scope) SkipLeft() { - scope.skipLeft = true +// Dialect get dialect +func (scope *Scope) Dialect() Dialect { + return scope.db.parent.dialect } -// Quote used to quote database column name according to database dialect +// Quote used to quote string to escape them for database func (scope *Scope) Quote(str string) string { if strings.Index(str, ".") != -1 { newStrs := []string{} @@ -82,55 +75,102 @@ func (scope *Scope) Quote(str string) string { newStrs = append(newStrs, scope.Dialect().Quote(str)) } return strings.Join(newStrs, ".") - } else { - return scope.Dialect().Quote(str) } -} -// Dialect get dialect -func (scope *Scope) Dialect() Dialect { - return scope.db.parent.dialect + return scope.Dialect().Quote(str) } -// Err write error +// Err add error to Scope func (scope *Scope) Err(err error) error { if err != nil { - scope.db.err(err) + scope.db.AddError(err) } return err } +// HasError check if there are any error +func (scope *Scope) HasError() bool { + return scope.db.Error != nil +} + // Log print log message func (scope *Scope) Log(v ...interface{}) { scope.db.log(v...) } -// HasError check if there are any error -func (scope *Scope) HasError() bool { - return scope.db.Error != nil +// SkipLeft skip remaining callbacks +func (scope *Scope) SkipLeft() { + scope.skipLeft = true +} + +// Fields get value's fields +func (scope *Scope) Fields() []*Field { + if scope.fields == nil { + var ( + fields []*Field + indirectScopeValue = scope.IndirectValue() + isStruct = indirectScopeValue.Kind() == reflect.Struct + ) + + for _, structField := range scope.GetModelStruct().StructFields { + if isStruct { + fieldValue := indirectScopeValue + for _, name := range structField.Names { + fieldValue = reflect.Indirect(fieldValue).FieldByName(name) + } + fields = append(fields, &Field{StructField: structField, Field: fieldValue, IsBlank: isBlank(fieldValue)}) + } else { + fields = append(fields, &Field{StructField: structField, IsBlank: true}) + } + } + scope.fields = &fields + } + + return *scope.fields +} + +// FieldByName find `gorm.Field` with field name or db name +func (scope *Scope) FieldByName(name string) (field *Field, ok bool) { + var ( + dbName = ToDBName(name) + mostMatchedField *Field + ) + + for _, field := range scope.Fields() { + if field.Name == name || field.DBName == name { + return field, true + } + if field.DBName == dbName { + mostMatchedField = field + } + } + return mostMatchedField, mostMatchedField != nil } -func (scope *Scope) PrimaryFields() []*Field { - var fields = []*Field{} - for _, field := range scope.GetModelStruct().PrimaryFields { - fields = append(fields, scope.Fields()[field.DBName]) +// PrimaryFields return scope's primary fields +func (scope *Scope) PrimaryFields() (fields []*Field) { + for _, field := range scope.Fields() { + if field.IsPrimaryKey { + fields = append(fields, field) + } } return fields } +// PrimaryField return scope's main primary field, if defined more that one primary fields, will return the one having column name `id` or the first one func (scope *Scope) PrimaryField() *Field { if primaryFields := scope.GetModelStruct().PrimaryFields; len(primaryFields) > 0 { if len(primaryFields) > 1 { - if field, ok := scope.Fields()["id"]; ok { + if field, ok := scope.FieldByName("id"); ok { return field } } - return scope.Fields()[primaryFields[0].DBName] + return scope.PrimaryFields()[0] } return nil } -// PrimaryKey get the primary key's column name +// PrimaryKey get main primary field's db name func (scope *Scope) PrimaryKey() string { if field := scope.PrimaryField(); field != nil { return field.DBName @@ -138,7 +178,7 @@ func (scope *Scope) PrimaryKey() string { return "" } -// PrimaryKeyZero check the primary key is blank or not +// PrimaryKeyZero check main primary field's value is blank or not func (scope *Scope) PrimaryKeyZero() bool { field := scope.PrimaryField() return field == nil || field.IsBlank @@ -162,68 +202,56 @@ func (scope *Scope) HasColumn(column string) bool { return false } -// SetColumn to set the column's value +// SetColumn to set the column's value, column could be field or field's name/dbname func (scope *Scope) SetColumn(column interface{}, value interface{}) error { + var updateAttrs = map[string]interface{}{} + if attrs, ok := scope.InstanceGet("gorm:update_attrs"); ok { + updateAttrs = attrs.(map[string]interface{}) + defer scope.InstanceSet("gorm:update_attrs", updateAttrs) + } + if field, ok := column.(*Field); ok { + updateAttrs[field.DBName] = value return field.Set(value) } else if name, ok := column.(string); ok { - - if field, ok := scope.Fields()[name]; ok { - return field.Set(value) - } - - dbName := ToDBName(name) - if field, ok := scope.Fields()[dbName]; ok { - return field.Set(value) + var ( + dbName = ToDBName(name) + mostMatchedField *Field + ) + for _, field := range scope.Fields() { + if field.DBName == value { + updateAttrs[field.DBName] = value + return field.Set(value) + } + if (field.DBName == dbName) || (field.Name == name && mostMatchedField == nil) { + mostMatchedField = field + } } - if field, ok := scope.FieldByName(name); ok { - return field.Set(value) + if mostMatchedField != nil { + updateAttrs[mostMatchedField.DBName] = value + return mostMatchedField.Set(value) } } return errors.New("could not convert column to field") } -func (scope *Scope) CallMethod(name string, checkError bool) { - if scope.Value == nil || (checkError && scope.HasError()) { +// CallMethod call scope value's method, if it is a slice, will call its element's method one by one +func (scope *Scope) CallMethod(methodName string) { + if scope.Value == nil { return } - call := func(value interface{}) { - if fm := reflect.ValueOf(value).MethodByName(name); fm.IsValid() { - switch f := fm.Interface().(type) { - case func(): - f() - case func(s *Scope): - f(scope) - case func(s *DB): - f(scope.NewDB()) - case func() error: - scope.Err(f()) - case func(s *Scope) error: - scope.Err(f(scope)) - case func(s *DB) error: - scope.Err(f(scope.NewDB())) - default: - scope.Err(fmt.Errorf("unsupported function %v", name)) - } - } - } - - if values := scope.IndirectValue(); values.Kind() == reflect.Slice { - for i := 0; i < values.Len(); i++ { - call(values.Index(i).Addr().Interface()) + if indirectScopeValue := scope.IndirectValue(); indirectScopeValue.Kind() == reflect.Slice { + for i := 0; i < indirectScopeValue.Len(); i++ { + scope.callMethod(methodName, indirectScopeValue.Index(i)) } } else { - call(scope.Value) + scope.callMethod(methodName, indirectScopeValue) } } -func (scope *Scope) CallMethodWithErrorCheck(name string) { - scope.CallMethod(name, true) -} - -// AddToVars add value as sql's vars, gorm will escape them +// AddToVars add value as sql's vars, used to prevent SQL injection func (scope *Scope) AddToVars(value interface{}) string { if expr, ok := value.(*expr); ok { exp := expr.expr @@ -231,10 +259,35 @@ func (scope *Scope) AddToVars(value interface{}) string { exp = strings.Replace(exp, "?", scope.AddToVars(arg), 1) } return exp - } else { - scope.SqlVars = append(scope.SqlVars, value) - return scope.Dialect().BinVar(len(scope.SqlVars)) } + + scope.SQLVars = append(scope.SQLVars, value) + return scope.Dialect().BindVar(len(scope.SQLVars)) +} + +// SelectAttrs return selected attributes +func (scope *Scope) SelectAttrs() []string { + if scope.selectAttrs == nil { + attrs := []string{} + for _, value := range scope.Search.selects { + if str, ok := value.(string); ok { + attrs = append(attrs, str) + } else if strs, ok := value.([]string); ok { + attrs = append(attrs, strs...) + } else if strs, ok := value.([]interface{}); ok { + for _, str := range strs { + attrs = append(attrs, fmt.Sprintf("%v", str)) + } + } + } + scope.selectAttrs = &attrs + } + return *scope.selectAttrs +} + +// OmitAttrs return omitted attributes +func (scope *Scope) OmitAttrs() []string { + return scope.Search.omits } type tabler interface { @@ -245,7 +298,7 @@ type dbTabler interface { TableName(*DB) string } -// TableName get table name +// TableName return table name func (scope *Scope) TableName() string { if scope.Search != nil && len(scope.Search.tableName) > 0 { return scope.Search.tableName @@ -262,44 +315,41 @@ func (scope *Scope) TableName() string { return scope.GetModelStruct().TableName(scope.db.Model(scope.Value)) } +// QuotedTableName return quoted table name func (scope *Scope) QuotedTableName() (name string) { if scope.Search != nil && len(scope.Search.tableName) > 0 { if strings.Index(scope.Search.tableName, " ") != -1 { return scope.Search.tableName } return scope.Quote(scope.Search.tableName) - } else { - return scope.Quote(scope.TableName()) } -} -// CombinedConditionSql get combined condition sql -func (scope *Scope) CombinedConditionSql() string { - return scope.joinsSql() + scope.whereSql() + scope.groupSql() + - scope.havingSql() + scope.orderSql() + scope.limitSql() + scope.offsetSql() + return scope.Quote(scope.TableName()) } -func (scope *Scope) FieldByName(name string) (field *Field, ok bool) { - for _, field := range scope.Fields() { - if field.Name == name || field.DBName == name { - return field, true - } +// CombinedConditionSql return combined condition sql +func (scope *Scope) CombinedConditionSql() string { + joinSql := scope.joinsSQL() + whereSql := scope.whereSQL() + if scope.Search.raw { + whereSql = strings.TrimSuffix(strings.TrimPrefix(whereSql, "WHERE ("), ")") } - return nil, false + return joinSql + whereSql + scope.groupSQL() + + scope.havingSQL() + scope.orderSQL() + scope.limitAndOffsetSQL() } -// Raw set sql +// Raw set raw sql func (scope *Scope) Raw(sql string) *Scope { - scope.Sql = strings.Replace(sql, "$$", "?", -1) + scope.SQL = strings.Replace(sql, "$$", "?", -1) return scope } -// Exec invoke sql +// Exec perform generated SQL func (scope *Scope) Exec() *Scope { - defer scope.Trace(NowFunc()) + defer scope.trace(NowFunc()) if !scope.HasError() { - if result, err := scope.SqlDB().Exec(scope.Sql, scope.SqlVars...); scope.Err(err) == nil { + if result, err := scope.SQLDB().Exec(scope.SQL, scope.SQLVars...); scope.Err(err) == nil { if count, err := result.RowsAffected(); scope.Err(err) == nil { scope.db.RowsAffected = count } @@ -314,37 +364,32 @@ func (scope *Scope) Set(name string, value interface{}) *Scope { return scope } -// Get get value by name +// Get get setting by name func (scope *Scope) Get(name string) (interface{}, bool) { return scope.db.Get(name) } -// InstanceId get InstanceId for scope -func (scope *Scope) InstanceId() string { - if scope.instanceId == "" { - scope.instanceId = fmt.Sprintf("%v%v", &scope, &scope.db) +// InstanceID get InstanceID for scope +func (scope *Scope) InstanceID() string { + if scope.instanceID == "" { + scope.instanceID = fmt.Sprintf("%v%v", &scope, &scope.db) } - return scope.instanceId + return scope.instanceID } +// InstanceSet set instance setting for current operation, but not for operations in callbacks, like saving associations callback func (scope *Scope) InstanceSet(name string, value interface{}) *Scope { - return scope.Set(name+scope.InstanceId(), value) + return scope.Set(name+scope.InstanceID(), value) } +// InstanceGet get instance setting from current operation func (scope *Scope) InstanceGet(name string) (interface{}, bool) { - return scope.Get(name + scope.InstanceId()) -} - -// Trace print sql log -func (scope *Scope) Trace(t time.Time) { - if len(scope.Sql) > 0 { - scope.db.slog(scope.Sql, t, scope.SqlVars...) - } + return scope.Get(name + scope.InstanceID()) } // Begin start a transaction func (scope *Scope) Begin() *Scope { - if db, ok := scope.SqlDB().(sqlDb); ok { + if db, ok := scope.SQLDB().(sqlDb); ok { if tx, err := db.Begin(); err == nil { scope.db.db = interface{}(tx).(sqlCommon) scope.InstanceSet("gorm:started_transaction", true) @@ -353,14 +398,14 @@ func (scope *Scope) Begin() *Scope { return scope } -// CommitOrRollback commit current transaction if there is no error, otherwise rollback it +// CommitOrRollback commit current transaction if no error happened, otherwise will rollback it func (scope *Scope) CommitOrRollback() *Scope { if _, ok := scope.InstanceGet("gorm:started_transaction"); ok { if db, ok := scope.db.db.(sqlTx); ok { if scope.HasError() { db.Rollback() } else { - db.Commit() + scope.Err(db.Commit()) } scope.db.db = scope.db.parent.db } @@ -368,55 +413,555 @@ func (scope *Scope) CommitOrRollback() *Scope { return scope } -func (scope *Scope) SelectAttrs() []string { - if scope.selectAttrs == nil { - attrs := []string{} - for _, value := range scope.Search.selects { - if str, ok := value.(string); ok { - attrs = append(attrs, str) - } else if strs, ok := value.([]string); ok { - attrs = append(attrs, strs...) - } else if strs, ok := value.([]interface{}); ok { - for _, str := range strs { - attrs = append(attrs, fmt.Sprintf("%v", str)) +//////////////////////////////////////////////////////////////////////////////// +// Private Methods For *gorm.Scope +//////////////////////////////////////////////////////////////////////////////// + +func (scope *Scope) callMethod(methodName string, reflectValue reflect.Value) { + // Only get address from non-pointer + if reflectValue.CanAddr() && reflectValue.Kind() != reflect.Ptr { + reflectValue = reflectValue.Addr() + } + + if methodValue := reflectValue.MethodByName(methodName); methodValue.IsValid() { + switch method := methodValue.Interface().(type) { + case func(): + method() + case func(*Scope): + method(scope) + case func(*DB): + newDB := scope.NewDB() + method(newDB) + scope.Err(newDB.Error) + case func() error: + scope.Err(method()) + case func(*Scope) error: + scope.Err(method(scope)) + case func(*DB) error: + newDB := scope.NewDB() + scope.Err(method(newDB)) + scope.Err(newDB.Error) + default: + scope.Err(fmt.Errorf("unsupported function %v", methodName)) + } + } +} + +var ( + columnRegexp = regexp.MustCompile("^[a-zA-Z]+(\\.[a-zA-Z]+)*$") // only match string like `name`, `users.name` + isNumberRegexp = regexp.MustCompile("^\\s*\\d+\\s*$") // match if string is number + comparisonRegexp = regexp.MustCompile("(?i) (=|<>|>|<|LIKE|IS|IN) ") + countingQueryRegexp = regexp.MustCompile("(?i)^count(.+)$") +) + +func (scope *Scope) quoteIfPossible(str string) string { + if columnRegexp.MatchString(str) { + return scope.Quote(str) + } + return str +} + +func (scope *Scope) scan(rows *sql.Rows, columns []string, fields []*Field) { + var ( + ignored interface{} + values = make([]interface{}, len(columns)) + selectFields []*Field + selectedColumnsMap = map[string]int{} + resetFields = map[int]*Field{} + ) + + for index, column := range columns { + values[index] = &ignored + + selectFields = fields + if idx, ok := selectedColumnsMap[column]; ok { + selectFields = selectFields[idx+1:] + } + + for fieldIndex, field := range selectFields { + if field.DBName == column { + if field.Field.Kind() == reflect.Ptr { + values[index] = field.Field.Addr().Interface() + } else { + reflectValue := reflect.New(reflect.PtrTo(field.Struct.Type)) + reflectValue.Elem().Set(field.Field.Addr()) + values[index] = reflectValue.Interface() + resetFields[index] = field + } + + selectedColumnsMap[column] = fieldIndex + + if field.IsNormal { + break } } } - scope.selectAttrs = &attrs } - return *scope.selectAttrs + + scope.Err(rows.Scan(values...)) + + for index, field := range resetFields { + if v := reflect.ValueOf(values[index]).Elem().Elem(); v.IsValid() { + field.Field.Set(v) + } + } } -func (scope *Scope) OmitAttrs() []string { - return scope.Search.omits +func (scope *Scope) primaryCondition(value interface{}) string { + return fmt.Sprintf("(%v.%v = %v)", scope.QuotedTableName(), scope.Quote(scope.PrimaryKey()), value) } -func (scope *Scope) changeableDBColumn(column string) bool { - selectAttrs := scope.SelectAttrs() - omitAttrs := scope.OmitAttrs() +func (scope *Scope) buildWhereCondition(clause map[string]interface{}) (str string) { + switch value := clause["query"].(type) { + case string: + if isNumberRegexp.MatchString(value) { + return scope.primaryCondition(scope.AddToVars(value)) + } else if value != "" { + str = fmt.Sprintf("(%v)", value) + } + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, sql.NullInt64: + return scope.primaryCondition(scope.AddToVars(value)) + case []int, []int8, []int16, []int32, []int64, []uint, []uint8, []uint16, []uint32, []uint64, []string, []interface{}: + str = fmt.Sprintf("(%v.%v IN (?))", scope.QuotedTableName(), scope.Quote(scope.PrimaryKey())) + clause["args"] = []interface{}{value} + case map[string]interface{}: + var sqls []string + for key, value := range value { + if value != nil { + sqls = append(sqls, fmt.Sprintf("(%v.%v = %v)", scope.QuotedTableName(), scope.Quote(key), scope.AddToVars(value))) + } else { + sqls = append(sqls, fmt.Sprintf("(%v.%v IS NULL)", scope.QuotedTableName(), scope.Quote(key))) + } + } + return strings.Join(sqls, " AND ") + case interface{}: + var sqls []string + newScope := scope.New(value) + for _, field := range newScope.Fields() { + if !field.IsIgnored && !field.IsBlank { + sqls = append(sqls, fmt.Sprintf("(%v.%v = %v)", scope.QuotedTableName(), scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface()))) + } + } + return strings.Join(sqls, " AND ") + } - if len(selectAttrs) > 0 { - for _, attr := range selectAttrs { - if column == ToDBName(attr) { - return true + args := clause["args"].([]interface{}) + for _, arg := range args { + switch reflect.ValueOf(arg).Kind() { + case reflect.Slice: // For where("id in (?)", []int64{1,2}) + if bytes, ok := arg.([]byte); ok { + str = strings.Replace(str, "?", scope.AddToVars(bytes), 1) + } else if values := reflect.ValueOf(arg); values.Len() > 0 { + var tempMarks []string + for i := 0; i < values.Len(); i++ { + tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface())) + } + str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1) + } else { + str = strings.Replace(str, "?", scope.AddToVars(Expr("NULL")), 1) + } + default: + if valuer, ok := interface{}(arg).(driver.Valuer); ok { + arg, _ = valuer.Value() } + + str = strings.Replace(str, "?", scope.AddToVars(arg), 1) } - return false } + return +} - for _, attr := range omitAttrs { - if column == ToDBName(attr) { - return false +func (scope *Scope) buildNotCondition(clause map[string]interface{}) (str string) { + var notEqualSQL string + var primaryKey = scope.PrimaryKey() + + switch value := clause["query"].(type) { + case string: + if isNumberRegexp.MatchString(value) { + id, _ := strconv.Atoi(value) + return fmt.Sprintf("(%v <> %v)", scope.Quote(primaryKey), id) + } else if comparisonRegexp.MatchString(value) { + str = fmt.Sprintf(" NOT (%v) ", value) + notEqualSQL = fmt.Sprintf("NOT (%v)", value) + } else { + str = fmt.Sprintf("(%v.%v NOT IN (?))", scope.QuotedTableName(), scope.Quote(value)) + notEqualSQL = fmt.Sprintf("(%v.%v <> ?)", scope.QuotedTableName(), scope.Quote(value)) + } + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, sql.NullInt64: + return fmt.Sprintf("(%v.%v <> %v)", scope.QuotedTableName(), scope.Quote(primaryKey), value) + case []int, []int8, []int16, []int32, []int64, []uint, []uint8, []uint16, []uint32, []uint64, []string: + if reflect.ValueOf(value).Len() > 0 { + str = fmt.Sprintf("(%v.%v NOT IN (?))", scope.QuotedTableName(), scope.Quote(primaryKey)) + clause["args"] = []interface{}{value} + } else { + return "" + } + case map[string]interface{}: + var sqls []string + for key, value := range value { + if value != nil { + sqls = append(sqls, fmt.Sprintf("(%v.%v <> %v)", scope.QuotedTableName(), scope.Quote(key), scope.AddToVars(value))) + } else { + sqls = append(sqls, fmt.Sprintf("(%v.%v IS NOT NULL)", scope.QuotedTableName(), scope.Quote(key))) + } + } + return strings.Join(sqls, " AND ") + case interface{}: + var sqls []string + var newScope = scope.New(value) + for _, field := range newScope.Fields() { + if !field.IsBlank { + sqls = append(sqls, fmt.Sprintf("(%v.%v <> %v)", scope.QuotedTableName(), scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface()))) + } } + return strings.Join(sqls, " AND ") } - return true + + args := clause["args"].([]interface{}) + for _, arg := range args { + switch reflect.ValueOf(arg).Kind() { + case reflect.Slice: // For where("id in (?)", []int64{1,2}) + if bytes, ok := arg.([]byte); ok { + str = strings.Replace(str, "?", scope.AddToVars(bytes), 1) + } else if values := reflect.ValueOf(arg); values.Len() > 0 { + var tempMarks []string + for i := 0; i < values.Len(); i++ { + tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface())) + } + str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1) + } else { + str = strings.Replace(str, "?", scope.AddToVars(Expr("NULL")), 1) + } + default: + if scanner, ok := interface{}(arg).(driver.Valuer); ok { + arg, _ = scanner.Value() + } + str = strings.Replace(notEqualSQL, "?", scope.AddToVars(arg), 1) + } + } + return } -func (scope *Scope) changeableField(field *Field) bool { - selectAttrs := scope.SelectAttrs() - omitAttrs := scope.OmitAttrs() +func (scope *Scope) buildSelectQuery(clause map[string]interface{}) (str string) { + switch value := clause["query"].(type) { + case string: + str = value + case []string: + str = strings.Join(value, ", ") + } + + args := clause["args"].([]interface{}) + for _, arg := range args { + switch reflect.ValueOf(arg).Kind() { + case reflect.Slice: + values := reflect.ValueOf(arg) + var tempMarks []string + for i := 0; i < values.Len(); i++ { + tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface())) + } + str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1) + default: + if valuer, ok := interface{}(arg).(driver.Valuer); ok { + arg, _ = valuer.Value() + } + str = strings.Replace(str, "?", scope.AddToVars(arg), 1) + } + } + return +} + +func (scope *Scope) whereSQL() (sql string) { + var ( + quotedTableName = scope.QuotedTableName() + deletedAtField, hasDeletedAtField = scope.FieldByName("DeletedAt") + primaryConditions, andConditions, orConditions []string + ) + + if !scope.Search.Unscoped && hasDeletedAtField { + sql := fmt.Sprintf("%v.%v IS NULL", quotedTableName, scope.Quote(deletedAtField.DBName)) + primaryConditions = append(primaryConditions, sql) + } + + if !scope.PrimaryKeyZero() { + for _, field := range scope.PrimaryFields() { + sql := fmt.Sprintf("%v.%v = %v", quotedTableName, scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface())) + primaryConditions = append(primaryConditions, sql) + } + } + + for _, clause := range scope.Search.whereConditions { + if sql := scope.buildWhereCondition(clause); sql != "" { + andConditions = append(andConditions, sql) + } + } + + for _, clause := range scope.Search.orConditions { + if sql := scope.buildWhereCondition(clause); sql != "" { + orConditions = append(orConditions, sql) + } + } + + for _, clause := range scope.Search.notConditions { + if sql := scope.buildNotCondition(clause); sql != "" { + andConditions = append(andConditions, sql) + } + } + + orSQL := strings.Join(orConditions, " OR ") + combinedSQL := strings.Join(andConditions, " AND ") + if len(combinedSQL) > 0 { + if len(orSQL) > 0 { + combinedSQL = combinedSQL + " OR " + orSQL + } + } else { + combinedSQL = orSQL + } + + if len(primaryConditions) > 0 { + sql = "WHERE " + strings.Join(primaryConditions, " AND ") + if len(combinedSQL) > 0 { + sql = sql + " AND (" + combinedSQL + ")" + } + } else if len(combinedSQL) > 0 { + sql = "WHERE " + combinedSQL + } + return +} + +func (scope *Scope) selectSQL() string { + if len(scope.Search.selects) == 0 { + if len(scope.Search.joinConditions) > 0 { + return fmt.Sprintf("%v.*", scope.QuotedTableName()) + } + return "*" + } + return scope.buildSelectQuery(scope.Search.selects) +} + +func (scope *Scope) orderSQL() string { + if len(scope.Search.orders) == 0 || scope.Search.ignoreOrderQuery { + return "" + } + + var orders []string + for _, order := range scope.Search.orders { + if str, ok := order.(string); ok { + orders = append(orders, scope.quoteIfPossible(str)) + } else if expr, ok := order.(*expr); ok { + exp := expr.expr + for _, arg := range expr.args { + exp = strings.Replace(exp, "?", scope.AddToVars(arg), 1) + } + orders = append(orders, exp) + } + } + return " ORDER BY " + strings.Join(orders, ",") +} + +func (scope *Scope) limitAndOffsetSQL() string { + return scope.Dialect().LimitAndOffsetSQL(scope.Search.limit, scope.Search.offset) +} + +func (scope *Scope) groupSQL() string { + if len(scope.Search.group) == 0 { + return "" + } + return " GROUP BY " + scope.Search.group +} + +func (scope *Scope) havingSQL() string { + if len(scope.Search.havingConditions) == 0 { + return "" + } + + var andConditions []string + for _, clause := range scope.Search.havingConditions { + if sql := scope.buildWhereCondition(clause); sql != "" { + andConditions = append(andConditions, sql) + } + } + + combinedSQL := strings.Join(andConditions, " AND ") + if len(combinedSQL) == 0 { + return "" + } + + return " HAVING " + combinedSQL +} + +func (scope *Scope) joinsSQL() string { + var joinConditions []string + for _, clause := range scope.Search.joinConditions { + if sql := scope.buildWhereCondition(clause); sql != "" { + joinConditions = append(joinConditions, strings.TrimSuffix(strings.TrimPrefix(sql, "("), ")")) + } + } + + return strings.Join(joinConditions, " ") + " " +} + +func (scope *Scope) prepareQuerySQL() { + if scope.Search.raw { + scope.Raw(scope.CombinedConditionSql()) + } else { + scope.Raw(fmt.Sprintf("SELECT %v FROM %v %v", scope.selectSQL(), scope.QuotedTableName(), scope.CombinedConditionSql())) + } + return +} + +func (scope *Scope) inlineCondition(values ...interface{}) *Scope { + if len(values) > 0 { + scope.Search.Where(values[0], values[1:]...) + } + return scope +} + +func (scope *Scope) callCallbacks(funcs []*func(s *Scope)) *Scope { + for _, f := range funcs { + (*f)(scope) + if scope.skipLeft { + break + } + } + return scope +} + +func convertInterfaceToMap(values interface{}, withIgnoredField bool) map[string]interface{} { + var attrs = map[string]interface{}{} + + switch value := values.(type) { + case map[string]interface{}: + return value + case []interface{}: + for _, v := range value { + for key, value := range convertInterfaceToMap(v, withIgnoredField) { + attrs[key] = value + } + } + case interface{}: + reflectValue := reflect.ValueOf(values) + + switch reflectValue.Kind() { + case reflect.Map: + for _, key := range reflectValue.MapKeys() { + attrs[ToDBName(key.Interface().(string))] = reflectValue.MapIndex(key).Interface() + } + default: + for _, field := range (&Scope{Value: values}).Fields() { + if !field.IsBlank && (withIgnoredField || !field.IsIgnored) { + attrs[field.DBName] = field.Field.Interface() + } + } + } + } + return attrs +} + +func (scope *Scope) updatedAttrsWithValues(value interface{}) (results map[string]interface{}, hasUpdate bool) { + if scope.IndirectValue().Kind() != reflect.Struct { + return convertInterfaceToMap(value, false), true + } + + results = map[string]interface{}{} + + for key, value := range convertInterfaceToMap(value, true) { + if field, ok := scope.FieldByName(key); ok && scope.changeableField(field) { + if _, ok := value.(*expr); ok { + hasUpdate = true + results[field.DBName] = value + } else { + err := field.Set(value) + if field.IsNormal { + hasUpdate = true + if err == ErrUnaddressable { + results[field.DBName] = value + } else { + results[field.DBName] = field.Field.Interface() + } + } + } + } + } + return +} + +func (scope *Scope) row() *sql.Row { + defer scope.trace(NowFunc()) + + result := &RowQueryResult{} + scope.InstanceSet("row_query_result", result) + scope.callCallbacks(scope.db.parent.callbacks.rowQueries) + + return result.Row +} + +func (scope *Scope) rows() (*sql.Rows, error) { + defer scope.trace(NowFunc()) + + result := &RowsQueryResult{} + scope.InstanceSet("row_query_result", result) + scope.callCallbacks(scope.db.parent.callbacks.rowQueries) + + return result.Rows, result.Error +} + +func (scope *Scope) initialize() *Scope { + for _, clause := range scope.Search.whereConditions { + scope.updatedAttrsWithValues(clause["query"]) + } + scope.updatedAttrsWithValues(scope.Search.initAttrs) + scope.updatedAttrsWithValues(scope.Search.assignAttrs) + return scope +} + +func (scope *Scope) pluck(column string, value interface{}) *Scope { + dest := reflect.Indirect(reflect.ValueOf(value)) + scope.Search.Select(column) + if dest.Kind() != reflect.Slice { + scope.Err(fmt.Errorf("results should be a slice, not %s", dest.Kind())) + return scope + } + + rows, err := scope.rows() + if scope.Err(err) == nil { + defer rows.Close() + for rows.Next() { + elem := reflect.New(dest.Type().Elem()).Interface() + scope.Err(rows.Scan(elem)) + dest.Set(reflect.Append(dest, reflect.ValueOf(elem).Elem())) + } + } + return scope +} + +func (scope *Scope) count(value interface{}) *Scope { + if query, ok := scope.Search.selects["query"]; !ok || !countingQueryRegexp.MatchString(fmt.Sprint(query)) { + scope.Search.Select("count(*)") + } + scope.Search.ignoreOrderQuery = true + scope.Err(scope.row().Scan(value)) + return scope +} + +func (scope *Scope) typeName() string { + typ := scope.IndirectValue().Type() + + for typ.Kind() == reflect.Slice || typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + + return typ.Name() +} - if len(selectAttrs) > 0 { +// trace print sql log +func (scope *Scope) trace(t time.Time) { + if len(scope.SQL) > 0 { + scope.db.slog(scope.SQL, t, scope.SQLVars...) + } +} + +func (scope *Scope) changeableField(field *Field) bool { + if selectAttrs := scope.SelectAttrs(); len(selectAttrs) > 0 { for _, attr := range selectAttrs { if field.Name == attr || field.DBName == attr { return true @@ -425,19 +970,344 @@ func (scope *Scope) changeableField(field *Field) bool { return false } - for _, attr := range omitAttrs { + for _, attr := range scope.OmitAttrs() { if field.Name == attr || field.DBName == attr { return false } } - return !field.IsIgnored + return true } func (scope *Scope) shouldSaveAssociations() bool { - saveAssociations, ok := scope.Get("gorm:save_associations") - if ok && !saveAssociations.(bool) { - return false + if saveAssociations, ok := scope.Get("gorm:save_associations"); ok { + if v, ok := saveAssociations.(bool); ok && !v { + return false + } + if v, ok := saveAssociations.(string); ok && (v != "skip") { + return false + } } - return true + return true && !scope.HasError() +} + +func (scope *Scope) related(value interface{}, foreignKeys ...string) *Scope { + toScope := scope.db.NewScope(value) + tx := scope.db.Set("gorm:association:source", scope.Value) + + for _, foreignKey := range append(foreignKeys, toScope.typeName()+"Id", scope.typeName()+"Id") { + fromField, _ := scope.FieldByName(foreignKey) + toField, _ := toScope.FieldByName(foreignKey) + + if fromField != nil { + if relationship := fromField.Relationship; relationship != nil { + if relationship.Kind == "many_to_many" { + joinTableHandler := relationship.JoinTableHandler + scope.Err(joinTableHandler.JoinWith(joinTableHandler, tx, scope.Value).Find(value).Error) + } else if relationship.Kind == "belongs_to" { + for idx, foreignKey := range relationship.ForeignDBNames { + if field, ok := scope.FieldByName(foreignKey); ok { + tx = tx.Where(fmt.Sprintf("%v = ?", scope.Quote(relationship.AssociationForeignDBNames[idx])), field.Field.Interface()) + } + } + scope.Err(tx.Find(value).Error) + } else if relationship.Kind == "has_many" || relationship.Kind == "has_one" { + for idx, foreignKey := range relationship.ForeignDBNames { + if field, ok := scope.FieldByName(relationship.AssociationForeignDBNames[idx]); ok { + tx = tx.Where(fmt.Sprintf("%v = ?", scope.Quote(foreignKey)), field.Field.Interface()) + } + } + + if relationship.PolymorphicType != "" { + tx = tx.Where(fmt.Sprintf("%v = ?", scope.Quote(relationship.PolymorphicDBName)), relationship.PolymorphicValue) + } + scope.Err(tx.Find(value).Error) + } + } else { + sql := fmt.Sprintf("%v = ?", scope.Quote(toScope.PrimaryKey())) + scope.Err(tx.Where(sql, fromField.Field.Interface()).Find(value).Error) + } + return scope + } else if toField != nil { + sql := fmt.Sprintf("%v = ?", scope.Quote(toField.DBName)) + scope.Err(tx.Where(sql, scope.PrimaryKeyValue()).Find(value).Error) + return scope + } + } + + scope.Err(fmt.Errorf("invalid association %v", foreignKeys)) + return scope +} + +// getTableOptions return the table options string or an empty string if the table options does not exist +func (scope *Scope) getTableOptions() string { + tableOptions, ok := scope.Get("gorm:table_options") + if !ok { + return "" + } + return tableOptions.(string) +} + +func (scope *Scope) createJoinTable(field *StructField) { + if relationship := field.Relationship; relationship != nil && relationship.JoinTableHandler != nil { + joinTableHandler := relationship.JoinTableHandler + joinTable := joinTableHandler.Table(scope.db) + if !scope.Dialect().HasTable(joinTable) { + toScope := &Scope{Value: reflect.New(field.Struct.Type).Interface()} + + var sqlTypes, primaryKeys []string + for idx, fieldName := range relationship.ForeignFieldNames { + if field, ok := scope.FieldByName(fieldName); ok { + foreignKeyStruct := field.clone() + foreignKeyStruct.IsPrimaryKey = false + foreignKeyStruct.TagSettings["IS_JOINTABLE_FOREIGNKEY"] = "true" + delete(foreignKeyStruct.TagSettings, "AUTO_INCREMENT") + sqlTypes = append(sqlTypes, scope.Quote(relationship.ForeignDBNames[idx])+" "+scope.Dialect().DataTypeOf(foreignKeyStruct)) + primaryKeys = append(primaryKeys, scope.Quote(relationship.ForeignDBNames[idx])) + } + } + + for idx, fieldName := range relationship.AssociationForeignFieldNames { + if field, ok := toScope.FieldByName(fieldName); ok { + foreignKeyStruct := field.clone() + foreignKeyStruct.IsPrimaryKey = false + foreignKeyStruct.TagSettings["IS_JOINTABLE_FOREIGNKEY"] = "true" + delete(foreignKeyStruct.TagSettings, "AUTO_INCREMENT") + sqlTypes = append(sqlTypes, scope.Quote(relationship.AssociationForeignDBNames[idx])+" "+scope.Dialect().DataTypeOf(foreignKeyStruct)) + primaryKeys = append(primaryKeys, scope.Quote(relationship.AssociationForeignDBNames[idx])) + } + } + + scope.Err(scope.NewDB().Exec(fmt.Sprintf("CREATE TABLE %v (%v, PRIMARY KEY (%v)) %s", scope.Quote(joinTable), strings.Join(sqlTypes, ","), strings.Join(primaryKeys, ","), scope.getTableOptions())).Error) + } + scope.NewDB().Table(joinTable).AutoMigrate(joinTableHandler) + } +} + +func (scope *Scope) createTable() *Scope { + var tags []string + var primaryKeys []string + var primaryKeyInColumnType = false + for _, field := range scope.GetModelStruct().StructFields { + if field.IsNormal { + sqlTag := scope.Dialect().DataTypeOf(field) + + // Check if the primary key constraint was specified as + // part of the column type. If so, we can only support + // one column as the primary key. + if strings.Contains(strings.ToLower(sqlTag), "primary key") { + primaryKeyInColumnType = true + } + + tags = append(tags, scope.Quote(field.DBName)+" "+sqlTag) + } + + if field.IsPrimaryKey { + primaryKeys = append(primaryKeys, scope.Quote(field.DBName)) + } + scope.createJoinTable(field) + } + + var primaryKeyStr string + if len(primaryKeys) > 0 && !primaryKeyInColumnType { + primaryKeyStr = fmt.Sprintf(", PRIMARY KEY (%v)", strings.Join(primaryKeys, ",")) + } + + scope.Raw(fmt.Sprintf("CREATE TABLE %v (%v %v) %s", scope.QuotedTableName(), strings.Join(tags, ","), primaryKeyStr, scope.getTableOptions())).Exec() + + scope.autoIndex() + return scope +} + +func (scope *Scope) dropTable() *Scope { + scope.Raw(fmt.Sprintf("DROP TABLE %v", scope.QuotedTableName())).Exec() + return scope +} + +func (scope *Scope) modifyColumn(column string, typ string) { + scope.Raw(fmt.Sprintf("ALTER TABLE %v MODIFY %v %v", scope.QuotedTableName(), scope.Quote(column), typ)).Exec() +} + +func (scope *Scope) dropColumn(column string) { + scope.Raw(fmt.Sprintf("ALTER TABLE %v DROP COLUMN %v", scope.QuotedTableName(), scope.Quote(column))).Exec() +} + +func (scope *Scope) addIndex(unique bool, indexName string, column ...string) { + if scope.Dialect().HasIndex(scope.TableName(), indexName) { + return + } + + var columns []string + for _, name := range column { + columns = append(columns, scope.quoteIfPossible(name)) + } + + sqlCreate := "CREATE INDEX" + if unique { + sqlCreate = "CREATE UNIQUE INDEX" + } + + scope.Raw(fmt.Sprintf("%s %v ON %v(%v) %v", sqlCreate, indexName, scope.QuotedTableName(), strings.Join(columns, ", "), scope.whereSQL())).Exec() +} + +func (scope *Scope) addForeignKey(field string, dest string, onDelete string, onUpdate string) { + keyName := scope.Dialect().BuildForeignKeyName(scope.TableName(), field, dest) + + if scope.Dialect().HasForeignKey(scope.TableName(), keyName) { + return + } + var query = `ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s ON DELETE %s ON UPDATE %s;` + scope.Raw(fmt.Sprintf(query, scope.QuotedTableName(), scope.quoteIfPossible(keyName), scope.quoteIfPossible(field), dest, onDelete, onUpdate)).Exec() +} + +func (scope *Scope) removeIndex(indexName string) { + scope.Dialect().RemoveIndex(scope.TableName(), indexName) +} + +func (scope *Scope) autoMigrate() *Scope { + tableName := scope.TableName() + quotedTableName := scope.QuotedTableName() + + if !scope.Dialect().HasTable(tableName) { + scope.createTable() + } else { + for _, field := range scope.GetModelStruct().StructFields { + if !scope.Dialect().HasColumn(tableName, field.DBName) { + if field.IsNormal { + sqlTag := scope.Dialect().DataTypeOf(field) + scope.Raw(fmt.Sprintf("ALTER TABLE %v ADD %v %v;", quotedTableName, scope.Quote(field.DBName), sqlTag)).Exec() + } + } + scope.createJoinTable(field) + } + scope.autoIndex() + } + return scope +} + +func (scope *Scope) autoIndex() *Scope { + var indexes = map[string][]string{} + var uniqueIndexes = map[string][]string{} + + for _, field := range scope.GetStructFields() { + if name, ok := field.TagSettings["INDEX"]; ok { + names := strings.Split(name, ",") + + for _, name := range names { + if name == "INDEX" || name == "" { + name = fmt.Sprintf("idx_%v_%v", scope.TableName(), field.DBName) + } + indexes[name] = append(indexes[name], field.DBName) + } + } + + if name, ok := field.TagSettings["UNIQUE_INDEX"]; ok { + names := strings.Split(name, ",") + + for _, name := range names { + if name == "UNIQUE_INDEX" || name == "" { + name = fmt.Sprintf("uix_%v_%v", scope.TableName(), field.DBName) + } + uniqueIndexes[name] = append(uniqueIndexes[name], field.DBName) + } + } + } + + for name, columns := range indexes { + scope.NewDB().Model(scope.Value).AddIndex(name, columns...) + } + + for name, columns := range uniqueIndexes { + scope.NewDB().Model(scope.Value).AddUniqueIndex(name, columns...) + } + + return scope +} + +func (scope *Scope) getColumnAsArray(columns []string, values ...interface{}) (results [][]interface{}) { + for _, value := range values { + indirectValue := indirect(reflect.ValueOf(value)) + + switch indirectValue.Kind() { + case reflect.Slice: + for i := 0; i < indirectValue.Len(); i++ { + var result []interface{} + var object = indirect(indirectValue.Index(i)) + var hasValue = false + for _, column := range columns { + field := object.FieldByName(column) + if hasValue || !isBlank(field) { + hasValue = true + } + result = append(result, field.Interface()) + } + + if hasValue { + results = append(results, result) + } + } + case reflect.Struct: + var result []interface{} + var hasValue = false + for _, column := range columns { + field := indirectValue.FieldByName(column) + if hasValue || !isBlank(field) { + hasValue = true + } + result = append(result, field.Interface()) + } + + if hasValue { + results = append(results, result) + } + } + } + + return +} + +func (scope *Scope) getColumnAsScope(column string) *Scope { + indirectScopeValue := scope.IndirectValue() + + switch indirectScopeValue.Kind() { + case reflect.Slice: + if fieldStruct, ok := scope.GetModelStruct().ModelType.FieldByName(column); ok { + fieldType := fieldStruct.Type + if fieldType.Kind() == reflect.Slice || fieldType.Kind() == reflect.Ptr { + fieldType = fieldType.Elem() + } + + resultsMap := map[interface{}]bool{} + results := reflect.New(reflect.SliceOf(reflect.PtrTo(fieldType))).Elem() + + for i := 0; i < indirectScopeValue.Len(); i++ { + result := indirect(indirect(indirectScopeValue.Index(i)).FieldByName(column)) + + if result.Kind() == reflect.Slice { + for j := 0; j < result.Len(); j++ { + if elem := result.Index(j); elem.CanAddr() && resultsMap[elem.Addr()] != true { + resultsMap[elem.Addr()] = true + results = reflect.Append(results, elem.Addr()) + } + } + } else if result.CanAddr() && resultsMap[result.Addr()] != true { + resultsMap[result.Addr()] = true + results = reflect.Append(results, result.Addr()) + } + } + return scope.New(results.Interface()) + } + case reflect.Struct: + if field := indirectScopeValue.FieldByName(column); field.CanAddr() { + return scope.New(field.Addr().Interface()) + } + } + return nil +} + +func (scope *Scope) hasConditions() bool { + return !scope.PrimaryKeyZero() || + len(scope.Search.whereConditions) > 0 || + len(scope.Search.orConditions) > 0 || + len(scope.Search.notConditions) > 0 } diff --git a/vendor/github.com/jinzhu/gorm/scope_private.go b/vendor/github.com/jinzhu/gorm/scope_private.go deleted file mode 100644 index edd0dbe9e..000000000 --- a/vendor/github.com/jinzhu/gorm/scope_private.go +++ /dev/null @@ -1,596 +0,0 @@ -package gorm - -import ( - "database/sql" - "database/sql/driver" - "fmt" - "reflect" - "regexp" - "strconv" - "strings" -) - -func (scope *Scope) primaryCondition(value interface{}) string { - return fmt.Sprintf("(%v = %v)", scope.Quote(scope.PrimaryKey()), value) -} - -func (scope *Scope) buildWhereCondition(clause map[string]interface{}) (str string) { - switch value := clause["query"].(type) { - case string: - // if string is number - if regexp.MustCompile("^\\s*\\d+\\s*$").MatchString(value) { - id, _ := strconv.Atoi(value) - return scope.primaryCondition(scope.AddToVars(id)) - } else if value != "" { - str = fmt.Sprintf("(%v)", value) - } - case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, sql.NullInt64: - return scope.primaryCondition(scope.AddToVars(value)) - case []int, []int8, []int16, []int32, []int64, []uint, []uint8, []uint16, []uint32, []uint64, []string, []interface{}: - str = fmt.Sprintf("(%v in (?))", scope.Quote(scope.PrimaryKey())) - clause["args"] = []interface{}{value} - case map[string]interface{}: - var sqls []string - for key, value := range value { - sqls = append(sqls, fmt.Sprintf("(%v = %v)", scope.Quote(key), scope.AddToVars(value))) - } - return strings.Join(sqls, " AND ") - case interface{}: - var sqls []string - for _, field := range scope.New(value).Fields() { - if !field.IsIgnored && !field.IsBlank { - sqls = append(sqls, fmt.Sprintf("(%v = %v)", scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface()))) - } - } - return strings.Join(sqls, " AND ") - } - - args := clause["args"].([]interface{}) - for _, arg := range args { - switch reflect.ValueOf(arg).Kind() { - case reflect.Slice: // For where("id in (?)", []int64{1,2}) - values := reflect.ValueOf(arg) - var tempMarks []string - for i := 0; i < values.Len(); i++ { - tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface())) - } - str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1) - default: - if valuer, ok := interface{}(arg).(driver.Valuer); ok { - arg, _ = valuer.Value() - } - - str = strings.Replace(str, "?", scope.AddToVars(arg), 1) - } - } - return -} - -func (scope *Scope) buildNotCondition(clause map[string]interface{}) (str string) { - var notEqualSql string - var primaryKey = scope.PrimaryKey() - - switch value := clause["query"].(type) { - case string: - // is number - if regexp.MustCompile("^\\s*\\d+\\s*$").MatchString(value) { - id, _ := strconv.Atoi(value) - return fmt.Sprintf("(%v <> %v)", scope.Quote(primaryKey), id) - } else if regexp.MustCompile("(?i) (=|<>|>|<|LIKE|IS) ").MatchString(value) { - str = fmt.Sprintf(" NOT (%v) ", value) - notEqualSql = fmt.Sprintf("NOT (%v)", value) - } else { - str = fmt.Sprintf("(%v NOT IN (?))", scope.Quote(value)) - notEqualSql = fmt.Sprintf("(%v <> ?)", scope.Quote(value)) - } - case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, sql.NullInt64: - return fmt.Sprintf("(%v <> %v)", scope.Quote(primaryKey), value) - case []int, []int8, []int16, []int32, []int64, []uint, []uint8, []uint16, []uint32, []uint64, []string: - if reflect.ValueOf(value).Len() > 0 { - str = fmt.Sprintf("(%v NOT IN (?))", scope.Quote(primaryKey)) - clause["args"] = []interface{}{value} - } - return "" - case map[string]interface{}: - var sqls []string - for key, value := range value { - sqls = append(sqls, fmt.Sprintf("(%v <> %v)", scope.Quote(key), scope.AddToVars(value))) - } - return strings.Join(sqls, " AND ") - case interface{}: - var sqls []string - for _, field := range scope.New(value).Fields() { - if !field.IsBlank { - sqls = append(sqls, fmt.Sprintf("(%v <> %v)", scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface()))) - } - } - return strings.Join(sqls, " AND ") - } - - args := clause["args"].([]interface{}) - for _, arg := range args { - switch reflect.ValueOf(arg).Kind() { - case reflect.Slice: // For where("id in (?)", []int64{1,2}) - values := reflect.ValueOf(arg) - var tempMarks []string - for i := 0; i < values.Len(); i++ { - tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface())) - } - str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1) - default: - if scanner, ok := interface{}(arg).(driver.Valuer); ok { - arg, _ = scanner.Value() - } - str = strings.Replace(notEqualSql, "?", scope.AddToVars(arg), 1) - } - } - return -} - -func (scope *Scope) buildSelectQuery(clause map[string]interface{}) (str string) { - switch value := clause["query"].(type) { - case string: - str = value - case []string: - str = strings.Join(value, ", ") - } - - args := clause["args"].([]interface{}) - for _, arg := range args { - switch reflect.ValueOf(arg).Kind() { - case reflect.Slice: - values := reflect.ValueOf(arg) - var tempMarks []string - for i := 0; i < values.Len(); i++ { - tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface())) - } - str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1) - default: - if valuer, ok := interface{}(arg).(driver.Valuer); ok { - arg, _ = valuer.Value() - } - str = strings.Replace(str, "?", scope.Dialect().Quote(fmt.Sprintf("%v", arg)), 1) - } - } - return -} - -func (scope *Scope) whereSql() (sql string) { - var primaryConditions, andConditions, orConditions []string - - if !scope.Search.Unscoped && scope.Fields()["deleted_at"] != nil { - sql := fmt.Sprintf("(%v.deleted_at IS NULL OR %v.deleted_at <= '0001-01-02')", scope.QuotedTableName(), scope.QuotedTableName()) - primaryConditions = append(primaryConditions, sql) - } - - if !scope.PrimaryKeyZero() { - primaryConditions = append(primaryConditions, scope.primaryCondition(scope.AddToVars(scope.PrimaryKeyValue()))) - } - - for _, clause := range scope.Search.whereConditions { - if sql := scope.buildWhereCondition(clause); sql != "" { - andConditions = append(andConditions, sql) - } - } - - for _, clause := range scope.Search.orConditions { - if sql := scope.buildWhereCondition(clause); sql != "" { - orConditions = append(orConditions, sql) - } - } - - for _, clause := range scope.Search.notConditions { - if sql := scope.buildNotCondition(clause); sql != "" { - andConditions = append(andConditions, sql) - } - } - - orSql := strings.Join(orConditions, " OR ") - combinedSql := strings.Join(andConditions, " AND ") - if len(combinedSql) > 0 { - if len(orSql) > 0 { - combinedSql = combinedSql + " OR " + orSql - } - } else { - combinedSql = orSql - } - - if len(primaryConditions) > 0 { - sql = "WHERE " + strings.Join(primaryConditions, " AND ") - if len(combinedSql) > 0 { - sql = sql + " AND (" + combinedSql + ")" - } - } else if len(combinedSql) > 0 { - sql = "WHERE " + combinedSql - } - return -} - -func (scope *Scope) selectSql() string { - if len(scope.Search.selects) == 0 { - return "*" - } - return scope.buildSelectQuery(scope.Search.selects) -} - -func (scope *Scope) orderSql() string { - if len(scope.Search.orders) == 0 { - return "" - } - return " ORDER BY " + strings.Join(scope.Search.orders, ",") -} - -func (scope *Scope) limitSql() string { - if !scope.Dialect().HasTop() { - if len(scope.Search.limit) == 0 { - return "" - } - return " LIMIT " + scope.Search.limit - } - - return "" -} - -func (scope *Scope) topSql() string { - if scope.Dialect().HasTop() && len(scope.Search.offset) == 0 { - if len(scope.Search.limit) == 0 { - return "" - } - return " TOP(" + scope.Search.limit + ")" - } - - return "" -} - -func (scope *Scope) offsetSql() string { - if len(scope.Search.offset) == 0 { - return "" - } - - if scope.Dialect().HasTop() { - sql := " OFFSET " + scope.Search.offset + " ROW " - if len(scope.Search.limit) > 0 { - sql += "FETCH NEXT " + scope.Search.limit + " ROWS ONLY" - } - return sql - } - return " OFFSET " + scope.Search.offset -} - -func (scope *Scope) groupSql() string { - if len(scope.Search.group) == 0 { - return "" - } - return " GROUP BY " + scope.Search.group -} - -func (scope *Scope) havingSql() string { - if scope.Search.havingCondition == nil { - return "" - } - return " HAVING " + scope.buildWhereCondition(scope.Search.havingCondition) -} - -func (scope *Scope) joinsSql() string { - return scope.Search.joins + " " -} - -func (scope *Scope) prepareQuerySql() { - if scope.Search.raw { - scope.Raw(strings.TrimSuffix(strings.TrimPrefix(scope.CombinedConditionSql(), " WHERE ("), ")")) - } else { - scope.Raw(fmt.Sprintf("SELECT %v %v FROM %v %v", scope.topSql(), scope.selectSql(), scope.QuotedTableName(), scope.CombinedConditionSql())) - } - return -} - -func (scope *Scope) inlineCondition(values ...interface{}) *Scope { - if len(values) > 0 { - scope.Search.Where(values[0], values[1:]...) - } - return scope -} - -func (scope *Scope) callCallbacks(funcs []*func(s *Scope)) *Scope { - for _, f := range funcs { - (*f)(scope) - if scope.skipLeft { - break - } - } - return scope -} - -func (scope *Scope) updatedAttrsWithValues(values map[string]interface{}, ignoreProtectedAttrs bool) (results map[string]interface{}, hasUpdate bool) { - if !scope.IndirectValue().CanAddr() { - return values, true - } - - var hasExpr bool - fields := scope.Fields() - for key, value := range values { - if field, ok := fields[ToDBName(key)]; ok && field.Field.IsValid() { - if !reflect.DeepEqual(field.Field, reflect.ValueOf(value)) { - if _, ok := value.(*expr); ok { - hasExpr = true - } else if !equalAsString(field.Field.Interface(), value) { - hasUpdate = true - field.Set(value) - } - } - } - } - if hasExpr { - var updateMap = map[string]interface{}{} - for key, value := range fields { - if v, ok := values[key]; ok { - updateMap[key] = v - } else { - updateMap[key] = value.Field.Interface() - } - } - return updateMap, true - } - return -} - -func (scope *Scope) row() *sql.Row { - defer scope.Trace(NowFunc()) - scope.callCallbacks(scope.db.parent.callback.rowQueries) - scope.prepareQuerySql() - return scope.SqlDB().QueryRow(scope.Sql, scope.SqlVars...) -} - -func (scope *Scope) rows() (*sql.Rows, error) { - defer scope.Trace(NowFunc()) - scope.callCallbacks(scope.db.parent.callback.rowQueries) - scope.prepareQuerySql() - return scope.SqlDB().Query(scope.Sql, scope.SqlVars...) -} - -func (scope *Scope) initialize() *Scope { - for _, clause := range scope.Search.whereConditions { - scope.updatedAttrsWithValues(convertInterfaceToMap(clause["query"]), false) - } - scope.updatedAttrsWithValues(convertInterfaceToMap(scope.Search.initAttrs), false) - scope.updatedAttrsWithValues(convertInterfaceToMap(scope.Search.assignAttrs), false) - return scope -} - -func (scope *Scope) pluck(column string, value interface{}) *Scope { - dest := reflect.Indirect(reflect.ValueOf(value)) - scope.Search.Select(column) - if dest.Kind() != reflect.Slice { - scope.Err(fmt.Errorf("results should be a slice, not %s", dest.Kind())) - return scope - } - - rows, err := scope.rows() - if scope.Err(err) == nil { - defer rows.Close() - for rows.Next() { - elem := reflect.New(dest.Type().Elem()).Interface() - scope.Err(rows.Scan(elem)) - dest.Set(reflect.Append(dest, reflect.ValueOf(elem).Elem())) - } - } - return scope -} - -func (scope *Scope) count(value interface{}) *Scope { - scope.Search.Select("count(*)") - scope.Err(scope.row().Scan(value)) - return scope -} - -func (scope *Scope) typeName() string { - value := scope.IndirectValue() - if value.Kind() == reflect.Slice { - return value.Type().Elem().Name() - } - - return value.Type().Name() -} - -func (scope *Scope) related(value interface{}, foreignKeys ...string) *Scope { - toScope := scope.db.NewScope(value) - fromFields := scope.Fields() - toFields := toScope.Fields() - for _, foreignKey := range append(foreignKeys, toScope.typeName()+"Id", scope.typeName()+"Id") { - var fromField, toField *Field - if field, ok := scope.FieldByName(foreignKey); ok { - fromField = field - } else { - fromField = fromFields[ToDBName(foreignKey)] - } - if field, ok := toScope.FieldByName(foreignKey); ok { - toField = field - } else { - toField = toFields[ToDBName(foreignKey)] - } - - if fromField != nil { - if relationship := fromField.Relationship; relationship != nil { - if relationship.Kind == "many_to_many" { - joinTableHandler := relationship.JoinTableHandler - scope.Err(joinTableHandler.JoinWith(joinTableHandler, toScope.db, scope.Value).Find(value).Error) - } else if relationship.Kind == "belongs_to" { - sql := fmt.Sprintf("%v = ?", scope.Quote(toScope.PrimaryKey())) - foreignKeyValue := fromFields[relationship.ForeignDBName].Field.Interface() - scope.Err(toScope.db.Where(sql, foreignKeyValue).Find(value).Error) - } else if relationship.Kind == "has_many" || relationship.Kind == "has_one" { - sql := fmt.Sprintf("%v = ?", scope.Quote(relationship.ForeignDBName)) - query := toScope.db.Where(sql, scope.PrimaryKeyValue()) - if relationship.PolymorphicType != "" { - query = query.Where(fmt.Sprintf("%v = ?", scope.Quote(relationship.PolymorphicDBName)), scope.TableName()) - } - scope.Err(query.Find(value).Error) - } - } else { - sql := fmt.Sprintf("%v = ?", scope.Quote(toScope.PrimaryKey())) - scope.Err(toScope.db.Where(sql, fromField.Field.Interface()).Find(value).Error) - } - return scope - } else if toField != nil { - sql := fmt.Sprintf("%v = ?", scope.Quote(toField.DBName)) - scope.Err(toScope.db.Where(sql, scope.PrimaryKeyValue()).Find(value).Error) - return scope - } - } - - scope.Err(fmt.Errorf("invalid association %v", foreignKeys)) - return scope -} - -func (scope *Scope) createJoinTable(field *StructField) { - if relationship := field.Relationship; relationship != nil && relationship.JoinTableHandler != nil { - joinTableHandler := relationship.JoinTableHandler - joinTable := joinTableHandler.Table(scope.db) - if !scope.Dialect().HasTable(scope, joinTable) { - toScope := &Scope{Value: reflect.New(field.Struct.Type).Interface()} - - var sqlTypes []string - for _, s := range []*Scope{scope, toScope} { - for _, primaryField := range s.GetModelStruct().PrimaryFields { - value := reflect.Indirect(reflect.New(primaryField.Struct.Type)) - primaryKeySqlType := scope.Dialect().SqlTag(value, 255, false) - dbName := ToDBName(s.GetModelStruct().ModelType.Name() + primaryField.Name) - sqlTypes = append(sqlTypes, scope.Quote(dbName)+" "+primaryKeySqlType) - } - } - - scope.Err(scope.NewDB().Exec(fmt.Sprintf("CREATE TABLE %v (%v)", scope.Quote(joinTable), strings.Join(sqlTypes, ","))).Error) - } - scope.NewDB().Table(joinTable).AutoMigrate(joinTableHandler) - } -} - -func (scope *Scope) createTable() *Scope { - var tags []string - var primaryKeys []string - for _, field := range scope.GetStructFields() { - if field.IsNormal { - sqlTag := scope.generateSqlTag(field) - tags = append(tags, scope.Quote(field.DBName)+" "+sqlTag) - } - - if field.IsPrimaryKey { - primaryKeys = append(primaryKeys, scope.Quote(field.DBName)) - } - scope.createJoinTable(field) - } - - var primaryKeyStr string - if len(primaryKeys) > 0 { - primaryKeyStr = fmt.Sprintf(", PRIMARY KEY (%v)", strings.Join(primaryKeys, ",")) - } - scope.Raw(fmt.Sprintf("CREATE TABLE %v (%v %v)", scope.QuotedTableName(), strings.Join(tags, ","), primaryKeyStr)).Exec() - return scope -} - -func (scope *Scope) dropTable() *Scope { - scope.Raw(fmt.Sprintf("DROP TABLE %v", scope.QuotedTableName())).Exec() - return scope -} - -func (scope *Scope) dropTableIfExists() *Scope { - if scope.Dialect().HasTable(scope, scope.TableName()) { - scope.dropTable() - } - return scope -} - -func (scope *Scope) modifyColumn(column string, typ string) { - scope.Raw(fmt.Sprintf("ALTER TABLE %v MODIFY %v %v", scope.QuotedTableName(), scope.Quote(column), typ)).Exec() -} - -func (scope *Scope) dropColumn(column string) { - scope.Raw(fmt.Sprintf("ALTER TABLE %v DROP COLUMN %v", scope.QuotedTableName(), scope.Quote(column))).Exec() -} - -func (scope *Scope) addIndex(unique bool, indexName string, column ...string) { - if scope.Dialect().HasIndex(scope, scope.TableName(), indexName) { - return - } - - var columns []string - for _, name := range column { - if regexp.MustCompile("^[a-zA-Z]+$").MatchString(name) { - columns = append(columns, scope.Quote(name)) - } else { - columns = append(columns, name) - } - } - - sqlCreate := "CREATE INDEX" - if unique { - sqlCreate = "CREATE UNIQUE INDEX" - } - - scope.Raw(fmt.Sprintf("%s %v ON %v(%v);", sqlCreate, indexName, scope.QuotedTableName(), strings.Join(columns, ", "))).Exec() -} - -func (scope *Scope) addForeignKey(field string, dest string, onDelete string, onUpdate string) { - var table = scope.TableName() - var keyName = fmt.Sprintf("%s_%s_foreign", table, field) - var query = `ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s ON DELETE %s ON UPDATE %s;` - scope.Raw(fmt.Sprintf(query, scope.QuotedTableName(), scope.Quote(keyName), scope.Quote(field), scope.Quote(dest), onDelete, onUpdate)).Exec() -} - -func (scope *Scope) removeIndex(indexName string) { - scope.Dialect().RemoveIndex(scope, indexName) -} - -func (scope *Scope) autoMigrate() *Scope { - tableName := scope.TableName() - quotedTableName := scope.QuotedTableName() - - if !scope.Dialect().HasTable(scope, tableName) { - scope.createTable() - } else { - for _, field := range scope.GetStructFields() { - if !scope.Dialect().HasColumn(scope, tableName, field.DBName) { - if field.IsNormal { - sqlTag := scope.generateSqlTag(field) - scope.Raw(fmt.Sprintf("ALTER TABLE %v ADD %v %v;", quotedTableName, scope.Quote(field.DBName), sqlTag)).Exec() - } - } - scope.createJoinTable(field) - } - } - - scope.autoIndex() - return scope -} - -func (scope *Scope) autoIndex() *Scope { - var indexes = map[string][]string{} - var uniqueIndexes = map[string][]string{} - - for _, field := range scope.GetStructFields() { - sqlSettings := parseTagSetting(field.Tag.Get("sql")) - if name, ok := sqlSettings["INDEX"]; ok { - if name == "INDEX" { - name = fmt.Sprintf("idx_%v_%v", scope.TableName(), field.DBName) - } - indexes[name] = append(indexes[name], field.DBName) - } - - if name, ok := sqlSettings["UNIQUE_INDEX"]; ok { - if name == "UNIQUE_INDEX" { - name = fmt.Sprintf("uix_%v_%v", scope.TableName(), field.DBName) - } - uniqueIndexes[name] = append(uniqueIndexes[name], field.DBName) - } - } - - for name, columns := range indexes { - scope.addIndex(false, name, columns...) - } - - for name, columns := range uniqueIndexes { - scope.addIndex(true, name, columns...) - } - - return scope -} diff --git a/vendor/github.com/jinzhu/gorm/search.go b/vendor/github.com/jinzhu/gorm/search.go index 9411af431..8a4f4df6f 100644 --- a/vendor/github.com/jinzhu/gorm/search.go +++ b/vendor/github.com/jinzhu/gorm/search.go @@ -1,26 +1,30 @@ package gorm -import "fmt" +import ( + "fmt" + "regexp" +) type search struct { - db *DB - whereConditions []map[string]interface{} - orConditions []map[string]interface{} - notConditions []map[string]interface{} - havingCondition map[string]interface{} - initAttrs []interface{} - assignAttrs []interface{} - selects map[string]interface{} - omits []string - orders []string - joins string - preload []searchPreload - offset string - limit string - group string - tableName string - raw bool - Unscoped bool + db *DB + whereConditions []map[string]interface{} + orConditions []map[string]interface{} + notConditions []map[string]interface{} + havingConditions []map[string]interface{} + joinConditions []map[string]interface{} + initAttrs []interface{} + assignAttrs []interface{} + selects map[string]interface{} + omits []string + orders []interface{} + preload []searchPreload + offset interface{} + limit interface{} + group string + tableName string + raw bool + Unscoped bool + ignoreOrderQuery bool } type searchPreload struct { @@ -58,16 +62,24 @@ func (s *search) Assign(attrs ...interface{}) *search { return s } -func (s *search) Order(value string, reorder ...bool) *search { +func (s *search) Order(value interface{}, reorder ...bool) *search { if len(reorder) > 0 && reorder[0] { - s.orders = []string{value} - } else { + s.orders = []interface{}{} + } + + if value != nil { s.orders = append(s.orders, value) } return s } +var distinctSQLRegexp = regexp.MustCompile(`(?i)distinct[^a-z]+[a-z]+`) + func (s *search) Select(query interface{}, args ...interface{}) *search { + if distinctSQLRegexp.MatchString(fmt.Sprint(query)) { + s.ignoreOrderQuery = true + } + s.selects = map[string]interface{}{"query": query, "args": args} return s } @@ -77,28 +89,28 @@ func (s *search) Omit(columns ...string) *search { return s } -func (s *search) Limit(value interface{}) *search { - s.limit = s.getInterfaceAsSql(value) +func (s *search) Limit(limit interface{}) *search { + s.limit = limit return s } -func (s *search) Offset(value interface{}) *search { - s.offset = s.getInterfaceAsSql(value) +func (s *search) Offset(offset interface{}) *search { + s.offset = offset return s } func (s *search) Group(query string) *search { - s.group = s.getInterfaceAsSql(query) + s.group = s.getInterfaceAsSQL(query) return s } func (s *search) Having(query string, values ...interface{}) *search { - s.havingCondition = map[string]interface{}{"query": query, "args": values} + s.havingConditions = append(s.havingConditions, map[string]interface{}{"query": query, "args": values}) return s } -func (s *search) Joins(query string) *search { - s.joins = query +func (s *search) Joins(query string, values ...interface{}) *search { + s.joinConditions = append(s.joinConditions, map[string]interface{}{"query": query, "args": values}) return s } @@ -129,12 +141,12 @@ func (s *search) Table(name string) *search { return s } -func (s *search) getInterfaceAsSql(value interface{}) (str string) { +func (s *search) getInterfaceAsSQL(value interface{}) (str string) { switch value.(type) { case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: str = fmt.Sprintf("%v", value) default: - s.db.err(InvalidSql) + s.db.AddError(ErrInvalidSQL) } if str == "-1" { diff --git a/vendor/github.com/jinzhu/gorm/sqlite3.go b/vendor/github.com/jinzhu/gorm/sqlite3.go deleted file mode 100644 index afe70e3a1..000000000 --- a/vendor/github.com/jinzhu/gorm/sqlite3.go +++ /dev/null @@ -1,63 +0,0 @@ -package gorm - -import ( - "fmt" - "reflect" - "time" -) - -type sqlite3 struct { - commonDialect -} - -func (sqlite3) SqlTag(value reflect.Value, size int, autoIncrease bool) string { - switch value.Kind() { - case reflect.Bool: - return "bool" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr: - return "integer" - case reflect.Int64, reflect.Uint64: - if autoIncrease { - return "integer" - } - return "bigint" - case reflect.Float32, reflect.Float64: - return "real" - case reflect.String: - if size > 0 && size < 65532 { - return fmt.Sprintf("varchar(%d)", size) - } - return "text" - case reflect.Struct: - if _, ok := value.Interface().(time.Time); ok { - return "datetime" - } - default: - if _, ok := value.Interface().([]byte); ok { - return "blob" - } - } - panic(fmt.Sprintf("invalid sql type %s (%s) for sqlite3", value.Type().Name(), value.Kind().String())) -} - -func (sqlite3) HasTable(scope *Scope, tableName string) bool { - var count int - scope.NewDB().Raw("SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?", tableName).Row().Scan(&count) - return count > 0 -} - -func (sqlite3) HasColumn(scope *Scope, tableName string, columnName string) bool { - var count int - scope.NewDB().Raw(fmt.Sprintf("SELECT count(*) FROM sqlite_master WHERE tbl_name = ? AND (sql LIKE '%%(\"%v\" %%' OR sql LIKE '%%,\"%v\" %%' OR sql LIKE '%%( %v %%' OR sql LIKE '%%, %v %%');\n", columnName, columnName, columnName, columnName), tableName).Row().Scan(&count) - return count > 0 -} - -func (sqlite3) HasIndex(scope *Scope, tableName string, indexName string) bool { - var count int - scope.NewDB().Raw(fmt.Sprintf("SELECT count(*) FROM sqlite_master WHERE tbl_name = ? AND sql LIKE '%%INDEX %v ON%%'", indexName), tableName).Row().Scan(&count) - return count > 0 -} - -func (sqlite3) RemoveIndex(scope *Scope, indexName string) { - scope.NewDB().Exec(fmt.Sprintf("DROP INDEX %v", indexName)) -} diff --git a/vendor/github.com/jinzhu/gorm/utils.go b/vendor/github.com/jinzhu/gorm/utils.go index ca7e04e8e..ee663f345 100644 --- a/vendor/github.com/jinzhu/gorm/utils.go +++ b/vendor/github.com/jinzhu/gorm/utils.go @@ -2,13 +2,33 @@ package gorm import ( "bytes" + "database/sql/driver" + "fmt" + "reflect" + "regexp" + "runtime" "strings" + "sync" + "time" ) +// NowFunc returns current time, this function is exported in order to be able +// to give the flexibility to the developer to customize it according to their +// needs, e.g: +// gorm.NowFunc = func() time.Time { +// return time.Now().UTC() +// } +var NowFunc = func() time.Time { + return time.Now() +} + // Copied from golint var commonInitialisms = []string{"API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "LHS", "QPS", "RAM", "RHS", "RPC", "SLA", "SMTP", "SSH", "TLS", "TTL", "UI", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XSRF", "XSS"} var commonInitialismsReplacer *strings.Replacer +var goSrcRegexp = regexp.MustCompile(`jinzhu/gorm/.*.go`) +var goTestRegexp = regexp.MustCompile(`jinzhu/gorm/.*test.go`) + func init() { var commonInitialismsForReplacer []string for _, initialism := range commonInitialisms { @@ -17,32 +37,246 @@ func init() { commonInitialismsReplacer = strings.NewReplacer(commonInitialismsForReplacer...) } -var smap = map[string]string{} +type safeMap struct { + m map[string]string + l *sync.RWMutex +} + +func (s *safeMap) Set(key string, value string) { + s.l.Lock() + defer s.l.Unlock() + s.m[key] = value +} + +func (s *safeMap) Get(key string) string { + s.l.RLock() + defer s.l.RUnlock() + return s.m[key] +} + +func newSafeMap() *safeMap { + return &safeMap{l: new(sync.RWMutex), m: make(map[string]string)} +} + +var smap = newSafeMap() + +type strCase bool + +const ( + lower strCase = false + upper strCase = true +) +// ToDBName convert string to db name func ToDBName(name string) string { - if v, ok := smap[name]; ok { + if v := smap.Get(name); v != "" { return v } - value := commonInitialismsReplacer.Replace(name) - buf := bytes.NewBufferString("") - for i, v := range value { - if i > 0 && v >= 'A' && v <= 'Z' { - buf.WriteRune('_') + if name == "" { + return "" + } + + var ( + value = commonInitialismsReplacer.Replace(name) + buf = bytes.NewBufferString("") + lastCase, currCase, nextCase strCase + ) + + for i, v := range value[:len(value)-1] { + nextCase = strCase(value[i+1] >= 'A' && value[i+1] <= 'Z') + if i > 0 { + if currCase == upper { + if lastCase == upper && nextCase == upper { + buf.WriteRune(v) + } else { + if value[i-1] != '_' && value[i+1] != '_' { + buf.WriteRune('_') + } + buf.WriteRune(v) + } + } else { + buf.WriteRune(v) + } + } else { + currCase = upper + buf.WriteRune(v) } - buf.WriteRune(v) + lastCase = currCase + currCase = nextCase } + buf.WriteByte(value[len(value)-1]) + s := strings.ToLower(buf.String()) - smap[name] = s + smap.Set(name, s) return s } +// SQL expression type expr struct { expr string args []interface{} } +// Expr generate raw SQL expression, for example: +// DB.Model(&product).Update("price", gorm.Expr("price * ? + ?", 2, 100)) func Expr(expression string, args ...interface{}) *expr { return &expr{expr: expression, args: args} } + +func indirect(reflectValue reflect.Value) reflect.Value { + for reflectValue.Kind() == reflect.Ptr { + reflectValue = reflectValue.Elem() + } + return reflectValue +} + +func toQueryMarks(primaryValues [][]interface{}) string { + var results []string + + for _, primaryValue := range primaryValues { + var marks []string + for range primaryValue { + marks = append(marks, "?") + } + + if len(marks) > 1 { + results = append(results, fmt.Sprintf("(%v)", strings.Join(marks, ","))) + } else { + results = append(results, strings.Join(marks, "")) + } + } + return strings.Join(results, ",") +} + +func toQueryCondition(scope *Scope, columns []string) string { + var newColumns []string + for _, column := range columns { + newColumns = append(newColumns, scope.Quote(column)) + } + + if len(columns) > 1 { + return fmt.Sprintf("(%v)", strings.Join(newColumns, ",")) + } + return strings.Join(newColumns, ",") +} + +func toQueryValues(values [][]interface{}) (results []interface{}) { + for _, value := range values { + for _, v := range value { + results = append(results, v) + } + } + return +} + +func fileWithLineNum() string { + for i := 2; i < 15; i++ { + _, file, line, ok := runtime.Caller(i) + if ok && (!goSrcRegexp.MatchString(file) || goTestRegexp.MatchString(file)) { + return fmt.Sprintf("%v:%v", file, line) + } + } + return "" +} + +func isBlank(value reflect.Value) bool { + switch value.Kind() { + case reflect.String: + return value.Len() == 0 + case reflect.Bool: + return !value.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return value.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return value.Uint() == 0 + case reflect.Float32, reflect.Float64: + return value.Float() == 0 + case reflect.Interface, reflect.Ptr: + return value.IsNil() + } + + return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface()) +} + +func toSearchableMap(attrs ...interface{}) (result interface{}) { + if len(attrs) > 1 { + if str, ok := attrs[0].(string); ok { + result = map[string]interface{}{str: attrs[1]} + } + } else if len(attrs) == 1 { + if attr, ok := attrs[0].(map[string]interface{}); ok { + result = attr + } + + if attr, ok := attrs[0].(interface{}); ok { + result = attr + } + } + return +} + +func equalAsString(a interface{}, b interface{}) bool { + return toString(a) == toString(b) +} + +func toString(str interface{}) string { + if values, ok := str.([]interface{}); ok { + var results []string + for _, value := range values { + results = append(results, toString(value)) + } + return strings.Join(results, "_") + } else if bytes, ok := str.([]byte); ok { + return string(bytes) + } else if reflectValue := reflect.Indirect(reflect.ValueOf(str)); reflectValue.IsValid() { + return fmt.Sprintf("%v", reflectValue.Interface()) + } + return "" +} + +func makeSlice(elemType reflect.Type) interface{} { + if elemType.Kind() == reflect.Slice { + elemType = elemType.Elem() + } + sliceType := reflect.SliceOf(elemType) + slice := reflect.New(sliceType) + slice.Elem().Set(reflect.MakeSlice(sliceType, 0, 0)) + return slice.Interface() +} + +func strInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} + +// getValueFromFields return given fields's value +func getValueFromFields(value reflect.Value, fieldNames []string) (results []interface{}) { + // If value is a nil pointer, Indirect returns a zero Value! + // Therefor we need to check for a zero value, + // as FieldByName could panic + if indirectValue := reflect.Indirect(value); indirectValue.IsValid() { + for _, fieldName := range fieldNames { + if fieldValue := indirectValue.FieldByName(fieldName); fieldValue.IsValid() { + result := fieldValue.Interface() + if r, ok := result.(driver.Valuer); ok { + result, _ = r.Value() + } + results = append(results, result) + } + } + } + return +} + +func addExtraSpaceIfExist(str string) string { + if str != "" { + return " " + str + } + return "" +} diff --git a/vendor/github.com/jinzhu/gorm/utils_private.go b/vendor/github.com/jinzhu/gorm/utils_private.go deleted file mode 100644 index 6f609ae0e..000000000 --- a/vendor/github.com/jinzhu/gorm/utils_private.go +++ /dev/null @@ -1,73 +0,0 @@ -package gorm - -import ( - "fmt" - "reflect" - "regexp" - "runtime" -) - -func fileWithLineNum() string { - for i := 2; i < 15; i++ { - _, file, line, ok := runtime.Caller(i) - if ok && (!regexp.MustCompile(`jinzhu/gorm/.*.go`).MatchString(file) || regexp.MustCompile(`jinzhu/gorm/.*test.go`).MatchString(file)) { - return fmt.Sprintf("%v:%v", file, line) - } - } - return "" -} - -func isBlank(value reflect.Value) bool { - return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface()) -} - -func toSearchableMap(attrs ...interface{}) (result interface{}) { - if len(attrs) > 1 { - if str, ok := attrs[0].(string); ok { - result = map[string]interface{}{str: attrs[1]} - } - } else if len(attrs) == 1 { - if attr, ok := attrs[0].(map[string]interface{}); ok { - result = attr - } - - if attr, ok := attrs[0].(interface{}); ok { - result = attr - } - } - return -} - -func convertInterfaceToMap(values interface{}) map[string]interface{} { - attrs := map[string]interface{}{} - - switch value := values.(type) { - case map[string]interface{}: - for k, v := range value { - attrs[ToDBName(k)] = v - } - case []interface{}: - for _, v := range value { - for key, value := range convertInterfaceToMap(v) { - attrs[key] = value - } - } - case interface{}: - reflectValue := reflect.ValueOf(values) - - switch reflectValue.Kind() { - case reflect.Map: - for _, key := range reflectValue.MapKeys() { - attrs[ToDBName(key.Interface().(string))] = reflectValue.MapIndex(key).Interface() - } - default: - scope := Scope{Value: values} - for _, field := range scope.Fields() { - if !field.IsBlank && !field.IsIgnored { - attrs[field.DBName] = field.Field.Interface() - } - } - } - } - return attrs -} diff --git a/vendor/github.com/jinzhu/inflection/LICENSE b/vendor/github.com/jinzhu/inflection/LICENSE new file mode 100644 index 000000000..a1ca9a0ff --- /dev/null +++ b/vendor/github.com/jinzhu/inflection/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 - Jinzhu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/jinzhu/inflection/inflections.go b/vendor/github.com/jinzhu/inflection/inflections.go new file mode 100644 index 000000000..606263bb7 --- /dev/null +++ b/vendor/github.com/jinzhu/inflection/inflections.go @@ -0,0 +1,273 @@ +/* +Package inflection pluralizes and singularizes English nouns. + + inflection.Plural("person") => "people" + inflection.Plural("Person") => "People" + inflection.Plural("PERSON") => "PEOPLE" + + inflection.Singular("people") => "person" + inflection.Singular("People") => "Person" + inflection.Singular("PEOPLE") => "PERSON" + + inflection.Plural("FancyPerson") => "FancydPeople" + inflection.Singular("FancyPeople") => "FancydPerson" + +Standard rules are from Rails's ActiveSupport (https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflections.rb) + +If you want to register more rules, follow: + + inflection.AddUncountable("fish") + inflection.AddIrregular("person", "people") + inflection.AddPlural("(bu)s$", "${1}ses") # "bus" => "buses" / "BUS" => "BUSES" / "Bus" => "Buses" + inflection.AddSingular("(bus)(es)?$", "${1}") # "buses" => "bus" / "Buses" => "Bus" / "BUSES" => "BUS" +*/ +package inflection + +import ( + "regexp" + "strings" +) + +type inflection struct { + regexp *regexp.Regexp + replace string +} + +// Regular is a regexp find replace inflection +type Regular struct { + find string + replace string +} + +// Irregular is a hard replace inflection, +// containing both singular and plural forms +type Irregular struct { + singular string + plural string +} + +// RegularSlice is a slice of Regular inflections +type RegularSlice []Regular + +// IrregularSlice is a slice of Irregular inflections +type IrregularSlice []Irregular + +var pluralInflections = RegularSlice{ + {"([a-z])$", "${1}s"}, + {"s$", "s"}, + {"^(ax|test)is$", "${1}es"}, + {"(octop|vir)us$", "${1}i"}, + {"(octop|vir)i$", "${1}i"}, + {"(alias|status)$", "${1}es"}, + {"(bu)s$", "${1}ses"}, + {"(buffal|tomat)o$", "${1}oes"}, + {"([ti])um$", "${1}a"}, + {"([ti])a$", "${1}a"}, + {"sis$", "ses"}, + {"(?:([^f])fe|([lr])f)$", "${1}${2}ves"}, + {"(hive)$", "${1}s"}, + {"([^aeiouy]|qu)y$", "${1}ies"}, + {"(x|ch|ss|sh)$", "${1}es"}, + {"(matr|vert|ind)(?:ix|ex)$", "${1}ices"}, + {"^(m|l)ouse$", "${1}ice"}, + {"^(m|l)ice$", "${1}ice"}, + {"^(ox)$", "${1}en"}, + {"^(oxen)$", "${1}"}, + {"(quiz)$", "${1}zes"}, +} + +var singularInflections = RegularSlice{ + {"s$", ""}, + {"(ss)$", "${1}"}, + {"(n)ews$", "${1}ews"}, + {"([ti])a$", "${1}um"}, + {"((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$", "${1}sis"}, + {"(^analy)(sis|ses)$", "${1}sis"}, + {"([^f])ves$", "${1}fe"}, + {"(hive)s$", "${1}"}, + {"(tive)s$", "${1}"}, + {"([lr])ves$", "${1}f"}, + {"([^aeiouy]|qu)ies$", "${1}y"}, + {"(s)eries$", "${1}eries"}, + {"(m)ovies$", "${1}ovie"}, + {"(c)ookies$", "${1}ookie"}, + {"(x|ch|ss|sh)es$", "${1}"}, + {"^(m|l)ice$", "${1}ouse"}, + {"(bus)(es)?$", "${1}"}, + {"(o)es$", "${1}"}, + {"(shoe)s$", "${1}"}, + {"(cris|test)(is|es)$", "${1}is"}, + {"^(a)x[ie]s$", "${1}xis"}, + {"(octop|vir)(us|i)$", "${1}us"}, + {"(alias|status)(es)?$", "${1}"}, + {"^(ox)en", "${1}"}, + {"(vert|ind)ices$", "${1}ex"}, + {"(matr)ices$", "${1}ix"}, + {"(quiz)zes$", "${1}"}, + {"(database)s$", "${1}"}, +} + +var irregularInflections = IrregularSlice{ + {"person", "people"}, + {"man", "men"}, + {"child", "children"}, + {"sex", "sexes"}, + {"move", "moves"}, + {"mombie", "mombies"}, +} + +var uncountableInflections = []string{"equipment", "information", "rice", "money", "species", "series", "fish", "sheep", "jeans", "police"} + +var compiledPluralMaps []inflection +var compiledSingularMaps []inflection + +func compile() { + compiledPluralMaps = []inflection{} + compiledSingularMaps = []inflection{} + for _, uncountable := range uncountableInflections { + inf := inflection{ + regexp: regexp.MustCompile("^(?i)(" + uncountable + ")$"), + replace: "${1}", + } + compiledPluralMaps = append(compiledPluralMaps, inf) + compiledSingularMaps = append(compiledSingularMaps, inf) + } + + for _, value := range irregularInflections { + infs := []inflection{ + inflection{regexp: regexp.MustCompile(strings.ToUpper(value.singular) + "$"), replace: strings.ToUpper(value.plural)}, + inflection{regexp: regexp.MustCompile(strings.Title(value.singular) + "$"), replace: strings.Title(value.plural)}, + inflection{regexp: regexp.MustCompile(value.singular + "$"), replace: value.plural}, + } + compiledPluralMaps = append(compiledPluralMaps, infs...) + } + + for _, value := range irregularInflections { + infs := []inflection{ + inflection{regexp: regexp.MustCompile(strings.ToUpper(value.plural) + "$"), replace: strings.ToUpper(value.singular)}, + inflection{regexp: regexp.MustCompile(strings.Title(value.plural) + "$"), replace: strings.Title(value.singular)}, + inflection{regexp: regexp.MustCompile(value.plural + "$"), replace: value.singular}, + } + compiledSingularMaps = append(compiledSingularMaps, infs...) + } + + for i := len(pluralInflections) - 1; i >= 0; i-- { + value := pluralInflections[i] + infs := []inflection{ + inflection{regexp: regexp.MustCompile(strings.ToUpper(value.find)), replace: strings.ToUpper(value.replace)}, + inflection{regexp: regexp.MustCompile(value.find), replace: value.replace}, + inflection{regexp: regexp.MustCompile("(?i)" + value.find), replace: value.replace}, + } + compiledPluralMaps = append(compiledPluralMaps, infs...) + } + + for i := len(singularInflections) - 1; i >= 0; i-- { + value := singularInflections[i] + infs := []inflection{ + inflection{regexp: regexp.MustCompile(strings.ToUpper(value.find)), replace: strings.ToUpper(value.replace)}, + inflection{regexp: regexp.MustCompile(value.find), replace: value.replace}, + inflection{regexp: regexp.MustCompile("(?i)" + value.find), replace: value.replace}, + } + compiledSingularMaps = append(compiledSingularMaps, infs...) + } +} + +func init() { + compile() +} + +// AddPlural adds a plural inflection +func AddPlural(find, replace string) { + pluralInflections = append(pluralInflections, Regular{find, replace}) + compile() +} + +// AddSingular adds a singular inflection +func AddSingular(find, replace string) { + singularInflections = append(singularInflections, Regular{find, replace}) + compile() +} + +// AddIrregular adds an irregular inflection +func AddIrregular(singular, plural string) { + irregularInflections = append(irregularInflections, Irregular{singular, plural}) + compile() +} + +// AddUncountable adds an uncountable inflection +func AddUncountable(values ...string) { + uncountableInflections = append(uncountableInflections, values...) + compile() +} + +// GetPlural retrieves the plural inflection values +func GetPlural() RegularSlice { + plurals := make(RegularSlice, len(pluralInflections)) + copy(plurals, pluralInflections) + return plurals +} + +// GetSingular retrieves the singular inflection values +func GetSingular() RegularSlice { + singulars := make(RegularSlice, len(singularInflections)) + copy(singulars, singularInflections) + return singulars +} + +// GetIrregular retrieves the irregular inflection values +func GetIrregular() IrregularSlice { + irregular := make(IrregularSlice, len(irregularInflections)) + copy(irregular, irregularInflections) + return irregular +} + +// GetUncountable retrieves the uncountable inflection values +func GetUncountable() []string { + uncountables := make([]string, len(uncountableInflections)) + copy(uncountables, uncountableInflections) + return uncountables +} + +// SetPlural sets the plural inflections slice +func SetPlural(inflections RegularSlice) { + pluralInflections = inflections + compile() +} + +// SetSingular sets the singular inflections slice +func SetSingular(inflections RegularSlice) { + singularInflections = inflections + compile() +} + +// SetIrregular sets the irregular inflections slice +func SetIrregular(inflections IrregularSlice) { + irregularInflections = inflections + compile() +} + +// SetUncountable sets the uncountable inflections slice +func SetUncountable(inflections []string) { + uncountableInflections = inflections + compile() +} + +// Plural converts a word to its plural form +func Plural(str string) string { + for _, inflection := range compiledPluralMaps { + if inflection.regexp.MatchString(str) { + return inflection.regexp.ReplaceAllString(str, inflection.replace) + } + } + return str +} + +// Singular converts a word to its singular form +func Singular(str string) string { + for _, inflection := range compiledSingularMaps { + if inflection.regexp.MatchString(str) { + return inflection.regexp.ReplaceAllString(str, inflection.replace) + } + } + return str +} diff --git a/vendor/github.com/lib/pq/hstore/hstore.go b/vendor/github.com/lib/pq/hstore/hstore.go deleted file mode 100644 index 72d5abf51..000000000 --- a/vendor/github.com/lib/pq/hstore/hstore.go +++ /dev/null @@ -1,118 +0,0 @@ -package hstore - -import ( - "database/sql" - "database/sql/driver" - "strings" -) - -// A wrapper for transferring Hstore values back and forth easily. -type Hstore struct { - Map map[string]sql.NullString -} - -// escapes and quotes hstore keys/values -// s should be a sql.NullString or string -func hQuote(s interface{}) string { - var str string - switch v := s.(type) { - case sql.NullString: - if !v.Valid { - return "NULL" - } - str = v.String - case string: - str = v - default: - panic("not a string or sql.NullString") - } - - str = strings.Replace(str, "\\", "\\\\", -1) - return `"` + strings.Replace(str, "\"", "\\\"", -1) + `"` -} - -// Scan implements the Scanner interface. -// -// Note h.Map is reallocated before the scan to clear existing values. If the -// hstore column's database value is NULL, then h.Map is set to nil instead. -func (h *Hstore) Scan(value interface{}) error { - if value == nil { - h.Map = nil - return nil - } - h.Map = make(map[string]sql.NullString) - var b byte - pair := [][]byte{{}, {}} - pi := 0 - inQuote := false - didQuote := false - sawSlash := false - bindex := 0 - for bindex, b = range value.([]byte) { - if sawSlash { - pair[pi] = append(pair[pi], b) - sawSlash = false - continue - } - - switch b { - case '\\': - sawSlash = true - continue - case '"': - inQuote = !inQuote - if !didQuote { - didQuote = true - } - continue - default: - if !inQuote { - switch b { - case ' ', '\t', '\n', '\r': - continue - case '=': - continue - case '>': - pi = 1 - didQuote = false - continue - case ',': - s := string(pair[1]) - if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" { - h.Map[string(pair[0])] = sql.NullString{String: "", Valid: false} - } else { - h.Map[string(pair[0])] = sql.NullString{String: string(pair[1]), Valid: true} - } - pair[0] = []byte{} - pair[1] = []byte{} - pi = 0 - continue - } - } - } - pair[pi] = append(pair[pi], b) - } - if bindex > 0 { - s := string(pair[1]) - if !didQuote && len(s) == 4 && strings.ToLower(s) == "null" { - h.Map[string(pair[0])] = sql.NullString{String: "", Valid: false} - } else { - h.Map[string(pair[0])] = sql.NullString{String: string(pair[1]), Valid: true} - } - } - return nil -} - -// Value implements the driver Valuer interface. Note if h.Map is nil, the -// database column value will be set to NULL. -func (h Hstore) Value() (driver.Value, error) { - if h.Map == nil { - return nil, nil - } - parts := []string{} - for key, val := range h.Map { - thispart := hQuote(key) + "=>" + hQuote(val) - parts = append(parts, thispart) - } - return []byte(strings.Join(parts, ",")), nil -} From 7bceca2efd170c7032466b6b983d01f52db6986c Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Fri, 31 Mar 2017 15:26:23 -0700 Subject: [PATCH 42/62] addressing riyaz's review Signed-off-by: David Lawrence (github: endophage) --- trustpinning/certs_test.go | 52 ++++++++++++++++++++++++++++++++++- trustpinning/trustpin.go | 10 +++---- trustpinning/trustpin_test.go | 3 +- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/trustpinning/certs_test.go b/trustpinning/certs_test.go index cfed8dcb3..897da7cc5 100644 --- a/trustpinning/certs_test.go +++ b/trustpinning/certs_test.go @@ -364,7 +364,7 @@ func TestValidateRootWithPinnedCertAndIntermediates(t *testing.T) { } require.Equal(t, typedSignedRoot, validatedRoot) - // test is also works with a wildcarded gun in certs + // test it also works with a wildcarded gun in certs validatedRoot, err = trustpinning.ValidateRoot( nil, signedRoot, @@ -383,6 +383,56 @@ func TestValidateRootWithPinnedCertAndIntermediates(t *testing.T) { } } require.Equal(t, typedSignedRoot, validatedRoot) + + // incorrect key id on wildcard match should fail + _, err = trustpinning.ValidateRoot( + nil, + signedRoot, + "docker.io/notary/test", + trustpinning.TrustPinConfig{ + Certs: map[string][]string{ + "docker.io/notar*": {"badID"}, + }, + DisableTOFU: true, + }, + ) + require.Error(t, err, "failed to validate certID with intermediate") + + // exact match should take precedence even if it fails validation + _, err = trustpinning.ValidateRoot( + nil, + signedRoot, + "docker.io/notary/test", + trustpinning.TrustPinConfig{ + Certs: map[string][]string{ + "docker.io/notary/test": {"badID"}, + "docker.io/notar*": {ecdsax509Key.ID()}, + }, + DisableTOFU: true, + }, + ) + require.Error(t, err, "failed to validate certID with intermediate") + + // exact match should take precedence + validatedRoot, err = trustpinning.ValidateRoot( + nil, + signedRoot, + "docker.io/notary/test", + trustpinning.TrustPinConfig{ + Certs: map[string][]string{ + "docker.io/notary/test": {ecdsax509Key.ID()}, + "docker.io/notar*": {"badID"}, + }, + DisableTOFU: true, + }, + ) + require.NoError(t, err, "failed to validate certID with intermediate") + for idx, sig := range typedSignedRoot.Signatures { + if sig.KeyID == ecdsax509Key.ID() { + typedSignedRoot.Signatures[idx].IsValid = true + } + } + require.Equal(t, typedSignedRoot, validatedRoot) } func TestValidateRootFailuresWithPinnedCert(t *testing.T) { diff --git a/trustpinning/trustpin.go b/trustpinning/trustpin.go index 990d7ebf9..caa74d80d 100644 --- a/trustpinning/trustpin.go +++ b/trustpinning/trustpin.go @@ -136,11 +136,11 @@ func wildcardMatch(gun data.GUN, certs map[string][]string) ([]string, bool) { longest = "" ids []string ) - for k, v := range certs { - if strings.HasSuffix(k, "*") { - if strings.HasPrefix(gun.String(), k[:len(k)-1]) && len(k) > len(longest) { - longest = k - ids = v + for gunPrefix, keyIDs := range certs { + if strings.HasSuffix(gunPrefix, "*") { + if strings.HasPrefix(gun.String(), gunPrefix[:len(gunPrefix)-1]) && len(gunPrefix) > len(longest) { + longest = gunPrefix + ids = keyIDs } } } diff --git a/trustpinning/trustpin_test.go b/trustpinning/trustpin_test.go index daee80d7a..aa35fa663 100644 --- a/trustpinning/trustpin_test.go +++ b/trustpinning/trustpin_test.go @@ -25,7 +25,8 @@ func TestWildcardMatch(t *testing.T) { require.True(t, ok) // wildcardMatch should also match between segment boundaries, and take - // the first match is finds as the ONLY match. + // the longest match it finds as the ONLY match (i.e. there is no merging + // of key IDs when there are multiple matches). res, ok = wildcardMatch("docker.io/endophage/bar", testCerts) require.Len(t, res, 1) require.Equal(t, "def", res[0]) From 64da591d75640a91de248d0a9c0fa62da6744de5 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 27 Mar 2017 17:37:05 +0200 Subject: [PATCH 43/62] Add export tuf command Signed-off-by: Nassim 'Nass' Eddequiouaq --- cmd/notary/tuf.go | 119 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index 06ab4c804..7bccdd651 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -32,6 +32,10 @@ import ( "github.com/docker/notary/utils" "github.com/spf13/cobra" "github.com/spf13/viper" + "encoding/json" + "io" + "path/filepath" + "github.com/docker/docker/pkg/testutil/cmd" ) var cmdTUFListTemplate = usageTemplate{ @@ -106,6 +110,12 @@ var cmdTUFDeleteTemplate = usageTemplate{ Long: "Deletes all local content for a trusted collection identified by the Globally Unique Name. Remote data can also be deleted with an additional flag.", } +var cmdTUFExportTemplate = usageTemplate{ + Use: "export [ roles ... ]", + Short: "Export the listed role files for a trusted collection.", + Long: "Export the listed role files for a trusted collection identified by the Globally Unique Name in the appropriate TUF file structure.", +} + type tufCommander struct { // these need to be set configGetter func() (*viper.Viper, error) @@ -182,6 +192,115 @@ func (t *tufCommander) AddToCommand(cmd *cobra.Command) { cmdTUFDeleteGUN := cmdTUFDeleteTemplate.ToCommand(t.tufDeleteGUN) cmdTUFDeleteGUN.Flags().BoolVar(&t.deleteRemote, "remote", false, "Delete remote data for GUN in addition to local cache") cmd.AddCommand(cmdTUFDeleteGUN) + + cmdTUFExportGUN := cmdTUFExportTemplate.ToCommand(t.tufExportGUN) + cmdTUFExportGUN.Flags().StringVarP(&t.output, "output", "o", "", "File to export role files to") + cmd.AddCommand(cmdTUFExportGUN) +} + +func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + cmd.Usage() + return fmt.Errorf("Please provide a GUN") + } + + config, err := t.configGetter() + if err != nil { + return err + } + + gun := data.GUN(args[0]) + roles := data.NewRoleList(args[1:]) + + outDir := t.output + if outDir == "" { + currDir, err := os.Getwd() + if err != nil { + return err + } + + outDir = path.Join(currDir, filepath.FromSlash(gun.String())) + } + + rt, err := getTransport(config, gun, readOnly) + if err != nil { + return err + } + + trustPin, err := getTrustPinning(config) + if err != nil { + return err + } + + nRepo, err := notaryclient.NewFileCachedNotaryRepository( + config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) + if err != nil { + return err + } + + // a map of roles to target names and their associated json files + exportFiles := make(map[data.RoleName]map[string][]byte) + + if len(roles) == 0 { + roles := make([]data.RoleName, len(data.BaseRoles)) + copy(roles, data.BaseRoles) + } + + for _, role := range roles { + targets, err := nRepo.ListTargets(role) + if err != nil { + return err + } + + for _, target := range targets { + metadata, err := nRepo.GetAllTargetMetadataByName(target.Name) + if err != nil { + return err + } + + metadataJson, err := json.Marshal(metadata) + if err != nil { + return err + } + + if _, ok := exportFiles[role]; !ok { + exportFiles[role] = make(map[string][]byte) + + } + + exportFiles[role][target.Name] = metadataJson + } + } + + return exportGUNFiles(outDir, exportFiles, roles...) +} + +func exportGUNFiles(outDir string, roleNameToTargetFiles map[data.RoleName]map[string][]byte, roles ...data.RoleName) error { + err := os.MkdirAll(outDir, notary.PrivExecPerms) + if err != nil { + return nil + } + + for role, targetNamesToFiles := range roleNameToTargetFiles { + filename := strings.Join([]string{"0", role.String(), "json"}, ".") + outFile := path.Join(outDir, filename) + + if _, err := os.Stat(outFile); os.IsExist(err) { + logrus.Warnf("Trying to export files for role %s but file %s exists, overwriting.", role.String(), outFile) + } + + content, err := json.Marshal(targetNamesToFiles) + if err != nil { + return err + } + + logrus.Debugf("Exporting targets for role %s in file %s.", role, outFile) + if err := ioutil.WriteFile(outFile, content, notary.PrivNoExecPerms); err != nil { + return err + } + } + + return nil } func (t *tufCommander) tufWitness(cmd *cobra.Command, args []string) error { From fb3f1c3eed91da6b57591d2da8a7e6cde8b56cf7 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 28 Mar 2017 14:20:30 +0200 Subject: [PATCH 44/62] Fix export command for delegations Signed-off-by: Nassim 'Nass' Eddequiouaq --- cmd/notary/tuf.go | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index 7bccdd651..28bd26213 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -16,6 +16,7 @@ import ( "golang.org/x/crypto/ssh/terminal" + "encoding/json" "github.com/Sirupsen/logrus" "github.com/docker/distribution/registry/client/auth" "github.com/docker/distribution/registry/client/auth/challenge" @@ -32,10 +33,7 @@ import ( "github.com/docker/notary/utils" "github.com/spf13/cobra" "github.com/spf13/viper" - "encoding/json" - "io" "path/filepath" - "github.com/docker/docker/pkg/testutil/cmd" ) var cmdTUFListTemplate = usageTemplate{ @@ -111,9 +109,9 @@ var cmdTUFDeleteTemplate = usageTemplate{ } var cmdTUFExportTemplate = usageTemplate{ - Use: "export [ roles ... ]", + Use: "export [ roles ... ]", Short: "Export the listed role files for a trusted collection.", - Long: "Export the listed role files for a trusted collection identified by the Globally Unique Name in the appropriate TUF file structure.", + Long: "Export the listed role files for a trusted collection identified by the Globally Unique Name in the appropriate TUF file structure.", } type tufCommander struct { @@ -210,6 +208,7 @@ func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) + roles := data.NewRoleList(args[1:]) outDir := t.output @@ -238,14 +237,22 @@ func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { return err } - // a map of roles to target names and their associated json files - exportFiles := make(map[data.RoleName]map[string][]byte) - + // if no role is provided, we export all targets for each registered role if len(roles) == 0 { - roles := make([]data.RoleName, len(data.BaseRoles)) - copy(roles, data.BaseRoles) + rolesWithSig, err := nRepo.ListRoles() + if err != nil { + return err + } + + roles = make([]data.RoleName, len(rolesWithSig)) + for index, roleWithSig := range rolesWithSig { + roles[index] = roleWithSig.Name + } } + // a map of roles to target names and their associated json files + exportFiles := make(map[data.RoleName]map[string][]byte) + for _, role := range roles { targets, err := nRepo.ListTargets(role) if err != nil { @@ -272,6 +279,10 @@ func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { } } + if len(exportFiles) == 0 { + return nil + } + return exportGUNFiles(outDir, exportFiles, roles...) } @@ -282,8 +293,14 @@ func exportGUNFiles(outDir string, roleNameToTargetFiles map[data.RoleName]map[s } for role, targetNamesToFiles := range roleNameToTargetFiles { - filename := strings.Join([]string{"0", role.String(), "json"}, ".") - outFile := path.Join(outDir, filename) + targetPath := strings.Join([]string{"0", role.String(), "json"}, ".") + outFile := path.Join(outDir, targetPath) + + // Make sure the parent directory of the file is created (ex: "0.targets/" for "0.targets/foo.json") + err := os.MkdirAll(filepath.Dir(outFile), notary.PrivExecPerms) + if err != nil { + return nil + } if _, err := os.Stat(outFile); os.IsExist(err) { logrus.Warnf("Trying to export files for role %s but file %s exists, overwriting.", role.String(), outFile) From 475cb36248a2ce2983be382ad847cdcbced9eb47 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 28 Mar 2017 14:33:36 +0200 Subject: [PATCH 45/62] Do not duplicate targets for delegations Signed-off-by: Nassim 'Nass' Eddequiouaq --- cmd/notary/tuf.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index 28bd26213..d91e1b755 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -260,6 +260,11 @@ func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { } for _, target := range targets { + // do not duplicate export of delegation's targets + if target.Role != role { + continue + } + metadata, err := nRepo.GetAllTargetMetadataByName(target.Name) if err != nil { return err From e0c59b91e6c360eb4aaac390716182fa4c3d2b11 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 3 Apr 2017 20:16:38 +0200 Subject: [PATCH 46/62] Create an Export cache to hook on notary repo caching --- cmd/notary/util_exportstore.go | 71 ++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 cmd/notary/util_exportstore.go diff --git a/cmd/notary/util_exportstore.go b/cmd/notary/util_exportstore.go new file mode 100644 index 000000000..f685c1063 --- /dev/null +++ b/cmd/notary/util_exportstore.go @@ -0,0 +1,71 @@ +package main + +import ( + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/storage" +) + +// ExportStore is a wrapper around a Filesystem store which filters requested roles. +type ExportStore struct { + store *storage.FilesystemStore + Roles []data.RoleName +} + +func NewExportStore(baseDir, fileExt string, roles []data.RoleName) (*ExportStore, error) { + store, err := storage.NewFileStore(baseDir, fileExt) + if err != nil { + return nil, err + } + + return &ExportStore{ + store: store, + Roles: roles, + }, nil +} + +func (e *ExportStore) GetSized(name string, size int64) ([]byte, error) { + if len(e.Roles) == 0 { + return e.store.GetSized(name, size) + } + + for _, role := range e.Roles { + if name == role.String() { + return e.store.GetSized(name, size) + } + } + + return nil, storage.ErrMetaNotFound{Resource: name} +} + +func (e *ExportStore) Set(name string, blob []byte) error { + if len(e.Roles) == 0 { + return e.store.Set(name, blob) + } + + for _, role := range e.Roles { + if name == role.String() { + return e.store.Set(name, blob) + } + } + + return nil +} + +func (e *ExportStore) SetMulti(metas map[string][]byte) error { + for role, blob := range metas { + err := e.Set(role, blob) + if err != nil { + return err + } + } + + return nil +} + +func (e *ExportStore) RemoveAll() error { + return e.store.RemoveAll() +} + +func (e *ExportStore) Remove(name string) error { + return e.store.Remove(name) +} From 896913fa37a0adf6a6b8295ca5813a28f4506765 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 3 Apr 2017 20:18:18 +0200 Subject: [PATCH 47/62] Allow cache injection on top of configured notary repo Signed-off-by: Nassim 'Nass' Eddequiouaq --- client/client.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/client/client.go b/client/client.go index edbaeffbc..22beadf1a 100644 --- a/client/client.go +++ b/client/client.go @@ -16,6 +16,7 @@ import ( "github.com/docker/notary" "github.com/docker/notary/client/changelist" "github.com/docker/notary/cryptoservice" + "github.com/docker/notary/storage" store "github.com/docker/notary/storage" "github.com/docker/notary/trustpinning" "github.com/docker/notary/tuf" @@ -52,10 +53,8 @@ type NotaryRepository struct { legacyVersions int // number of versions back to fetch roots to sign with } -// NewFileCachedNotaryRepository is a wrapper for NewNotaryRepository that initializes -// a file cache from the provided repository, local config information and a crypto service. -// It also retrieves the remote store associated to the base directory under where all the -// trust files will be stored and the specified GUN. +// NewFileCachedNotaryRepository is a wrapper for NewCachedNotaryRepository and hence NewCachedNotaryRepository +// that initializes a file cache from the provided repository. func NewFileCachedNotaryRepository(baseDir string, gun data.GUN, baseURL string, rt http.RoundTripper, retriever notary.PassRetriever, trustPinning trustpinning.TrustPinConfig) ( *NotaryRepository, error) { @@ -68,6 +67,18 @@ func NewFileCachedNotaryRepository(baseDir string, gun data.GUN, baseURL string, return nil, err } + return NewCachedNotaryRepository(baseDir, gun, baseURL, rt, retriever, trustPinning, cache, nil) +} + +// NewCachedNotaryRepository is a wrapper for local NewNotaryRepository that initializes a config information and +// a crypto service. +// It also retrieves the remote store associated to the base directory under where all the +// trust files will be stored and the specified GUN. +func NewCachedNotaryRepository(baseDir string, gun data.GUN, baseURL string, rt http.RoundTripper, + retriever notary.PassRetriever, trustPinning trustpinning.TrustPinConfig, cache storage.MetadataStore, + tufRepo *tuf.Repo) ( + *NotaryRepository, error) { + keyStores, err := getKeyStores(baseDir, retriever) if err != nil { return nil, err @@ -88,7 +99,7 @@ func NewFileCachedNotaryRepository(baseDir string, gun data.GUN, baseURL string, return nil, err } - return NewNotaryRepository(baseDir, gun, baseURL, remoteStore, cache, trustPinning, cryptoService, cl) + return NewNotaryRepository(baseDir, gun, baseURL, remoteStore, cache, trustPinning, cryptoService, cl, tufRepo) } // NewNotaryRepository is the base method that returns a new notary repository. @@ -97,7 +108,7 @@ func NewFileCachedNotaryRepository(baseDir string, gun data.GUN, baseURL string, // docker content trust). // It expects an initialized remote store and cache. func NewNotaryRepository(baseDir string, gun data.GUN, baseURL string, remoteStore store.RemoteStore, cache store.MetadataStore, - trustPinning trustpinning.TrustPinConfig, cryptoService signed.CryptoService, cl changelist.Changelist) ( + trustPinning trustpinning.TrustPinConfig, cryptoService signed.CryptoService, cl changelist.Changelist, tufRepo *tuf.Repo) ( *NotaryRepository, error) { // Repo's remote store is either a valid remote store or an OfflineStore @@ -112,6 +123,7 @@ func NewNotaryRepository(baseDir string, gun data.GUN, baseURL string, remoteSto changelist: cl, cache: cache, remoteStore: remoteStore, + tufRepo: tufRepo, trustPinning: trustPinning, cryptoService: cryptoService, legacyVersions: 0, // By default, don't sign with legacy roles From f080c62193456a73b3e47bc2d1ca33e607300c17 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Mon, 3 Apr 2017 20:22:15 +0200 Subject: [PATCH 48/62] Refactor export cmd with a hook on the cache and add import through publish Signed-off-by: Nassim 'Nass' Eddequiouaq --- cmd/notary/tuf.go | 179 +++++++++++++++++++++++++++++----------------- 1 file changed, 115 insertions(+), 64 deletions(-) diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index d91e1b755..ed762d6f9 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -16,7 +16,6 @@ import ( "golang.org/x/crypto/ssh/terminal" - "encoding/json" "github.com/Sirupsen/logrus" "github.com/docker/distribution/registry/client/auth" "github.com/docker/distribution/registry/client/auth/challenge" @@ -29,11 +28,13 @@ import ( "github.com/docker/notary/trustmanager" "github.com/docker/notary/trustpinning" "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf" tufutils "github.com/docker/notary/tuf/utils" "github.com/docker/notary/utils" "github.com/spf13/cobra" "github.com/spf13/viper" "path/filepath" + "github.com/docker/notary/storage" ) var cmdTUFListTemplate = usageTemplate{ @@ -114,6 +115,12 @@ var cmdTUFExportTemplate = usageTemplate{ Long: "Export the listed role files for a trusted collection identified by the Globally Unique Name in the appropriate TUF file structure.", } +var cmdTUFImportTemplate = usageTemplate{ + Use: "import [ role files ... ]", + Short: "Import the listed role files for a trusted collection.", + Long: "Import the listed role files for a trusted collection identified by the Globally Unique Name from the appropriate TUF file structure.", +} + type tufCommander struct { // these need to be set configGetter func() (*viper.Viper, error) @@ -192,16 +199,19 @@ func (t *tufCommander) AddToCommand(cmd *cobra.Command) { cmd.AddCommand(cmdTUFDeleteGUN) cmdTUFExportGUN := cmdTUFExportTemplate.ToCommand(t.tufExportGUN) - cmdTUFExportGUN.Flags().StringVarP(&t.output, "output", "o", "", "File to export role files to") + cmdTUFExportGUN.Flags().StringVarP(&t.output, "output", "o", "", "Directory to export role files to") cmd.AddCommand(cmdTUFExportGUN) + + cmdTUFImportGUN := cmdTUFImportTemplate.ToCommand(t.tufImportGUN) + cmdTUFImportGUN.Flags().StringVarP(&t.input, "input", "i", "", "Directory to import role files from") + cmd.AddCommand(cmdTUFImportGUN) } -func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { +func (t *tufCommander) tufImportGUN(cmd *cobra.Command, args []string) error { if len(args) < 1 { cmd.Usage() return fmt.Errorf("Please provide a GUN") } - config, err := t.configGetter() if err != nil { return err @@ -211,16 +221,22 @@ func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { roles := data.NewRoleList(args[1:]) - outDir := t.output - if outDir == "" { + inDir := t.input + if inDir == "" { currDir, err := os.Getwd() if err != nil { return err } - outDir = path.Join(currDir, filepath.FromSlash(gun.String())) + inDir = path.Join(currDir, filepath.FromSlash(gun.String())) } + return importGUNRoles(config, gun, t.retriever, inDir, roles) +} + +func importGUNRoles(config *viper.Viper, gun data.GUN, retriever notary.PassRetriever, importDir string, roles []data.RoleName) error { + baseDir := config.GetString("trust_dir") + rt, err := getTransport(config, gun, readOnly) if err != nil { return err @@ -231,98 +247,133 @@ func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { return err } - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) + exportCache, err := NewExportStore(importDir, "json", roles) if err != nil { return err } - // if no role is provided, we export all targets for each registered role - if len(roles) == 0 { - rolesWithSig, err := nRepo.ListRoles() - if err != nil { - return err - } + exportRepo, err := notaryclient.NewCachedNotaryRepository( + baseDir, gun, getRemoteTrustServer(config), rt, retriever, + trustPin, exportCache, nil) + if err != nil { + return err + } - roles = make([]data.RoleName, len(rolesWithSig)) - for index, roleWithSig := range rolesWithSig { - roles[index] = roleWithSig.Name - } + // FIXME: use NewFileStore... and set nRepo.tufRepo when moving this code to notaryclient package. + refCache, err := storage.NewFileStore( + filepath.Join(baseDir, "tuf", filepath.FromSlash(gun.String()), "metadata"), "json", + ) + if err != nil { + return err } - // a map of roles to target names and their associated json files - exportFiles := make(map[data.RoleName]map[string][]byte) - for _, role := range roles { - targets, err := nRepo.ListTargets(role) - if err != nil { - return err - } + if len(roles) == 0 { + roles = data.BaseRoles + } - for _, target := range targets { - // do not duplicate export of delegation's targets - if target.Role != role { - continue - } + b := tuf.NewRepoBuilder(gun, exportRepo.CryptoService, trustPin) - metadata, err := nRepo.GetAllTargetMetadataByName(target.Name) - if err != nil { - return err - } + logrus.Debugf("Importing trusted collections.") - metadataJson, err := json.Marshal(metadata) - if err != nil { + // We load the rool role from the export directory + rootBytes, err := exportCache.GetSized(data.CanonicalRootRole.String(), storage.NoSizeLimit) + if err != nil { + if _, ok := err.(storage.ErrMetaNotFound); ok { + // Or from the reference cache if not provided + rootBytes, err = refCache.GetSized(data.CanonicalRootRole.String(), storage.NoSizeLimit) + if _, ok := err.(storage.ErrMetaNotFound); ok { return err } + } + } - if _, ok := exportFiles[role]; !ok { - exportFiles[role] = make(map[string][]byte) + if err := b.Load(data.CanonicalRootRole, rootBytes, 1, true); err != nil { + return err + } + + for _, role := range roles { + // We've already loaded root files + if role == data.CanonicalRootRole { + continue + } + jsonBytes, err := exportCache.GetSized(role.String(), storage.NoSizeLimit) + if err != nil { + if _, ok := err.(storage.ErrMetaNotFound); ok { + jsonBytes, err = refCache.GetSized(role.String(), storage.NoSizeLimit) + if _, ok := err.(storage.ErrMetaNotFound); ok { + return err + } } + } - exportFiles[role][target.Name] = metadataJson + if err := b.Load(role, jsonBytes, 1, true); err != nil { + return err } } - if len(exportFiles) == 0 { - return nil + tufRepo, _, err := b.Finish() + if err != nil { + return err + } + + refRepo, err := notaryclient.NewCachedNotaryRepository( + baseDir, gun, getRemoteTrustServer(config), rt, retriever, + trustPin, refCache, tufRepo) + if err != nil { + return err } - return exportGUNFiles(outDir, exportFiles, roles...) + return refRepo.Publish() } -func exportGUNFiles(outDir string, roleNameToTargetFiles map[data.RoleName]map[string][]byte, roles ...data.RoleName) error { - err := os.MkdirAll(outDir, notary.PrivExecPerms) +func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + cmd.Usage() + return fmt.Errorf("Please provide a GUN") + } + config, err := t.configGetter() if err != nil { - return nil + return err } - for role, targetNamesToFiles := range roleNameToTargetFiles { - targetPath := strings.Join([]string{"0", role.String(), "json"}, ".") - outFile := path.Join(outDir, targetPath) - - // Make sure the parent directory of the file is created (ex: "0.targets/" for "0.targets/foo.json") - err := os.MkdirAll(filepath.Dir(outFile), notary.PrivExecPerms) - if err != nil { - return nil - } + gun := data.GUN(args[0]) - if _, err := os.Stat(outFile); os.IsExist(err) { - logrus.Warnf("Trying to export files for role %s but file %s exists, overwriting.", role.String(), outFile) - } + roles := data.NewRoleList(args[1:]) - content, err := json.Marshal(targetNamesToFiles) + outDir := t.output + if outDir == "" { + currDir, err := os.Getwd() if err != nil { return err } - logrus.Debugf("Exporting targets for role %s in file %s.", role, outFile) - if err := ioutil.WriteFile(outFile, content, notary.PrivNoExecPerms); err != nil { - return err - } + outDir = path.Join(currDir, filepath.FromSlash(gun.String())) } - return nil + + rt, err := getTransport(config, gun, readOnly) + if err != nil { + return err + } + + trustPin, err := getTrustPinning(config) + if err != nil { + return err + } + + cache, err := NewExportStore(outDir, "json", roles) + if err != nil { + return err + } + + nRepo, err := notaryclient.NewCachedNotaryRepository(config.GetString("trust_dir"), gun, + getRemoteTrustServer(config), rt, t.retriever, trustPin, cache, nil) + if err != nil { + return err + } + return nRepo.Update(false) } func (t *tufCommander) tufWitness(cmd *cobra.Command, args []string) error { From b0b3c4da88e088e5bdcb9957205d2a3a33d24065 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 4 Apr 2017 02:05:35 +0200 Subject: [PATCH 49/62] Import hook on remote store's SetMulti rather than repo's Publish Signed-off-by: Nassim 'Nass' Eddequiouaq --- client/client.go | 8 ++++ client/helpers.go | 4 ++ cmd/notary/tuf.go | 81 ++++++---------------------------- cmd/notary/util_exportstore.go | 13 +++++- 4 files changed, 37 insertions(+), 69 deletions(-) diff --git a/client/client.go b/client/client.go index 22beadf1a..6bc5d971e 100644 --- a/client/client.go +++ b/client/client.go @@ -551,6 +551,14 @@ func (r *NotaryRepository) GetChangelist() (changelist.Changelist, error) { return r.changelist, nil } +func (r *NotaryRepository) GetRemoteStore() store.RemoteStore { + return r.remoteStore +} + +func (r *NotaryRepository) GetTUFRepo() *tuf.Repo { + return r.tufRepo +} + // getRemoteStore returns the remoteStore of a repository if valid or // or an OfflineStore otherwise func (r *NotaryRepository) getRemoteStore() store.RemoteStore { diff --git a/client/helpers.go b/client/helpers.go index ce24c87c5..1ced0301e 100644 --- a/client/helpers.go +++ b/client/helpers.go @@ -248,6 +248,10 @@ func rotateRemoteKey(role data.RoleName, remote store.RemoteStore) (data.PublicK return pubKey, nil } +func SerializeCanonicalRole(tufRepo *tuf.Repo, role data.RoleName, extraSigningKeys data.KeyList) (out []byte, err error) { + return serializeCanonicalRole(tufRepo, role, extraSigningKeys) +} + // signs and serializes the metadata for a canonical role in a TUF repo to JSON func serializeCanonicalRole(tufRepo *tuf.Repo, role data.RoleName, extraSigningKeys data.KeyList) (out []byte, err error) { var s *data.Signed diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index ed762d6f9..09234c5ad 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -28,7 +28,6 @@ import ( "github.com/docker/notary/trustmanager" "github.com/docker/notary/trustpinning" "github.com/docker/notary/tuf/data" - "github.com/docker/notary/tuf" tufutils "github.com/docker/notary/tuf/utils" "github.com/docker/notary/utils" "github.com/spf13/cobra" @@ -212,6 +211,7 @@ func (t *tufCommander) tufImportGUN(cmd *cobra.Command, args []string) error { cmd.Usage() return fmt.Errorf("Please provide a GUN") } + config, err := t.configGetter() if err != nil { return err @@ -220,6 +220,9 @@ func (t *tufCommander) tufImportGUN(cmd *cobra.Command, args []string) error { gun := data.GUN(args[0]) roles := data.NewRoleList(args[1:]) + if len(roles) == 0 { + roles = data.BaseRoles + } inDir := t.input if inDir == "" { @@ -231,13 +234,7 @@ func (t *tufCommander) tufImportGUN(cmd *cobra.Command, args []string) error { inDir = path.Join(currDir, filepath.FromSlash(gun.String())) } - return importGUNRoles(config, gun, t.retriever, inDir, roles) -} - -func importGUNRoles(config *viper.Viper, gun data.GUN, retriever notary.PassRetriever, importDir string, roles []data.RoleName) error { - baseDir := config.GetString("trust_dir") - - rt, err := getTransport(config, gun, readOnly) + rt, err := getTransport(config, gun, readWrite) if err != nil { return err } @@ -247,85 +244,35 @@ func importGUNRoles(config *viper.Viper, gun data.GUN, retriever notary.PassRetr return err } - exportCache, err := NewExportStore(importDir, "json", roles) - if err != nil { - return err - } - - exportRepo, err := notaryclient.NewCachedNotaryRepository( - baseDir, gun, getRemoteTrustServer(config), rt, retriever, - trustPin, exportCache, nil) + nRepo, err := notaryclient.NewFileCachedNotaryRepository( + config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) if err != nil { return err } - // FIXME: use NewFileStore... and set nRepo.tufRepo when moving this code to notaryclient package. - refCache, err := storage.NewFileStore( - filepath.Join(baseDir, "tuf", filepath.FromSlash(gun.String()), "metadata"), "json", - ) - if err != nil { + if err = nRepo.Update(false); err != nil { return err } - - if len(roles) == 0 { - roles = data.BaseRoles - } - - b := tuf.NewRepoBuilder(gun, exportRepo.CryptoService, trustPin) - - logrus.Debugf("Importing trusted collections.") - - // We load the rool role from the export directory - rootBytes, err := exportCache.GetSized(data.CanonicalRootRole.String(), storage.NoSizeLimit) + exportCache, err := NewExportStore(inDir, "json", roles) if err != nil { - if _, ok := err.(storage.ErrMetaNotFound); ok { - // Or from the reference cache if not provided - rootBytes, err = refCache.GetSized(data.CanonicalRootRole.String(), storage.NoSizeLimit) - if _, ok := err.(storage.ErrMetaNotFound); ok { - return err - } - } - } - - if err := b.Load(data.CanonicalRootRole, rootBytes, 1, true); err != nil { return err } + updatedRolefiles := make(map[data.RoleName][]byte) for _, role := range roles { - // We've already loaded root files - if role == data.CanonicalRootRole { - continue - } - jsonBytes, err := exportCache.GetSized(role.String(), storage.NoSizeLimit) + jsonByte, err := exportCache.GetSized(role.String(), storage.NoSizeLimit) if err != nil { - if _, ok := err.(storage.ErrMetaNotFound); ok { - jsonBytes, err = refCache.GetSized(role.String(), storage.NoSizeLimit) - if _, ok := err.(storage.ErrMetaNotFound); ok { - return err - } - } - } - - if err := b.Load(role, jsonBytes, 1, true); err != nil { return err } - } - tufRepo, _, err := b.Finish() - if err != nil { - return err + updatedRolefiles[role] = jsonByte } - refRepo, err := notaryclient.NewCachedNotaryRepository( - baseDir, gun, getRemoteTrustServer(config), rt, retriever, - trustPin, refCache, tufRepo) - if err != nil { - return err - } + remote := nRepo.GetRemoteStore() - return refRepo.Publish() + return remote.SetMulti(data.MetadataRoleMapToStringMap(updatedRolefiles)) } func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { diff --git a/cmd/notary/util_exportstore.go b/cmd/notary/util_exportstore.go index f685c1063..df6ee20f8 100644 --- a/cmd/notary/util_exportstore.go +++ b/cmd/notary/util_exportstore.go @@ -6,12 +6,16 @@ import ( ) // ExportStore is a wrapper around a Filesystem store which filters requested roles. +// It references the set of roles it contains for export and import and the cache +// from the reference repository. type ExportStore struct { store *storage.FilesystemStore Roles []data.RoleName + refCache *storage.FilesystemStore } -func NewExportStore(baseDir, fileExt string, roles []data.RoleName) (*ExportStore, error) { +func NewExportStore(baseDir, fileExt string, roles []data.RoleName) ( + *ExportStore, error) { store, err := storage.NewFileStore(baseDir, fileExt) if err != nil { return nil, err @@ -30,7 +34,12 @@ func (e *ExportStore) GetSized(name string, size int64) ([]byte, error) { for _, role := range e.Roles { if name == role.String() { - return e.store.GetSized(name, size) + jsonBytes, err := e.store.GetSized(name, size) + if err != nil { + return nil, err + } + + return jsonBytes, nil } } From 1949bf13b45aaa7ae056a13b1f94278d2f9c2f81 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Tue, 4 Apr 2017 02:25:46 +0200 Subject: [PATCH 50/62] Directly use HTTPStore as a remote to load the new metadata Signed-off-by: Nassim 'Nass' Eddequiouaq --- cmd/notary/tuf.go | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index 09234c5ad..8182203dc 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -239,21 +239,6 @@ func (t *tufCommander) tufImportGUN(cmd *cobra.Command, args []string) error { return err } - trustPin, err := getTrustPinning(config) - if err != nil { - return err - } - - nRepo, err := notaryclient.NewFileCachedNotaryRepository( - config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin) - if err != nil { - return err - } - - if err = nRepo.Update(false); err != nil { - return err - } - exportCache, err := NewExportStore(inDir, "json", roles) if err != nil { return err @@ -270,7 +255,13 @@ func (t *tufCommander) tufImportGUN(cmd *cobra.Command, args []string) error { updatedRolefiles[role] = jsonByte } - remote := nRepo.GetRemoteStore() + remote, err := storage.NewHTTPStore( + getRemoteTrustServer(config)+"/v2/"+gun.String()+"/_trust/tuf/", + "", + "json", + "key", + rt, + ) return remote.SetMulti(data.MetadataRoleMapToStringMap(updatedRolefiles)) } From bc0f3f1033765542e7c3f32c36cab5e2875398f9 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Tue, 11 Apr 2017 14:22:26 -0700 Subject: [PATCH 51/62] making lint,vet,etc... pass Signed-off-by: David Lawrence (github: endophage) --- client/client.go | 2 ++ client/helpers.go | 4 ---- cmd/notary/util_exportstore.go | 12 +++++++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/client/client.go b/client/client.go index 6bc5d971e..9b39ef42e 100644 --- a/client/client.go +++ b/client/client.go @@ -551,10 +551,12 @@ func (r *NotaryRepository) GetChangelist() (changelist.Changelist, error) { return r.changelist, nil } +// GetRemoteStore returns the remoteStore in use for this NotaryRepository func (r *NotaryRepository) GetRemoteStore() store.RemoteStore { return r.remoteStore } +// GetTUFRepo returns the instance of the tuf.Repo being used by this NotaryRepository func (r *NotaryRepository) GetTUFRepo() *tuf.Repo { return r.tufRepo } diff --git a/client/helpers.go b/client/helpers.go index 1ced0301e..ce24c87c5 100644 --- a/client/helpers.go +++ b/client/helpers.go @@ -248,10 +248,6 @@ func rotateRemoteKey(role data.RoleName, remote store.RemoteStore) (data.PublicK return pubKey, nil } -func SerializeCanonicalRole(tufRepo *tuf.Repo, role data.RoleName, extraSigningKeys data.KeyList) (out []byte, err error) { - return serializeCanonicalRole(tufRepo, role, extraSigningKeys) -} - // signs and serializes the metadata for a canonical role in a TUF repo to JSON func serializeCanonicalRole(tufRepo *tuf.Repo, role data.RoleName, extraSigningKeys data.KeyList) (out []byte, err error) { var s *data.Signed diff --git a/cmd/notary/util_exportstore.go b/cmd/notary/util_exportstore.go index df6ee20f8..ff21e5680 100644 --- a/cmd/notary/util_exportstore.go +++ b/cmd/notary/util_exportstore.go @@ -1,19 +1,20 @@ package main import ( - "github.com/docker/notary/tuf/data" "github.com/docker/notary/storage" + "github.com/docker/notary/tuf/data" ) // ExportStore is a wrapper around a Filesystem store which filters requested roles. // It references the set of roles it contains for export and import and the cache // from the reference repository. type ExportStore struct { - store *storage.FilesystemStore - Roles []data.RoleName + store *storage.FilesystemStore + Roles []data.RoleName refCache *storage.FilesystemStore } +// NewExportStore returns a new instance of an ExportStore func NewExportStore(baseDir, fileExt string, roles []data.RoleName) ( *ExportStore, error) { store, err := storage.NewFileStore(baseDir, fileExt) @@ -27,6 +28,7 @@ func NewExportStore(baseDir, fileExt string, roles []data.RoleName) ( }, nil } +// GetSized returns the file requested by name, up to size bytes func (e *ExportStore) GetSized(name string, size int64) ([]byte, error) { if len(e.Roles) == 0 { return e.store.GetSized(name, size) @@ -46,6 +48,7 @@ func (e *ExportStore) GetSized(name string, size int64) ([]byte, error) { return nil, storage.ErrMetaNotFound{Resource: name} } +// Set sets the value for the provided name func (e *ExportStore) Set(name string, blob []byte) error { if len(e.Roles) == 0 { return e.store.Set(name, blob) @@ -60,6 +63,7 @@ func (e *ExportStore) Set(name string, blob []byte) error { return nil } +// SetMulti sets the values for all names in the metas map func (e *ExportStore) SetMulti(metas map[string][]byte) error { for role, blob := range metas { err := e.Set(role, blob) @@ -71,10 +75,12 @@ func (e *ExportStore) SetMulti(metas map[string][]byte) error { return nil } +// RemoveAll cleans out the store func (e *ExportStore) RemoveAll() error { return e.store.RemoveAll() } +// Remove deletes a single item, references by name, from the store func (e *ExportStore) Remove(name string) error { return e.store.Remove(name) } From 8583f60bc9a9776cc5d1feebe38c4f1f501e8fe4 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Tue, 11 Apr 2017 14:28:14 -0700 Subject: [PATCH 52/62] some cleanup of the export store Signed-off-by: David Lawrence (github: endophage) --- cmd/notary/tuf.go | 5 +- cmd/notary/util_exportstore.go | 86 ---------------------------------- storage/role_filter.go | 74 +++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 89 deletions(-) delete mode 100644 cmd/notary/util_exportstore.go create mode 100644 storage/role_filter.go diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index 8182203dc..111420db0 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -25,6 +25,7 @@ import ( notaryclient "github.com/docker/notary/client" "github.com/docker/notary/cryptoservice" "github.com/docker/notary/passphrase" + "github.com/docker/notary/storage" "github.com/docker/notary/trustmanager" "github.com/docker/notary/trustpinning" "github.com/docker/notary/tuf/data" @@ -33,7 +34,6 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "path/filepath" - "github.com/docker/notary/storage" ) var cmdTUFListTemplate = usageTemplate{ @@ -290,7 +290,6 @@ func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { outDir = path.Join(currDir, filepath.FromSlash(gun.String())) } - rt, err := getTransport(config, gun, readOnly) if err != nil { return err @@ -301,7 +300,7 @@ func (t *tufCommander) tufExportGUN(cmd *cobra.Command, args []string) error { return err } - cache, err := NewExportStore(outDir, "json", roles) + cache, err := storage.NewRoleFilter(outDir, "json", roles) if err != nil { return err } diff --git a/cmd/notary/util_exportstore.go b/cmd/notary/util_exportstore.go deleted file mode 100644 index ff21e5680..000000000 --- a/cmd/notary/util_exportstore.go +++ /dev/null @@ -1,86 +0,0 @@ -package main - -import ( - "github.com/docker/notary/storage" - "github.com/docker/notary/tuf/data" -) - -// ExportStore is a wrapper around a Filesystem store which filters requested roles. -// It references the set of roles it contains for export and import and the cache -// from the reference repository. -type ExportStore struct { - store *storage.FilesystemStore - Roles []data.RoleName - refCache *storage.FilesystemStore -} - -// NewExportStore returns a new instance of an ExportStore -func NewExportStore(baseDir, fileExt string, roles []data.RoleName) ( - *ExportStore, error) { - store, err := storage.NewFileStore(baseDir, fileExt) - if err != nil { - return nil, err - } - - return &ExportStore{ - store: store, - Roles: roles, - }, nil -} - -// GetSized returns the file requested by name, up to size bytes -func (e *ExportStore) GetSized(name string, size int64) ([]byte, error) { - if len(e.Roles) == 0 { - return e.store.GetSized(name, size) - } - - for _, role := range e.Roles { - if name == role.String() { - jsonBytes, err := e.store.GetSized(name, size) - if err != nil { - return nil, err - } - - return jsonBytes, nil - } - } - - return nil, storage.ErrMetaNotFound{Resource: name} -} - -// Set sets the value for the provided name -func (e *ExportStore) Set(name string, blob []byte) error { - if len(e.Roles) == 0 { - return e.store.Set(name, blob) - } - - for _, role := range e.Roles { - if name == role.String() { - return e.store.Set(name, blob) - } - } - - return nil -} - -// SetMulti sets the values for all names in the metas map -func (e *ExportStore) SetMulti(metas map[string][]byte) error { - for role, blob := range metas { - err := e.Set(role, blob) - if err != nil { - return err - } - } - - return nil -} - -// RemoveAll cleans out the store -func (e *ExportStore) RemoveAll() error { - return e.store.RemoveAll() -} - -// Remove deletes a single item, references by name, from the store -func (e *ExportStore) Remove(name string) error { - return e.store.Remove(name) -} diff --git a/storage/role_filter.go b/storage/role_filter.go new file mode 100644 index 000000000..329823cb0 --- /dev/null +++ b/storage/role_filter.go @@ -0,0 +1,74 @@ +package storage + +import ( + "github.com/docker/notary/tuf/data" +) + +// RoleFilter is a wrapper around a MetadataStore which filters requested roles. +// It references the set of roles it contains for export and import and the cache +// from the reference repository. +type RoleFilter struct { + MetadataStore + Roles []data.RoleName +} + +// NewRoleFilter returns a new instance of an ExportStore +func NewRoleFilter(baseDir, fileExt string, roles []data.RoleName) ( + *RoleFilter, error) { + store, err := NewFileStore(baseDir, fileExt) + if err != nil { + return nil, err + } + + return &RoleFilter{ + MetadataStore: store, + Roles: roles, + }, nil +} + +// GetSized returns the file requested by name, up to size bytes +func (e *RoleFilter) GetSized(name string, size int64) ([]byte, error) { + if len(e.Roles) == 0 { + return e.MetadataStore.GetSized(name, size) + } + + for _, role := range e.Roles { + if name == role.String() { + jsonBytes, err := e.MetadataStore.GetSized(name, size) + if err != nil { + return nil, err + } + + return jsonBytes, nil + } + } + + return nil, ErrMetaNotFound{Resource: name} +} + +// Set sets the value for the provided name +func (e *RoleFilter) Set(name string, blob []byte) error { + if len(e.Roles) == 0 { + return e.MetadataStore.Set(name, blob) + } + + for _, role := range e.Roles { + if name == role.String() { + return e.MetadataStore.Set(name, blob) + } + } + + return nil +} + +// SetMulti sets the values for all names in the metas map +func (e *RoleFilter) SetMulti(metas map[string][]byte) error { + for role, blob := range metas { + err := e.Set(role, blob) + if err != nil { + return err + } + } + + return nil +} From 62586ece8b899b0cea4d8dddb82336511610db1a Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Tue, 11 Apr 2017 14:34:04 -0700 Subject: [PATCH 53/62] making import super simple: "notary import gun role file" Signed-off-by: David Lawrence (github: endophage) --- cmd/notary/tuf.go | 47 ++++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index 111420db0..f7c5d4798 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -201,15 +201,13 @@ func (t *tufCommander) AddToCommand(cmd *cobra.Command) { cmdTUFExportGUN.Flags().StringVarP(&t.output, "output", "o", "", "Directory to export role files to") cmd.AddCommand(cmdTUFExportGUN) - cmdTUFImportGUN := cmdTUFImportTemplate.ToCommand(t.tufImportGUN) - cmdTUFImportGUN.Flags().StringVarP(&t.input, "input", "i", "", "Directory to import role files from") - cmd.AddCommand(cmdTUFImportGUN) + cmd.AddCommand(cmdTUFImportTemplate.ToCommand(t.tufImportGUN)) } func (t *tufCommander) tufImportGUN(cmd *cobra.Command, args []string) error { - if len(args) < 1 { + if len(args) < 3 { cmd.Usage() - return fmt.Errorf("Please provide a GUN") + return fmt.Errorf("Please provide a GUN, role, and file to import") } config, err := t.configGetter() @@ -218,41 +216,28 @@ func (t *tufCommander) tufImportGUN(cmd *cobra.Command, args []string) error { } gun := data.GUN(args[0]) - - roles := data.NewRoleList(args[1:]) - if len(roles) == 0 { - roles = data.BaseRoles - } - - inDir := t.input - if inDir == "" { - currDir, err := os.Getwd() - if err != nil { - return err - } - - inDir = path.Join(currDir, filepath.FromSlash(gun.String())) - } + role := data.RoleName(args[1]) + file := args[2] rt, err := getTransport(config, gun, readWrite) if err != nil { return err } - exportCache, err := NewExportStore(inDir, "json", roles) + fileData, err := ioutil.ReadFile(file) if err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("file does not exist: %s", file) + } return err } - updatedRolefiles := make(map[data.RoleName][]byte) - for _, role := range roles { - - jsonByte, err := exportCache.GetSized(role.String(), storage.NoSizeLimit) - if err != nil { - return err - } + if !data.ValidRole(role) { + return fmt.Errorf("role \"%s\" is not a valid role name", role) + } - updatedRolefiles[role] = jsonByte + updatedRolefiles := map[data.RoleName][]byte{ + role: fileData, } remote, err := storage.NewHTTPStore( @@ -263,6 +248,10 @@ func (t *tufCommander) tufImportGUN(cmd *cobra.Command, args []string) error { rt, ) + if err != nil { + return err + } + return remote.SetMulti(data.MetadataRoleMapToStringMap(updatedRolefiles)) } From 2cc5c31636f532427e412f0b1a3510a3876414bf Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Mon, 3 Apr 2017 17:06:38 -0700 Subject: [PATCH 54/62] working basic version of add to file directly, no tests Signed-off-by: David Lawrence (github: endophage) add ability to sign with specific provided private keys. Still need to add CLI component, only underlying logic in place Signed-off-by: David Lawrence (github: endophage) add ability to use signing keys from files on disk rather than key store Signed-off-by: David Lawrence (github: endophage) adding tests Signed-off-by: David Lawrence (github: endophage) adding a test for parseKeysCerts Signed-off-by: David Lawrence (github: endophage) require an --output file for notary add(byhash) if an --input file is in use (and change --file to use the already standard -i/--input Signed-off-by: David Lawrence (github: endophage) --- client/isolated.go | 124 +++++++++++++++++ client/isolated_test.go | 176 ++++++++++++++++++++++++ cmd/notary/tuf.go | 100 +++++++++++--- cmd/notary/util.go | 51 +++++++ cmd/notary/util_test.go | 18 +++ fixtures/testkeys/targets_qa.priv | 9 ++ fixtures/testkeys/targets_qa.pub | 6 + fixtures/testkeys/targets_releases.priv | 9 ++ fixtures/testkeys/targets_releases.pub | 6 + tuf/signed/sign.go | 19 ++- 10 files changed, 496 insertions(+), 22 deletions(-) create mode 100644 client/isolated.go create mode 100644 client/isolated_test.go create mode 100644 fixtures/testkeys/targets_qa.priv create mode 100644 fixtures/testkeys/targets_qa.pub create mode 100644 fixtures/testkeys/targets_releases.priv create mode 100644 fixtures/testkeys/targets_releases.pub diff --git a/client/isolated.go b/client/isolated.go new file mode 100644 index 000000000..3cb42a96f --- /dev/null +++ b/client/isolated.go @@ -0,0 +1,124 @@ +package client + +import ( + "encoding/json" + "errors" + "github.com/Sirupsen/logrus" + "github.com/docker/notary" + "github.com/docker/notary/cryptoservice" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" + "io" + "io/ioutil" +) + +// AddTargetToFile adds the target to the file found at filePath, and writes the updated and re-signed version +// to the outBuf. +// If signingKeys are provided, they are used to sign the file. If lookupKeys are provided, they +// will be looked up in the CryptoService and used for signing where found. +// If _both_ signingKeys, and lookupKeys are provided, the public keys in lookupKeys will be added to signingKeys +// and the merged list will be used for signing. +// If _neither_ signingKeys, no lookupKeys are provided, the key IDs associated with any existing signatures are +// used to search for keys in the CryptoService and used to sign. +func AddTargetToFile(baseDir string, retriever notary.PassRetriever, outBuf io.Writer, filePath string, target *Target, signingKeys map[string]data.PrivateKey, lookupKeys map[string]data.PublicKey) error { + // do some setup + var fakeRole data.RoleName = data.CanonicalTargetsRole + ks, err := getKeyStores(baseDir, retriever) + if err != nil { + return err + } + cs := cryptoservice.NewCryptoService(ks...) + + var parsed *data.SignedTargets + if filePath == "-" { + // setting the filePath to "-" indicates we have no starting file, a new one should be created + parsed = data.NewTargets() + } else { + // read and parse input file + file, err := ioutil.ReadFile(filePath) + if err != nil { + return err + } + + parsed = &data.SignedTargets{} + err = json.Unmarshal(file, parsed) + if err != nil { + return err + } + } + + // add target + parsed.Signed.Targets[target.Name] = data.FileMeta{ + Length: target.Length, + Hashes: target.Hashes, + } + + // sign file + parsed.Signed.Expires = data.DefaultExpires(fakeRole) + parsed.Signed.Version = parsed.Signed.Version + 1 + signedObj, err := parsed.ToSigned() + if err != nil { + return err + } + + if signingKeys == nil { + // just in case, we don't want to panic when we try and assign + signingKeys = make(map[string]data.PrivateKey) + } + for canonID, pubKey := range lookupKeys { + privKey, _, err := cs.GetPrivateKey(canonID) + if err != nil { + // log the canonical ID as this would be the filename the person should look for + logrus.Errorf("key with ID %s not found", canonID) + continue + } + signingKeys[pubKey.ID()] = privKey + } + + err = signIsolated(cs, signedObj, signingKeys) + if err != nil { + return err + } + + // marshal and output to write buffer + out, err := json.Marshal(signedObj) + if err != nil { + return err + } + n, err := outBuf.Write(out) + if n < len(out) { + return errors.New("failed to write all output data") + } + return err +} + +func signIsolated(cs signed.CryptoService, signedObj *data.Signed, signingKeys map[string]data.PrivateKey) error { + if len(signingKeys) > 0 { + return signed.SignWithPrivateKeys( + signedObj, + signingKeys, + nil, + ) + } + // collect key IDs from current signatures + keys := make([]data.PublicKey, 0, len(signedObj.Signatures)) + for _, sig := range signedObj.Signatures { + logrus.Info("no signing keys provided, attempting to look up keys bsaed on existing signature key IDs.") + key := cs.GetKey(sig.KeyID) + if key == nil { + logrus.Infof("unable to find key with ID %s", sig.KeyID) + continue + } + keys = append(keys, key) + } + if len(keys) == 0 { + return errors.New("unable to find any signing keys") + } + return signed.Sign( + cs, + signedObj, + keys, + 1, + nil, + ) +} diff --git a/client/isolated_test.go b/client/isolated_test.go new file mode 100644 index 000000000..bf26bb298 --- /dev/null +++ b/client/isolated_test.go @@ -0,0 +1,176 @@ +package client + +import ( + "bytes" + "crypto/rand" + "github.com/docker/notary" + "github.com/docker/notary/cryptoservice" + "github.com/docker/notary/trustmanager" + "github.com/docker/notary/tuf/data" + tufutils "github.com/docker/notary/tuf/utils" + "github.com/stretchr/testify/require" + "io" + "io/ioutil" + "testing" +) + +func TestSignIsolated(t *testing.T) { + privKey, err := tufutils.GenerateECDSAKey(rand.Reader) + require.NoError(t, err) + + tgt := data.NewTargets() + sgnd, err := tgt.ToSigned() + require.NoError(t, err) + + require.NoError(t, signIsolated( + nil, // we don't use the cryptoservice when specific private keys are provided + sgnd, + map[string]data.PrivateKey{ + privKey.ID(): privKey, + }, + )) + + cs := cryptoservice.NewCryptoService( + trustmanager.NewKeyMemoryStore(passphraseRetriever), + ) + + // no signing keys provided and no keys in cryptoservice + require.Error(t, signIsolated( + cs, // we don't use the cryptoservice when specific private keys are provided + sgnd, + nil, + )) + + // add the key + require.NoError(t, cs.AddKey("targets", "", privKey)) + + // allow key to be detected via signature key ID + require.NoError(t, signIsolated( + cs, // we don't use the cryptoservice when specific private keys are provided + sgnd, + nil, + )) +} + +func TestAddTargetToFile(t *testing.T) { + tmpDir, err := ioutil.TempDir("", "notary-test-") + require.NoError(t, err) + + privKey, err := tufutils.GenerateECDSAKey(rand.Reader) + require.NoError(t, err) + + out := new(bytes.Buffer) + + require.NoError(t, AddTargetToFile( + tmpDir, + passphraseRetriever, + out, + "-", // create a new file + &Target{ + Name: "isolated", + Hashes: data.Hashes{ + notary.SHA256: []byte("abcdef"), + }, + Length: 0xdeadbeef, + }, + map[string]data.PrivateKey{ + privKey.ID(): privKey, + }, + nil, + )) + + tmpFile, err := ioutil.TempFile("", "notary-test-targets-") + require.NoError(t, err) + + io.Copy(tmpFile, out) + tmpFile.Close() + + filePath := tmpFile.Name() + + // check we error when no keys are provided and no keys are in the key storage + require.Error(t, AddTargetToFile( + tmpDir, + passphraseRetriever, + out, + filePath, + &Target{ + Name: "isolated", + Hashes: data.Hashes{ + notary.SHA256: []byte("abcdef"), + }, + Length: 0xdeadbeef, + }, + nil, + nil, + )) + + // reset out buffer + out = new(bytes.Buffer) + + require.NoError(t, AddTargetToFile( + tmpDir, + passphraseRetriever, + out, + filePath, + &Target{ + Name: "isolated", + Hashes: data.Hashes{ + notary.SHA256: []byte("abcdef"), + }, + Length: 0xdeadbeef, + }, + map[string]data.PrivateKey{ + privKey.ID(): privKey, + }, + nil, + )) + + // Add private key to key stores and check we can sign when + // looking up the signature ID + ks, err := getKeyStores(tmpDir, passphraseRetriever) + require.NoError(t, err) + cs := cryptoservice.NewCryptoService(ks...) + err = cs.AddKey("targets", "", privKey) + require.NoError(t, err) + + // reset out buffer + out = new(bytes.Buffer) + + require.NoError(t, AddTargetToFile( + tmpDir, + passphraseRetriever, + out, + filePath, // create a new file + &Target{ + Name: "isolated", + Hashes: data.Hashes{ + notary.SHA256: []byte("abcdef"), + }, + Length: 0xdeadbeef, + }, + nil, + nil, + )) + + // reset out buffer + out = new(bytes.Buffer) + + // check that we can sign when we provide lookup keys that are in the key store. + require.NoError(t, AddTargetToFile( + tmpDir, + passphraseRetriever, + out, + "-", // create a new file to guarantee we're not looking up signature key IDs + &Target{ + Name: "isolated", + Hashes: data.Hashes{ + notary.SHA256: []byte("abcdef"), + }, + Length: 0xdeadbeef, + }, + nil, + map[string]data.PublicKey{ + privKey.ID(): data.PublicKeyFromPrivate(privKey), + }, + )) +} diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index f7c5d4798..dae3879c4 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -3,6 +3,7 @@ package main import ( "bufio" "encoding/hex" + "errors" "fmt" "io/ioutil" "net" @@ -10,13 +11,16 @@ import ( "net/url" "os" "path" + "path/filepath" "strconv" "strings" "time" + "github.com/Sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/viper" "golang.org/x/crypto/ssh/terminal" - "github.com/Sirupsen/logrus" "github.com/docker/distribution/registry/client/auth" "github.com/docker/distribution/registry/client/auth/challenge" "github.com/docker/distribution/registry/client/transport" @@ -31,9 +35,6 @@ import ( "github.com/docker/notary/tuf/data" tufutils "github.com/docker/notary/tuf/utils" "github.com/docker/notary/utils" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "path/filepath" ) var cmdTUFListTemplate = usageTemplate{ @@ -45,13 +46,21 @@ var cmdTUFListTemplate = usageTemplate{ var cmdTUFAddTemplate = usageTemplate{ Use: "add [ GUN ] ", Short: "Adds the file as a target to the trusted collection.", - Long: "Adds the file as a target to the local trusted collection identified by the Globally Unique Name. This is an offline operation. Please then use `publish` to push the changes to the remote trusted collection.", + Long: "Adds the file as a target to the local trusted collection identified by the Globally Unique Name. This is an " + + "offline operation. Please then use `publish` to push the changes to the remote trusted collection. " + + "If the --input flag is provided with a path to a syntactically valid targets or delegation file, the provided target " + + "information will be added to that file instead, and the file will be re-signed with keys matching the IDs of existing " + + "signatures. If --input is used, a --output file path must also be provided.", } var cmdTUFAddHashTemplate = usageTemplate{ Use: "addhash [ GUN ] ", Short: "Adds the byte size and hash(es) as a target to the trusted collection.", - Long: "Adds the specified byte size and hash(es) as a target to the local trusted collection identified by the Globally Unique Name. This is an offline operation. Please then use `publish` to push the changes to the remote trusted collection.", + Long: "Adds the specified byte size and hash(es) as a target to the local trusted collection identified by the Globally Unique Name. This is an offline operation. " + + "Please then use `publish` to push the changes to the remote trusted collection." + + "If the --input flag is provided with a path to a syntactically valid targets or delegation file, the provided target " + + "information will be added to that file instead, and the file will be re-signed with keys matching the IDs of existing " + + "signatures. If --input is used, a --output file path must also be provided.", } var cmdTUFRemoveTemplate = usageTemplate{ @@ -126,10 +135,12 @@ type tufCommander struct { retriever notary.PassRetriever // these are for command line parsing - no need to set - roles []string - sha256 string - sha512 string - rootKey string + roles []string + sha256 string + sha512 string + rootKey string + privKeyPaths []string + certPaths []string input string output string @@ -168,7 +179,11 @@ func (t *tufCommander) AddToCommand(cmd *cobra.Command) { cmdTUFAdd := cmdTUFAddTemplate.ToCommand(t.tufAdd) cmdTUFAdd.Flags().StringSliceVarP(&t.roles, "roles", "r", nil, "Delegation roles to add this target to") + cmdTUFAdd.Flags().StringVarP(&t.input, "input", "i", "", "Specific file to add the target to") + cmdTUFAdd.Flags().StringVarP(&t.output, "output", "o", "", "File to output result to. Only used in tandem with --input.") cmdTUFAdd.Flags().BoolVarP(&t.autoPublish, "publish", "p", false, htAutoPublish) + cmdTUFAdd.Flags().StringSliceVar(&t.privKeyPaths, "keys", nil, "Private keys to sign with. Only valid if used with the --file flag") + cmdTUFAdd.Flags().StringSliceVar(&t.certPaths, "certs", nil, "Public certificates that match private keys found in the --keys flag, or are in the notary key storage. Only valid if used with the --file flag") cmd.AddCommand(cmdTUFAdd) cmdTUFRemove := cmdTUFRemoveTemplate.ToCommand(t.tufRemove) @@ -178,6 +193,10 @@ func (t *tufCommander) AddToCommand(cmd *cobra.Command) { cmdTUFAddHash := cmdTUFAddHashTemplate.ToCommand(t.tufAddByHash) cmdTUFAddHash.Flags().StringSliceVarP(&t.roles, "roles", "r", nil, "Delegation roles to add this target to") + cmdTUFAddHash.Flags().StringVarP(&t.input, "input", "i", "", "Specific file to add the target to") + cmdTUFAddHash.Flags().StringVarP(&t.output, "output", "o", "", "File to output result to. Only used in tandem with --input.") + cmdTUFAddHash.Flags().StringSliceVar(&t.privKeyPaths, "keys", nil, "Private keys to sign with. Only valid if used with the --file flag") + cmdTUFAddHash.Flags().StringSliceVar(&t.certPaths, "certs", nil, "Public certificates that match private keys found in the --keys flag, or are in the notary key storage. Only valid if used with the --file flag") cmdTUFAddHash.Flags().StringVar(&t.sha256, notary.SHA256, "", "hex encoded sha256 of the target to add") cmdTUFAddHash.Flags().StringVar(&t.sha512, notary.SHA512, "", "hex encoded sha512 of the target to add") cmdTUFAddHash.Flags().BoolVarP(&t.autoPublish, "publish", "p", false, htAutoPublish) @@ -381,12 +400,6 @@ func (t *tufCommander) tufAddByHash(cmd *cobra.Command, args []string) error { return err } - fact := ConfigureRepo(config, t.retriever, false) - nRepo, err := fact(gun) - if err != nil { - return err - } - targetHashes, err := getTargetHashes(t) if err != nil { return err @@ -395,6 +408,33 @@ func (t *tufCommander) tufAddByHash(cmd *cobra.Command, args []string) error { // Manually construct the target with the given byte size and hashes target := ¬aryclient.Target{Name: targetName, Hashes: targetHashes, Length: targetInt64Len} + if t.input != "" { + if t.output == "" { + return errors.New("you must provide an --output file when using an --input file") + } + fd, err := os.OpenFile(t.output, os.O_TRUNC, 0600) + if err != nil { + return err + } + defer fd.Close() + privKeys, pubKeys := parseKeysCerts(t.retriever, t.privKeyPaths, t.certPaths) + return notaryclient.AddTargetToFile( + config.GetString("trust_dir"), + t.retriever, + fd, + t.input, + target, + privKeys, + pubKeys, + ) + } + + fact := ConfigureRepo(config, t.retriever, false) + nRepo, err := fact(gun) + if err != nil { + return err + } + roleNames := data.NewRoleList(t.roles) // If roles is empty, we default to adding to targets @@ -428,16 +468,38 @@ func (t *tufCommander) tufAdd(cmd *cobra.Command, args []string) error { targetName := args[1] targetPath := args[2] - fact := ConfigureRepo(config, t.retriever, false) - nRepo, err := fact(gun) + target, err := notaryclient.NewTarget(targetName, targetPath) if err != nil { return err } - target, err := notaryclient.NewTarget(targetName, targetPath) + if t.input != "" { + if t.output == "" { + return errors.New("you must provide an --output file when using an --input file") + } + fd, err := os.OpenFile(t.output, os.O_TRUNC, 0600) + if err != nil { + return err + } + defer fd.Close() + privKeys, pubKeys := parseKeysCerts(t.retriever, t.privKeyPaths, t.certPaths) + return notaryclient.AddTargetToFile( + config.GetString("trust_dir"), + t.retriever, + fd, + t.input, + target, + privKeys, + pubKeys, + ) + } + + fact := ConfigureRepo(config, t.retriever, false) + nRepo, err := fact(gun) if err != nil { return err } + // If roles is empty, we default to adding to targets if err = nRepo.AddTarget(target, data.NewRoleList(t.roles)...); err != nil { return err diff --git a/cmd/notary/util.go b/cmd/notary/util.go index fef9e8dbe..f8fe8344e 100644 --- a/cmd/notary/util.go +++ b/cmd/notary/util.go @@ -2,6 +2,11 @@ package main import ( "fmt" + "github.com/Sirupsen/logrus" + "github.com/docker/notary" + "github.com/docker/notary/trustmanager" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/utils" "io/ioutil" "os" ) @@ -52,3 +57,49 @@ func feedback(t *tufCommander, payload []byte) error { os.Stdout.Write(payload) return nil } + +func parseKeysCerts(retriever notary.PassRetriever, privKeys []string, certs []string) (map[string]data.PrivateKey, map[string]data.PublicKey) { + privateKeys := make(map[string]data.PrivateKey) + idMap := make(map[string]data.PublicKey) + for _, fp := range certs { + byt, err := ioutil.ReadFile(fp) + if err != nil { + logrus.Errorf("could not read file at %s", fp) + continue + } + pubKey, err := utils.ParsePEMPublicKey(byt) + if err != nil { + logrus.Errorf("could not parse key found in file %s, received error: %s", fp, err.Error()) + continue + } + canonicalID, err := utils.CanonicalKeyID(pubKey) + if err != nil { + logrus.Errorf("could not generate canonical ID for key found in file %s, received error: %s", fp, err.Error()) + continue + } + idMap[canonicalID] = pubKey + } + + for _, fp := range privKeys { + byt, err := ioutil.ReadFile(fp) + if err != nil { + logrus.Errorf("could not read file at %s", fp) + continue + } + privKey, _, err := trustmanager.GetPasswdDecryptBytes(retriever, byt, "", fp) + if err != nil { + logrus.Errorf("could not parse key found in file %s, received error: %s", fp, err.Error()) + continue + } + if pubKey, ok := idMap[privKey.ID()]; ok { + // if we have a matching public key, use the non-canonical ID + privateKeys[pubKey.ID()] = privKey + // we found the key, remove it from the map + delete(idMap, pubKey.ID()) + } else { + privateKeys[privKey.ID()] = privKey + } + } + + return privateKeys, idMap +} diff --git a/cmd/notary/util_test.go b/cmd/notary/util_test.go index 8949ffd4c..5f29e22dd 100644 --- a/cmd/notary/util_test.go +++ b/cmd/notary/util_test.go @@ -7,6 +7,7 @@ import ( "path/filepath" "testing" + "github.com/docker/notary/passphrase" "github.com/stretchr/testify/require" ) @@ -52,3 +53,20 @@ func TestFeedback(t *testing.T) { require.NoError(t, err) require.Equal(t, "", string(content)) } + +func TestParseKeysCerts(t *testing.T) { + privKeys, certs := parseKeysCerts( + passphrase.ConstantRetriever(testPassphrase), + []string{ + "../../fixtures/testkeys/targets_releases.priv", + }, + []string{ + "../../fixtures/testkeys/targets_releases.pub", + "../../fixtures/testkeys/targets_qa.pub", + }, + ) + // we should match the target_releases pub and priv keys and + // end up with one entry in each map. + require.Len(t, privKeys, 1) + require.Len(t, certs, 1) +} diff --git a/fixtures/testkeys/targets_qa.priv b/fixtures/testkeys/targets_qa.priv new file mode 100644 index 000000000..0585d6825 --- /dev/null +++ b/fixtures/testkeys/targets_qa.priv @@ -0,0 +1,9 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,24e89012de0364ae7e6a40023048ade1 +role: targets/releases + +G3W+mR6KazkjpDEBM625NgttNleQ5k5flogcKc/m6RwKWdrBTOmWYT8QmD2Wg6IE +z3QH98X29+jA4LdiUY8PMftSLX/dh3S30v1vbUvkKxJ2U7LjS1jeOksygpBUSXc5 +lg1if2WgaehiAY1IkDXGeNIM/GBThIolhqebuRpURZM= +-----END EC PRIVATE KEY----- diff --git a/fixtures/testkeys/targets_qa.pub b/fixtures/testkeys/targets_qa.pub new file mode 100644 index 000000000..9709783b8 --- /dev/null +++ b/fixtures/testkeys/targets_qa.pub @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +role: targets/releases + +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoE5u6DkDwVnI52cFlYdIzDC+9lfR +WUVV4IcfiwQzulmg0Icj7/JmrXq1SVjKE9Naa1INXEjLEn6ii+21tv3i1A== +-----END PUBLIC KEY----- diff --git a/fixtures/testkeys/targets_releases.priv b/fixtures/testkeys/targets_releases.priv new file mode 100644 index 000000000..c9be223e1 --- /dev/null +++ b/fixtures/testkeys/targets_releases.priv @@ -0,0 +1,9 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,601e89562b2713552d762bbb4fc6cc3b +role: targets/releases + +HCbJQOUTliNkPutqrP+kHa9JMz5xbTMpi0o6Xs2Mv/07LR9LoU0/Nnq1nv0L+mPh +2sssRWJgrCbuOB0oMwkcckQaDK0NNvWn0kgzo0m83o7NepXWT2K5EwdYVhEyDAmA +Jg1ix6St/MepLo6B7qi33zLMMaUd2ZsoTPz+xC9a4lU= +-----END EC PRIVATE KEY----- diff --git a/fixtures/testkeys/targets_releases.pub b/fixtures/testkeys/targets_releases.pub new file mode 100644 index 000000000..4dead9a76 --- /dev/null +++ b/fixtures/testkeys/targets_releases.pub @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +role: targets/releases + +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/BBk0g+8Q9NXbjZlL4OxEIuWnuqe +EOa2E7yljHNChnnBfCvMpYXcdHKMDCBAAHEABqaQiJaBzMMLWJhYz+RvvA== +-----END PUBLIC KEY----- diff --git a/tuf/signed/sign.go b/tuf/signed/sign.go index 31abb1204..d9e1a2936 100644 --- a/tuf/signed/sign.go +++ b/tuf/signed/sign.go @@ -33,8 +33,6 @@ func Sign(service CryptoService, s *data.Signed, signingKeys []data.PublicKey, minSignatures int, otherWhitelistedKeys []data.PublicKey) error { logrus.Debugf("sign called with %d/%d required keys", minSignatures, len(signingKeys)) - signatures := make([]data.Signature, 0, len(s.Signatures)+1) - signingKeyIDs := make(map[string]struct{}) tufIDs := make(map[string]data.PublicKey) privKeys := make(map[string]data.PrivateKey) @@ -71,7 +69,22 @@ func Sign(service CryptoService, s *data.Signed, signingKeys []data.PublicKey, NeededKeys: minSignatures, MissingKeyIDs: missingKeyIDs} } - emptyStruct := struct{}{} + return SignWithPrivateKeys(s, privKeys, tufIDs) +} + +// SignWithPrivateKeys takes a data.Signed object a set of private keys, and a set of public keys. +// It signed the data.Signed object using the private keys, then prunes any old signatures, keeping +// only those that are still for a valid key (as indicated by presence in tufIDs), and for which the +// the signature is still valid. +// N.B. all new signatures generated from the list of private keys are kept regardless of whether they +// are valid or not. +// N.B.B the privKeys map _must_ use non-Canonical IDs if your public keys happen to be certificates. +func SignWithPrivateKeys(s *data.Signed, privKeys map[string]data.PrivateKey, tufIDs map[string]data.PublicKey) error { + var ( + signingKeyIDs = make(map[string]struct{}) + signatures = make([]data.Signature, 0, len(s.Signatures)+1) + emptyStruct = struct{}{} + ) // Do signing and generate list of signatures for keyID, pk := range privKeys { sig, err := pk.Sign(rand.Reader, *s.Signed, nil) From 9ab801d05327cd4264df851f0ff22857e6de016e Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 6 Apr 2017 23:25:08 -0700 Subject: [PATCH 55/62] generate any key and output it to a pair of .pub and .priv files Signed-off-by: David Lawrence (github: endophage) --- cmd/notary/keys.go | 123 ++++++++++++++++++++++++++------ cmd/notary/keys_test.go | 29 ++++++++ cryptoservice/crypto_service.go | 40 ++--------- tuf/utils/x509.go | 14 ++++ 4 files changed, 150 insertions(+), 56 deletions(-) diff --git a/cmd/notary/keys.go b/cmd/notary/keys.go index 5e70b6dd7..3ab977add 100644 --- a/cmd/notary/keys.go +++ b/cmd/notary/keys.go @@ -1,22 +1,26 @@ package main import ( + "encoding/pem" + "errors" "fmt" "io" + "io/ioutil" "os" "path/filepath" "strconv" "strings" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/docker/notary" "github.com/docker/notary/cryptoservice" store "github.com/docker/notary/storage" "github.com/docker/notary/trustmanager" "github.com/docker/notary/tuf/data" + tufutils "github.com/docker/notary/tuf/utils" "github.com/docker/notary/utils" - - "github.com/spf13/cobra" - "github.com/spf13/viper" ) var cmdKeyTemplate = usageTemplate{ @@ -37,10 +41,17 @@ var cmdRotateKeyTemplate = usageTemplate{ Long: `Generates a new key for the given Globally Unique Name and role (one of "snapshot", "targets", "root", or "timestamp"). If rotating to a server-managed key, a new key is requested from the server rather than generated. If the generation or key request is successful, the key rotation is immediately published. No other changes, even if they are staged, will be published.`, } -var cmdKeyGenerateRootKeyTemplate = usageTemplate{ +var cmdKeyGenerateKeyTemplate = usageTemplate{ Use: "generate [ algorithm ]", - Short: "Generates a new root key with a given algorithm.", - Long: "Generates a new root key with a given algorithm. If hardware key storage (e.g. a Yubikey) is available, the key will be stored both on hardware and on disk (so that it can be backed up). Please make sure to back up and then remove this on-key disk immediately afterwards.", + Short: "Generates a new key with a given algorithm.", + Long: "Generates a new key with a given algorithm. If hardware key " + + "storage (e.g. a Yubikey) is available, the key will be stored both " + + "on hardware and on disk (so that it can be backed up). Please make " + + "sure to back up and then remove this on-key disk immediately" + + "afterwards. If a `--output` file name is provided, two files will " + + "be written, .pub and .priv, containing the public" + + "and private keys respectively (the key will not be stored in Notary's " + + "key storage). If no `--role` is provided, \"root\" will be assumed.", } var cmdKeyRemoveTemplate = usageTemplate{ @@ -79,17 +90,29 @@ type keyCommander struct { legacyVersions int input io.Reader - keysImportRole string - keysImportGUN string - exportGUNs []string - exportKeyIDs []string - outFile string + importRole string + generateRole string + keysImportGUN string + exportGUNs []string + exportKeyIDs []string + outFile string } func (k *keyCommander) GetCommand() *cobra.Command { cmd := cmdKeyTemplate.ToCommand(nil) cmd.AddCommand(cmdKeyListTemplate.ToCommand(k.keysList)) - cmd.AddCommand(cmdKeyGenerateRootKeyTemplate.ToCommand(k.keysGenerateRootKey)) + cmdGenerate := cmdKeyGenerateKeyTemplate.ToCommand(k.keysGenerate) + cmdGenerate.Flags().StringVarP( + &k.outFile, + "output", + "o", + "", + "Filepath to write export output to", + ) + cmdGenerate.Flags().StringVarP( + &k.generateRole, "role", "r", "root", "Role to generate key with, defaulting to \"root\".", + ) + cmd.AddCommand(cmdGenerate) cmd.AddCommand(cmdKeyRemoveTemplate.ToCommand(k.keyRemove)) cmd.AddCommand(cmdKeyPasswdTemplate.ToCommand(k.keyPassphraseChange)) cmdRotateKey := cmdRotateKeyTemplate.ToCommand(k.keysRotate) @@ -109,7 +132,7 @@ func (k *keyCommander) GetCommand() *cobra.Command { cmdKeysImport := cmdKeyImportTemplate.ToCommand(k.importKeys) cmdKeysImport.Flags().StringVarP( - &k.keysImportRole, "role", "r", "", "Role to import key with, if a role is not already given in a PEM header") + &k.importRole, "role", "r", "", "Role to import key with, if a role is not already given in a PEM header") cmdKeysImport.Flags().StringVarP( &k.keysImportGUN, "gun", "g", "", "Gun to import key with, if a gun is not already given in a PEM header") cmd.AddCommand(cmdKeysImport) @@ -158,7 +181,7 @@ func (k *keyCommander) keysList(cmd *cobra.Command, args []string) error { return nil } -func (k *keyCommander) keysGenerateRootKey(cmd *cobra.Command, args []string) error { +func (k *keyCommander) keysGenerate(cmd *cobra.Command, args []string) error { // We require one or no arguments (since we have a default value), but if the // user passes in more than one argument, we error out. if len(args) > 1 { @@ -188,19 +211,77 @@ func (k *keyCommander) keysGenerateRootKey(cmd *cobra.Command, args []string) er if err != nil { return err } - ks, err := k.getKeyStores(config, true, true) + + // if no outFile is provided, use the known key stores + if k.outFile == "" { + ks, err := k.getKeyStores(config, true, true) + if err != nil { + return err + } + cs := cryptoservice.NewCryptoService(ks...) + + pubKey, err := cs.Create(data.RoleName(k.generateRole), "", algorithm) + if err != nil { + return fmt.Errorf("Failed to create a new root key: %v", err) + } + + cmd.Printf("Generated new %s %s key with keyID: %s\n", algorithm, k.generateRole, pubKey.ID()) + return nil + } + + // if we had an outfile set, we'll write 2 files with the given name, appending .pub and .priv for the + // public and private keys respectively + return generateKeyToFile(k.generateRole, algorithm, k.getRetriever(), k.outFile) +} + +func generateKeyToFile(role, algorithm string, retriever notary.PassRetriever, outFile string) error { + privKey, err := tufutils.GenerateKey(algorithm) if err != nil { return err } - cs := cryptoservice.NewCryptoService(ks...) + pubKey := data.PublicKeyFromPrivate(privKey) + + var ( + chosenPassphrase string + giveup bool + pemPrivKey []byte + ) + keyID := privKey.ID() + for attempts := 0; ; attempts++ { + chosenPassphrase, giveup, err = retriever(keyID, "", true, attempts) + if err == nil { + break + } + if giveup || attempts > 10 { + return trustmanager.ErrAttemptsExceeded{} + } + } - pubKey, err := cs.Create(data.CanonicalRootRole, "", algorithm) + if chosenPassphrase != "" { + pemPrivKey, err = tufutils.EncryptPrivateKey(privKey, data.RoleName(role), "", chosenPassphrase) + if err != nil { + return err + } + } else { + return errors.New("no password provided") + } + + privFile := strings.Join([]string{outFile, "priv"}, ".") + pubFile := strings.Join([]string{outFile, "pub"}, ".") + + err = ioutil.WriteFile(privFile, pemPrivKey, notary.PrivNoExecPerms) if err != nil { - return fmt.Errorf("Failed to create a new root key: %v", err) + return err } - cmd.Printf("Generated new %s root key with keyID: %s\n", algorithm, pubKey.ID()) - return nil + pubPEM := pem.Block{ + Type: "PUBLIC KEY", + Headers: map[string]string{ + "role": role, + }, + Bytes: pubKey.Public(), + } + return ioutil.WriteFile(pubFile, pem.EncodeToMemory(&pubPEM), notary.PrivNoExecPerms) } func (k *keyCommander) keysRotate(cmd *cobra.Command, args []string) error { @@ -430,7 +511,7 @@ func (k *keyCommander) importKeys(cmd *cobra.Command, args []string) error { return err } defer from.Close() - if err = utils.ImportKeys(from, importers, k.keysImportRole, k.keysImportGUN, k.getRetriever()); err != nil { + if err = utils.ImportKeys(from, importers, k.importRole, k.keysImportGUN, k.getRetriever()); err != nil { return err } } diff --git a/cmd/notary/keys_test.go b/cmd/notary/keys_test.go index da3573c32..dfaa46f09 100644 --- a/cmd/notary/keys_test.go +++ b/cmd/notary/keys_test.go @@ -30,6 +30,7 @@ import ( "github.com/docker/notary/trustpinning" "github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/utils" + "path/filepath" ) var ret = passphrase.ConstantRetriever("pass") @@ -806,3 +807,31 @@ func TestImportKeysNonexistentFile(t *testing.T) { err = k.importKeys(&cobra.Command{}, []string{"Idontexist"}) require.Error(t, err) } + +func TestKeyGeneration(t *testing.T) { + tempDir := tempDirWithConfig(t, "{}") + defer os.RemoveAll(tempDir) + + _, err := runCommand(t, tempDir, "key", "generate", data.ECDSAKey, "--role", "targets") + require.NoError(t, err) + assertNumKeys(t, tempDir, 0, 1, false) + + _, err = runCommand(t, tempDir, "key", "generate", data.ECDSAKey, "--role", "targets", "-o", filepath.Join(tempDir, "testkeys")) + require.NoError(t, err) + assertNumKeys(t, tempDir, 0, 1, false) // key shouldn't be written to store and won't show up in keylist + + // test that we can read the keys we created + pub, err := ioutil.ReadFile(filepath.Join(tempDir, "testkeys.pub")) + require.NoError(t, err) + pubK, err := utils.ParsePEMPublicKey(pub) + require.NoError(t, err) + + priv, err := ioutil.ReadFile(filepath.Join(tempDir, "testkeys.priv")) + require.NoError(t, err) + privK, err := utils.ParsePEMPrivateKey(priv, testPassphrase) + require.NoError(t, err) + + // the ID is only generated from the public part of the key so they should be identical + require.Equal(t, pubK.ID(), privK.ID()) + +} diff --git a/cryptoservice/crypto_service.go b/cryptoservice/crypto_service.go index d8f42535c..9cafb2816 100644 --- a/cryptoservice/crypto_service.go +++ b/cryptoservice/crypto_service.go @@ -1,14 +1,12 @@ package cryptoservice import ( - "crypto/rand" "fmt" "crypto/x509" "encoding/pem" "errors" "github.com/Sirupsen/logrus" - "github.com/docker/notary" "github.com/docker/notary/trustmanager" "github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/utils" @@ -37,42 +35,14 @@ func NewCryptoService(keyStores ...trustmanager.KeyStore) *CryptoService { // Create is used to generate keys for targets, snapshots and timestamps func (cs *CryptoService) Create(role data.RoleName, gun data.GUN, algorithm string) (data.PublicKey, error) { - var privKey data.PrivateKey - var err error - - switch algorithm { - case data.RSAKey: - privKey, err = utils.GenerateRSAKey(rand.Reader, notary.MinRSABitSize) - if err != nil { - return nil, fmt.Errorf("failed to generate RSA key: %v", err) - } - case data.ECDSAKey: - privKey, err = utils.GenerateECDSAKey(rand.Reader) - if err != nil { - return nil, fmt.Errorf("failed to generate EC key: %v", err) - } - case data.ED25519Key: - privKey, err = utils.GenerateED25519Key(rand.Reader) - if err != nil { - return nil, fmt.Errorf("failed to generate ED25519 key: %v", err) - } - default: - return nil, fmt.Errorf("private key type not supported for key generation: %s", algorithm) - } - logrus.Debugf("generated new %s key for role: %s and keyID: %s", algorithm, role.String(), privKey.ID()) - - // Store the private key into our keystore - for _, ks := range cs.keyStores { - err = ks.AddKey(trustmanager.KeyInfo{Role: role, Gun: gun}, privKey) - if err == nil { - return data.PublicKeyFromPrivate(privKey), nil - } - } + privKey, err := utils.GenerateKey(algorithm) if err != nil { - return nil, fmt.Errorf("failed to add key to filestore: %v", err) + return nil, fmt.Errorf("failed to generate %s key: %v", algorithm, err) } + logrus.Debugf("generated new %s key for role: %s and keyID: %s", algorithm, role.String(), privKey.ID()) + pubKey := data.PublicKeyFromPrivate(privKey) - return nil, fmt.Errorf("keystores would not accept new private keys for unknown reasons") + return pubKey, cs.AddKey(role, gun, privKey) } // GetPrivateKey returns a private key and role if present by ID. diff --git a/tuf/utils/x509.go b/tuf/utils/x509.go index 7cf8fff88..614d52d52 100644 --- a/tuf/utils/x509.go +++ b/tuf/utils/x509.go @@ -313,6 +313,20 @@ func ValidateCertificate(c *x509.Certificate, checkExpiry bool) error { return nil } +// GenerateKey returns a new private key using the provided algorithm or an +// error detailing why the key could not be generated +func GenerateKey(algorithm string) (data.PrivateKey, error) { + switch algorithm { + case data.RSAKey: + return GenerateRSAKey(rand.Reader, notary.MinRSABitSize) + case data.ECDSAKey: + return GenerateECDSAKey(rand.Reader) + case data.ED25519Key: + return GenerateED25519Key(rand.Reader) + } + return nil, fmt.Errorf("private key type not supported for key generation: %s", algorithm) +} + // GenerateRSAKey generates an RSA private key and returns a TUF PrivateKey func GenerateRSAKey(random io.Reader, bits int) (data.PrivateKey, error) { rsaPrivKey, err := rsa.GenerateKey(random, bits) From 1d4737b2bfb2ac5d84f96cc9c02fecd9feba5614 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 12 Apr 2017 17:12:06 -0700 Subject: [PATCH 56/62] bugfixes Signed-off-by: David Lawrence (github: endophage) --- Makefile | 2 +- client_api/api/server.go | 1 + cmd/notary/root-ca.crt | 52 ++++----- docker-compose.clientapi.yml | 17 ++- escrow.Dockerfile | 2 +- fixtures/clientapi-server-config.toml | 9 +- fixtures/clientapi-server.crt | 86 +++++++------- fixtures/escrow-config-local.toml | 6 +- fixtures/intermediate-ca.crt | 58 +++++----- fixtures/notary-escrow.crt | 64 ++++++++--- fixtures/notary-server.crt | 120 +++++++------------- fixtures/notary-signer.crt | 86 +++++++------- fixtures/regenerateTestingCerts.sh | 2 +- fixtures/root-ca.crt | 52 ++++----- fixtures/secure.example.com.crt | 28 ++--- fixtures/self-signed_docker.com-notary.crt | 18 +-- fixtures/self-signed_secure.example.com.crt | 14 +-- utils/configuration.go | 11 +- utils/transport.go | 3 +- 19 files changed, 323 insertions(+), 308 deletions(-) diff --git a/Makefile b/Makefile index ba28925a1..71502d3eb 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ ifneq ($(GITUNTRACKEDCHANGES),) GITCOMMIT := $(GITCOMMIT)-dirty endif CTIMEVAR=-X $(NOTARY_PKG)/version.GitCommit=$(GITCOMMIT) -X $(NOTARY_PKG)/version.NotaryVersion=$(NOTARY_VERSION) -GO_LDFLAGS=-ldflags "-w $(CTIMEVAR)" +GO_LDFLAGS=-ldflags "-s -w $(CTIMEVAR)" GO_LDFLAGS_STATIC=-ldflags "-w $(CTIMEVAR) -extldflags -static" GOOSES = darwin linux windows NOTARY_BUILDTAGS ?= pkcs11 diff --git a/client_api/api/server.go b/client_api/api/server.go index 218652123..dc33678ed 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -784,6 +784,7 @@ func (srv *Server) initRepo(ctx context.Context, gun data.GUN) (*client.NotaryRe trustpinning.TrustPinConfig{}, cryptoService, changelist.NewMemChangelist(), + nil, ) } diff --git a/cmd/notary/root-ca.crt b/cmd/notary/root-ca.crt index 8210c3480..85bc4c5b2 100644 --- a/cmd/notary/root-ca.crt +++ b/cmd/notary/root-ca.crt @@ -1,32 +1,32 @@ -----BEGIN CERTIFICATE----- -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 -mSU+sXjNtnlrP4jBgWMl074YdvqQ4Tj6xeg= +BBRH8tpSaZTkqGqcqKKXjCU8HGuhaTANBgkqhkiG9w0BAQsFAAOCAgEAd9QlLe6q +Nrl10Gg5WqeKcTzu0EjPXWOzf3Wu54Gb9CqZThOXG5/qFufCXeymp3sVoaer9WqY +bpzkFde2LEDaxLt2PTtUCe0u4fe/gFZb9g+XbAmYr20CBgOeGG113KGTtfTZMzV3 +fDfFWS7fiHQh1yP63RzURfL4JP0Jcz7TPOFiK20BtHvHDVJ9K2E1XIItYNxdWEd0 +XvRxk+fvXuU707Ir8W8oAgoA3r0BT3YujCIVMD8hc84pZxZLtQzGaMmVmH4C81bD +SZ40fyoVbhXNABmBcQz/3YN6g5OvTJ1TXkIjC3g+XI/y2esigWCY4DY848J1ZsQy +cty/e3NJO171UPROOImnxm/sktb7FBkQYu0bnD+mHlW7p16v2sX3Yxg0tOfoO8gB +/9ah/4sCNA/cAh0/fMh+ZlFr5cvZzmg2YWwMa+7Pl8y8/NQIgYz5gEhN7R0qgVa+ +DEiWqccd1oS5v3RSCrPW/DAMa9Eb3659GgRBBIKvJ0VEtWVKlkDnWUF0lxbWEOxX +l3TrbhTb9eFgCkYNhMRhNQemWp9wKW8Se/lQwZM0nK6oxK92QMtWirD47tBUG1dq +ZU+fmZH4LSQOFDpmw/KvygkQ/+Zq/i1bJ0vikTxV1n0jcHYofGzIBLNgOYC+AAS0 ++nKtHL0QfEXViSNuVD6/3k4JFIbuPdq8CdA= -----END CERTIFICATE----- diff --git a/docker-compose.clientapi.yml b/docker-compose.clientapi.yml index 3604af88b..d7d7d7b7c 100644 --- a/docker-compose.clientapi.yml +++ b/docker-compose.clientapi.yml @@ -7,11 +7,10 @@ services: depends_on: - server ports: - - "4449:4449" - volumes: - - clientapi_data:/var/lib/clientapi + - "4449:4449" networks: api: + esc: entrypoint: clientapi command: -config=./fixtures/clientapi-server-config.toml server: @@ -47,6 +46,16 @@ services: command: -c "./migrations/migrate.sh && notary-signer -config=./fixtures/signer-config.json" depends_on: - mysql + escrow: + build: + context: . + dockerfile: escrow.Dockerfile + networks: + esc: + aliases: + - notaryescrow + entrypoint: escrow + command: -config=./fixtures/escrow-config-local.toml mysql: networks: - mdb @@ -70,3 +79,5 @@ networks: external: false api: external: false + esc: + external: false diff --git a/escrow.Dockerfile b/escrow.Dockerfile index da7a03ede..baaaed030 100644 --- a/escrow.Dockerfile +++ b/escrow.Dockerfile @@ -14,4 +14,4 @@ EXPOSE 4450 RUN go install ${NOTARYPKG}/cmd/escrow ENTRYPOINT [ "escrow" ] -CMD [ "-config=cmd/escrow/config.toml" ] +CMD [ "-config=fixtures/config.toml" ] diff --git a/fixtures/clientapi-server-config.toml b/fixtures/clientapi-server-config.toml index 87948555c..1d61507bf 100644 --- a/fixtures/clientapi-server-config.toml +++ b/fixtures/clientapi-server-config.toml @@ -11,6 +11,9 @@ addr = "https://notaryserver:4443" tls_ca_file = "./root-ca.crt" [key_storage] -method = "remote" -addr = "https://escrow:4450" -tls_ca_file = "./root-ca.crt" \ No newline at end of file +type = "remote" +addr = "notaryescrow:4450" +tls_ca_file = "./root-ca.crt" +tls_cert_file = "./clientapi-server.crt" +tls_key_file = "./clientapi-server.key" +secret = "fixturesecret" diff --git a/fixtures/clientapi-server.crt b/fixtures/clientapi-server.crt index faba655f3..8e879bb45 100644 --- a/fixtures/clientapi-server.crt +++ b/fixtures/clientapi-server.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIE/DCCAuSgAwIBAgIJAMzwtUOFSlr2MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIE/DCCAuSgAwIBAgIJAJ9DIuw+4GnpMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjBeMQswCQYDVQQG +bmcgQ0EwHhcNMTcwNDEyMjM0ODQ3WhcNMTkwNTAyMjM0ODQ3WjBeMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEZMBcGA1UEAxMQY2xpZW50YXBpLXNlcnZlcjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBALlrIUZNfqnIkEpcs2ItUMgMLtn9zP2fd77t @@ -11,53 +11,53 @@ N3/H5fogqum2etNY7CvJIPN4c5Tvusp3oMfPL79ZuT19JgbhQFnNLMZu8Y+CI5by Uqw4g2lXYVGfYqF1zV3cnRU3C8ShhnDdh+e0P5yYYogL736G3Wn/v/ESm4TuR6Us F7DoHAXerr7N9gSwf0c+MmCBY5CW1JqkUk2KqbyYaBswLQc9h1AA41pFRwVuNCPk RyUoXijbaLLCg5kAIMkUfXtev5O/DdKXSIObwLhhzF1FL7Ub8nUCAwEAAaOBrjCB -qzAfBgNVHSMEGDAWgBS93XfIVLXXsmij+c9k5PMbNWoVEjAMBgNVHRMBAf8EAjAA +qzAfBgNVHSMEGDAWgBQdelk1/nXWpf6zoi2TLFNEaWleezAMBgNVHRMBAf8EAjAA MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8BAf8EBAMCBaAw LAYDVR0RBCUwI4IQY2xpZW50YXBpLXNlcnZlcoIJbG9jYWxob3N0hwR/AAABMB0G A1UdDgQWBBTeA9HMKfdg6RSZsr3U+IJoqb5N7jANBgkqhkiG9w0BAQsFAAOCAgEA -C4UvAQoj+uAolSVj/msJsN0wv4JxxyMxewNgMmpI10ryt+2WbgQ+t39gv5gZu17f -QhX3vjJx9QlXr6w+5Wc6L5ioDjPS/g1MdWe+Ox+acYAhS6W+RUiwhT9/8gB+SDIt -H7Y/bZLRDjfgrZMEBnN3NEj/xvsRVLYGo6T08mq7Yc2nuUkoynZiqKqZXv9RsfGg -qy1PuBeehDs5sMY3DOc1eKcNLGDgazbrNDLK9uirbEuL+K4fFskI8IStpK5bHDqQ -UHUwfwyLnViQQ+RA87L5ceqfVoOB62jVFpeGlIGl4g7yGMvYd3gYR6qpWO8vWy+M -c/0FTWSnyPeU3+5/gAJvmjTodrxoo9afUO2r3NfeXt4flKbhHs5HntCmh2Hcafnc -VHlSGzRTAzKzJICHyFnp4B5UtTdSaYpHFcSCjIfbRaxR2X3x1VdcqWJBA8xP3kp6 -OEUnFhihFiQ7zzPViA8YS9AS/LziLkkSSvUKlrUckV7vRNs0xUq8fbSgnTZsHGA5 -rOZAhYFfM4nKyl47lLTGw4RASzjZ445yqPq/4hX1aZbU/suqQXBadmbyRgS3GQ1/ -CFirQcg5zHwkrfA/wY2UifSZAO2FQoLAruzdXDI5c0dVgt3qtLUEs1W0TT6DA4+r -IgjBlT0ugi/toxFbzRiXUlmb+x4c79vJws0GgD1XwD4= +rdN61rsMwNdzM+odEd2oLF13TmfdjoENoCh9u0e+S0qndATkBpJgT4X5YhYOc//b +kbtaY2XbY9biMFQsVfv0THWe8u4gb+UwCzER5QUhgEhlMSGq2hz/aFWiN1PviDYh +Dyd/Ykgpk6xvRohN5hrPI1On+cbv6hUdrrPvdduBHgd4AbqWdv9V6TTNoE86fY6e +BHB10Gla2LoFd87tWnoImbx7DwIv+7mWAk7ycY9XlD9pD6w+u1gqOC3yNvz4RJw+ +DCcEyNGq9NwNciJXdbKEAttQNhABoM/C1hJFjIStTVE7+FE646zbs8OogeXVGBpd +UYlh7yFGOlHoNZyHUHfAp19MRJiVyeBXH8dAhV7XRQJZT3zwS3IOiGzRDdoqgU0L +3CAC5nxOok9yZr5kn2eqaQ1eP/Nvke5+roLwX9mHhU4H4cEsBhqpKUVx8eaw9tyB +4ew8K8dwgwiVkhbHmEBCKQxH/5twlPJAhjYiFHiLhclwAFjnuTz2b+xCBhdEJYjk +NWpxEjjpTDTRzXYtLUzRaMrYwl2LWk62QoTQ/D/z5aFJEzY6fJzKU/LElVnMwC0n +aNRx7dm9V0C3URS8K6s83AZvG3+7G5Oacv2AAAiV/6zFmi7E+Ycu3GOtHNOoEtU0 +TWS5gmfxB88AdH1EaXgcVbsQzsTpoajDESWYgM6o5hk= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -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 -YKGxswAOLRmF +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDP2gv9obOxQSXVJ16+jeSXv2BD4KS1HVWl +121XL2aijmBVMn8xarYxjjqDCTssvFNdaxM9g1UcVxOR3ixJT492RxlcE4eC2UEv +XUS9mGcLFnKwCZSqFf5ern3YZK8zi4Z1YJaqdrRSaU2pbPyjDzCXs0wNBN53Dpi1 +PEvsHt+EgTQrEe7IBNIcsrtJPVxovAp0FTlgVH6w8rxm+7q/SjDz8aJmLVDNMGY5 +Yccbsu4Q2wJc0TwJkSGESfcO3sIQxbLVTTPQTQ18hciwBIbtJj0QI1HXpOmwLSpC +dopfvyW7wtvb3owQtU+ObBf1X2ENldYngEMi6F5sPzokjG9Z8YW1gM8IvUW1Q7pz +gO5QUmL/HlGaisylKRQcpNErRp7XFEU3wfyEOEi8AAxrgDUfXwFLpBP/kLSrZjcG +Jd1zt5KzHA5+xqn13t6+J9urYD88tEgXvgL8qbD7mWJKi6xau67UR32OOEWew3n6 +8sCOz6LzomRCEuQsHrbrK/aXEusClopu0yDpCVmfKPSVN43lsmEH1bQUBPMztSBi +euxcJpkMrDugDuzlvcup8bnz2NEwrB0xcCGCTnE3y8Px0cx+qSS96lX4hWA6chiy +cEwVBMAJaRRJojQv39E/ahgL7aUVfkkwAmAdFxF/NuyV6bxTJjf+WuYX1c6qYG25 +LRuPBGgVfwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFEfy2lJplOSoapyoopeMJTwc +a6FpMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUHXpZNf511qX+s6ItkyxT +RGlpXnswDQYJKoZIhvcNAQELBQADggIBAHoJ3soYK5fwndYh+7MAsQM8SG75pSgF +0fJE7D7i6JYrB1o/zSY3QyI+X+ruFlSXhvWO4oCoI84oSfbo5lxHIjFEd8BCNM1q +rVz+KkUKfT41K8itG+m3ib7GTAOFi2k6PW7U4cFmyDYh1udGm1dAATdgeTmBVScr +PoAT6dYtFsI71dRItanLdnn61k3ggve7irmTuGDYdzyu3rw/owG53V8NxoYdZD2X +s66x5LBfRiNTyIxuyo6DFYGnrKhEy6ZoGqZlC4sHLWPYJaS04/NtNFIMWQgFohm/ +8GlEONDAG2KprMAkb6zxoDWOd7nu72TQ2QD1LF4fu0IYQXhvpJRXlME55eX9vYt+ +26CD8E8G0GpbUz1+H4ps90No55859kn3+0nlRRYMi7QS5oIIhyPc39bA2EDHyruj +yM+QOeHH/1sts7VlPck9jUFxranhqqJp+SLBDdCR5WHWEm9pCBlmirXIC4WQPZsG +eso6mOA+bw/Tc9vVZyCtLXsyxu9J4OIk3hlkN1TRJVZoYZ4ujUgRxsIaoJG6ICxe +mo5C5GdLgibzcW72gIvW2drJeHYZp1vCt7ZmnsGErm/joiWz9v+C1FUDfwuG4+cW +7htPiraNFMBCvN5g1lOILMgoM2sQXrQ1jbNjQvvbqmboL7RFXgTZlP0NkiM1FNUw +QSj/BUN/VvY6 -----END CERTIFICATE----- diff --git a/fixtures/escrow-config-local.toml b/fixtures/escrow-config-local.toml index e03e19a09..36b58f665 100644 --- a/fixtures/escrow-config-local.toml +++ b/fixtures/escrow-config-local.toml @@ -4,6 +4,6 @@ path = "/tmp/keys" [server] addr = "0.0.0.0:4450" -tls_key_file = "notary-escrow.key" -tls_cert_file = "notary-escrow.crt" -client_ca_file = "" +tls_key_file = "./notary-escrow.key" +tls_cert_file = "./notary-escrow.crt" +tls_ca_file = "./root-ca.crt" \ No newline at end of file diff --git a/fixtures/intermediate-ca.crt b/fixtures/intermediate-ca.crt index c6263aff3..4cd1d70ab 100644 --- a/fixtures/intermediate-ca.crt +++ b/fixtures/intermediate-ca.crt @@ -1,34 +1,34 @@ -----BEGIN CERTIFICATE----- -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 -YKGxswAOLRmF +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDP2gv9obOxQSXVJ16+jeSXv2BD4KS1HVWl +121XL2aijmBVMn8xarYxjjqDCTssvFNdaxM9g1UcVxOR3ixJT492RxlcE4eC2UEv +XUS9mGcLFnKwCZSqFf5ern3YZK8zi4Z1YJaqdrRSaU2pbPyjDzCXs0wNBN53Dpi1 +PEvsHt+EgTQrEe7IBNIcsrtJPVxovAp0FTlgVH6w8rxm+7q/SjDz8aJmLVDNMGY5 +Yccbsu4Q2wJc0TwJkSGESfcO3sIQxbLVTTPQTQ18hciwBIbtJj0QI1HXpOmwLSpC +dopfvyW7wtvb3owQtU+ObBf1X2ENldYngEMi6F5sPzokjG9Z8YW1gM8IvUW1Q7pz +gO5QUmL/HlGaisylKRQcpNErRp7XFEU3wfyEOEi8AAxrgDUfXwFLpBP/kLSrZjcG +Jd1zt5KzHA5+xqn13t6+J9urYD88tEgXvgL8qbD7mWJKi6xau67UR32OOEWew3n6 +8sCOz6LzomRCEuQsHrbrK/aXEusClopu0yDpCVmfKPSVN43lsmEH1bQUBPMztSBi +euxcJpkMrDugDuzlvcup8bnz2NEwrB0xcCGCTnE3y8Px0cx+qSS96lX4hWA6chiy +cEwVBMAJaRRJojQv39E/ahgL7aUVfkkwAmAdFxF/NuyV6bxTJjf+WuYX1c6qYG25 +LRuPBGgVfwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFEfy2lJplOSoapyoopeMJTwc +a6FpMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUHXpZNf511qX+s6ItkyxT +RGlpXnswDQYJKoZIhvcNAQELBQADggIBAHoJ3soYK5fwndYh+7MAsQM8SG75pSgF +0fJE7D7i6JYrB1o/zSY3QyI+X+ruFlSXhvWO4oCoI84oSfbo5lxHIjFEd8BCNM1q +rVz+KkUKfT41K8itG+m3ib7GTAOFi2k6PW7U4cFmyDYh1udGm1dAATdgeTmBVScr +PoAT6dYtFsI71dRItanLdnn61k3ggve7irmTuGDYdzyu3rw/owG53V8NxoYdZD2X +s66x5LBfRiNTyIxuyo6DFYGnrKhEy6ZoGqZlC4sHLWPYJaS04/NtNFIMWQgFohm/ +8GlEONDAG2KprMAkb6zxoDWOd7nu72TQ2QD1LF4fu0IYQXhvpJRXlME55eX9vYt+ +26CD8E8G0GpbUz1+H4ps90No55859kn3+0nlRRYMi7QS5oIIhyPc39bA2EDHyruj +yM+QOeHH/1sts7VlPck9jUFxranhqqJp+SLBDdCR5WHWEm9pCBlmirXIC4WQPZsG +eso6mOA+bw/Tc9vVZyCtLXsyxu9J4OIk3hlkN1TRJVZoYZ4ujUgRxsIaoJG6ICxe +mo5C5GdLgibzcW72gIvW2drJeHYZp1vCt7ZmnsGErm/joiWz9v+C1FUDfwuG4+cW +7htPiraNFMBCvN5g1lOILMgoM2sQXrQ1jbNjQvvbqmboL7RFXgTZlP0NkiM1FNUw +QSj/BUN/VvY6 -----END CERTIFICATE----- diff --git a/fixtures/notary-escrow.crt b/fixtures/notary-escrow.crt index 6d4db1057..baac75339 100644 --- a/fixtures/notary-escrow.crt +++ b/fixtures/notary-escrow.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIGBDCCA+ygAwIBAgIJAMzwtUOFSlrzMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIGBDCCA+ygAwIBAgIJAJ9DIuw+4GnmMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjBbMQswCQYDVQQG +bmcgQ0EwHhcNMTcwNDEyMjM0ODQ2WhcNMTkwNTAyMjM0ODQ2WjBbMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEWMBQGA1UEAxMNbm90YXJ5LWVzY3JvdzCCAiIwDQYJKoZIhvcN AQEBBQADggIPADCCAgoCggIBAMFzgrRu1r3leMdD19sSgfqW85Bi4FCv6LCDbnAO @@ -16,20 +16,54 @@ voL/5206/Npd0bCodXGX62ARUdEuTayG5a7fJ6NCZa+C7W6hhAs9Mvw6LC8Webuw +wuzFE1v/Ktt2dLkwtvYC2N+J3nmxbBN4y0Uud0MqnO+SFV+Ib2nzlLKtZoNAG9x kcMQzuubdsj0HHq0ywYCCkjDaz+ltcUqF7NNhRJL47ccNfOumJD5LY9KbRPeZ19X f63g0iniyBFxcAmwwCql2PX07i8X4FcteH5J2ehiLuAJ8inz7uwMPEVFSr8n3AqS -y079AgMBAAGjgbkwgbYwHwYDVR0jBBgwFoAUvd13yFS117Joo/nPZOTzGzVqFRIw +y079AgMBAAGjgbkwgbYwHwYDVR0jBBgwFoAUHXpZNf511qX+s6ItkyxTRGlpXnsw DAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYD VR0PAQH/BAQDAgWgMDcGA1UdEQQwMC6CDW5vdGFyeS1lc2Nyb3eCDG5vdGFyeWVz Y3Jvd4IJbG9jYWxob3N0hwR/AAABMB0GA1UdDgQWBBQdk/HK+26ISl+VOgKh5vtV -WRmqWzANBgkqhkiG9w0BAQsFAAOCAgEAEQMQTzu/BikIWXXvptGUAVl5XJ4bbz1P -anwlcJjxOOjAPEGz6/K3frLnZSoHH9dUtQW6D/CjdfFKGzkdJ+2f908AOdiTOuFL -VcWdp+zcW4ee7yr7PbZxlPYkVNFONF4fILJO2U2JNFt7I0bTljOWZzpChePmKaD5 -77mjv71YpiH+sj7w7m6no4lrc19fkDFtMl6blskdjZlHehFLmekRhq9gaRpe7Igz -+QDiOLL/8M8xBOvycs4x5B0qs59rIr2uZtsUDXGuvSz0z9JWCLMnlbmtAzClmcCv -sj3ClDxJEQdyqE1Y0La4EwMHJjV55gqzl/Q4ypgwxqOdb8/8xrM6E6rnb2uhlqlj -7pAa0/IYXZYds6V/DtcUQGkGBK18ky3f5d8jfxVGnFwldK5Ug3RmwbatjqZrtBGX -t0ETaV2YW+29TGUl9ikNqFqcoRPbK/77ljSnCvxoX1SdBJY095zkM9OLBVnGwk0W -R2HJwds2qIT8WYTV1t23SEyEPT0BqBZESTEeoIJqlT1lgXXElwDS0ddXJjCCVXOI -LJBOrBFcckJy7JAyYF+ZYAOesjP7GVNUnsYKJ1CvyD3LVXQhGV7fElHUNujvl3MU -q0iMGgCNYpAiw7oG7rRXV4nHB4Jmsfw6gIATUCgUjXTwjOxxsgu65WF7BR2smYs4 -d0v/58k1s6I= +WRmqWzANBgkqhkiG9w0BAQsFAAOCAgEADZ3hR67u3TkibypTuWAkWgwqGjP1pY87 +dqjzMQ+/h8mSxQahSrok2Da6LsazzKLZanDNq78jnpsu9Abx22XNSdiGq1wZjsBx ++Fe/L7G8ntNMlIjyV3U7USjGJ8Jb5Vyg+FkY6Rkk8QD/gJSUNtChFIY34HKipISf +dTfit5omiIu5USo7M5z+8sBvnIspyK6XgPu0+Iy3ALGAy59x0AYNupLlcd/nFHNP +Vb7rzQtf3SgOfIatdPjOP1TMH3NoG54AjHkB1umFuGpmNnDZBDcnlL4t5vvkyeKn +FxQXyiWMZ+hw1zdDRZbY7991CmN7/95onYpklXloeQFlis8E4JsJDZDtLZdbePor +rdfy5hGlN8zV3H3CqBorG2TchP7CIEwrk1UKx5cxPKkgtVWSqpUxo8B4gvgMBGLz +elr+P6fLw2BoB5ZApphONdckLHWNVSsmuvWsg2l/GUkZbCd4TuCmjiC1F+127zRl +QS+RzDpI6v2vV/mkbQfodb3q79fCVmgbnPH73ZvLO5wz8MXQx4WVAKKkF7+cyGM0 +IOqHNLCMxIbiu2r8Y4IJu/0JKURxdLrzvbK6dKE6O+UMMlQgaCUB/0Rr98PlC9Qx +efbRCI9vPeb0Gy+ctOJpKZjO04FWXGPgh/al1WTl8EJr0Kg+6wCJhuOOR+yXusDz +R2gvQhcaZro= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +QSj/BUN/VvY6 -----END CERTIFICATE----- diff --git a/fixtures/notary-server.crt b/fixtures/notary-server.crt index a3171e949..d11abb0af 100644 --- a/fixtures/notary-server.crt +++ b/fixtures/notary-server.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFBDCCAuygAwIBAgIJAMzwtUOFSlryMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIFBDCCAuygAwIBAgIJAJ9DIuw+4GnlMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMzAxMTkzNjI4WhcNMTkwMzIxMTkzNjI4WjBbMQswCQYDVQQG +bmcgQ0EwHhcNMTcwNDEyMjM0ODQ2WhcNMTkwNTAyMjM0ODQ2WjBbMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEWMBQGA1UEAxMNbm90YXJ5LXNlcnZlcjCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAKjbeflOtVrOv0IOeJGKfi5LHH3Di0O2nlZu8AIT @@ -11,87 +11,53 @@ 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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIF1TCCA72gAwIBAgIJAMELzHI4DbdfMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV +MIIF1TCCA72gAwIBAgIJAPlIuLEI6CXUMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G -A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAz -MDExOTM2MjhaFw0yNzAyMjcxOTM2MjhaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI +A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzA0 +MTIyMzQ4NDZaFw0yNzA0MTAyMzQ4NDZaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI EwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0GA1UEChMGRG9ja2VyMScw JQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3RpbmcgQ0EwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQC5gi0twJAtlvL9XwzeXpu6zAUGUkPIU3Wp -GA3zYqqFcYKBxPuQ8AfexGCRJZ6MDteQMUKbtQFbbPj3x7OcXx0OAwlirvZAajec -9o7jmmhGJ0jZWFlMtTs9ZvqR5nkRESWdVcegzX+/zVVDgbNkHRd0iQCPvcfBZskg -G6t1LksQwKunhssaaDSk1vbS/QaxCE5/ywBqMocvxarkg+sklPC+/iBUN8/KUa2j -oqaOkcSUiKsqXskAyYLDTdqGpVee5nmg1WMUUpfmuBXYSxuxEmqu+9pjzFfBQDu9 -Fn+LY0UviccascCYT6h/RNU/hVqaLc9NnMsF388HXXo7T7OChzWkr+7qJvAxUctn -y94eUBzLkS4LmYlUvpE6YYLDSab8AUNJYLHFXIbn93A0wukfboCqucERiMz1qtSg -ZYyx5Vy8RcmVC8bB5LfCFoZLTZ+WT6+NyumVbCFebHARMGyaJPlUlcaNwHWlwMlv -fUJQM454alIfLartvdXVpAhibCB7HLk3GDCs5jec9pKtwpQqXVfv07/FeRl67QfR -EQYhXxs2iUK4L1IJZRoroVg2NdG9+z5kF7SxZHmZKagQIUQYcnSXT63QaCC6KsmH -SjMxEH81OSYbJoV3Jrj4sgp4uKG7tkEgYnmjvFpyvay6ymZioff6+QPZi02RKjag -jeut/4XjIQIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFL/NOhPhwQx/tUwrHU4NJ4+W -XbwAMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG -AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUvd13yFS117Joo/nPZOTz -GzVqFRIwDQYJKoZIhvcNAQELBQADggIBAE0jLDhm8Cn6N+TvGqbdtOKwCo5JPY1Z -eUxz1O5lDbcLAOG8AGPCRdT+TEdnsm9fG8nnv0d7X5GciSIqd5zv0Zi5oSItUUwm -qjAgbJMAFMTQTA0KbzNf0QaWvfeUPSIHTr8S19QctoDYXtvO5afkuT1V30uYY9u7 -IJHJHAM/IaWDaQcJw1f4TUPb5wFmvVof6vl19KcU4NtO3CLJpcL4w4OzSEWWepJ7 -3kz4PEibhHnY3zDotbVXSK5R6RceOwF9Jzw0IzTrfL5WGKcm4vq369/BfHSWZ5IP -RazsSK/aFfQI1C1uJPogPmpP2bMRWEWp/RrWkonMQLM2etRRi6Nq4G+H5SSIIjzB -vr/FzqsFQS0H9JsT6B7Br+3OCjjeLk0G17okrVihVQ8N95wxGMWRbuUVAWdrJsAQ -Ep3leFQdlR0tJnw4Jh8vPT8BwzQQXR4DqCNFxWFZnbDUr5eSpfuaoC9JLUP7vm9t -231i3h8r6cZontwXcAuVZsMnwqwtrYNb/L9yb0Uz+kR1SnBfrY5Yd9sV6gWbhDol -RcB4Cv2EHTOrQCz06VsA91lFprKP+aqA5qA63tHlmVe5jTfJDJsIQVJS31bT6DES -877VDtKsXNWZ/gq91q3dAXLopDtW9OvO13E0tBhUgOSC8Sc3r4N4Gv8SObAFuawQ -YKGxswAOLRmF ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -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 -YKGxswAOLRmF +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDP2gv9obOxQSXVJ16+jeSXv2BD4KS1HVWl +121XL2aijmBVMn8xarYxjjqDCTssvFNdaxM9g1UcVxOR3ixJT492RxlcE4eC2UEv +XUS9mGcLFnKwCZSqFf5ern3YZK8zi4Z1YJaqdrRSaU2pbPyjDzCXs0wNBN53Dpi1 +PEvsHt+EgTQrEe7IBNIcsrtJPVxovAp0FTlgVH6w8rxm+7q/SjDz8aJmLVDNMGY5 +Yccbsu4Q2wJc0TwJkSGESfcO3sIQxbLVTTPQTQ18hciwBIbtJj0QI1HXpOmwLSpC +dopfvyW7wtvb3owQtU+ObBf1X2ENldYngEMi6F5sPzokjG9Z8YW1gM8IvUW1Q7pz +gO5QUmL/HlGaisylKRQcpNErRp7XFEU3wfyEOEi8AAxrgDUfXwFLpBP/kLSrZjcG +Jd1zt5KzHA5+xqn13t6+J9urYD88tEgXvgL8qbD7mWJKi6xau67UR32OOEWew3n6 +8sCOz6LzomRCEuQsHrbrK/aXEusClopu0yDpCVmfKPSVN43lsmEH1bQUBPMztSBi +euxcJpkMrDugDuzlvcup8bnz2NEwrB0xcCGCTnE3y8Px0cx+qSS96lX4hWA6chiy +cEwVBMAJaRRJojQv39E/ahgL7aUVfkkwAmAdFxF/NuyV6bxTJjf+WuYX1c6qYG25 +LRuPBGgVfwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFEfy2lJplOSoapyoopeMJTwc +a6FpMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUHXpZNf511qX+s6ItkyxT +RGlpXnswDQYJKoZIhvcNAQELBQADggIBAHoJ3soYK5fwndYh+7MAsQM8SG75pSgF +0fJE7D7i6JYrB1o/zSY3QyI+X+ruFlSXhvWO4oCoI84oSfbo5lxHIjFEd8BCNM1q +rVz+KkUKfT41K8itG+m3ib7GTAOFi2k6PW7U4cFmyDYh1udGm1dAATdgeTmBVScr +PoAT6dYtFsI71dRItanLdnn61k3ggve7irmTuGDYdzyu3rw/owG53V8NxoYdZD2X +s66x5LBfRiNTyIxuyo6DFYGnrKhEy6ZoGqZlC4sHLWPYJaS04/NtNFIMWQgFohm/ +8GlEONDAG2KprMAkb6zxoDWOd7nu72TQ2QD1LF4fu0IYQXhvpJRXlME55eX9vYt+ +26CD8E8G0GpbUz1+H4ps90No55859kn3+0nlRRYMi7QS5oIIhyPc39bA2EDHyruj +yM+QOeHH/1sts7VlPck9jUFxranhqqJp+SLBDdCR5WHWEm9pCBlmirXIC4WQPZsG +eso6mOA+bw/Tc9vVZyCtLXsyxu9J4OIk3hlkN1TRJVZoYZ4ujUgRxsIaoJG6ICxe +mo5C5GdLgibzcW72gIvW2drJeHYZp1vCt7ZmnsGErm/joiWz9v+C1FUDfwuG4+cW +7htPiraNFMBCvN5g1lOILMgoM2sQXrQ1jbNjQvvbqmboL7RFXgTZlP0NkiM1FNUw +QSj/BUN/VvY6 -----END CERTIFICATE----- diff --git a/fixtures/notary-signer.crt b/fixtures/notary-signer.crt index 1eb32c937..a0e388d74 100644 --- a/fixtures/notary-signer.crt +++ b/fixtures/notary-signer.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFBDCCAuygAwIBAgIJAMzwtUOFSlr0MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIFBDCCAuygAwIBAgIJAJ9DIuw+4GnnMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjBbMQswCQYDVQQG +bmcgQ0EwHhcNMTcwNDEyMjM0ODQ2WhcNMTkwNTAyMjM0ODQ2WjBbMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEWMBQGA1UEAxMNbm90YXJ5LXNpZ25lcjCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBANhO8+K9xT6M9dQC90Hxs6bmTXWQzE5oV2kLeVKq @@ -11,53 +11,53 @@ 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 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -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 -YKGxswAOLRmF +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDP2gv9obOxQSXVJ16+jeSXv2BD4KS1HVWl +121XL2aijmBVMn8xarYxjjqDCTssvFNdaxM9g1UcVxOR3ixJT492RxlcE4eC2UEv +XUS9mGcLFnKwCZSqFf5ern3YZK8zi4Z1YJaqdrRSaU2pbPyjDzCXs0wNBN53Dpi1 +PEvsHt+EgTQrEe7IBNIcsrtJPVxovAp0FTlgVH6w8rxm+7q/SjDz8aJmLVDNMGY5 +Yccbsu4Q2wJc0TwJkSGESfcO3sIQxbLVTTPQTQ18hciwBIbtJj0QI1HXpOmwLSpC +dopfvyW7wtvb3owQtU+ObBf1X2ENldYngEMi6F5sPzokjG9Z8YW1gM8IvUW1Q7pz +gO5QUmL/HlGaisylKRQcpNErRp7XFEU3wfyEOEi8AAxrgDUfXwFLpBP/kLSrZjcG +Jd1zt5KzHA5+xqn13t6+J9urYD88tEgXvgL8qbD7mWJKi6xau67UR32OOEWew3n6 +8sCOz6LzomRCEuQsHrbrK/aXEusClopu0yDpCVmfKPSVN43lsmEH1bQUBPMztSBi +euxcJpkMrDugDuzlvcup8bnz2NEwrB0xcCGCTnE3y8Px0cx+qSS96lX4hWA6chiy +cEwVBMAJaRRJojQv39E/ahgL7aUVfkkwAmAdFxF/NuyV6bxTJjf+WuYX1c6qYG25 +LRuPBGgVfwIDAQABo4GGMIGDMB8GA1UdIwQYMBaAFEfy2lJplOSoapyoopeMJTwc +a6FpMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMA4GA1UdDwEB/wQEAwIBRjAdBgNVHQ4EFgQUHXpZNf511qX+s6ItkyxT +RGlpXnswDQYJKoZIhvcNAQELBQADggIBAHoJ3soYK5fwndYh+7MAsQM8SG75pSgF +0fJE7D7i6JYrB1o/zSY3QyI+X+ruFlSXhvWO4oCoI84oSfbo5lxHIjFEd8BCNM1q +rVz+KkUKfT41K8itG+m3ib7GTAOFi2k6PW7U4cFmyDYh1udGm1dAATdgeTmBVScr +PoAT6dYtFsI71dRItanLdnn61k3ggve7irmTuGDYdzyu3rw/owG53V8NxoYdZD2X +s66x5LBfRiNTyIxuyo6DFYGnrKhEy6ZoGqZlC4sHLWPYJaS04/NtNFIMWQgFohm/ +8GlEONDAG2KprMAkb6zxoDWOd7nu72TQ2QD1LF4fu0IYQXhvpJRXlME55eX9vYt+ +26CD8E8G0GpbUz1+H4ps90No55859kn3+0nlRRYMi7QS5oIIhyPc39bA2EDHyruj +yM+QOeHH/1sts7VlPck9jUFxranhqqJp+SLBDdCR5WHWEm9pCBlmirXIC4WQPZsG +eso6mOA+bw/Tc9vVZyCtLXsyxu9J4OIk3hlkN1TRJVZoYZ4ujUgRxsIaoJG6ICxe +mo5C5GdLgibzcW72gIvW2drJeHYZp1vCt7ZmnsGErm/joiWz9v+C1FUDfwuG4+cW +7htPiraNFMBCvN5g1lOILMgoM2sQXrQ1jbNjQvvbqmboL7RFXgTZlP0NkiM1FNUw +QSj/BUN/VvY6 -----END CERTIFICATE----- diff --git a/fixtures/regenerateTestingCerts.sh b/fixtures/regenerateTestingCerts.sh index 645cb7269..5aac06fdb 100755 --- a/fixtures/regenerateTestingCerts.sh +++ b/fixtures/regenerateTestingCerts.sh @@ -65,7 +65,7 @@ openssl x509 -req -days 750 -in "notary-escrow.csr" -sha256 \ -CA "intermediate-ca.crt" -CAkey "intermediate-ca.key" -CAcreateserial \ -out "notary-escrow.crt" -extfile "cert_config.cnf" -extensions notary_escrow # append the intermediate cert to this one to make it a proper bundle -cat "intermediate-ca.crt" >> "notary-server.crt" +cat "intermediate-ca.crt" >> "notary-escrow.crt" rm "notary-escrow.csr" diff --git a/fixtures/root-ca.crt b/fixtures/root-ca.crt index 8210c3480..85bc4c5b2 100644 --- a/fixtures/root-ca.crt +++ b/fixtures/root-ca.crt @@ -1,32 +1,32 @@ -----BEGIN CERTIFICATE----- -MIIFhjCCA26gAwIBAgIJAK0FdgyLVW1EMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV +MIIFhjCCA26gAwIBAgIJAL7PnqkhMLJVMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G -A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzAz -MDExOTM2MjdaFw0yNzAyMjcxOTM2MjdaMF8xCzAJBgNVBAYTAlVTMQswCQYDVQQI +A1UEChMGRG9ja2VyMRowGAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTAeFw0xNzA0 +MTIyMzQ4NDRaFw0yNzA0MTAyMzQ4NDRaMF8xCzAJBgNVBAYTAlVTMQswCQYDVQQI EwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0GA1UEChMGRG9ja2VyMRow GAYDVQQDExFOb3RhcnkgVGVzdGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBALqnWDhdyZtx8M+AuFQFIfVsuxii+zj97I4W/XLrStAeZdkQNuWN -KExdRCtA8jY6ayCU+NmQ5d7tB2MyQ4vLlJWFaXtzQT+DLbAkUl7lPl784CyqYZRi -zzqnSW4BEGhWPbE+uaWRMv6KjnqP0YxQ5/+/vK4mKk8vowziPXm1g8/M0VgHg1C6 -WlC+U9pEvYrt8fiJsS4zJq/yj8Ej7EhRigKvJjF1mwn4hdsIwQch3spgAW5JFN4P -vadisCcmeV4BKEVbyHEgb3a9RQewSiabU0MxAVyKnc+Gfs8PbolE0vKtKFUiCnbb -+eRQi/gWeU4+P4Bz5+Bp9Ece7yVnuGw8N7fPLAQesqcXSjr2HXpmFb1vZm9YjvON -ogrG6U7gu3QaPGSqjcWkvvvdg+463T4ZDBRIaL56q9irJdhC4KJ/okflcR/TD7Y5 -UUpe42expANjC2yo+GBJ4uHANQsF4H13/K8I0ycP0I+JMoptWBSvWRE6yQwxAUMT -SN+bgL1+DlwirCM+0xtQGtGnEgukZhAt0USxYb3rjSkYUTE7957y2SQLRY98eDEY -eEZ2AZlRpPCrXZkgWIkpqTx9d2DnTD8fGa6T74zI9Fe9rX0ZzFUDuGdVOtcA901N -gG8uuwo0dvzZ/8Ut928qU9DBt/Qff1hHLzOopHJXHfw3jNcbm24+o0yxAgMBAAGj +ADCCAgoCggIBAMU+PBH37tKqr71UClGVditDjx4zFKmgPM8SavLK1FPhZ8+IXmP7 +53LMhxQNeejkfrVddZvrF7CXEdaqmOZhiQ6Rj9CldODSQ9TDYU5sJGgtSk8xeUln +4NLx6Xp0T3vHImW4+hTES5WWOh8nRbbGlwxUtV+TzwDiCopGGAj7jKJccQQuKxJI +w2qarJV6HneE60y2EHyg3ZJ1a2MraoDPBwmsQzr4a+IIPrQrb4nbYfzleD2Fv/qv +4pTVaFtv2wXsvfhwUFho2bY+EnGrGxJ40LHdDbNpdeRK8/AIjhatUwNve84rtwgD +Sh7mV7fmWNWKqS63NpIu5b46sUrY8MdXEybcS6l/WQMkBeQJqlOQzL5nMk9DkIoo +qcZuxjNAp5HrqbfpPQ+j4UgeiNpdAln4hWlNfMeC/jHqFQJkYfSk9Ug4OCgar20h +EGcGijLifpqFl+yycTbfR89Vo/0OxrO1GfT5DhFprKdh42pUC0u9UT3FgeotDO7S +uKGmbRaPXRZLnuX+WXNilrSza4lHiDS2NWhPJnI9t8jr9ZRMSIiDYdXnU7lsq6TQ +pIH55spgwW+BMZ5D+TltWdYgIbncQwB9+z806Qa2tzbCXLQ3JbloKVcVeoqtyEoV +3POVKY8o7Q21JQl/IwsMitO0oU8S+qdTNMprDUBQTRPYSXPha4KB0RODAgMBAAGj RTBDMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgFGMB0GA1UdDgQW -BBS/zToT4cEMf7VMKx1ODSePll28ADANBgkqhkiG9w0BAQsFAAOCAgEAcKJSgy6t -MqjEG+r008jzic7lNciX+sHp6j6kfLau9d0oYjBXQDfeBXNlqdGSvZeT157bhtrT -V64ouh5os9l+t67nbYrg1e2G/XdtA7rK0DGFW+6+M3f2KJzDtqaEBRnt+b/o3pG8 -MnTGWKt7Dqok9wmP+QMo4rAXM2dgB40CNhJae8EQGlmNHKM+O13CZfaGWRzw0aZr -ivDYNYblxKc6hTSYU01ZlYaHSF/D/kzeObbtPurWsg2wtcmXo8s4kbVdJcMXK3+R -oHzYhj7G67Ol0bVHdJXzj5xVYqVz5g473U5cmKXCNS7EtSCgO/kU7Zt/hrKY81rs -/Auv4zZ3gooaTcpDSvhHh0ZkXDOrUS3JtkSkUcU4OYV+Z7p/+CU7pHcJXUwHBLoC -tTl3SBTjrOzFvH54qf8TZ7cSVSmM3jSzS54a8K9+2eqFRW3/zwxzKZRPJimwuMUt -3YcHPH/Tk+yARvvlPiBwZqYlnLadi/Kew5Enur3eqCWeH5UcYUdC6lTA4bNHnywZ -rjQqIvQuA2MnkJDOU5DC23svXjsxIKDqIbvkh5CS/2veJ0y1ALfMNRmkmXwjP2Y2 -7/bGHP6HWYaxOCjfsOomcGwuc1DCDCu4jBFtLNXllqrsCp3dGIsEMGNbERhPfUvJ -mSU+sXjNtnlrP4jBgWMl074YdvqQ4Tj6xeg= +BBRH8tpSaZTkqGqcqKKXjCU8HGuhaTANBgkqhkiG9w0BAQsFAAOCAgEAd9QlLe6q +Nrl10Gg5WqeKcTzu0EjPXWOzf3Wu54Gb9CqZThOXG5/qFufCXeymp3sVoaer9WqY +bpzkFde2LEDaxLt2PTtUCe0u4fe/gFZb9g+XbAmYr20CBgOeGG113KGTtfTZMzV3 +fDfFWS7fiHQh1yP63RzURfL4JP0Jcz7TPOFiK20BtHvHDVJ9K2E1XIItYNxdWEd0 +XvRxk+fvXuU707Ir8W8oAgoA3r0BT3YujCIVMD8hc84pZxZLtQzGaMmVmH4C81bD +SZ40fyoVbhXNABmBcQz/3YN6g5OvTJ1TXkIjC3g+XI/y2esigWCY4DY848J1ZsQy +cty/e3NJO171UPROOImnxm/sktb7FBkQYu0bnD+mHlW7p16v2sX3Yxg0tOfoO8gB +/9ah/4sCNA/cAh0/fMh+ZlFr5cvZzmg2YWwMa+7Pl8y8/NQIgYz5gEhN7R0qgVa+ +DEiWqccd1oS5v3RSCrPW/DAMa9Eb3659GgRBBIKvJ0VEtWVKlkDnWUF0lxbWEOxX +l3TrbhTb9eFgCkYNhMRhNQemWp9wKW8Se/lQwZM0nK6oxK92QMtWirD47tBUG1dq +ZU+fmZH4LSQOFDpmw/KvygkQ/+Zq/i1bJ0vikTxV1n0jcHYofGzIBLNgOYC+AAS0 ++nKtHL0QfEXViSNuVD6/3k4JFIbuPdq8CdA= -----END CERTIFICATE----- diff --git a/fixtures/secure.example.com.crt b/fixtures/secure.example.com.crt index 4a668d231..5e09fdd83 100644 --- a/fixtures/secure.example.com.crt +++ b/fixtures/secure.example.com.crt @@ -1,8 +1,8 @@ -----BEGIN CERTIFICATE----- -MIIFADCCAuigAwIBAgIJAMzwtUOFSlr1MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV +MIIFADCCAuigAwIBAgIJAJ9DIuw+4GnoMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G A1UEChMGRG9ja2VyMScwJQYDVQQDEx5Ob3RhcnkgSW50ZXJtZWRpYXRlIFRlc3Rp -bmcgQ0EwHhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjBgMQswCQYDVQQG +bmcgQ0EwHhcNMTcwNDEyMjM0ODQ2WhcNMTkwNTAyMjM0ODQ2WjBgMQswCQYDVQQG EwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNV BAoTBkRvY2tlcjEbMBkGA1UEAxMSc2VjdXJlLmV4YW1wbGUuY29tMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmLYiYCTAWJBWAuxZLqVmV4FiUdGgEqoQ @@ -11,19 +11,19 @@ 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 -----END CERTIFICATE----- diff --git a/fixtures/self-signed_docker.com-notary.crt b/fixtures/self-signed_docker.com-notary.crt index 25b0c9a88..bd8ab6791 100644 --- a/fixtures/self-signed_docker.com-notary.crt +++ b/fixtures/self-signed_docker.com-notary.crt @@ -1,11 +1,11 @@ -----BEGIN CERTIFICATE----- -MIIBojCCAUqgAwIBAgIJAJ/QvR7begAjMAkGByqGSM49BAEwLTEPMA0GA1UEChMG -RG9ja2VyMRowGAYDVQQDExFkb2NrZXIuY29tL25vdGFyeTAeFw0xNzAzMDExOTM2 -MjlaFw0xOTAzMjExOTM2MjlaMC0xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UEAxMR -ZG9ja2VyLmNvbS9ub3RhcnkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARhDFJB -B0yw20CDHoOWUU/bDKykjGy78yo1P608zugjy3cfiGFXXuuzcBsd/qV/btceqYrS -Eih1ygc06ql0UzsZo1QwUjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAT -BgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUH7glsL3UQMQFdJpbmZN3GE9u -nsEwCQYHKoZIzj0EAQNHADBEAiAjIdQW0DyQT1Kj5MvrohJ+PIAp6/z4Gy7gEKv0 -IWQJNAIgM1lndnPUo+pyGVBRdhqqwi2ilEW1IFfYkeuj2qjo37o= +MIIBozCCAUqgAwIBAgIJAMet9A3jY0w3MAkGByqGSM49BAEwLTEPMA0GA1UEChMG +RG9ja2VyMRowGAYDVQQDExFkb2NrZXIuY29tL25vdGFyeTAeFw0xNzA0MTIyMzQ4 +NDZaFw0xOTA1MDIyMzQ4NDZaMC0xDzANBgNVBAoTBkRvY2tlcjEaMBgGA1UEAxMR +ZG9ja2VyLmNvbS9ub3RhcnkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARYAr6n +ca1IRMdWTDjFVLELKRt/SfunjqmFWev1iLhwuBwphw8fGdR66sobRXo5X7xu7lPd +29CRQItclgoFXcTGo1QwUjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAT +BgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUotaBfYlg9rKz33VuMmtOTg7n +kaowCQYHKoZIzj0EAQNIADBFAiEAsFw5jq+EfgJw76RZemNUYL1+tOzwgUsyHpdN +HehFJtYCICjWuITzZjNQ8JALiwaCQpBghMR92zH1u+9Z4Fan2T9h -----END CERTIFICATE----- diff --git a/fixtures/self-signed_secure.example.com.crt b/fixtures/self-signed_secure.example.com.crt index 198746694..e8edbf892 100755 --- a/fixtures/self-signed_secure.example.com.crt +++ b/fixtures/self-signed_secure.example.com.crt @@ -1,12 +1,12 @@ -----BEGIN CERTIFICATE----- -MIIBvTCCAWSgAwIBAgIJANDdYEto/G43MAkGByqGSM49BAEwOjEbMBkGA1UEChMS +MIIBvTCCAWSgAwIBAgIJAK96Ln1E3HXDMAkGByqGSM49BAEwOjEbMBkGA1UEChMS c2VjdXJlLmV4YW1wbGUuY29tMRswGQYDVQQDExJzZWN1cmUuZXhhbXBsZS5jb20w -HhcNMTcwMzAxMTkzNjI5WhcNMTkwMzIxMTkzNjI5WjA6MRswGQYDVQQKExJzZWN1 +HhcNMTcwNDEyMjM0ODQ3WhcNMTkwNTAyMjM0ODQ3WjA6MRswGQYDVQQKExJzZWN1 cmUuZXhhbXBsZS5jb20xGzAZBgNVBAMTEnNlY3VyZS5leGFtcGxlLmNvbTBZMBMG -ByqGSM49AgEGCCqGSM49AwEHA0IABEfv3eYe/i6sM+Z0paRbiXGeCJ8puGcOHnGG -j5zgmcYgbP3LQ8V7EXVR9d1c4/UkiP/h8hngf7jIpN7c4cv02f6jVDBSMAwGA1Ud +ByqGSM49AgEGCCqGSM49AwEHA0IABHdz9vemdI4L5tgPTMWal7xnjnJGUc9+pMVQ +w1lU3BKKsAdJfKRjJgTHIcvDdKjtKsJDVPE0XIs+1rU4aE9Q+wmjVDBSMAwGA1Ud EwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0G -A1UdDgQWBBR8BdSOsCrM6DW8JEPY+eQIsdfJbTAJBgcqhkjOPQQBA0gAMEUCIQD1 -gCl7JkpOoh82V+B1wfIorq75c0dDUjf9wC/Rc6wlqAIgebuKMb8/kIyplETYeKyo -Eg0uVIQTi6aZA62T0/W1Umw= +A1UdDgQWBBT9jDYd30Xv0NRKNC5AQ6wKAwMe9jAJBgcqhkjOPQQBA0gAMEUCIQDI +B7B1cOmQcODtcfSE9CDTpumb7Y+vi6GMviLhwxw8+AIgV2SRjwNuDSotCjYCZbz4 +sdtkUu50i1M6++Kr8LSn2t8= -----END CERTIFICATE----- diff --git a/utils/configuration.go b/utils/configuration.go index 1d091a0ec..fd3fb10c7 100644 --- a/utils/configuration.go +++ b/utils/configuration.go @@ -69,12 +69,13 @@ func ParseTLS(configuration *viper.Viper, prefix string, tlsRequired bool) (tlsc ) clientCert := GetPathRelativeToConfig( configuration, - strings.Join([]string{prefix, "tls_client_cert"}, "."), + strings.Join([]string{prefix, "tls_cert_file"}, "."), ) clientKey := GetPathRelativeToConfig( configuration, - strings.Join([]string{prefix, "tls_client_key"}, "."), + strings.Join([]string{prefix, "tls_key_file"}, "."), ) + logrus.Infof("tls files: \nCA: %s\ncert: %s\nkey: %s", rootCA, clientCert, clientKey) tlsOpts := tlsconfig.Options{ CertFile: clientCert, @@ -88,16 +89,16 @@ func ParseTLS(configuration *viper.Viper, prefix string, tlsRequired bool) (tlsc if !tlsRequired { cert, key, ca := tlsOpts.CertFile, tlsOpts.KeyFile, tlsOpts.CAFile if cert == "" && key == "" && ca == "" { - return nil, nil + return tlsconfig.Options{}, nil } if (cert == "" && key != "") || (cert != "" && key == "") || (cert == "" && key == "" && ca != "") { - return nil, fmt.Errorf( + return tlsconfig.Options{}, fmt.Errorf( "either include both a cert and key file, or no TLS information at all to disable TLS") } } - return &tlsOpts, nil + return tlsOpts, nil } // ParseLogLevel tries to parse out a log level from a Viper. If there is no diff --git a/utils/transport.go b/utils/transport.go index 53ff260f9..634fed1dc 100644 --- a/utils/transport.go +++ b/utils/transport.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "crypto/x509" "fmt" + "io/ioutil" "net" "net/http" "net/url" @@ -12,8 +13,6 @@ import ( "github.com/docker/distribution/registry/client/auth" "github.com/docker/distribution/registry/client/auth/challenge" "github.com/docker/distribution/registry/client/transport" - "io/ioutil" - "strings" ) // Stolen from a mix of UCP + nautilus signer, some might be able to be cleaned up / streamlined From a8eac65d4ae570bfd10489424bf64eea3b79e666 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 12 Apr 2017 22:55:05 -0700 Subject: [PATCH 57/62] some refactoring and more bugfixes for client api Signed-off-by: David Lawrence (github: endophage) --- client_api/api/api.pb.go | 621 +++++++++------------------------------ client_api/api/api.proto | 57 ++-- client_api/api/client.go | 94 ++++-- client_api/api/server.go | 184 ++++-------- cmd/notary/tuf.go | 4 +- 5 files changed, 278 insertions(+), 682 deletions(-) diff --git a/client_api/api/api.pb.go b/client_api/api/api.pb.go index 354d5d1eb..19e6b037a 100644 --- a/client_api/api/api.pb.go +++ b/client_api/api/api.pb.go @@ -48,25 +48,20 @@ It has these top-level messages: RoleWithSignatures RoleWithSignaturesList RoleWithSignaturesListResponse - CryptoServiceMessage CryptoServiceCreateMessage - Signer PrivateKey CryptoServiceAddKeyMessage PrivateKeyResponse KeyIDMessage KeyIDsListResponse - CryptoServicePrivateKeySignMessage - SignatureResponse SigningKeyIDsToRolesResponse - VersionMessage */ package api import proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" -import google_protobuf "github.com/golang/protobuf/ptypes/empty" +import _ "github.com/golang/protobuf/ptypes/empty" import ( context "golang.org/x/net/context" @@ -1217,15 +1212,6 @@ func (m *RoleWithSignaturesListResponse) GetMessage() string { return "" } -// FIXME: unimplemented -type CryptoServiceMessage struct { -} - -func (m *CryptoServiceMessage) Reset() { *m = CryptoServiceMessage{} } -func (m *CryptoServiceMessage) String() string { return proto.CompactTextString(m) } -func (*CryptoServiceMessage) ProtoMessage() {} -func (*CryptoServiceMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} } - type CryptoServiceCreateMessage struct { RoleName string `protobuf:"bytes,1,opt,name=roleName" json:"roleName,omitempty"` Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` @@ -1235,7 +1221,7 @@ type CryptoServiceCreateMessage struct { func (m *CryptoServiceCreateMessage) Reset() { *m = CryptoServiceCreateMessage{} } func (m *CryptoServiceCreateMessage) String() string { return proto.CompactTextString(m) } func (*CryptoServiceCreateMessage) ProtoMessage() {} -func (*CryptoServiceCreateMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{40} } +func (*CryptoServiceCreateMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{39} } func (m *CryptoServiceCreateMessage) GetRoleName() string { if m != nil { @@ -1258,58 +1244,34 @@ func (m *CryptoServiceCreateMessage) GetAlgorithm() string { return "" } -type Signer struct { - Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` -} - -func (m *Signer) Reset() { *m = Signer{} } -func (m *Signer) String() string { return proto.CompactTextString(m) } -func (*Signer) ProtoMessage() {} -func (*Signer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41} } - -func (m *Signer) GetPubkey() *PublicKey { - if m != nil { - return m.Pubkey - } - return nil -} - type PrivateKey struct { - Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` - Privkey []byte `protobuf:"bytes,2,opt,name=privkey,proto3" json:"privkey,omitempty"` - CryptoSigner *Signer `protobuf:"bytes,3,opt,name=cryptoSigner" json:"cryptoSigner,omitempty"` - SigAlgorithm string `protobuf:"bytes,4,opt,name=sigAlgorithm" json:"sigAlgorithm,omitempty"` + PubKey []byte `protobuf:"bytes,1,opt,name=pubKey,proto3" json:"pubKey,omitempty"` + PrivKey []byte `protobuf:"bytes,2,opt,name=privKey,proto3" json:"privKey,omitempty"` + Algorithm string `protobuf:"bytes,4,opt,name=algorithm" json:"algorithm,omitempty"` } func (m *PrivateKey) Reset() { *m = PrivateKey{} } func (m *PrivateKey) String() string { return proto.CompactTextString(m) } func (*PrivateKey) ProtoMessage() {} -func (*PrivateKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{42} } +func (*PrivateKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{40} } -func (m *PrivateKey) GetPubkey() *PublicKey { +func (m *PrivateKey) GetPubKey() []byte { if m != nil { - return m.Pubkey + return m.PubKey } return nil } -func (m *PrivateKey) GetPrivkey() []byte { +func (m *PrivateKey) GetPrivKey() []byte { if m != nil { - return m.Privkey + return m.PrivKey } return nil } -func (m *PrivateKey) GetCryptoSigner() *Signer { +func (m *PrivateKey) GetAlgorithm() string { if m != nil { - return m.CryptoSigner - } - return nil -} - -func (m *PrivateKey) GetSigAlgorithm() string { - if m != nil { - return m.SigAlgorithm + return m.Algorithm } return "" } @@ -1323,7 +1285,7 @@ type CryptoServiceAddKeyMessage struct { func (m *CryptoServiceAddKeyMessage) Reset() { *m = CryptoServiceAddKeyMessage{} } func (m *CryptoServiceAddKeyMessage) String() string { return proto.CompactTextString(m) } func (*CryptoServiceAddKeyMessage) ProtoMessage() {} -func (*CryptoServiceAddKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{43} } +func (*CryptoServiceAddKeyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{41} } func (m *CryptoServiceAddKeyMessage) GetRoleName() string { if m != nil { @@ -1357,7 +1319,7 @@ type PrivateKeyResponse struct { func (m *PrivateKeyResponse) Reset() { *m = PrivateKeyResponse{} } func (m *PrivateKeyResponse) String() string { return proto.CompactTextString(m) } func (*PrivateKeyResponse) ProtoMessage() {} -func (*PrivateKeyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{44} } +func (*PrivateKeyResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{42} } func (m *PrivateKeyResponse) GetRole() string { if m != nil { @@ -1402,7 +1364,7 @@ type KeyIDMessage struct { func (m *KeyIDMessage) Reset() { *m = KeyIDMessage{} } func (m *KeyIDMessage) String() string { return proto.CompactTextString(m) } func (*KeyIDMessage) ProtoMessage() {} -func (*KeyIDMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{45} } +func (*KeyIDMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{43} } func (m *KeyIDMessage) GetKeyID() string { if m != nil { @@ -1427,7 +1389,7 @@ type KeyIDsListResponse struct { func (m *KeyIDsListResponse) Reset() { *m = KeyIDsListResponse{} } func (m *KeyIDsListResponse) String() string { return proto.CompactTextString(m) } func (*KeyIDsListResponse) ProtoMessage() {} -func (*KeyIDsListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{46} } +func (*KeyIDsListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{44} } func (m *KeyIDsListResponse) GetKeyIDs() []string { if m != nil { @@ -1450,80 +1412,6 @@ func (m *KeyIDsListResponse) GetMessage() string { return "" } -type CryptoServicePrivateKeySignMessage struct { - Pubkey *PublicKey `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"` - Digest []byte `protobuf:"bytes,2,opt,name=digest,proto3" json:"digest,omitempty"` - Privkey []byte `protobuf:"bytes,3,opt,name=privkey,proto3" json:"privkey,omitempty"` - Gun string `protobuf:"bytes,4,opt,name=gun" json:"gun,omitempty"` -} - -func (m *CryptoServicePrivateKeySignMessage) Reset() { *m = CryptoServicePrivateKeySignMessage{} } -func (m *CryptoServicePrivateKeySignMessage) String() string { return proto.CompactTextString(m) } -func (*CryptoServicePrivateKeySignMessage) ProtoMessage() {} -func (*CryptoServicePrivateKeySignMessage) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{47} -} - -func (m *CryptoServicePrivateKeySignMessage) GetPubkey() *PublicKey { - if m != nil { - return m.Pubkey - } - return nil -} - -func (m *CryptoServicePrivateKeySignMessage) GetDigest() []byte { - if m != nil { - return m.Digest - } - return nil -} - -func (m *CryptoServicePrivateKeySignMessage) GetPrivkey() []byte { - if m != nil { - return m.Privkey - } - return nil -} - -func (m *CryptoServicePrivateKeySignMessage) GetGun() string { - if m != nil { - return m.Gun - } - return "" -} - -type SignatureResponse struct { - Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` - Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"` -} - -func (m *SignatureResponse) Reset() { *m = SignatureResponse{} } -func (m *SignatureResponse) String() string { return proto.CompactTextString(m) } -func (*SignatureResponse) ProtoMessage() {} -func (*SignatureResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{48} } - -func (m *SignatureResponse) GetSignature() []byte { - if m != nil { - return m.Signature - } - return nil -} - -func (m *SignatureResponse) GetSuccess() bool { - if m != nil { - return m.Success - } - return false -} - -func (m *SignatureResponse) GetMessage() string { - if m != nil { - return m.Message - } - return "" -} - type SigningKeyIDsToRolesResponse struct { KeyIDs map[string]string `protobuf:"bytes,1,rep,name=keyIDs" json:"keyIDs,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Success bool `protobuf:"varint,2,opt,name=success" json:"success,omitempty"` @@ -1533,7 +1421,7 @@ type SigningKeyIDsToRolesResponse struct { func (m *SigningKeyIDsToRolesResponse) Reset() { *m = SigningKeyIDsToRolesResponse{} } func (m *SigningKeyIDsToRolesResponse) String() string { return proto.CompactTextString(m) } func (*SigningKeyIDsToRolesResponse) ProtoMessage() {} -func (*SigningKeyIDsToRolesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{49} } +func (*SigningKeyIDsToRolesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{45} } func (m *SigningKeyIDsToRolesResponse) GetKeyIDs() map[string]string { if m != nil { @@ -1556,30 +1444,6 @@ func (m *SigningKeyIDsToRolesResponse) GetMessage() string { return "" } -type VersionMessage struct { - Version int32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"` - Gun string `protobuf:"bytes,2,opt,name=gun" json:"gun,omitempty"` -} - -func (m *VersionMessage) Reset() { *m = VersionMessage{} } -func (m *VersionMessage) String() string { return proto.CompactTextString(m) } -func (*VersionMessage) ProtoMessage() {} -func (*VersionMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{50} } - -func (m *VersionMessage) GetVersion() int32 { - if m != nil { - return m.Version - } - return 0 -} - -func (m *VersionMessage) GetGun() string { - if m != nil { - return m.Gun - } - return "" -} - func init() { proto.RegisterType((*GunMessage)(nil), "api.GunMessage") proto.RegisterType((*AddDelegationMessage)(nil), "api.AddDelegationMessage") @@ -1620,18 +1484,13 @@ func init() { proto.RegisterType((*RoleWithSignatures)(nil), "api.RoleWithSignatures") proto.RegisterType((*RoleWithSignaturesList)(nil), "api.RoleWithSignaturesList") proto.RegisterType((*RoleWithSignaturesListResponse)(nil), "api.RoleWithSignaturesListResponse") - proto.RegisterType((*CryptoServiceMessage)(nil), "api.CryptoServiceMessage") proto.RegisterType((*CryptoServiceCreateMessage)(nil), "api.CryptoServiceCreateMessage") - proto.RegisterType((*Signer)(nil), "api.Signer") proto.RegisterType((*PrivateKey)(nil), "api.PrivateKey") proto.RegisterType((*CryptoServiceAddKeyMessage)(nil), "api.CryptoServiceAddKeyMessage") proto.RegisterType((*PrivateKeyResponse)(nil), "api.PrivateKeyResponse") proto.RegisterType((*KeyIDMessage)(nil), "api.KeyIDMessage") proto.RegisterType((*KeyIDsListResponse)(nil), "api.KeyIDsListResponse") - proto.RegisterType((*CryptoServicePrivateKeySignMessage)(nil), "api.CryptoServicePrivateKeySignMessage") - proto.RegisterType((*SignatureResponse)(nil), "api.SignatureResponse") proto.RegisterType((*SigningKeyIDsToRolesResponse)(nil), "api.SigningKeyIDsToRolesResponse") - proto.RegisterType((*VersionMessage)(nil), "api.VersionMessage") } // Reference imports to suppress errors if they are not otherwise used. @@ -1658,8 +1517,6 @@ type NotaryClient interface { GetTargetByName(ctx context.Context, in *TargetByNameAction, opts ...grpc.CallOption) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName GetAllTargetMetadataByName(ctx context.Context, in *TargetNameMessage, opts ...grpc.CallOption) (*TargetSignedListResponse, error) - // GetChangelist returns the list of the repository's unpublished changes - GetChangelist(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*ChangeListResponse, error) ListRoles(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) GetDelegationRoles(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*RoleListResponse, error) AddDelegation(ctx context.Context, in *AddDelegationMessage, opts ...grpc.CallOption) (*BasicResponse, error) @@ -1673,16 +1530,14 @@ type NotaryClient interface { Witness(ctx context.Context, in *RoleNameListMessage, opts ...grpc.CallOption) (*RoleNameListResponse, error) RotateKey(ctx context.Context, in *RotateKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) // CryptoService implementation - CryptoService(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*CryptoServiceMessage, error) CryptoServiceCreate(ctx context.Context, in *CryptoServiceCreateMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) - CryptoServicePrivateKeySign(ctx context.Context, in *CryptoServicePrivateKeySignMessage, opts ...grpc.CallOption) (*SignatureResponse, error) + // rpc CryptoServicePrivateKeySign(CryptoServicePrivateKeySignMessage) returns (SignatureResponse) {} CryptoServiceAddKey(ctx context.Context, in *CryptoServiceAddKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) CryptoServiceGetKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) - CryptoServiceGetPrivateKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PrivateKeyResponse, error) - CryptoServiceRemoveKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*BasicResponse, error) + // rpc CryptoServiceGetPrivateKey(KeyIDMessage) returns (PrivateKeyResponse) {} + // rpc CryptoServiceRemoveKey(KeyIDMessage) returns (BasicResponse) {} CryptoServiceListKeys(ctx context.Context, in *RoleNameMessage, opts ...grpc.CallOption) (*KeyIDsListResponse, error) CryptoServiceListAllKeys(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*SigningKeyIDsToRolesResponse, error) - SetLegacyVersions(ctx context.Context, in *VersionMessage, opts ...grpc.CallOption) (*google_protobuf.Empty, error) } type notaryClient struct { @@ -1756,15 +1611,6 @@ func (c *notaryClient) GetAllTargetMetadataByName(ctx context.Context, in *Targe return out, nil } -func (c *notaryClient) GetChangelist(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*ChangeListResponse, error) { - out := new(ChangeListResponse) - err := grpc.Invoke(ctx, "/api.Notary/GetChangelist", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *notaryClient) ListRoles(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*RoleWithSignaturesListResponse, error) { out := new(RoleWithSignaturesListResponse) err := grpc.Invoke(ctx, "/api.Notary/ListRoles", in, out, c.cc, opts...) @@ -1873,15 +1719,6 @@ func (c *notaryClient) RotateKey(ctx context.Context, in *RotateKeyMessage, opts return out, nil } -func (c *notaryClient) CryptoService(ctx context.Context, in *GunMessage, opts ...grpc.CallOption) (*CryptoServiceMessage, error) { - out := new(CryptoServiceMessage) - err := grpc.Invoke(ctx, "/api.Notary/CryptoService", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *notaryClient) CryptoServiceCreate(ctx context.Context, in *CryptoServiceCreateMessage, opts ...grpc.CallOption) (*PublicKeyResponse, error) { out := new(PublicKeyResponse) err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceCreate", in, out, c.cc, opts...) @@ -1891,15 +1728,6 @@ func (c *notaryClient) CryptoServiceCreate(ctx context.Context, in *CryptoServic return out, nil } -func (c *notaryClient) CryptoServicePrivateKeySign(ctx context.Context, in *CryptoServicePrivateKeySignMessage, opts ...grpc.CallOption) (*SignatureResponse, error) { - out := new(SignatureResponse) - err := grpc.Invoke(ctx, "/api.Notary/CryptoServicePrivateKeySign", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *notaryClient) CryptoServiceAddKey(ctx context.Context, in *CryptoServiceAddKeyMessage, opts ...grpc.CallOption) (*BasicResponse, error) { out := new(BasicResponse) err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceAddKey", in, out, c.cc, opts...) @@ -1918,24 +1746,6 @@ func (c *notaryClient) CryptoServiceGetKey(ctx context.Context, in *KeyIDMessage return out, nil } -func (c *notaryClient) CryptoServiceGetPrivateKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*PrivateKeyResponse, error) { - out := new(PrivateKeyResponse) - err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceGetPrivateKey", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *notaryClient) CryptoServiceRemoveKey(ctx context.Context, in *KeyIDMessage, opts ...grpc.CallOption) (*BasicResponse, error) { - out := new(BasicResponse) - err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceRemoveKey", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *notaryClient) CryptoServiceListKeys(ctx context.Context, in *RoleNameMessage, opts ...grpc.CallOption) (*KeyIDsListResponse, error) { out := new(KeyIDsListResponse) err := grpc.Invoke(ctx, "/api.Notary/CryptoServiceListKeys", in, out, c.cc, opts...) @@ -1954,15 +1764,6 @@ func (c *notaryClient) CryptoServiceListAllKeys(ctx context.Context, in *GunMess return out, nil } -func (c *notaryClient) SetLegacyVersions(ctx context.Context, in *VersionMessage, opts ...grpc.CallOption) (*google_protobuf.Empty, error) { - out := new(google_protobuf.Empty) - err := grpc.Invoke(ctx, "/api.Notary/SetLegacyVersions", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // Server API for Notary service type NotaryServer interface { @@ -1979,8 +1780,6 @@ type NotaryServer interface { GetTargetByName(context.Context, *TargetByNameAction) (*TargetWithRoleResponse, error) // GetAllTargetMetadataByName GetAllTargetMetadataByName(context.Context, *TargetNameMessage) (*TargetSignedListResponse, error) - // GetChangelist returns the list of the repository's unpublished changes - GetChangelist(context.Context, *GunMessage) (*ChangeListResponse, error) ListRoles(context.Context, *GunMessage) (*RoleWithSignaturesListResponse, error) GetDelegationRoles(context.Context, *GunMessage) (*RoleListResponse, error) AddDelegation(context.Context, *AddDelegationMessage) (*BasicResponse, error) @@ -1994,16 +1793,14 @@ type NotaryServer interface { Witness(context.Context, *RoleNameListMessage) (*RoleNameListResponse, error) RotateKey(context.Context, *RotateKeyMessage) (*BasicResponse, error) // CryptoService implementation - CryptoService(context.Context, *GunMessage) (*CryptoServiceMessage, error) CryptoServiceCreate(context.Context, *CryptoServiceCreateMessage) (*PublicKeyResponse, error) - CryptoServicePrivateKeySign(context.Context, *CryptoServicePrivateKeySignMessage) (*SignatureResponse, error) + // rpc CryptoServicePrivateKeySign(CryptoServicePrivateKeySignMessage) returns (SignatureResponse) {} CryptoServiceAddKey(context.Context, *CryptoServiceAddKeyMessage) (*BasicResponse, error) CryptoServiceGetKey(context.Context, *KeyIDMessage) (*PublicKeyResponse, error) - CryptoServiceGetPrivateKey(context.Context, *KeyIDMessage) (*PrivateKeyResponse, error) - CryptoServiceRemoveKey(context.Context, *KeyIDMessage) (*BasicResponse, error) + // rpc CryptoServiceGetPrivateKey(KeyIDMessage) returns (PrivateKeyResponse) {} + // rpc CryptoServiceRemoveKey(KeyIDMessage) returns (BasicResponse) {} CryptoServiceListKeys(context.Context, *RoleNameMessage) (*KeyIDsListResponse, error) CryptoServiceListAllKeys(context.Context, *GunMessage) (*SigningKeyIDsToRolesResponse, error) - SetLegacyVersions(context.Context, *VersionMessage) (*google_protobuf.Empty, error) } func RegisterNotaryServer(s *grpc.Server, srv NotaryServer) { @@ -2136,24 +1933,6 @@ func _Notary_GetAllTargetMetadataByName_Handler(srv interface{}, ctx context.Con return interceptor(ctx, in, info, handler) } -func _Notary_GetChangelist_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GunMessage) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotaryServer).GetChangelist(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Notary/GetChangelist", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).GetChangelist(ctx, req.(*GunMessage)) - } - return interceptor(ctx, in, info, handler) -} - func _Notary_ListRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GunMessage) if err := dec(in); err != nil { @@ -2370,24 +2149,6 @@ func _Notary_RotateKey_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } -func _Notary_CryptoService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GunMessage) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotaryServer).CryptoService(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Notary/CryptoService", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).CryptoService(ctx, req.(*GunMessage)) - } - return interceptor(ctx, in, info, handler) -} - func _Notary_CryptoServiceCreate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CryptoServiceCreateMessage) if err := dec(in); err != nil { @@ -2406,24 +2167,6 @@ func _Notary_CryptoServiceCreate_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } -func _Notary_CryptoServicePrivateKeySign_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CryptoServicePrivateKeySignMessage) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotaryServer).CryptoServicePrivateKeySign(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Notary/CryptoServicePrivateKeySign", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).CryptoServicePrivateKeySign(ctx, req.(*CryptoServicePrivateKeySignMessage)) - } - return interceptor(ctx, in, info, handler) -} - func _Notary_CryptoServiceAddKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CryptoServiceAddKeyMessage) if err := dec(in); err != nil { @@ -2460,42 +2203,6 @@ func _Notary_CryptoServiceGetKey_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } -func _Notary_CryptoServiceGetPrivateKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(KeyIDMessage) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotaryServer).CryptoServiceGetPrivateKey(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Notary/CryptoServiceGetPrivateKey", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).CryptoServiceGetPrivateKey(ctx, req.(*KeyIDMessage)) - } - return interceptor(ctx, in, info, handler) -} - -func _Notary_CryptoServiceRemoveKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(KeyIDMessage) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotaryServer).CryptoServiceRemoveKey(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Notary/CryptoServiceRemoveKey", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).CryptoServiceRemoveKey(ctx, req.(*KeyIDMessage)) - } - return interceptor(ctx, in, info, handler) -} - func _Notary_CryptoServiceListKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RoleNameMessage) if err := dec(in); err != nil { @@ -2532,24 +2239,6 @@ func _Notary_CryptoServiceListAllKeys_Handler(srv interface{}, ctx context.Conte return interceptor(ctx, in, info, handler) } -func _Notary_SetLegacyVersions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(VersionMessage) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NotaryServer).SetLegacyVersions(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/api.Notary/SetLegacyVersions", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NotaryServer).SetLegacyVersions(ctx, req.(*VersionMessage)) - } - return interceptor(ctx, in, info, handler) -} - var _Notary_serviceDesc = grpc.ServiceDesc{ ServiceName: "api.Notary", HandlerType: (*NotaryServer)(nil), @@ -2582,10 +2271,6 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "GetAllTargetMetadataByName", Handler: _Notary_GetAllTargetMetadataByName_Handler, }, - { - MethodName: "GetChangelist", - Handler: _Notary_GetChangelist_Handler, - }, { MethodName: "ListRoles", Handler: _Notary_ListRoles_Handler, @@ -2634,18 +2319,10 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "RotateKey", Handler: _Notary_RotateKey_Handler, }, - { - MethodName: "CryptoService", - Handler: _Notary_CryptoService_Handler, - }, { MethodName: "CryptoServiceCreate", Handler: _Notary_CryptoServiceCreate_Handler, }, - { - MethodName: "CryptoServicePrivateKeySign", - Handler: _Notary_CryptoServicePrivateKeySign_Handler, - }, { MethodName: "CryptoServiceAddKey", Handler: _Notary_CryptoServiceAddKey_Handler, @@ -2654,14 +2331,6 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "CryptoServiceGetKey", Handler: _Notary_CryptoServiceGetKey_Handler, }, - { - MethodName: "CryptoServiceGetPrivateKey", - Handler: _Notary_CryptoServiceGetPrivateKey_Handler, - }, - { - MethodName: "CryptoServiceRemoveKey", - Handler: _Notary_CryptoServiceRemoveKey_Handler, - }, { MethodName: "CryptoServiceListKeys", Handler: _Notary_CryptoServiceListKeys_Handler, @@ -2670,10 +2339,6 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ MethodName: "CryptoServiceListAllKeys", Handler: _Notary_CryptoServiceListAllKeys_Handler, }, - { - MethodName: "SetLegacyVersions", - Handler: _Notary_SetLegacyVersions_Handler, - }, }, Streams: []grpc.StreamDesc{}, Metadata: "api.proto", @@ -2682,131 +2347,117 @@ var _Notary_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("api.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 2003 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0x5f, 0x73, 0xdb, 0xc6, - 0x11, 0x37, 0x48, 0x89, 0x32, 0x97, 0x94, 0x2c, 0x9d, 0x65, 0x8a, 0xa6, 0x6d, 0x59, 0x86, 0xdd, - 0xda, 0x69, 0x26, 0x54, 0xa2, 0xb4, 0x69, 0xd2, 0x34, 0xad, 0x69, 0xda, 0xc3, 0x28, 0xb2, 0x3d, - 0x2a, 0x94, 0xd8, 0x33, 0xcd, 0x4c, 0x27, 0x30, 0x71, 0x25, 0x31, 0x02, 0x01, 0x06, 0x38, 0x69, - 0x8a, 0x3e, 0xb4, 0xd3, 0xbe, 0xb5, 0xd3, 0x99, 0xb6, 0x8f, 0x7d, 0xee, 0x53, 0x5f, 0xfb, 0x59, - 0xf2, 0x4d, 0xfa, 0x05, 0x3a, 0xf7, 0x0f, 0xb8, 0x03, 0x0e, 0x94, 0xcc, 0x69, 0xdf, 0x78, 0x87, - 0xdd, 0xdf, 0xfe, 0xb9, 0xdd, 0xdb, 0xbd, 0x25, 0x34, 0xdd, 0xb9, 0xdf, 0x9f, 0xc7, 0x11, 0x89, - 0x50, 0xdd, 0x9d, 0xfb, 0xbd, 0x5b, 0x93, 0x28, 0x9a, 0x04, 0x78, 0x9f, 0x6d, 0xbd, 0x39, 0xfb, - 0xf5, 0xfe, 0xb3, 0xd9, 0x9c, 0xa4, 0x9c, 0xc2, 0xde, 0x05, 0x18, 0x9d, 0x85, 0x2f, 0x70, 0x92, - 0xb8, 0x13, 0x8c, 0x36, 0xa1, 0x3e, 0x39, 0x0b, 0xbb, 0xd6, 0x9e, 0xf5, 0xa8, 0xe9, 0xd0, 0x9f, - 0xf6, 0x9f, 0x2d, 0xd8, 0x1e, 0x78, 0xde, 0x53, 0x1c, 0xe0, 0x89, 0x4b, 0xfc, 0x28, 0x23, 0x45, - 0xb0, 0x12, 0xba, 0x33, 0x2c, 0x68, 0xd9, 0x6f, 0xf4, 0x11, 0x6c, 0x78, 0x19, 0xe1, 0x11, 0x4e, - 0x93, 0x6e, 0x6d, 0xaf, 0xfe, 0xa8, 0x75, 0xb0, 0xd1, 0xa7, 0x2a, 0x1d, 0x9f, 0xbd, 0x09, 0xfc, - 0xf1, 0x11, 0x4e, 0x9d, 0x02, 0x15, 0xda, 0x86, 0xd5, 0xb9, 0x4b, 0xa6, 0x49, 0xb7, 0xbe, 0x57, - 0x7f, 0xd4, 0x74, 0xf8, 0x42, 0x2a, 0xb3, 0x92, 0x2b, 0xf3, 0x7b, 0xb8, 0xab, 0xe9, 0xe2, 0x44, - 0x01, 0x1e, 0x84, 0x1e, 0xc5, 0xf8, 0x7f, 0xa8, 0x25, 0x14, 0xa8, 0xe7, 0x0a, 0xbc, 0x86, 0x9b, - 0x9a, 0x02, 0xc7, 0x54, 0xd1, 0x45, 0xa2, 0x33, 0xcb, 0x6a, 0x06, 0xcb, 0x14, 0xe0, 0x14, 0xee, - 0x3b, 0x78, 0x16, 0x9d, 0xe3, 0xa7, 0x9a, 0x0a, 0x83, 0xd0, 0xbb, 0x50, 0x44, 0x07, 0x1a, 0xa7, - 0x38, 0x3d, 0x7c, 0x2a, 0x65, 0x88, 0xd5, 0xa5, 0x9d, 0x3a, 0x84, 0x5b, 0x45, 0xd1, 0xd4, 0xaf, - 0x8b, 0x44, 0x0a, 0x90, 0x5a, 0x0e, 0xf2, 0x4b, 0xb8, 0x5d, 0x04, 0xf9, 0x9f, 0xf9, 0xe6, 0xeb, - 0xb2, 0x82, 0x17, 0x9d, 0x78, 0x95, 0x4f, 0xca, 0xe0, 0x3f, 0x86, 0x6b, 0xd4, 0xda, 0x97, 0xee, - 0x4c, 0xb5, 0x38, 0x8e, 0x82, 0x0c, 0x90, 0xfe, 0x36, 0x58, 0xfc, 0x3b, 0xd8, 0x74, 0x22, 0xe2, - 0x12, 0x7c, 0x84, 0xd3, 0x45, 0x9c, 0x3f, 0x80, 0xcd, 0x04, 0xc7, 0xe7, 0x38, 0x7e, 0xe1, 0x86, - 0xee, 0x04, 0x27, 0x47, 0x38, 0x65, 0x30, 0x57, 0x9d, 0xd2, 0x3e, 0xea, 0xc2, 0xda, 0x29, 0x4e, - 0x9f, 0xfb, 0x09, 0x11, 0x87, 0x26, 0x97, 0x86, 0x63, 0xfb, 0xa3, 0x05, 0xad, 0xc3, 0xd0, 0x27, - 0x52, 0xf6, 0x2e, 0x40, 0x1c, 0x45, 0xe4, 0x88, 0x9b, 0x6d, 0x31, 0x76, 0x65, 0x07, 0x0d, 0x00, - 0xa9, 0xf2, 0x3c, 0x6a, 0x75, 0xc2, 0x34, 0x69, 0x1d, 0x6c, 0xb1, 0x44, 0x90, 0x7e, 0xa0, 0x02, - 0x1d, 0x03, 0xb1, 0xc1, 0x7b, 0x0f, 0xa0, 0xad, 0x72, 0xd1, 0x23, 0x8d, 0x19, 0x2e, 0x97, 0xcf, - 0x17, 0xf6, 0x67, 0x70, 0x5d, 0xa5, 0x92, 0x1a, 0x1b, 0x89, 0x0d, 0x9e, 0xfe, 0x83, 0x05, 0xdb, - 0x9a, 0x6e, 0x38, 0x99, 0x47, 0x61, 0x82, 0xd1, 0x8f, 0xa0, 0x1d, 0x2b, 0xfb, 0xcc, 0xed, 0x46, - 0x63, 0x34, 0x32, 0xea, 0xe5, 0xe4, 0x6c, 0x3c, 0xc6, 0x49, 0x22, 0x0e, 0x42, 0x2e, 0xe9, 0x97, - 0x19, 0x57, 0x4e, 0x18, 0x29, 0x97, 0xf6, 0x27, 0xb0, 0xf5, 0xa5, 0x1b, 0x4f, 0x30, 0x29, 0x04, - 0xca, 0x25, 0x52, 0xe3, 0xdf, 0x16, 0x34, 0x38, 0x6f, 0xf9, 0x7a, 0xcd, 0x20, 0x6a, 0x7a, 0xf0, - 0x06, 0x38, 0x9c, 0x90, 0x29, 0x53, 0xa2, 0xee, 0x88, 0x15, 0xda, 0x87, 0xc6, 0xd4, 0x4d, 0xa6, - 0x38, 0xe9, 0xae, 0xb0, 0xeb, 0x6b, 0x87, 0x19, 0xca, 0xa1, 0xfb, 0x9f, 0xb3, 0x2f, 0xcf, 0x42, - 0x12, 0xa7, 0x8e, 0x20, 0xeb, 0x7d, 0x02, 0x2d, 0x65, 0x9b, 0x4a, 0x3f, 0xc5, 0xa9, 0x94, 0x7e, - 0x8a, 0x53, 0x7a, 0x02, 0xe7, 0x6e, 0x70, 0xc6, 0xc5, 0xb7, 0x1d, 0xbe, 0xf8, 0x49, 0xed, 0x63, - 0xcb, 0x3e, 0x84, 0x0d, 0x0e, 0xfc, 0xda, 0x27, 0x53, 0xea, 0x4b, 0x74, 0x1f, 0x1a, 0x84, 0xed, - 0x08, 0x37, 0xb7, 0x14, 0xe9, 0x8e, 0xf8, 0x94, 0x25, 0x40, 0x2d, 0x4f, 0x00, 0xfb, 0x4f, 0x16, - 0x74, 0x74, 0xac, 0xec, 0x00, 0x3f, 0x85, 0x0d, 0xa2, 0x7d, 0x11, 0xd8, 0xd7, 0x15, 0xec, 0x8c, - 0xa9, 0x40, 0xba, 0xd4, 0x31, 0x8e, 0x8a, 0xaa, 0x64, 0x41, 0xf1, 0x1e, 0xac, 0x71, 0x7c, 0x1e, - 0x8e, 0x15, 0x3a, 0x48, 0x1a, 0xfb, 0xaf, 0x16, 0xec, 0x9a, 0x91, 0x32, 0xe3, 0x4e, 0xa0, 0x43, - 0x8c, 0x14, 0xc2, 0xc8, 0x5b, 0x06, 0x01, 0x19, 0x48, 0x05, 0x6b, 0xb5, 0xd1, 0xf6, 0x18, 0x10, - 0xc7, 0x7a, 0x92, 0x52, 0xea, 0xc1, 0x98, 0xde, 0x93, 0xc6, 0x10, 0x7d, 0x28, 0xf3, 0xae, 0x32, - 0xf9, 0xf5, 0x54, 0x54, 0xf2, 0xfd, 0x5b, 0x68, 0x9e, 0xf8, 0x93, 0xd0, 0x25, 0x67, 0x31, 0xcb, - 0x5f, 0x76, 0xad, 0x0a, 0x70, 0xbe, 0xa0, 0xd1, 0x3b, 0xc3, 0x64, 0x1a, 0x79, 0x22, 0x08, 0xc4, - 0x0a, 0xdd, 0x86, 0x66, 0x22, 0x59, 0x19, 0x64, 0xdb, 0xc9, 0x37, 0xa8, 0x5d, 0x7e, 0xf2, 0xca, - 0x0d, 0x7c, 0x8f, 0xdd, 0x71, 0x57, 0x1d, 0xb9, 0xb4, 0x7f, 0x01, 0xcd, 0xac, 0x42, 0xa3, 0x0d, - 0xa8, 0xf9, 0x9e, 0x90, 0x57, 0xf3, 0x19, 0xa8, 0x1b, 0x4c, 0xa2, 0xd8, 0x27, 0xd3, 0x99, 0x90, - 0x97, 0x6f, 0x50, 0x55, 0xe6, 0x8c, 0x55, 0xc8, 0x13, 0x2b, 0xfb, 0x2b, 0xd8, 0xca, 0x8b, 0xbe, - 0x3c, 0xae, 0xef, 0x33, 0x62, 0x99, 0x20, 0xe5, 0xe6, 0x40, 0x7c, 0x5d, 0x70, 0x02, 0xdf, 0x59, - 0xb0, 0xa1, 0xd7, 0x50, 0xf4, 0x01, 0xac, 0x9c, 0xd2, 0x7e, 0x83, 0x87, 0xd4, 0x1d, 0x06, 0xa9, - 0x93, 0xf4, 0x69, 0x29, 0xe3, 0x69, 0xcb, 0x48, 0x8d, 0x37, 0xc2, 0x6d, 0x68, 0x92, 0x69, 0x8c, - 0x93, 0x69, 0x14, 0x78, 0xcc, 0x96, 0x55, 0x27, 0xdf, 0xc8, 0xeb, 0xe8, 0x8a, 0x52, 0x47, 0x7b, - 0x23, 0x68, 0x66, 0xd0, 0x86, 0xd4, 0x7f, 0xa0, 0xa6, 0x7e, 0xd9, 0x5a, 0xe5, 0x2a, 0xf8, 0x8b, - 0x05, 0x6d, 0x1e, 0x59, 0xf4, 0xe8, 0xb1, 0x87, 0x1e, 0x2a, 0x55, 0x4e, 0xe6, 0x89, 0x6e, 0x94, - 0x28, 0x7d, 0xf9, 0x95, 0x51, 0xab, 0xbe, 0x32, 0xfa, 0x00, 0x59, 0x18, 0xf0, 0x5e, 0x45, 0x6a, - 0x93, 0x45, 0x9a, 0xa3, 0x50, 0xd8, 0x3f, 0x87, 0x4d, 0x55, 0x1b, 0x96, 0x15, 0xef, 0x16, 0x93, - 0x77, 0x4b, 0x91, 0xc4, 0xe9, 0xf2, 0xd4, 0xfd, 0xbb, 0x05, 0xdd, 0x22, 0x42, 0x16, 0x05, 0x03, - 0xd8, 0x24, 0x85, 0x6f, 0xc2, 0xce, 0x1b, 0x25, 0x48, 0xc6, 0x58, 0x22, 0x5f, 0xea, 0x5e, 0x1a, - 0xc2, 0xfa, 0x13, 0x37, 0xf1, 0xc7, 0x99, 0x1e, 0x0a, 0x88, 0x55, 0x09, 0x52, 0xd3, 0x41, 0x7e, - 0x03, 0x8d, 0xe1, 0xd4, 0x0d, 0x27, 0xac, 0x82, 0xb8, 0x2c, 0xff, 0xc5, 0x89, 0x8b, 0x15, 0x8d, - 0x94, 0x64, 0x1c, 0xcd, 0x25, 0x27, 0x5f, 0xd0, 0x88, 0x23, 0xe9, 0x5c, 0xea, 0xc4, 0x7e, 0xd3, - 0x3d, 0x1a, 0x46, 0xa2, 0xe1, 0x60, 0xbf, 0xa9, 0xe4, 0x71, 0x14, 0x12, 0x1c, 0x92, 0xee, 0x2a, - 0xcb, 0x27, 0xb9, 0xb4, 0x3f, 0x04, 0xe0, 0x92, 0x99, 0x03, 0xbe, 0x07, 0x6b, 0x63, 0xb6, 0x92, - 0xa7, 0xc1, 0xcf, 0x9d, 0x53, 0x38, 0xf2, 0x9b, 0x9d, 0x02, 0xca, 0x99, 0x32, 0xc3, 0xf7, 0x01, - 0x38, 0x41, 0x90, 0xbb, 0xfe, 0x9a, 0xc2, 0xcf, 0x88, 0x15, 0x92, 0xa5, 0xdc, 0xfd, 0x18, 0xae, - 0x3a, 0x51, 0x44, 0x58, 0x8a, 0xe6, 0xad, 0xa2, 0xa5, 0xb5, 0x8a, 0x5a, 0xce, 0xd5, 0x0a, 0x39, - 0x67, 0x7f, 0x0d, 0x2b, 0x8c, 0xfb, 0x1d, 0xb8, 0x1a, 0x0b, 0x24, 0xa1, 0xec, 0xba, 0xb8, 0x4e, - 0xf9, 0xa6, 0x93, 0x7d, 0x36, 0x26, 0xb6, 0xb1, 0x47, 0xb7, 0xdf, 0xa5, 0xea, 0x05, 0xdc, 0x99, - 0x77, 0xd5, 0x26, 0xa9, 0x75, 0xd0, 0xcc, 0x2e, 0x6b, 0xd9, 0x5c, 0x7d, 0x4b, 0xfb, 0xd0, 0x40, - 0x77, 0x22, 0xd3, 0x2a, 0x50, 0x8b, 0xcd, 0x7a, 0xc6, 0xc7, 0x08, 0xb3, 0xcf, 0x4b, 0xb9, 0x6f, - 0x0c, 0x88, 0x22, 0xd1, 0xe2, 0x94, 0xe5, 0x68, 0x52, 0x48, 0x64, 0xeb, 0xa2, 0x44, 0x46, 0x77, - 0x94, 0x5e, 0x41, 0x33, 0x8c, 0xb7, 0x0d, 0x2e, 0x74, 0xca, 0x42, 0x98, 0xca, 0x23, 0x40, 0x71, - 0xe9, 0x8b, 0x10, 0xb8, 0x93, 0xc1, 0xe8, 0x9f, 0x1d, 0x03, 0x8b, 0xfd, 0x2f, 0x0b, 0x76, 0xcd, - 0x32, 0xd4, 0x22, 0x1e, 0x1b, 0x29, 0xb4, 0x22, 0x5e, 0x01, 0x52, 0xc1, 0xba, 0x94, 0xcf, 0x3b, - 0xb0, 0x3d, 0x8c, 0xd3, 0x39, 0x89, 0x4e, 0x70, 0x7c, 0xee, 0x8f, 0x65, 0x0f, 0x6a, 0x4f, 0xa1, - 0xa7, 0xed, 0x0f, 0x63, 0xec, 0x92, 0xac, 0x43, 0xed, 0xf1, 0x40, 0x78, 0x99, 0xb7, 0x00, 0xd9, - 0xba, 0xdc, 0xa9, 0xea, 0xd5, 0xb4, 0x5e, 0xa8, 0xa6, 0xf6, 0xfb, 0xd0, 0x60, 0xb7, 0x5c, 0x7c, - 0xd9, 0x52, 0x69, 0xff, 0xd3, 0x02, 0x38, 0x8e, 0xfd, 0x73, 0xfe, 0x48, 0x7a, 0x9b, 0x0a, 0x3b, - 0x8f, 0xfd, 0xf3, 0x53, 0xf1, 0x50, 0x6a, 0x3b, 0x72, 0x89, 0xf6, 0xa1, 0x3d, 0xe6, 0xc6, 0x32, - 0x45, 0x98, 0x8e, 0xf2, 0x7a, 0xe1, 0x5b, 0x8e, 0x46, 0x80, 0x6c, 0x68, 0x27, 0xfe, 0x64, 0x90, - 0x19, 0xc5, 0xaf, 0x33, 0x6d, 0xcf, 0x9e, 0x15, 0x3c, 0x38, 0xf0, 0x3c, 0xe5, 0x49, 0xf7, 0x76, - 0x1e, 0xbc, 0xc7, 0xeb, 0x6c, 0x5d, 0xb9, 0xb6, 0x72, 0x07, 0xb0, 0xc2, 0x6b, 0xff, 0xc3, 0x02, - 0xa4, 0xec, 0xc9, 0x40, 0xbb, 0xd4, 0xa3, 0x13, 0xbd, 0x93, 0xbb, 0xa6, 0x42, 0x46, 0xe6, 0x2b, - 0x25, 0xc8, 0x56, 0x2a, 0x83, 0x6c, 0x55, 0x0f, 0xb2, 0x8f, 0xa0, 0xcd, 0x5e, 0x8b, 0xca, 0x0b, - 0xcd, 0xd0, 0xe1, 0x95, 0x9f, 0x38, 0xdf, 0x00, 0xe2, 0xaf, 0x4c, 0x2d, 0x77, 0xaa, 0x6e, 0xd6, - 0x65, 0xc2, 0xff, 0x6f, 0x16, 0xd8, 0xda, 0x29, 0xe5, 0x26, 0xd3, 0xa3, 0x96, 0x0a, 0x5f, 0x36, - 0xc4, 0x3a, 0xd0, 0xf0, 0xfc, 0x09, 0x4e, 0x88, 0x88, 0x30, 0xb1, 0x52, 0x43, 0xaf, 0xae, 0x87, - 0x5e, 0xf9, 0x01, 0x8e, 0x61, 0x2b, 0xbf, 0xd8, 0xa4, 0xcd, 0x5a, 0x97, 0x6b, 0x19, 0xba, 0xdc, - 0xb7, 0xb6, 0xfc, 0x3b, 0x0b, 0x6e, 0x53, 0x39, 0x7e, 0x38, 0xe1, 0x3e, 0xfe, 0x32, 0x62, 0xaf, - 0xf1, 0x4c, 0xe4, 0x33, 0xcd, 0xcd, 0xad, 0x83, 0xf7, 0xb2, 0x74, 0xa8, 0x62, 0xe9, 0xf3, 0x5d, - 0xf1, 0x58, 0x5c, 0xfe, 0x54, 0xe8, 0x03, 0x53, 0x81, 0xba, 0xe8, 0x81, 0xd9, 0x54, 0xbb, 0xca, - 0x9f, 0xc2, 0xc6, 0x2b, 0x1c, 0x27, 0xca, 0x40, 0xb1, 0x0b, 0x6b, 0xe7, 0x7c, 0x87, 0x21, 0xac, - 0x3a, 0x72, 0x59, 0x0e, 0xb8, 0x83, 0xff, 0x6c, 0x42, 0xe3, 0x65, 0x44, 0xdc, 0x38, 0x45, 0x3f, - 0x04, 0x38, 0x0c, 0x7d, 0xe2, 0xbb, 0x81, 0xff, 0x5b, 0x8c, 0x36, 0x99, 0xf1, 0xca, 0x5c, 0xa4, - 0x87, 0xd8, 0x8e, 0xd6, 0x5d, 0xd9, 0x57, 0xd0, 0xfb, 0xb0, 0xc6, 0xa2, 0x22, 0x99, 0x22, 0x9e, - 0x42, 0xf9, 0x10, 0xb4, 0x82, 0xa3, 0x0f, 0xcd, 0x81, 0xe7, 0x89, 0x87, 0xbc, 0xda, 0xc9, 0x56, - 0xd0, 0x7f, 0x00, 0x6d, 0x3e, 0xb5, 0xba, 0x3c, 0xcb, 0x4b, 0x68, 0xd1, 0x04, 0xe2, 0x34, 0x09, - 0xea, 0x96, 0x1e, 0x66, 0x52, 0xc3, 0xfb, 0x8b, 0x9e, 0x8e, 0x39, 0xde, 0x21, 0x5c, 0x1b, 0x61, - 0xa2, 0xbe, 0x0a, 0x91, 0x3a, 0x33, 0x50, 0x1f, 0x8a, 0x3d, 0xd3, 0x6b, 0x54, 0x81, 0xfa, 0x0a, - 0x7a, 0x23, 0x4c, 0x06, 0x41, 0xc0, 0x29, 0x5e, 0x60, 0xe2, 0x7a, 0x2e, 0x71, 0x05, 0x6a, 0x47, - 0x61, 0x56, 0x06, 0x24, 0xbd, 0x3b, 0xe6, 0x9e, 0x39, 0x87, 0xfd, 0x14, 0xd6, 0x47, 0x98, 0x0c, - 0xf3, 0x6e, 0xae, 0x74, 0x18, 0x3b, 0xc5, 0xde, 0x2f, 0x67, 0x1e, 0x42, 0x93, 0xed, 0xb0, 0xb7, - 0x6a, 0x89, 0xf1, 0xfe, 0xa2, 0xca, 0x9c, 0x83, 0xfc, 0x0c, 0xd0, 0x08, 0x13, 0xfd, 0xf9, 0x62, - 0x40, 0xbb, 0xa1, 0xf7, 0x4f, 0x39, 0xff, 0x63, 0x58, 0xd7, 0x26, 0xc2, 0xe8, 0x26, 0xa3, 0x34, - 0x8d, 0xcc, 0x2b, 0x4e, 0xfd, 0x15, 0x74, 0xab, 0x86, 0xda, 0xe8, 0x41, 0x19, 0xac, 0x3c, 0xf3, - 0xae, 0xc0, 0xfd, 0x02, 0x50, 0x79, 0x56, 0x8d, 0x76, 0xcb, 0x88, 0xea, 0xa0, 0xb6, 0x02, 0xeb, - 0x57, 0xe5, 0xf1, 0xae, 0x3a, 0x9e, 0x46, 0x8f, 0xb8, 0x7b, 0x2e, 0x9e, 0x60, 0x57, 0x46, 0xfe, - 0xb6, 0x69, 0x06, 0x8d, 0xf6, 0x8c, 0xb8, 0xca, 0x78, 0xba, 0x02, 0xef, 0x18, 0x6e, 0x18, 0xc7, - 0xd1, 0xe8, 0x9e, 0x11, 0x70, 0x39, 0x0d, 0xd9, 0x09, 0xed, 0x55, 0x5a, 0xbe, 0x18, 0xef, 0x09, - 0x6c, 0x0f, 0x03, 0xec, 0xc6, 0x45, 0x05, 0xb7, 0xb5, 0xa4, 0x5f, 0x8c, 0xf1, 0x18, 0xd6, 0x5e, - 0xfb, 0x24, 0x64, 0x77, 0x74, 0xe5, 0x5d, 0x71, 0xb3, 0x3c, 0xde, 0xc9, 0x11, 0x3e, 0x86, 0x66, - 0x36, 0xc4, 0x46, 0x32, 0xc6, 0xf5, 0xa1, 0x76, 0x85, 0xec, 0xcf, 0x60, 0x5d, 0xab, 0xc7, 0xe5, - 0x94, 0xe1, 0x82, 0x8d, 0x4d, 0x2b, 0x3d, 0xa0, 0xeb, 0x86, 0xb6, 0x15, 0xdd, 0x2d, 0xf3, 0x68, - 0x0d, 0x6d, 0xaf, 0x53, 0x28, 0xe8, 0xb9, 0x42, 0xdf, 0xc0, 0xad, 0x05, 0x0d, 0x02, 0x7a, 0x58, - 0x46, 0x36, 0xb6, 0x10, 0x42, 0x42, 0xa9, 0xb2, 0xdb, 0x57, 0xd0, 0xf3, 0x82, 0xce, 0xbc, 0x51, - 0x34, 0xe9, 0xac, 0xb5, 0x90, 0x95, 0x01, 0xa0, 0xa3, 0x8d, 0x30, 0xa1, 0x68, 0x7c, 0x72, 0xa1, - 0x76, 0x61, 0x0b, 0x6c, 0xfe, 0xa2, 0xd0, 0xba, 0x8e, 0x30, 0x51, 0xfa, 0x6d, 0x03, 0xd4, 0x4e, - 0xb1, 0x5d, 0xcc, 0xb1, 0x06, 0xd0, 0xd1, 0xb0, 0x78, 0x48, 0x57, 0xe0, 0x98, 0x4d, 0xfa, 0x1c, - 0x6e, 0x68, 0x10, 0x34, 0xd8, 0xf8, 0xff, 0x7b, 0xc6, 0xa0, 0xde, 0xc9, 0x71, 0x8b, 0xb7, 0xf2, - 0x31, 0x74, 0x4b, 0x48, 0x83, 0x20, 0x60, 0x60, 0xa5, 0x40, 0xbb, 0x77, 0x61, 0xc3, 0xc3, 0xdc, - 0xbd, 0x75, 0x82, 0xc9, 0x73, 0x3c, 0x71, 0xc7, 0xa9, 0x68, 0x3c, 0x12, 0xc4, 0x67, 0x57, 0x7a, - 0x1f, 0xd2, 0xeb, 0xf4, 0xf9, 0xff, 0xa5, 0x7d, 0xf9, 0x7f, 0x69, 0x9f, 0xfd, 0x5f, 0x6a, 0x5f, - 0x79, 0xd3, 0x60, 0x3b, 0x1f, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0x1d, 0xd1, 0xf4, 0x21, 0x61, - 0x1d, 0x00, 0x00, + // 1787 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x59, 0xdd, 0x6e, 0xdb, 0x46, + 0x16, 0x0e, 0x25, 0xf9, 0x47, 0x47, 0xb2, 0x63, 0x4f, 0x6c, 0x47, 0x51, 0x1c, 0xc7, 0xa1, 0xb3, + 0x1b, 0x67, 0x83, 0xd8, 0x1b, 0x67, 0x37, 0x9b, 0xec, 0x62, 0x77, 0xa3, 0x38, 0x81, 0xe2, 0x75, + 0x62, 0x78, 0x99, 0x3f, 0x60, 0xb3, 0x28, 0xca, 0x88, 0x53, 0x89, 0x30, 0x45, 0x2a, 0xe4, 0xd8, + 0x28, 0x7b, 0xd1, 0xa2, 0xbd, 0x6b, 0x51, 0xa0, 0xe8, 0x65, 0x1f, 0xa1, 0xb7, 0x7d, 0x84, 0x3e, + 0x43, 0x1e, 0xa8, 0x98, 0x1f, 0x92, 0x33, 0xe4, 0x50, 0x76, 0x85, 0xf6, 0x4e, 0x33, 0x3c, 0xf3, + 0x9d, 0xff, 0x39, 0xe7, 0x8c, 0xa0, 0x6e, 0x8f, 0xdc, 0xad, 0x51, 0x18, 0x90, 0x00, 0x55, 0xed, + 0x91, 0xdb, 0xbe, 0xdc, 0x0f, 0x82, 0xbe, 0x87, 0xb7, 0xd9, 0xd6, 0xbb, 0xe3, 0x4f, 0xb6, 0x9f, + 0x0c, 0x47, 0x24, 0xe6, 0x14, 0xe6, 0x1a, 0x40, 0xf7, 0xd8, 0x7f, 0x8e, 0xa3, 0xc8, 0xee, 0x63, + 0xb4, 0x00, 0xd5, 0xfe, 0xb1, 0xdf, 0x32, 0xd6, 0x8d, 0xcd, 0xba, 0x45, 0x7f, 0x9a, 0xdf, 0x18, + 0xb0, 0xd4, 0x71, 0x9c, 0xc7, 0xd8, 0xc3, 0x7d, 0x9b, 0xb8, 0x41, 0x4a, 0x8a, 0xa0, 0xe6, 0xdb, + 0x43, 0x2c, 0x68, 0xd9, 0x6f, 0x74, 0x0f, 0xe6, 0x9d, 0x94, 0x70, 0x1f, 0xc7, 0x51, 0xab, 0xb2, + 0x5e, 0xdd, 0x6c, 0xec, 0xcc, 0x6f, 0x51, 0x91, 0x0e, 0x8f, 0xdf, 0x79, 0x6e, 0x6f, 0x1f, 0xc7, + 0x56, 0x8e, 0x0a, 0x2d, 0xc1, 0xd4, 0xc8, 0x26, 0x83, 0xa8, 0x55, 0x5d, 0xaf, 0x6e, 0xd6, 0x2d, + 0xbe, 0x48, 0x84, 0xa9, 0x65, 0xc2, 0x7c, 0x01, 0x57, 0x15, 0x59, 0xac, 0xc0, 0xc3, 0x1d, 0xdf, + 0xa1, 0x18, 0xbf, 0x87, 0x58, 0x42, 0x80, 0x6a, 0x26, 0xc0, 0x1b, 0xb8, 0xa4, 0x08, 0x70, 0x48, + 0x05, 0x1d, 0xc7, 0x3a, 0xd5, 0xac, 0xa2, 0xd1, 0x4c, 0x02, 0x8e, 0x61, 0xc3, 0xc2, 0xc3, 0xe0, + 0x04, 0x3f, 0x56, 0x44, 0xe8, 0xf8, 0xce, 0xa9, 0x2c, 0x56, 0x60, 0xfa, 0x08, 0xc7, 0x7b, 0x8f, + 0x13, 0x1e, 0x62, 0x75, 0x66, 0xa3, 0xee, 0xc2, 0xe5, 0x3c, 0x6b, 0x6a, 0xd7, 0x71, 0x2c, 0x05, + 0x48, 0x25, 0x03, 0xf9, 0x1f, 0xac, 0xe6, 0x41, 0x7e, 0x33, 0xdb, 0xbc, 0x2d, 0x0a, 0x78, 0x9a, + 0xc7, 0xcb, 0x6c, 0x52, 0x04, 0xff, 0x1b, 0x9c, 0xa7, 0xda, 0x1e, 0xd8, 0x43, 0x59, 0xe3, 0x30, + 0xf0, 0x52, 0x40, 0xfa, 0x5b, 0xa3, 0xf1, 0xe7, 0xb0, 0x60, 0x05, 0xc4, 0x26, 0x78, 0x1f, 0xc7, + 0xe3, 0x4e, 0xfe, 0x09, 0x16, 0x22, 0x1c, 0x9e, 0xe0, 0xf0, 0xb9, 0xed, 0xdb, 0x7d, 0x1c, 0xed, + 0xe3, 0x98, 0xc1, 0xcc, 0x5a, 0x85, 0x7d, 0xd4, 0x82, 0x99, 0x23, 0x1c, 0x3f, 0x73, 0x23, 0x22, + 0x9c, 0x96, 0x2c, 0x35, 0x6e, 0xfb, 0xca, 0x80, 0xc6, 0x9e, 0xef, 0x92, 0x84, 0xf7, 0x1a, 0x40, + 0x18, 0x04, 0x64, 0x9f, 0xab, 0x6d, 0xb0, 0xe3, 0xd2, 0x0e, 0xea, 0x00, 0x92, 0xf9, 0x39, 0x54, + 0xeb, 0x88, 0x49, 0xd2, 0xd8, 0x59, 0x64, 0x89, 0x90, 0xd8, 0x81, 0x32, 0xb4, 0x34, 0xc4, 0x1a, + 0xeb, 0x5d, 0x87, 0xa6, 0x7c, 0x8a, 0xba, 0x34, 0x64, 0xb8, 0x9c, 0x3f, 0x5f, 0x98, 0xff, 0x84, + 0x0b, 0x32, 0x55, 0x22, 0xb1, 0x96, 0x58, 0x63, 0xe9, 0x2f, 0x0d, 0x58, 0x52, 0x64, 0xc3, 0xd1, + 0x28, 0xf0, 0x23, 0x8c, 0xfe, 0x0a, 0xcd, 0x50, 0xda, 0x67, 0x66, 0xd7, 0x2a, 0xa3, 0x90, 0x51, + 0x2b, 0x47, 0xc7, 0xbd, 0x1e, 0x8e, 0x22, 0xe1, 0x88, 0x64, 0x49, 0xbf, 0x0c, 0xb9, 0x70, 0x42, + 0xc9, 0x64, 0x69, 0x3e, 0x80, 0xc5, 0x97, 0x76, 0xd8, 0xc7, 0x24, 0x17, 0x28, 0x67, 0x48, 0x8d, + 0x9f, 0x0c, 0x98, 0xe6, 0x67, 0x8b, 0xd7, 0x6b, 0x0a, 0x51, 0x51, 0x83, 0xd7, 0xc3, 0x7e, 0x9f, + 0x0c, 0x98, 0x10, 0x55, 0x4b, 0xac, 0xd0, 0x36, 0x4c, 0x0f, 0xec, 0x68, 0x80, 0xa3, 0x56, 0x8d, + 0x5d, 0x5f, 0x17, 0x99, 0xa2, 0x1c, 0x7a, 0xeb, 0x29, 0xfb, 0xf2, 0xc4, 0x27, 0x61, 0x6c, 0x09, + 0xb2, 0xf6, 0x03, 0x68, 0x48, 0xdb, 0x94, 0xfb, 0x11, 0x8e, 0x13, 0xee, 0x47, 0x38, 0xa6, 0x1e, + 0x38, 0xb1, 0xbd, 0x63, 0xce, 0xbe, 0x69, 0xf1, 0xc5, 0xdf, 0x2b, 0xf7, 0x0d, 0x73, 0x0f, 0xe6, + 0x39, 0xf0, 0x1b, 0x97, 0x0c, 0xa8, 0x2d, 0xd1, 0x06, 0x4c, 0x13, 0xb6, 0x23, 0xcc, 0xdc, 0x90, + 0xb8, 0x5b, 0xe2, 0x53, 0x9a, 0x00, 0x95, 0x2c, 0x01, 0xcc, 0xaf, 0x0d, 0x58, 0x51, 0xb1, 0x52, + 0x07, 0xfe, 0x03, 0xe6, 0x89, 0xf2, 0x45, 0x60, 0x5f, 0x90, 0xb0, 0xd3, 0x43, 0x39, 0xd2, 0x89, + 0xdc, 0xd8, 0xcd, 0x8b, 0x92, 0x06, 0xc5, 0x6d, 0x98, 0xe1, 0xf8, 0x3c, 0x1c, 0x4b, 0x64, 0x48, + 0x68, 0xcc, 0xef, 0x0c, 0x58, 0xd3, 0x23, 0xa5, 0xca, 0xbd, 0x80, 0x15, 0xa2, 0xa5, 0x10, 0x4a, + 0x5e, 0xd6, 0x30, 0x48, 0x41, 0x4a, 0x8e, 0x96, 0x2b, 0x6d, 0xf6, 0x00, 0x71, 0xac, 0x47, 0x31, + 0xa5, 0xee, 0xf4, 0xe8, 0x3d, 0xa9, 0x0d, 0xd1, 0x1b, 0x49, 0xde, 0x95, 0x26, 0xbf, 0x9a, 0x8a, + 0x52, 0xbe, 0xbf, 0x87, 0xfa, 0x0b, 0xb7, 0xef, 0xdb, 0xe4, 0x38, 0x64, 0xf9, 0xcb, 0xae, 0x55, + 0x01, 0xce, 0x17, 0x34, 0x7a, 0x87, 0x98, 0x0c, 0x02, 0x47, 0x04, 0x81, 0x58, 0xa1, 0x55, 0xa8, + 0x47, 0xc9, 0x51, 0x06, 0xd9, 0xb4, 0xb2, 0x0d, 0xaa, 0x97, 0x1b, 0xbd, 0xb6, 0x3d, 0xd7, 0x61, + 0x77, 0xdc, 0xac, 0x95, 0x2c, 0xcd, 0xff, 0x42, 0x3d, 0xad, 0xd0, 0x68, 0x1e, 0x2a, 0xae, 0x23, + 0xf8, 0x55, 0x5c, 0x06, 0x6a, 0x7b, 0xfd, 0x20, 0x74, 0xc9, 0x60, 0x28, 0xf8, 0x65, 0x1b, 0x54, + 0x94, 0x11, 0x3b, 0x2a, 0xf8, 0x89, 0x95, 0xf9, 0x0a, 0x16, 0xb3, 0xa2, 0x9f, 0xb8, 0xeb, 0x8f, + 0x8c, 0x38, 0x49, 0x90, 0x62, 0x73, 0x20, 0xbe, 0x8e, 0xf1, 0xc0, 0x07, 0x03, 0xe6, 0xd5, 0x1a, + 0x8a, 0xee, 0x40, 0xed, 0x88, 0xf6, 0x1b, 0x3c, 0xa4, 0xae, 0x30, 0x48, 0x95, 0x64, 0x8b, 0x96, + 0x32, 0x9e, 0xb6, 0x8c, 0x54, 0x7b, 0x23, 0xac, 0x42, 0x9d, 0x0c, 0x42, 0x1c, 0x0d, 0x02, 0xcf, + 0x61, 0xba, 0x4c, 0x59, 0xd9, 0x46, 0x56, 0x47, 0x6b, 0x52, 0x1d, 0x6d, 0x77, 0xa1, 0x9e, 0x42, + 0x6b, 0x52, 0xff, 0xba, 0x9c, 0xfa, 0x45, 0x6d, 0xa5, 0xab, 0xe0, 0x5b, 0x03, 0x9a, 0x3c, 0xb2, + 0xa8, 0xeb, 0xb1, 0x83, 0x6e, 0x48, 0x55, 0x2e, 0xc9, 0x13, 0x55, 0x29, 0x51, 0xfa, 0xb2, 0x2b, + 0xa3, 0x52, 0x7e, 0x65, 0x6c, 0x01, 0xa4, 0x61, 0xc0, 0x7b, 0x95, 0x44, 0x9a, 0x34, 0xd2, 0x2c, + 0x89, 0xc2, 0xfc, 0x37, 0x2c, 0xc8, 0xd2, 0xb0, 0xac, 0xb8, 0x95, 0x4f, 0xde, 0x45, 0x89, 0x13, + 0xa7, 0xcb, 0x52, 0xf7, 0x7b, 0x03, 0x5a, 0x79, 0x84, 0x34, 0x0a, 0x3a, 0xb0, 0x40, 0x72, 0xdf, + 0x84, 0x9e, 0xcb, 0x05, 0x48, 0x76, 0xb0, 0x40, 0x3e, 0xd1, 0xbd, 0xb4, 0x0b, 0x73, 0x8f, 0xec, + 0xc8, 0xed, 0xa5, 0x72, 0x48, 0x20, 0x46, 0x29, 0x48, 0x45, 0x05, 0xf9, 0x14, 0xa6, 0x77, 0x07, + 0xb6, 0xdf, 0x67, 0x15, 0xc4, 0x66, 0xf9, 0x2f, 0x3c, 0x2e, 0x56, 0x34, 0x52, 0xa2, 0x5e, 0x30, + 0x4a, 0x4e, 0xf2, 0x05, 0x8d, 0x38, 0x12, 0x8f, 0x12, 0x99, 0xd8, 0x6f, 0xba, 0x47, 0xc3, 0x48, + 0x34, 0x1c, 0xec, 0x37, 0xe5, 0xdc, 0x0b, 0x7c, 0x82, 0x7d, 0xd2, 0x9a, 0x62, 0xf9, 0x94, 0x2c, + 0xcd, 0xbb, 0x00, 0x9c, 0x33, 0x33, 0xc0, 0x1f, 0x60, 0xa6, 0xc7, 0x56, 0x89, 0x37, 0xb8, 0xdf, + 0x39, 0x85, 0x95, 0x7c, 0x33, 0x63, 0x40, 0xd9, 0xa1, 0x54, 0xf1, 0x6d, 0x00, 0x4e, 0xe0, 0x65, + 0xa6, 0x3f, 0x2f, 0x9d, 0x67, 0xc4, 0x12, 0xc9, 0x44, 0xe6, 0x7e, 0x08, 0xb3, 0x56, 0x10, 0x10, + 0x96, 0xa2, 0x59, 0xab, 0x68, 0x28, 0xad, 0xa2, 0x92, 0x73, 0x95, 0x5c, 0xce, 0x99, 0x6f, 0xa1, + 0xc6, 0x4e, 0xdf, 0x84, 0xd9, 0x50, 0x20, 0x09, 0x61, 0xe7, 0xc4, 0x75, 0xca, 0x37, 0xad, 0xf4, + 0xb3, 0x36, 0xb1, 0xb5, 0x3d, 0xba, 0x79, 0x8b, 0x8a, 0xe7, 0x71, 0x63, 0x5e, 0x95, 0x9b, 0xa4, + 0xc6, 0x4e, 0x3d, 0xbd, 0xac, 0x93, 0xe6, 0xea, 0x3d, 0xed, 0x43, 0x3d, 0xd5, 0x88, 0x4c, 0x2a, + 0x4f, 0x2e, 0x36, 0x73, 0xe9, 0x39, 0x46, 0x98, 0x7e, 0x9e, 0xc8, 0x7c, 0x3d, 0x40, 0x14, 0x89, + 0x16, 0xa7, 0x34, 0x47, 0xa3, 0x5c, 0x22, 0x1b, 0xa7, 0x25, 0x32, 0xba, 0x22, 0xf5, 0x0a, 0x8a, + 0x62, 0xbc, 0x6d, 0xb0, 0x61, 0xa5, 0xc8, 0x84, 0x89, 0xdc, 0x05, 0x14, 0x16, 0xbe, 0x08, 0x86, + 0x17, 0x53, 0x18, 0xf5, 0xb3, 0xa5, 0x39, 0x62, 0xfe, 0x68, 0xc0, 0x9a, 0x9e, 0x87, 0x5c, 0xc4, + 0x43, 0x2d, 0x85, 0x52, 0xc4, 0x4b, 0x40, 0x4a, 0x8e, 0x4e, 0x64, 0xf3, 0x01, 0xb4, 0x77, 0xc3, + 0x78, 0x44, 0x82, 0x17, 0x38, 0x3c, 0x71, 0x7b, 0x78, 0x37, 0xc4, 0x36, 0x49, 0x3b, 0xd1, 0x36, + 0x77, 0xf8, 0x41, 0x56, 0xea, 0xd3, 0x75, 0xb1, 0x23, 0x55, 0xab, 0x66, 0x35, 0x57, 0x35, 0xcd, + 0xff, 0x03, 0x1c, 0x86, 0xee, 0x09, 0x9f, 0x6c, 0x44, 0x0d, 0xdd, 0x17, 0xc5, 0x83, 0xd7, 0x50, + 0x31, 0xaa, 0x8c, 0x42, 0xf7, 0x24, 0x99, 0x66, 0x9a, 0x56, 0xb2, 0x54, 0xd1, 0x6b, 0x79, 0xf4, + 0x61, 0x4e, 0x8f, 0x8e, 0xe3, 0x48, 0x03, 0xd4, 0xaf, 0xd3, 0xe3, 0x1a, 0xaf, 0x6a, 0x55, 0xe9, + 0x92, 0xc8, 0x24, 0x67, 0x65, 0xce, 0xfc, 0xc1, 0x00, 0x24, 0xed, 0x25, 0x6e, 0x3d, 0xd3, 0x88, + 0x87, 0x6e, 0x72, 0x1d, 0xc7, 0xf0, 0x48, 0xbe, 0xcb, 0x2e, 0xad, 0x95, 0xba, 0x74, 0x4a, 0x75, + 0xe9, 0x3d, 0x68, 0xb2, 0xd9, 0x4c, 0x9a, 0x87, 0x34, 0xfd, 0x54, 0x71, 0xa0, 0xf8, 0x18, 0x10, + 0x9f, 0xe9, 0x94, 0x48, 0x2d, 0xbb, 0xc7, 0x26, 0x09, 0xb6, 0x0f, 0x06, 0xac, 0xd2, 0x98, 0x75, + 0xfd, 0x3e, 0xe7, 0xf4, 0x32, 0x60, 0x13, 0x60, 0xca, 0xec, 0x89, 0xc2, 0xac, 0xb1, 0x73, 0x3b, + 0xcd, 0xf3, 0xb2, 0x23, 0x5b, 0x7c, 0x57, 0x0c, 0x28, 0x93, 0xcb, 0x46, 0x87, 0x1a, 0x09, 0xea, + 0xb4, 0xa1, 0xa6, 0x2e, 0x75, 0x32, 0x3b, 0x3f, 0xcf, 0xc1, 0xf4, 0x41, 0x40, 0xec, 0x30, 0x46, + 0x7f, 0x01, 0xa0, 0xc3, 0xb3, 0x6b, 0x7b, 0xee, 0x67, 0x18, 0x2d, 0x30, 0xf1, 0xa5, 0x69, 0xba, + 0x8d, 0xd8, 0x8e, 0x52, 0x93, 0xcd, 0x73, 0xe8, 0xcf, 0x30, 0xc3, 0x5a, 0xa4, 0x68, 0x80, 0x78, + 0x28, 0x64, 0x4f, 0x67, 0x25, 0x27, 0xb6, 0xa0, 0xde, 0x71, 0x1c, 0x31, 0xfe, 0xc9, 0xfd, 0x4f, + 0x09, 0xfd, 0x1d, 0x68, 0xf2, 0xb7, 0x8e, 0xb3, 0x1f, 0x39, 0x80, 0x06, 0x0d, 0x04, 0x4e, 0x13, + 0xa1, 0x56, 0xa1, 0x9d, 0x4f, 0x24, 0xdc, 0x18, 0x37, 0x70, 0x64, 0x78, 0x7b, 0x70, 0xbe, 0x8b, + 0x89, 0x3c, 0x4b, 0x20, 0x79, 0xd2, 0x94, 0xc7, 0x8b, 0xb6, 0x6e, 0x86, 0x91, 0xa0, 0x5e, 0x41, + 0xbb, 0x8b, 0x49, 0xc7, 0xf3, 0x38, 0xc5, 0x73, 0x4c, 0x6c, 0xc7, 0x26, 0xb6, 0x40, 0x5d, 0x91, + 0x0e, 0x4b, 0x63, 0x75, 0xfb, 0x8a, 0xbe, 0xd3, 0xca, 0x60, 0x77, 0xa1, 0xce, 0x76, 0xd8, 0x90, + 0x52, 0x70, 0xc4, 0xc6, 0xb8, 0x2b, 0x39, 0x03, 0xf9, 0x17, 0xa0, 0x2e, 0x26, 0x6a, 0xdf, 0xaa, + 0x41, 0x5b, 0x56, 0x0b, 0x67, 0x76, 0xfe, 0x21, 0xcc, 0x29, 0x4f, 0x81, 0xe8, 0x12, 0xa3, 0xd4, + 0xbd, 0x95, 0x96, 0x38, 0xee, 0x35, 0xb4, 0xca, 0x5e, 0x33, 0xd1, 0xf5, 0x22, 0x58, 0xf1, 0xb1, + 0xb3, 0x04, 0xf7, 0x3f, 0x80, 0x8a, 0x8f, 0x94, 0x68, 0xad, 0x88, 0x28, 0xbf, 0xd0, 0x95, 0x60, + 0x7d, 0x54, 0x7c, 0xd7, 0x93, 0xdf, 0x25, 0xd1, 0x26, 0x37, 0xcf, 0xe9, 0x4f, 0x97, 0xa5, 0xc1, + 0xbb, 0xa4, 0x7b, 0x7c, 0x44, 0xeb, 0x5a, 0x5c, 0xe9, 0x5d, 0xb2, 0x04, 0xef, 0x10, 0x96, 0xb5, + 0xef, 0x90, 0xe8, 0x9a, 0x16, 0x70, 0x32, 0x09, 0x99, 0x87, 0xd6, 0x4b, 0x35, 0x1f, 0x8f, 0xf7, + 0x08, 0x96, 0x76, 0x3d, 0x6c, 0x87, 0x79, 0x01, 0x97, 0x94, 0xbc, 0x1d, 0x8f, 0xf1, 0x10, 0x66, + 0xde, 0xb8, 0xc4, 0x67, 0x17, 0x65, 0x69, 0xba, 0x5f, 0x2a, 0xce, 0xf5, 0x19, 0xc2, 0x7d, 0xa8, + 0xa7, 0xaf, 0x97, 0x28, 0x89, 0x71, 0xf5, 0x35, 0xb3, 0xd4, 0xc2, 0x17, 0x34, 0x8d, 0x08, 0xba, + 0xca, 0x7b, 0xf4, 0xd2, 0x16, 0xa5, 0xbd, 0x92, 0x9b, 0x30, 0x33, 0xc4, 0x67, 0x39, 0x44, 0xde, + 0x12, 0xe8, 0x10, 0x95, 0x66, 0xa1, 0xd4, 0xbe, 0x2a, 0x5a, 0x17, 0x13, 0x8a, 0xc6, 0x27, 0x42, + 0xb9, 0xde, 0x8e, 0x91, 0xe8, 0x29, 0x2c, 0x2b, 0x18, 0xd4, 0x78, 0xfc, 0x8f, 0x0a, 0xad, 0x93, + 0x2e, 0x66, 0xd8, 0xf9, 0x5b, 0xe6, 0x10, 0x5a, 0x05, 0xa4, 0x8e, 0xe7, 0x31, 0xb0, 0xc2, 0x5d, + 0x73, 0xed, 0xd4, 0x2a, 0x6a, 0x9e, 0x7b, 0x37, 0xcd, 0xfe, 0xb7, 0xb9, 0xfb, 0x4b, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x02, 0x3f, 0x0e, 0x40, 0xe6, 0x19, 0x00, 0x00, } diff --git a/client_api/api/api.proto b/client_api/api/api.proto index 3c4cb5da8..cc7ef8e63 100644 --- a/client_api/api/api.proto +++ b/client_api/api/api.proto @@ -21,9 +21,6 @@ service Notary { // GetAllTargetMetadataByName rpc GetAllTargetMetadataByName(TargetNameMessage) returns (TargetSignedListResponse) {} - // GetChangelist returns the list of the repository's unpublished changes - rpc GetChangelist(GunMessage) returns (ChangeListResponse) {} - rpc ListRoles(GunMessage) returns (RoleWithSignaturesListResponse) {} rpc GetDelegationRoles(GunMessage) returns (RoleListResponse) {} rpc AddDelegation(AddDelegationMessage) returns (BasicResponse) {} @@ -40,17 +37,16 @@ service Notary { rpc RotateKey(RotateKeyMessage) returns (BasicResponse) {} // CryptoService implementation - rpc CryptoService(GunMessage) returns (CryptoServiceMessage) {} rpc CryptoServiceCreate(CryptoServiceCreateMessage) returns (PublicKeyResponse) {} - rpc CryptoServicePrivateKeySign(CryptoServicePrivateKeySignMessage) returns (SignatureResponse) {} +// rpc CryptoServicePrivateKeySign(CryptoServicePrivateKeySignMessage) returns (SignatureResponse) {} rpc CryptoServiceAddKey(CryptoServiceAddKeyMessage) returns (BasicResponse) {} rpc CryptoServiceGetKey(KeyIDMessage) returns (PublicKeyResponse) {} - rpc CryptoServiceGetPrivateKey(KeyIDMessage) returns (PrivateKeyResponse) {} - rpc CryptoServiceRemoveKey(KeyIDMessage) returns (BasicResponse) {} +// rpc CryptoServiceGetPrivateKey(KeyIDMessage) returns (PrivateKeyResponse) {} +// rpc CryptoServiceRemoveKey(KeyIDMessage) returns (BasicResponse) {} rpc CryptoServiceListKeys(RoleNameMessage) returns (KeyIDsListResponse) {} rpc CryptoServiceListAllKeys(GunMessage) returns (SigningKeyIDsToRolesResponse) {} - rpc SetLegacyVersions(VersionMessage) returns (google.protobuf.Empty) {} +// rpc SetLegacyVersions(VersionMessage) returns (google.protobuf.Empty) {} } message GunMessage { @@ -282,25 +278,16 @@ message RoleWithSignaturesListResponse { string message = 3; } -// FIXME: unimplemented -message CryptoServiceMessage { -} - message CryptoServiceCreateMessage { string roleName = 1; string gun = 2; string algorithm = 3; } -message Signer { - PublicKey pubkey = 1; -} - message PrivateKey { - PublicKey pubkey = 1; - bytes privkey = 2; - Signer cryptoSigner = 3; - string sigAlgorithm = 4; + bytes pubKey = 1; + bytes privKey = 2; + string algorithm = 4; } message CryptoServiceAddKeyMessage { @@ -328,18 +315,18 @@ message KeyIDsListResponse { string message = 3; } -message CryptoServicePrivateKeySignMessage { - PublicKey pubkey = 1; - bytes digest = 2; - bytes privkey = 3; - string gun = 4; -} +//message CryptoServicePrivateKeySignMessage { +// PublicKey pubkey = 1; +// bytes digest = 2; +// bytes privkey = 3; +// string gun = 4; +//} -message SignatureResponse { - bytes signature = 1; - bool success = 2; - string message = 3; -} +//message SignatureResponse { +// bytes signature = 1; +// bool success = 2; +// string message = 3; +//} message SigningKeyIDsToRolesResponse { map keyIDs = 1; @@ -347,8 +334,8 @@ message SigningKeyIDsToRolesResponse { string message = 3; } -message VersionMessage { - int32 version = 1; - string gun = 2; -} +//message VersionMessage { +// int32 version = 1; +// string gun = 2; +//} diff --git a/client_api/api/client.go b/client_api/api/client.go index 4b8349675..3b9932531 100644 --- a/client_api/api/client.go +++ b/client_api/api/client.go @@ -3,6 +3,7 @@ package api import ( "google.golang.org/grpc" + "errors" "github.com/docker/notary/client" "github.com/docker/notary/client/changelist" "github.com/docker/notary/tuf/data" @@ -198,21 +199,7 @@ func (c *Client) GetAllTargetMetadataByName(name string) ([]client.TargetSignedS } func (c *Client) GetChangelist() (changelist.Changelist, error) { - changes, err := c.client.GetChangelist(context.Background(), &GunMessage{Gun: c.gun.String()}) - if err != nil { - return nil, err - } - - currChangeList := changelist.NewMemChangelist() - for _, change := range changes.Changelist.Changes { - c := changelist.NewTUFChange(change.Action, data.RoleName(change.Scope), change.Type, change.Path, change.Content) - err := currChangeList.Add(c) - if err != nil { - return nil, err - } - } - - return currChangeList, err + return changelist.NewMemChangelist(), errors.New("the Client API does not maintain a changelist") } func (c *Client) ListRoles() ([]client.RoleWithSignatures, error) { @@ -429,7 +416,7 @@ func (c *Client) SetLegacyVersions(n int) { } func (c *Client) CryptoService() signed.CryptoService { - return c.cs + return &CryptoService{client: c.client} } func (c *Client) GetGUN() data.GUN { @@ -443,50 +430,97 @@ type CryptoService struct { // Create issues a new key pair and is responsible for loading // the private key into the appropriate signing service. func (cs *CryptoService) Create(role data.RoleName, gun data.GUN, algorithm string) (data.PublicKey, error) { - pub, err := cs.Create(role, gun, algorithm) + pub, err := cs.client.CryptoServiceCreate( + context.Background(), + &CryptoServiceCreateMessage{ + RoleName: role.String(), + Gun: gun.String(), + Algorithm: algorithm, + }, + ) if err != nil { return nil, err } - - return pub, nil + return data.NewPublicKey( + pub.Pubkey.Algorithm, + pub.Pubkey.Public, + ), nil } // AddKey adds a private key to the specified role and gun func (cs *CryptoService) AddKey(role data.RoleName, gun data.GUN, key data.PrivateKey) error { - err := cs.AddKey(role, gun, key) + _, err := cs.client.CryptoServiceAddKey( + context.Background(), + &CryptoServiceAddKeyMessage{ + Gun: gun.String(), + RoleName: role.String(), + Key: &PrivateKey{ + PrivKey: key.Private(), + PubKey: key.Public(), + Algorithm: key.Algorithm(), + }, + }, + ) + return err } // GetKey retrieves the public key if present, otherwise it returns nil func (cs *CryptoService) GetKey(keyID string) data.PublicKey { - pubkey := cs.GetKey(keyID) - return pubkey + pub, err := cs.client.CryptoServiceGetKey( + context.Background(), + &KeyIDMessage{ + KeyID: keyID, + }, + ) + if err != nil { + return nil + } + return data.NewPublicKey(pub.Pubkey.Algorithm, pub.Pubkey.Public) } // GetPrivateKey retrieves the private key and role if present and retrievable, // otherwise it returns nil and an error func (cs *CryptoService) GetPrivateKey(keyID string) (data.PrivateKey, data.RoleName, error) { - priv, role, err := cs.GetPrivateKey(keyID) - return priv, role, err + return nil, "", errors.New("it is not permitted to retrieve private keys from the Client API") } // RemoveKey deletes the specified key, and returns an error only if the key // removal fails. If the key doesn't exist, no error should be returned. func (cs *CryptoService) RemoveKey(keyID string) error { - err := cs.RemoveKey(keyID) - return err + return errors.New("it is not permitted to delete keys from the Client API") } // ListKeys returns a list of key IDs for the role, or an empty list or // nil if there are no keys. func (cs *CryptoService) ListKeys(role data.RoleName) []string { - keys := cs.ListKeys(role) - return keys + list, err := cs.client.CryptoServiceListKeys( + context.Background(), + &RoleNameMessage{ + Role: role.String(), + }, + ) + if err != nil { + return nil + } + return list.KeyIDs } // ListAllKeys returns a map of all available signing key IDs to role, or // an empty map or nil if there are no keys. func (cs *CryptoService) ListAllKeys() map[string]data.RoleName { - keyIDsToRoles := cs.ListAllKeys() - return keyIDsToRoles + list, err := cs.client.CryptoServiceListAllKeys( + context.Background(), + &GunMessage{ + Gun: "", + }, + ) + if err != nil { + return nil + } + res := make(map[string]data.RoleName) + for id, role := range list.KeyIDs { + res[id] = data.RoleName(role) + } + return res } diff --git a/client_api/api/server.go b/client_api/api/server.go index dc33678ed..ceaabb116 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -2,11 +2,9 @@ package api import ( "github.com/Sirupsen/logrus" - google_protobuf "github.com/golang/protobuf/ptypes/empty" "golang.org/x/net/context" "google.golang.org/grpc" - "crypto/rand" "errors" "github.com/docker/notary/client" "github.com/docker/notary/client/changelist" @@ -244,37 +242,6 @@ func (srv *Server) GetAllTargetMetadataByName(ctx context.Context, message *Targ }, nil } -// GetChangelist returns the list of the repository's unpublished changes -func (srv *Server) GetChangelist(ctx context.Context, message *GunMessage) (*ChangeListResponse, error) { - r, err := srv.initRepo(ctx, data.GUN(message.Gun)) - if err != nil { - return nil, err - } - - cl, err := r.GetChangelist() - if err != nil { - return nil, err - } - - resChangelist := make([]*Change, len(cl.List())) - for index, change := range cl.List() { - resChangelist[index] = &Change{ - Action: change.Action(), - Scope: change.Scope().String(), - Type: change.Type(), - Path: change.Path(), - Content: change.Content(), - } - } - - return &ChangeListResponse{ - Changelist: &ChangeList{ - Changes: resChangelist, - }, - Success: true, - }, nil -} - func (srv *Server) ListRoles(ctx context.Context, message *GunMessage) (*RoleWithSignaturesListResponse, error) { r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { @@ -364,7 +331,9 @@ func (srv *Server) AddDelegation(ctx context.Context, message *AddDelegationMess if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } return &BasicResponse{ Success: true, }, nil @@ -385,7 +354,9 @@ func (srv *Server) AddDelegationRoleAndKeys(ctx context.Context, message *AddDel if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } return &BasicResponse{ Success: true, }, nil @@ -401,7 +372,9 @@ func (srv *Server) AddDelegationPaths(ctx context.Context, message *AddDelegatio if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } return &BasicResponse{ Success: true, }, nil @@ -417,7 +390,9 @@ func (srv *Server) RemoveDelegationKeysAndPaths(ctx context.Context, message *Re if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } return &BasicResponse{ Success: true, }, nil @@ -433,7 +408,9 @@ func (srv *Server) RemoveDelegationRole(ctx context.Context, message *RemoveDele if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } return &BasicResponse{ Success: true, }, nil @@ -449,7 +426,9 @@ func (srv *Server) RemoveDelegationPaths(ctx context.Context, message *RemoveDel if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } return &BasicResponse{ Success: true, }, nil @@ -465,7 +444,9 @@ func (srv *Server) RemoveDelegationKeys(ctx context.Context, message *RemoveDele if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } return &BasicResponse{ Success: true, }, nil @@ -481,7 +462,9 @@ func (srv *Server) ClearDelegationPaths(ctx context.Context, message *RoleNameMe if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } return &BasicResponse{ Success: true, }, nil @@ -502,7 +485,9 @@ func (srv *Server) Witness(ctx context.Context, message *RoleNameListMessage) (* if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } resRoles := make([]string, len(currRoles)) for index, role := range currRoles { resRoles[index] = role.String() @@ -526,17 +511,14 @@ func (srv *Server) RotateKey(ctx context.Context, message *RotateKeyMessage) (*B if err != nil { return nil, err } - + if err := publishRepo(r); err != nil { + return nil, err + } return &BasicResponse{ Success: true, }, nil } -// CryptoService implementation -func (srv *Server) CryptoService(ctx context.Context, message *GunMessage) (*CryptoServiceMessage, error) { - return nil, ErrNotImplemented -} - func (srv *Server) CryptoServiceCreate(ctx context.Context, message *CryptoServiceCreateMessage) (*PublicKeyResponse, error) { r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { @@ -560,24 +542,6 @@ func (srv *Server) CryptoServiceCreate(ctx context.Context, message *CryptoServi }, nil } -func (srv *Server) CryptoServicePrivateKeySign(ctx context.Context, message *CryptoServicePrivateKeySignMessage) (*SignatureResponse, error) { - pubkey := data.NewPublicKey(message.Pubkey.Algorithm, message.Pubkey.Public) - privkey, err := data.NewPrivateKey(pubkey, message.Privkey) - if err != nil { - return nil, err - } - - sig, err := privkey.Sign(rand.Reader, message.Digest, nil) - if err != nil { - return nil, err - } - - return &SignatureResponse{ - Signature: sig, - Success: true, - }, nil -} - func (srv *Server) CryptoServiceAddKey(ctx context.Context, message *CryptoServiceAddKeyMessage) (*BasicResponse, error) { r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { @@ -586,9 +550,9 @@ func (srv *Server) CryptoServiceAddKey(ctx context.Context, message *CryptoServi cs := r.CryptoService() - pubKey := data.NewPublicKey(message.Key.Pubkey.Algorithm, message.Key.Pubkey.Public) + pubKey := data.NewPublicKey(message.Key.Algorithm, message.Key.PubKey) - privKey, err := data.NewPrivateKey(pubKey, message.Key.Privkey) + privKey, err := data.NewPrivateKey(pubKey, message.Key.PrivKey) if err != nil { return nil, err } @@ -623,62 +587,6 @@ func (srv *Server) CryptoServiceGetKey(ctx context.Context, message *KeyIDMessag }, nil } -func (srv *Server) CryptoServiceGetPrivateKey(ctx context.Context, message *KeyIDMessage) (*PrivateKeyResponse, error) { - r, err := srv.initRepo(ctx, data.GUN(message.Gun)) - if err != nil { - return nil, err - } - - cs := r.CryptoService() - - privkey, rolename, err := cs.GetPrivateKey(message.KeyID) - if err != nil { - return nil, err - } - - resPrivkey := &PrivateKey{ - Pubkey: &PublicKey{ - Id: privkey.ID(), - Algorithm: privkey.Algorithm(), - Public: privkey.Public(), - }, - Privkey: privkey.Private(), - CryptoSigner: &Signer{ - Pubkey: &PublicKey{ - Id: privkey.ID(), - Algorithm: privkey.Algorithm(), - Public: privkey.Public(), - }, - }, - SigAlgorithm: privkey.SignatureAlgorithm().String(), - } - - return &PrivateKeyResponse{ - Role: rolename.String(), - Gun: message.Gun, - Privkey: resPrivkey, - Success: true, - }, nil -} - -func (srv *Server) CryptoServiceRemoveKey(ctx context.Context, message *KeyIDMessage) (*BasicResponse, error) { - r, err := srv.initRepo(ctx, data.GUN(message.Gun)) - if err != nil { - return nil, err - } - - cs := r.CryptoService() - - err = cs.RemoveKey(message.KeyID) - if err != nil { - return nil, err - } - - return &BasicResponse{ - Success: true, - }, nil -} - func (srv *Server) CryptoServiceListKeys(ctx context.Context, message *RoleNameMessage) (*KeyIDsListResponse, error) { r, err := srv.initRepo(ctx, data.GUN(message.Gun)) if err != nil { @@ -716,10 +624,6 @@ func (srv *Server) CryptoServiceListAllKeys(ctx context.Context, message *GunMes }, nil } -func (srv *Server) SetLegacyVersions(ctx context.Context, message *VersionMessage) (*google_protobuf.Empty, error) { - return nil, ErrNotImplemented -} - func publishRepo(r *client.NotaryRepository) error { if err := r.Publish(); err != nil { if _, ok := err.(client.ErrRepoNotInitialized); !ok { @@ -790,7 +694,27 @@ func (srv *Server) initRepo(ctx context.Context, gun data.GUN) (*client.NotaryRe func DefaultPermissions() map[string][]string { return map[string][]string{ - "/api.Notary/AddTarget": {"push", "pull"}, - "/api.Notary/RemoveTarget": {"push", "pull"}, + "/api.Notary/AddTarget": {"push", "pull"}, + "/api.Notary/RemoveTarget": {"push", "pull"}, + "/api.Notary/ListTargets": {"pull"}, + "/api.Notary/GetTargetByName": {"pull"}, + "/api.Notary/GetAllTargetMetadataByName": {"pull"}, + "/api.Notary/ListRoles": {"pull"}, + "/api.Notary/GetDelegationRoles": {"pull"}, + "/api.Notary/AddDelegation": {"push", "pull"}, + "/api.Notary/AddDelegationRoleAndKeys": {"push", "pull"}, + "/api.Notary/AddDelegationPaths": {"push", "pull"}, + "/api.Notary/RemoveDelegationKeysAndPaths": {"push", "pull"}, + "/api.Notary/RemoveDelegationRole": {"push", "pull"}, + "/api.Notary/RemoveDelegationPaths": {"push", "pull"}, + "/api.Notary/RemoveDelegationKeys": {"push", "pull"}, + "/api.Notary/ClearDelegationPaths": {"push", "pull"}, + "/api.Notary/Witness": {"push", "pull"}, + "/api.Notary/RotateKey": {"push", "pull"}, + "/api.Notary/CryptoServiceCreate": {"push", "pull"}, + "/api.Notary/CryptoServiceAddKey": {"push", "pull"}, + "/api.Notary/CryptoServiceGetKey": {"push", "pull"}, + "/api.Notary/CryptoServiceListKeys": {"push", "pull"}, + "/api.Notary/CryptoServiceListAllKeys": {"push", "pull"}, } } diff --git a/cmd/notary/tuf.go b/cmd/notary/tuf.go index dae3879c4..bafb2fc49 100644 --- a/cmd/notary/tuf.go +++ b/cmd/notary/tuf.go @@ -412,7 +412,7 @@ func (t *tufCommander) tufAddByHash(cmd *cobra.Command, args []string) error { if t.output == "" { return errors.New("you must provide an --output file when using an --input file") } - fd, err := os.OpenFile(t.output, os.O_TRUNC, 0600) + fd, err := os.OpenFile(t.output, os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0600) if err != nil { return err } @@ -477,7 +477,7 @@ func (t *tufCommander) tufAdd(cmd *cobra.Command, args []string) error { if t.output == "" { return errors.New("you must provide an --output file when using an --input file") } - fd, err := os.OpenFile(t.output, os.O_TRUNC, 0600) + fd, err := os.OpenFile(t.output, os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0600) if err != nil { return err } From 3972417f8d01b4293e768228fc83f91f95ef469b Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 13 Apr 2017 15:23:31 -0700 Subject: [PATCH 58/62] final fixes to work with prod Signed-off-by: David Lawrence (github: endophage) --- auth/grpc/auth.go | 25 +++++++----- client_api/api/server.go | 3 +- clientapi.Dockerfile | 2 +- cmd/clientapi/setup/config.go | 37 +++++------------ cmd/notary/repo_factory.go | 7 +++- docker-compose.clientapi.yml | 58 +-------------------------- fixtures/clientapi-server-config.toml | 13 +++++- utils/grpc.go | 5 ++- 8 files changed, 50 insertions(+), 100 deletions(-) diff --git a/auth/grpc/auth.go b/auth/grpc/auth.go index 4c01647fa..59382fbb8 100644 --- a/auth/grpc/auth.go +++ b/auth/grpc/auth.go @@ -13,6 +13,7 @@ import ( "google.golang.org/grpc/metadata" "net/http" "net/url" + "strings" ) type guner interface { @@ -55,6 +56,7 @@ func (s ServerAuthorizer) Interceptor(ctx context.Context, req interface{}, info rawToken = ts[0] } } + rawToken = strings.TrimPrefix(rawToken, "Bearer ") if _, err := s.authVerifier.Authorize(rawToken); !ok || err != nil { md := s.authVerifier.ChallengeHeaders( err, @@ -79,11 +81,11 @@ type ClientAuthorizer struct { authHandler *auth.TokenHandler } -func NewClientAuthorizer() grpc.UnaryClientInterceptor { +func NewClientAuthorizer(credStr auth.CredentialStore) grpc.UnaryClientInterceptor { c := ClientAuthorizer{ authHandler: auth.NewTokenHandler( http.DefaultTransport, - credStore{}, + credStr, "registry-client", "", ), @@ -142,7 +144,7 @@ func (c *ClientAuthorizer) getToken(challengeHeader []string) (string, error) { return c.authHandler.AuthorizeRequest(challenges[0].Parameters, challenges[0].Parameters["scope"]) } -func NewCredStore(username, password string, refreshTokens, accessTokens map[string]string) auth.CredentialStore { +func NewCredStore(store auth.CredentialStore, refreshTokens, accessTokens map[string]string) auth.CredentialStore { if refreshTokens == nil { refreshTokens = make(map[string]string) } @@ -150,24 +152,25 @@ func NewCredStore(username, password string, refreshTokens, accessTokens map[str accessTokens = make(map[string]string) } return &credStore{ - username: username, - password: password, + store: store, refreshTokens: refreshTokens, accessTokens: accessTokens, } } type credStore struct { - username, password string + store auth.CredentialStore refreshTokens, accessTokens map[string]string } -func (cs credStore) Basic(*url.URL) (string, string) { - return cs.username, cs.password +func (cs credStore) Basic(u *url.URL) (string, string) { + return cs.store.Basic(u) } -func (cs credStore) RefreshToken(*url.URL, string) string { - return "" +func (cs credStore) RefreshToken(u *url.URL, t string) string { + return cs.store.RefreshToken(u, t) } -func (cs credStore) SetRefreshToken(realm *url.URL, service, token string) {} +func (cs credStore) SetRefreshToken(realm *url.URL, service, token string) { + cs.store.SetRefreshToken(realm, service, token) +} diff --git a/client_api/api/server.go b/client_api/api/server.go index ceaabb116..d2b837567 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -660,7 +660,8 @@ func (srv *Server) initRepo(ctx context.Context, gun data.GUN) (*client.NotaryRe if !ok { return nil, errors.New("initRepo may only be used with GRPC contexts") } - tokens := md["Authorization"] + tokens := md["authorization"] + logrus.Debugf("forwarding tokens: %s", tokens) rt, err := utils.GetForwardingAuthTransport( srv.upstreamCAPath, tokens, diff --git a/clientapi.Dockerfile b/clientapi.Dockerfile index 04528fa1a..d83a6faf9 100644 --- a/clientapi.Dockerfile +++ b/clientapi.Dockerfile @@ -1,6 +1,6 @@ FROM golang:1.7.5-alpine -RUN apk add --update git gcc libc-dev && rm -rf /var/cache/apk/* +RUN apk add --update git gcc libc-dev ca-certificates && rm -rf /var/cache/apk/* ENV NOTARY_PKG github.com/docker/notary diff --git a/cmd/clientapi/setup/config.go b/cmd/clientapi/setup/config.go index 814e445d3..3c27c02ea 100644 --- a/cmd/clientapi/setup/config.go +++ b/cmd/clientapi/setup/config.go @@ -73,20 +73,21 @@ func Authorization(vc *viper.Viper) (grpc.UnaryServerInterceptor, error) { switch authType { case notary.AuthTypeToken: var ( - realm = vc.GetString("auth.options.realm") - service = vc.GetString("auth.options.service") - issuer = vc.GetString("auth.options.issuer") - rootCAPath = vc.GetString("auth.options.rootcertbundle") - permissions = vc.GetStringMap("auth.options.permissions") - tokenAuth, err = token.NewAuth(realm, issuer, service, rootCAPath) + realm = vc.GetString("auth.options.realm") + service = vc.GetString("auth.options.service") + issuer = vc.GetString("auth.options.issuer") + rootCAPath = utils.GetPathRelativeToConfig(vc, "auth.options.rootcertbundle") + permissions = vc.GetStringMap("auth.options.permissions") ) + logrus.Debugf("token realm: %s", realm) + logrus.Debugf("token service: %s", service) + logrus.Debugf("token issuer: %s", issuer) + logrus.Debugf("token ca path: %s", rootCAPath) + tokenAuth, err := token.NewAuth(realm, issuer, service, rootCAPath) if err != nil { return nil, err } - basePerms, err := buildBasePermissionList("push", "pull") - if err != nil { - return nil, err - } + basePerms := api.DefaultPermissions() basePerms, err = mergePermissions(basePerms, permissions) if err != nil { return nil, err @@ -146,22 +147,6 @@ func KeyStorage(vc *viper.Viper) ([]trustmanager.KeyStore, error) { return []trustmanager.KeyStore{keyStore}, nil } -func buildBasePermissionList(requiredPerms ...string) (map[string][]string, error) { - srv := grpc.Server{} - apiSrv := api.Server{} - api.RegisterNotaryServer(&srv, &apiSrv) - srvInfo := srv.GetServiceInfo() - svc, ok := srvInfo["api.Notary"] - if !ok { - return nil, errors.New("could not find api.Notary service") - } - permissions := make(map[string][]string) - for _, method := range svc.Methods { - permissions[method.Name] = requiredPerms - } - return permissions, nil -} - func mergePermissions(basePerms map[string][]string, additional map[string]interface{}) (map[string][]string, error) { for k, v := range basePerms { if more, ok := additional[k]; ok { diff --git a/cmd/notary/repo_factory.go b/cmd/notary/repo_factory.go index e0fd0d013..183462e6a 100644 --- a/cmd/notary/repo_factory.go +++ b/cmd/notary/repo_factory.go @@ -9,6 +9,7 @@ import ( "github.com/docker/notary/tuf/data" "github.com/docker/notary/utils" "net/http" + "github.com/docker/notary/auth/grpc" ) const remoteConfigField = "api" @@ -39,7 +40,11 @@ func ConfigureRepo(v *viper.Viper, retriever notary.PassRetriever, onlineOperati } remoteRepo := func(gun data.GUN) (client.Repository, error) { - conn, err := utils.GetGRPCClient(v, remoteConfigField) + conn, err := utils.GetGRPCClient( + v, + remoteConfigField, + grpcauth.NewCredStore(&passwordStore{false}, nil, nil), + ) if err != nil { return nil, err } diff --git a/docker-compose.clientapi.yml b/docker-compose.clientapi.yml index d7d7d7b7c..1eeac70a8 100644 --- a/docker-compose.clientapi.yml +++ b/docker-compose.clientapi.yml @@ -5,47 +5,13 @@ services: context: . dockerfile: clientapi.Dockerfile depends_on: - - server + - escrow ports: - "4449:4449" networks: - api: esc: entrypoint: clientapi command: -config=./fixtures/clientapi-server-config.toml - server: - build: - context: . - dockerfile: server.Dockerfile - networks: - mdb: - sig: - api: - aliases: - - notaryserver - ports: - - "8080" - - "4443:4443" - entrypoint: /usr/bin/env sh - command: -c "./migrations/migrate.sh && notary-server -config=./fixtures/server-config.json" - depends_on: - - mysql - - signer - signer: - build: - context: . - dockerfile: signer.Dockerfile - networks: - mdb: - sig: - aliases: - - notarysigner - ports: - - "7899:7899" - entrypoint: /usr/bin/env sh - command: -c "./migrations/migrate.sh && notary-signer -config=./fixtures/signer-config.json" - depends_on: - - mysql escrow: build: context: . @@ -56,28 +22,6 @@ services: - notaryescrow entrypoint: escrow command: -config=./fixtures/escrow-config-local.toml - mysql: - networks: - - mdb - volumes: - - ./notarysql/mysql-initdb.d:/docker-entrypoint-initdb.d - - notary_data:/var/lib/mysql - image: mariadb:10.1.10 - environment: - - TERM=dumb - - MYSQL_ALLOW_EMPTY_PASSWORD="true" - command: mysqld --innodb_file_per_table -volumes: - notary_data: - external: false - clientapi_data: - external: false networks: - mdb: - external: false - sig: - external: false - api: - external: false esc: external: false diff --git a/fixtures/clientapi-server-config.toml b/fixtures/clientapi-server-config.toml index 1d61507bf..8289dd0de 100644 --- a/fixtures/clientapi-server-config.toml +++ b/fixtures/clientapi-server-config.toml @@ -7,8 +7,7 @@ tls_key_file = "./clientapi-server.key" level = "debug" [upstream] -addr = "https://notaryserver:4443" -tls_ca_file = "./root-ca.crt" +addr = "https://notary.docker.io" [key_storage] type = "remote" @@ -17,3 +16,13 @@ tls_ca_file = "./root-ca.crt" tls_cert_file = "./clientapi-server.crt" tls_key_file = "./clientapi-server.key" secret = "fixturesecret" + +[auth] +type = "token" + + [auth.options] + realm = "https://auth.docker.io/token" + service = "notary.docker.io" + issuer = "auth.docker.io" + rootcertbundle = "./tokencertbundle.pem" + diff --git a/utils/grpc.go b/utils/grpc.go index 397a520dc..7d7408271 100644 --- a/utils/grpc.go +++ b/utils/grpc.go @@ -5,6 +5,8 @@ import ( "fmt" "github.com/Sirupsen/logrus" "github.com/docker/go-connections/tlsconfig" + auth "github.com/docker/notary/auth/client" + "github.com/docker/notary/auth/grpc" "github.com/spf13/viper" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -43,7 +45,7 @@ func grpcTLS(configuration *viper.Viper, prefix string) (*tls.Config, error) { return tlsConfig, nil } -func GetGRPCClient(vc *viper.Viper, prefix string) (*grpc.ClientConn, error) { +func GetGRPCClient(vc *viper.Viper, prefix string, credStore auth.CredentialStore) (*grpc.ClientConn, error) { var ( dialOpts = []grpc.DialOption{ grpc.WithBlock(), @@ -76,6 +78,7 @@ func GetGRPCClient(vc *viper.Viper, prefix string) (*grpc.ClientConn, error) { dialOpts = append(dialOpts, grpc.WithTransportCredentials(creds)) } } + dialOpts = append(dialOpts, grpc.WithUnaryInterceptor(grpcauth.NewClientAuthorizer(credStore))) return grpc.Dial(addr, dialOpts...) } From 1c7b2e73f6d4c49a8598af5ffaa6276ab3522579 Mon Sep 17 00:00:00 2001 From: Nassim 'Nass' Eddequiouaq Date: Thu, 13 Apr 2017 18:00:54 -0700 Subject: [PATCH 59/62] Move default locally/remotely managed role keys to a package local var Signed-off-by: Nassim 'Nass' Eddequiouaq --- client/client.go | 55 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/client/client.go b/client/client.go index 9b39ef42e..236fba1f5 100644 --- a/client/client.go +++ b/client/client.go @@ -34,6 +34,7 @@ const ( func init() { data.SetDefaultExpiryTimes(data.NotaryDefaultExpiries) + SetManagedRoleKeys(defaultManagedRoleKeys) } // NotaryRepository stores all the information needed to operate on a notary @@ -185,6 +186,28 @@ func rootCertKey(gun data.GUN, privKey data.PrivateKey) (data.PublicKey, error) return x509PublicKey, nil } +// These values are configurable lists of locally and remotely managed roles +type ManagedRoleKeys struct { + locallyManagedKeys []data.RoleName + remotelyManagedKeys []data.RoleName +} +var defaultManagedRoleKeys = ManagedRoleKeys{ + locallyManagedKeys: []data.RoleName{ + data.CanonicalTargetsRole, + data.CanonicalSnapshotRole, + data.CanonicalRootRole, + }, + remotelyManagedKeys: []data.RoleName{ + data.CanonicalTimestampRole, + }, +} + +// SetManagedRolesKeys allows one to change the default locally and remotely managed role keys +func SetManagedRoleKeys(roleKeys ManagedRoleKeys) { + defaultManagedRoleKeys.locallyManagedKeys = roleKeys.locallyManagedKeys + defaultManagedRoleKeys.remotelyManagedKeys = roleKeys.remotelyManagedKeys +} + // Initialize creates a new repository by using rootKey as the root Key for the // TUF repository. The server must be reachable (and is asked to generate a // timestamp key and possibly other serverManagedRoles), but the created repository @@ -201,23 +224,25 @@ func (r *NotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles .. // (do not have to be passed in as part of `serverManagedRoles`, so that // the API of Initialize doesn't change). var serverManagesSnapshot bool - locallyManagedKeys := []data.RoleName{ - data.CanonicalTargetsRole, - data.CanonicalSnapshotRole, - // root is also locally managed, but that should have been created - // already - } - remotelyManagedKeys := []data.RoleName{data.CanonicalTimestampRole} + locallyManagedKeys := defaultManagedRoleKeys.locallyManagedKeys + remotelyManagedKeys := defaultManagedRoleKeys.remotelyManagedKeys for _, role := range serverManagedRoles { switch role { - case data.CanonicalTimestampRole: - continue // timestamp is already in the right place - case data.CanonicalSnapshotRole: - // because we put Snapshot last - locallyManagedKeys = []data.RoleName{data.CanonicalTargetsRole} - remotelyManagedKeys = append( - remotelyManagedKeys, data.CanonicalSnapshotRole) - serverManagesSnapshot = true + // We add timestamp or snapshot role if not already present in the remotely managed list + case data.CanonicalTimestampRole, data.CanonicalSnapshotRole: + present := false + for _, remotelyManagedKey := range remotelyManagedKeys { + if remotelyManagedKey == role { + present = true + } + } + + if !present { + remotelyManagedKeys = append(remotelyManagedKeys, role) + if role == data.CanonicalSnapshotRole { + serverManagesSnapshot = true + } + } default: return ErrInvalidRemoteRole{Role: role} } From ace829393a1939171ed43c961238213216c27ce4 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 13 Apr 2017 16:06:43 -0700 Subject: [PATCH 60/62] catalog tokens for cryptoservice operations Signed-off-by: David Lawrence (github: endophage) --- auth/grpc/auth.go | 3 +-- auth/token/util.go | 11 ++++++++++- client_api/api/server.go | 10 +++++----- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/auth/grpc/auth.go b/auth/grpc/auth.go index 59382fbb8..199dc4d04 100644 --- a/auth/grpc/auth.go +++ b/auth/grpc/auth.go @@ -131,8 +131,7 @@ func (c *ClientAuthorizer) Interceptor(ctx context.Context, method string, req, } ctx = metadata.NewContext(ctx, md) - err = invoker(ctx, method, req, reply, cc, opts...) - return err + return invoker(ctx, method, req, reply, cc, opts...) } func (c *ClientAuthorizer) getToken(challengeHeader []string) (string, error) { diff --git a/auth/token/util.go b/auth/token/util.go index 0b283ad8b..f7df3dd12 100644 --- a/auth/token/util.go +++ b/auth/token/util.go @@ -58,12 +58,21 @@ func contains(ss []string, q string) bool { return false } +// BuildAccessRecords takes a repo and a set of actions and builds a list of Access +// records for use with token auth. This version has been specifically tweaked for +// the Client API and will interpret an action of "*" to mean you want "catalog" +// access rather than access to a specific gun. func BuildAccessRecords(repo string, actions ...string) []auth.Access { + accessType := "repository" + if len(actions) == 1 && actions[0] == "*" { + accessType = "registry" + repo = "catalog" + } requiredAccess := make([]auth.Access, 0, len(actions)) for _, action := range actions { requiredAccess = append(requiredAccess, auth.Access{ Resource: auth.Resource{ - Type: "repository", + Type: accessType, Name: repo, }, Action: action, diff --git a/client_api/api/server.go b/client_api/api/server.go index d2b837567..b6dc9281c 100644 --- a/client_api/api/server.go +++ b/client_api/api/server.go @@ -712,10 +712,10 @@ func DefaultPermissions() map[string][]string { "/api.Notary/ClearDelegationPaths": {"push", "pull"}, "/api.Notary/Witness": {"push", "pull"}, "/api.Notary/RotateKey": {"push", "pull"}, - "/api.Notary/CryptoServiceCreate": {"push", "pull"}, - "/api.Notary/CryptoServiceAddKey": {"push", "pull"}, - "/api.Notary/CryptoServiceGetKey": {"push", "pull"}, - "/api.Notary/CryptoServiceListKeys": {"push", "pull"}, - "/api.Notary/CryptoServiceListAllKeys": {"push", "pull"}, + "/api.Notary/CryptoServiceCreate": {"*"}, + "/api.Notary/CryptoServiceAddKey": {"*"}, + "/api.Notary/CryptoServiceGetKey": {"*"}, + "/api.Notary/CryptoServiceListKeys": {"*"}, + "/api.Notary/CryptoServiceListAllKeys": {"*"}, } } From 362c486030cd46d08506c9697673a8e0bc8bedf2 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 13 Apr 2017 21:42:13 -0700 Subject: [PATCH 61/62] fixing server managed snapshots for Client API Signed-off-by: David Lawrence (github: endophage) --- client/client.go | 65 ++++++++++++++++++------------------------- cmd/clientapi/main.go | 2 ++ 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/client/client.go b/client/client.go index 236fba1f5..f189b8e40 100644 --- a/client/client.go +++ b/client/client.go @@ -32,9 +32,12 @@ const ( SignWithAllOldVersions = -1 ) +var ( + serverManagesSnapshotKeyByDefault = false +) + func init() { data.SetDefaultExpiryTimes(data.NotaryDefaultExpiries) - SetManagedRoleKeys(defaultManagedRoleKeys) } // NotaryRepository stores all the information needed to operate on a notary @@ -186,26 +189,10 @@ func rootCertKey(gun data.GUN, privKey data.PrivateKey) (data.PublicKey, error) return x509PublicKey, nil } -// These values are configurable lists of locally and remotely managed roles -type ManagedRoleKeys struct { - locallyManagedKeys []data.RoleName - remotelyManagedKeys []data.RoleName -} -var defaultManagedRoleKeys = ManagedRoleKeys{ - locallyManagedKeys: []data.RoleName{ - data.CanonicalTargetsRole, - data.CanonicalSnapshotRole, - data.CanonicalRootRole, - }, - remotelyManagedKeys: []data.RoleName{ - data.CanonicalTimestampRole, - }, -} - -// SetManagedRolesKeys allows one to change the default locally and remotely managed role keys -func SetManagedRoleKeys(roleKeys ManagedRoleKeys) { - defaultManagedRoleKeys.locallyManagedKeys = roleKeys.locallyManagedKeys - defaultManagedRoleKeys.remotelyManagedKeys = roleKeys.remotelyManagedKeys +// SetServerManagesSnapshot changes the default behaviour so that the server +// always manages the snaoshot +func SetServerManagesSnapshot() { + serverManagesSnapshotKeyByDefault = true } // Initialize creates a new repository by using rootKey as the root Key for the @@ -223,31 +210,33 @@ func (r *NotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles .. // nothing else - timestamps are always managed by the server, and implicit // (do not have to be passed in as part of `serverManagedRoles`, so that // the API of Initialize doesn't change). - var serverManagesSnapshot bool - locallyManagedKeys := defaultManagedRoleKeys.locallyManagedKeys - remotelyManagedKeys := defaultManagedRoleKeys.remotelyManagedKeys + serverManagesSnapshot := serverManagesSnapshotKeyByDefault + locallyManagedKeys := []data.RoleName{ + data.CanonicalTargetsRole, + data.CanonicalSnapshotRole, + // root is also locally managed, but that should have been created + // already + } + remotelyManagedKeys := []data.RoleName{data.CanonicalTimestampRole} + for _, role := range serverManagedRoles { switch role { // We add timestamp or snapshot role if not already present in the remotely managed list - case data.CanonicalTimestampRole, data.CanonicalSnapshotRole: - present := false - for _, remotelyManagedKey := range remotelyManagedKeys { - if remotelyManagedKey == role { - present = true - } - } - - if !present { - remotelyManagedKeys = append(remotelyManagedKeys, role) - if role == data.CanonicalSnapshotRole { - serverManagesSnapshot = true - } - } + case data.CanonicalTimestampRole: + continue + case data.CanonicalSnapshotRole: + serverManagesSnapshot = true default: return ErrInvalidRemoteRole{Role: role} } } + if serverManagesSnapshot { + locallyManagedKeys = []data.RoleName{data.CanonicalTargetsRole} + remotelyManagedKeys = append( + remotelyManagedKeys, data.CanonicalSnapshotRole) + } + rootKeys := make([]data.PublicKey, 0, len(privKeys)) for _, privKey := range privKeys { rootKey, err := rootCertKey(r.gun, privKey) diff --git a/cmd/clientapi/main.go b/cmd/clientapi/main.go index f6acb9eda..6903c5db8 100644 --- a/cmd/clientapi/main.go +++ b/cmd/clientapi/main.go @@ -3,6 +3,7 @@ package main import ( "flag" "github.com/Sirupsen/logrus" + "github.com/docker/notary/client" "github.com/docker/notary/client_api/api" "github.com/docker/notary/cmd/clientapi/setup" "github.com/docker/notary/utils" @@ -22,6 +23,7 @@ func init() { "path to configuration file; supported formats are JSON, YAML, and TOML", ) flag.Parse() + client.SetServerManagesSnapshot() } func main() { From 791ceafe9f8c32b7bbea47a7c365cd6e875d2371 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Fri, 14 Apr 2017 08:17:10 -0700 Subject: [PATCH 62/62] include seperate configs and compose files for full local dev, and dev against prod notary server Signed-off-by: David Lawrence (github: endophage) --- docker-compose.clientapi.prod.yml | 27 ++++++++++ docker-compose.clientapi.yml | 58 +++++++++++++++++++++- fixtures/clientapi-server-config.toml | 13 +---- fixtures/clientapi-server-prod-config.toml | 28 +++++++++++ 4 files changed, 114 insertions(+), 12 deletions(-) create mode 100644 docker-compose.clientapi.prod.yml create mode 100644 fixtures/clientapi-server-prod-config.toml diff --git a/docker-compose.clientapi.prod.yml b/docker-compose.clientapi.prod.yml new file mode 100644 index 000000000..1eeac70a8 --- /dev/null +++ b/docker-compose.clientapi.prod.yml @@ -0,0 +1,27 @@ +version: "2" +services: + clientapi: + build: + context: . + dockerfile: clientapi.Dockerfile + depends_on: + - escrow + ports: + - "4449:4449" + networks: + esc: + entrypoint: clientapi + command: -config=./fixtures/clientapi-server-config.toml + escrow: + build: + context: . + dockerfile: escrow.Dockerfile + networks: + esc: + aliases: + - notaryescrow + entrypoint: escrow + command: -config=./fixtures/escrow-config-local.toml +networks: + esc: + external: false diff --git a/docker-compose.clientapi.yml b/docker-compose.clientapi.yml index 1eeac70a8..d7d7d7b7c 100644 --- a/docker-compose.clientapi.yml +++ b/docker-compose.clientapi.yml @@ -5,13 +5,47 @@ services: context: . dockerfile: clientapi.Dockerfile depends_on: - - escrow + - server ports: - "4449:4449" networks: + api: esc: entrypoint: clientapi command: -config=./fixtures/clientapi-server-config.toml + server: + build: + context: . + dockerfile: server.Dockerfile + networks: + mdb: + sig: + api: + aliases: + - notaryserver + ports: + - "8080" + - "4443:4443" + entrypoint: /usr/bin/env sh + command: -c "./migrations/migrate.sh && notary-server -config=./fixtures/server-config.json" + depends_on: + - mysql + - signer + signer: + build: + context: . + dockerfile: signer.Dockerfile + networks: + mdb: + sig: + aliases: + - notarysigner + ports: + - "7899:7899" + entrypoint: /usr/bin/env sh + command: -c "./migrations/migrate.sh && notary-signer -config=./fixtures/signer-config.json" + depends_on: + - mysql escrow: build: context: . @@ -22,6 +56,28 @@ services: - notaryescrow entrypoint: escrow command: -config=./fixtures/escrow-config-local.toml + mysql: + networks: + - mdb + volumes: + - ./notarysql/mysql-initdb.d:/docker-entrypoint-initdb.d + - notary_data:/var/lib/mysql + image: mariadb:10.1.10 + environment: + - TERM=dumb + - MYSQL_ALLOW_EMPTY_PASSWORD="true" + command: mysqld --innodb_file_per_table +volumes: + notary_data: + external: false + clientapi_data: + external: false networks: + mdb: + external: false + sig: + external: false + api: + external: false esc: external: false diff --git a/fixtures/clientapi-server-config.toml b/fixtures/clientapi-server-config.toml index 8289dd0de..1d61507bf 100644 --- a/fixtures/clientapi-server-config.toml +++ b/fixtures/clientapi-server-config.toml @@ -7,7 +7,8 @@ tls_key_file = "./clientapi-server.key" level = "debug" [upstream] -addr = "https://notary.docker.io" +addr = "https://notaryserver:4443" +tls_ca_file = "./root-ca.crt" [key_storage] type = "remote" @@ -16,13 +17,3 @@ tls_ca_file = "./root-ca.crt" tls_cert_file = "./clientapi-server.crt" tls_key_file = "./clientapi-server.key" secret = "fixturesecret" - -[auth] -type = "token" - - [auth.options] - realm = "https://auth.docker.io/token" - service = "notary.docker.io" - issuer = "auth.docker.io" - rootcertbundle = "./tokencertbundle.pem" - diff --git a/fixtures/clientapi-server-prod-config.toml b/fixtures/clientapi-server-prod-config.toml new file mode 100644 index 000000000..8289dd0de --- /dev/null +++ b/fixtures/clientapi-server-prod-config.toml @@ -0,0 +1,28 @@ +[server] +grpc_addr = ":4449" +tls_cert_file = "./clientapi-server.crt" +tls_key_file = "./clientapi-server.key" + +[logging] +level = "debug" + +[upstream] +addr = "https://notary.docker.io" + +[key_storage] +type = "remote" +addr = "notaryescrow:4450" +tls_ca_file = "./root-ca.crt" +tls_cert_file = "./clientapi-server.crt" +tls_key_file = "./clientapi-server.key" +secret = "fixturesecret" + +[auth] +type = "token" + + [auth.options] + realm = "https://auth.docker.io/token" + service = "notary.docker.io" + issuer = "auth.docker.io" + rootcertbundle = "./tokencertbundle.pem" +