mirror of
https://github.com/netbirdio/dex.git
synced 2026-05-22 18:43:53 -07:00
Merge pull request #585 from ericchiang/dev-api
dev branch: add a simple gRPC API
This commit is contained in:
@@ -8,21 +8,26 @@ VERSION=$(shell ./scripts/git-version)
|
||||
DOCKER_REPO=quay.io/ericchiang/dex
|
||||
DOCKER_IMAGE=$(DOCKER_REPO):$(VERSION)
|
||||
|
||||
$( shell mkdir -p bin )
|
||||
|
||||
export GOBIN=$(PWD)/bin
|
||||
# Prefer ./bin instead of system packages for things like protoc, where we want
|
||||
# to use the version dex uses, not whatever a developer has installed.
|
||||
export PATH=$(GOBIN):$(shell printenv PATH)
|
||||
export GO15VENDOREXPERIMENT=1
|
||||
|
||||
LD_FLAGS="-w -X $(REPO_PATH)/version.Version=$(VERSION)"
|
||||
|
||||
GOOS=$(shell go env GOOS)
|
||||
GOARCH=$(shell go env GOARCH)
|
||||
|
||||
build: bin/dex bin/example-app
|
||||
|
||||
bin/dex: FORCE server/templates_default.go
|
||||
@go install -ldflags $(LD_FLAGS) $(REPO_PATH)/cmd/dex
|
||||
bin/dex: FORCE generated
|
||||
@go install -v -ldflags $(LD_FLAGS) $(REPO_PATH)/cmd/dex
|
||||
|
||||
bin/example-app: FORCE
|
||||
@go install -ldflags $(LD_FLAGS) $(REPO_PATH)/cmd/example-app
|
||||
@go install -v -ldflags $(LD_FLAGS) $(REPO_PATH)/cmd/example-app
|
||||
|
||||
.PHONY: generated
|
||||
generated: server/templates_default.go
|
||||
|
||||
test:
|
||||
@go test -v -i $(shell go list ./... | grep -v '/vendor/')
|
||||
@@ -39,7 +44,7 @@ fmt:
|
||||
@go fmt $(shell go list ./... | grep -v '/vendor/')
|
||||
|
||||
lint:
|
||||
@for package in $(shell go list ./... | grep -v '/vendor/' | grep -v 'api/apipb'); do \
|
||||
@for package in $(shell go list ./... | grep -v '/vendor/' | grep -v '/api'); do \
|
||||
golint -set_exit_status $$package; \
|
||||
done
|
||||
|
||||
@@ -56,6 +61,18 @@ docker-push: docker-build
|
||||
@docker push $(DOCKER_IMAGE)
|
||||
@docker push $(DOCKER_REPO):latest
|
||||
|
||||
.PHONY: grpc
|
||||
grpc: api/api.pb.go
|
||||
|
||||
api/api.pb.go: api/api.proto bin/protoc bin/protoc-gen-go
|
||||
@protoc --go_out=plugins=grpc:. api/*.proto
|
||||
|
||||
bin/protoc: scripts/get-protoc
|
||||
@./scripts/get-protoc bin/protoc
|
||||
|
||||
bin/protoc-gen-go:
|
||||
@go install -v $(REPO_PATH)/vendor/github.com/golang/protobuf/protoc-gen-go
|
||||
|
||||
clean:
|
||||
@rm bin/*
|
||||
|
||||
|
||||
@@ -8,15 +8,6 @@ OpenID Connect / OAuth2
|
||||
- [ ] Add a "NextSigningKey" to the storage.Keys type so clients can cache more aggressively
|
||||
- [ ] Support grant_type=password
|
||||
|
||||
API
|
||||
|
||||
- [ ] Determine best way to expose an API
|
||||
- [ ] Use access tokens so we don't expose the underlying credentials implementation
|
||||
- [ ] Support grant_type=client_credentials so clients can operate on their own
|
||||
- [ ] Figure out a spec for the access tokens so other services can use them
|
||||
- [ ] Group API, ability to list groups, members, etc.
|
||||
- [ ] Expose capabilities of the server (implicit support, group API, etc.)
|
||||
|
||||
Connectors
|
||||
|
||||
- [ ] Port BitBucket connector
|
||||
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: api/api.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package api is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
api/api.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Client
|
||||
CreateClientReq
|
||||
CreateClientResp
|
||||
DeleteClientReq
|
||||
DeleteClientResp
|
||||
*/
|
||||
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
|
||||
|
||||
// Client represents an OAuth2 client.
|
||||
type Client struct {
|
||||
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||
Secret string `protobuf:"bytes,2,opt,name=secret" json:"secret,omitempty"`
|
||||
RedirectUris []string `protobuf:"bytes,3,rep,name=redirect_uris,json=redirectUris" json:"redirect_uris,omitempty"`
|
||||
TrustedPeers []string `protobuf:"bytes,4,rep,name=trusted_peers,json=trustedPeers" json:"trusted_peers,omitempty"`
|
||||
Public bool `protobuf:"varint,5,opt,name=public" json:"public,omitempty"`
|
||||
Name string `protobuf:"bytes,6,opt,name=name" json:"name,omitempty"`
|
||||
LogoUrl string `protobuf:"bytes,7,opt,name=logo_url,json=logoUrl" json:"logo_url,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Client) Reset() { *m = Client{} }
|
||||
func (m *Client) String() string { return proto.CompactTextString(m) }
|
||||
func (*Client) ProtoMessage() {}
|
||||
func (*Client) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
// CreateClientReq is a request to make a client.
|
||||
type CreateClientReq struct {
|
||||
Client *Client `protobuf:"bytes,1,opt,name=client" json:"client,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CreateClientReq) Reset() { *m = CreateClientReq{} }
|
||||
func (m *CreateClientReq) String() string { return proto.CompactTextString(m) }
|
||||
func (*CreateClientReq) ProtoMessage() {}
|
||||
func (*CreateClientReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *CreateClientReq) GetClient() *Client {
|
||||
if m != nil {
|
||||
return m.Client
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateClientResp returns the response from creating a client.
|
||||
type CreateClientResp struct {
|
||||
AlreadyExists bool `protobuf:"varint,1,opt,name=already_exists,json=alreadyExists" json:"already_exists,omitempty"`
|
||||
Client *Client `protobuf:"bytes,2,opt,name=client" json:"client,omitempty"`
|
||||
}
|
||||
|
||||
func (m *CreateClientResp) Reset() { *m = CreateClientResp{} }
|
||||
func (m *CreateClientResp) String() string { return proto.CompactTextString(m) }
|
||||
func (*CreateClientResp) ProtoMessage() {}
|
||||
func (*CreateClientResp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *CreateClientResp) GetClient() *Client {
|
||||
if m != nil {
|
||||
return m.Client
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteClientReq is a request to delete a client.
|
||||
type DeleteClientReq struct {
|
||||
// The ID of the client.
|
||||
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DeleteClientReq) Reset() { *m = DeleteClientReq{} }
|
||||
func (m *DeleteClientReq) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeleteClientReq) ProtoMessage() {}
|
||||
func (*DeleteClientReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
// DeleteClientResp determines if the.
|
||||
type DeleteClientResp struct {
|
||||
NotFound bool `protobuf:"varint,1,opt,name=not_found,json=notFound" json:"not_found,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DeleteClientResp) Reset() { *m = DeleteClientResp{} }
|
||||
func (m *DeleteClientResp) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeleteClientResp) ProtoMessage() {}
|
||||
func (*DeleteClientResp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Client)(nil), "api.Client")
|
||||
proto.RegisterType((*CreateClientReq)(nil), "api.CreateClientReq")
|
||||
proto.RegisterType((*CreateClientResp)(nil), "api.CreateClientResp")
|
||||
proto.RegisterType((*DeleteClientReq)(nil), "api.DeleteClientReq")
|
||||
proto.RegisterType((*DeleteClientResp)(nil), "api.DeleteClientResp")
|
||||
}
|
||||
|
||||
// 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.SupportPackageIsVersion3
|
||||
|
||||
// Client API for Dex service
|
||||
|
||||
type DexClient interface {
|
||||
// CreateClient attempts to create the client.
|
||||
CreateClient(ctx context.Context, in *CreateClientReq, opts ...grpc.CallOption) (*CreateClientResp, error)
|
||||
// DeleteClient attempts to delete the provided client.
|
||||
DeleteClient(ctx context.Context, in *DeleteClientReq, opts ...grpc.CallOption) (*DeleteClientResp, error)
|
||||
}
|
||||
|
||||
type dexClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewDexClient(cc *grpc.ClientConn) DexClient {
|
||||
return &dexClient{cc}
|
||||
}
|
||||
|
||||
func (c *dexClient) CreateClient(ctx context.Context, in *CreateClientReq, opts ...grpc.CallOption) (*CreateClientResp, error) {
|
||||
out := new(CreateClientResp)
|
||||
err := grpc.Invoke(ctx, "/api.Dex/CreateClient", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *dexClient) DeleteClient(ctx context.Context, in *DeleteClientReq, opts ...grpc.CallOption) (*DeleteClientResp, error) {
|
||||
out := new(DeleteClientResp)
|
||||
err := grpc.Invoke(ctx, "/api.Dex/DeleteClient", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Dex service
|
||||
|
||||
type DexServer interface {
|
||||
// CreateClient attempts to create the client.
|
||||
CreateClient(context.Context, *CreateClientReq) (*CreateClientResp, error)
|
||||
// DeleteClient attempts to delete the provided client.
|
||||
DeleteClient(context.Context, *DeleteClientReq) (*DeleteClientResp, error)
|
||||
}
|
||||
|
||||
func RegisterDexServer(s *grpc.Server, srv DexServer) {
|
||||
s.RegisterService(&_Dex_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Dex_CreateClient_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CreateClientReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(DexServer).CreateClient(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/api.Dex/CreateClient",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(DexServer).CreateClient(ctx, req.(*CreateClientReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Dex_DeleteClient_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DeleteClientReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(DexServer).DeleteClient(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/api.Dex/DeleteClient",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(DexServer).DeleteClient(ctx, req.(*DeleteClientReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Dex_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "api.Dex",
|
||||
HandlerType: (*DexServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "CreateClient",
|
||||
Handler: _Dex_CreateClient_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "DeleteClient",
|
||||
Handler: _Dex_DeleteClient_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: fileDescriptor0,
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("api/api.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 337 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x92, 0x4f, 0x6b, 0xe3, 0x30,
|
||||
0x10, 0xc5, 0x63, 0x3b, 0xeb, 0x38, 0x93, 0xbf, 0x88, 0xdd, 0xc5, 0xbb, 0xbd, 0xa4, 0x0e, 0x85,
|
||||
0x9c, 0x12, 0x48, 0xa1, 0xb7, 0x9e, 0x92, 0xf6, 0x5c, 0x0c, 0xb9, 0xd6, 0x28, 0xf6, 0xb4, 0x08,
|
||||
0x54, 0x4b, 0x95, 0x64, 0x48, 0xcf, 0xfd, 0x64, 0xfd, 0x66, 0x45, 0x8a, 0x0a, 0x4e, 0x68, 0x6f,
|
||||
0x7e, 0x3f, 0xcd, 0xcc, 0x7b, 0x33, 0x18, 0x46, 0x54, 0xb2, 0x15, 0x95, 0x6c, 0x29, 0x95, 0x30,
|
||||
0x82, 0x44, 0x54, 0xb2, 0xec, 0x23, 0x80, 0x78, 0xc3, 0x19, 0xd6, 0x86, 0x8c, 0x21, 0x64, 0x55,
|
||||
0x1a, 0xcc, 0x82, 0x45, 0x3f, 0x0f, 0x59, 0x45, 0xfe, 0x42, 0xac, 0xb1, 0x54, 0x68, 0xd2, 0xd0,
|
||||
0x31, 0xaf, 0xc8, 0x1c, 0x46, 0x0a, 0x2b, 0xa6, 0xb0, 0x34, 0x45, 0xa3, 0x98, 0x4e, 0xa3, 0x59,
|
||||
0xb4, 0xe8, 0xe7, 0xc3, 0x2f, 0xb8, 0x53, 0x4c, 0xdb, 0x22, 0xa3, 0x1a, 0x6d, 0xb0, 0x2a, 0x24,
|
||||
0xa2, 0xd2, 0x69, 0xf7, 0x58, 0xe4, 0xe1, 0x83, 0x65, 0xd6, 0x41, 0x36, 0x7b, 0xce, 0xca, 0xf4,
|
||||
0xd7, 0x2c, 0x58, 0x24, 0xb9, 0x57, 0x84, 0x40, 0xb7, 0xa6, 0x2f, 0x98, 0xc6, 0xce, 0xd7, 0x7d,
|
||||
0x93, 0x7f, 0x90, 0x70, 0xf1, 0x2c, 0x8a, 0x46, 0xf1, 0xb4, 0xe7, 0x78, 0xcf, 0xea, 0x9d, 0xe2,
|
||||
0xd9, 0x0d, 0x4c, 0x36, 0x0a, 0xa9, 0xc1, 0xe3, 0x22, 0x39, 0xbe, 0x92, 0x39, 0xc4, 0xa5, 0x13,
|
||||
0x6e, 0x9f, 0xc1, 0x7a, 0xb0, 0xb4, 0x7b, 0xfb, 0x77, 0xff, 0x94, 0x3d, 0xc2, 0xf4, 0xb4, 0x4f,
|
||||
0x4b, 0x72, 0x05, 0x63, 0xca, 0x15, 0xd2, 0xea, 0xad, 0xc0, 0x03, 0xd3, 0x46, 0xbb, 0x01, 0x49,
|
||||
0x3e, 0xf2, 0xf4, 0xce, 0xc1, 0xd6, 0xfc, 0xf0, 0xe7, 0xf9, 0x97, 0x30, 0xd9, 0x22, 0xc7, 0x76,
|
||||
0xae, 0xb3, 0x1b, 0x67, 0x2b, 0x98, 0x9e, 0x96, 0x68, 0x49, 0x2e, 0xa0, 0x5f, 0x0b, 0x53, 0x3c,
|
||||
0x89, 0xa6, 0xae, 0xbc, 0x7b, 0x52, 0x0b, 0x73, 0x6f, 0xf5, 0xfa, 0x3d, 0x80, 0x68, 0x8b, 0x07,
|
||||
0x72, 0x0b, 0xc3, 0x76, 0x76, 0xf2, 0xfb, 0x18, 0xe0, 0xf4, 0x0c, 0xff, 0xff, 0x7c, 0x43, 0xb5,
|
||||
0xcc, 0x3a, 0xb6, 0xbd, 0xed, 0xeb, 0xdb, 0xcf, 0xd2, 0xfa, 0xf6, 0xf3, 0x80, 0x59, 0x67, 0x1f,
|
||||
0xbb, 0x3f, 0xe8, 0xfa, 0x33, 0x00, 0x00, 0xff, 0xff, 0xd1, 0x13, 0xbd, 0x1b, 0x52, 0x02, 0x00,
|
||||
0x00,
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package api;
|
||||
|
||||
// Client represents an OAuth2 client.
|
||||
message Client {
|
||||
string id = 1;
|
||||
string secret = 2;
|
||||
repeated string redirect_uris = 3;
|
||||
repeated string trusted_peers = 4;
|
||||
bool public = 5;
|
||||
string name = 6;
|
||||
string logo_url = 7;
|
||||
}
|
||||
|
||||
// CreateClientReq is a request to make a client.
|
||||
message CreateClientReq {
|
||||
Client client = 1;
|
||||
}
|
||||
|
||||
// CreateClientResp returns the response from creating a client.
|
||||
message CreateClientResp {
|
||||
bool already_exists = 1;
|
||||
Client client = 2;
|
||||
}
|
||||
|
||||
// DeleteClientReq is a request to delete a client.
|
||||
message DeleteClientReq {
|
||||
// The ID of the client.
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
// DeleteClientResp determines if the.
|
||||
message DeleteClientResp {
|
||||
bool not_found = 1;
|
||||
}
|
||||
|
||||
// TODO(ericchiang): expand this.
|
||||
|
||||
// Dex represents the dex gRPC service.
|
||||
service Dex {
|
||||
// CreateClient attempts to create the client.
|
||||
rpc CreateClient(CreateClientReq) returns (CreateClientResp) {};
|
||||
// DeleteClient attempts to delete the provided client.
|
||||
rpc DeleteClient(DeleteClientReq) returns (DeleteClientResp) {};
|
||||
}
|
||||
@@ -22,6 +22,7 @@ type Config struct {
|
||||
Connectors []Connector `yaml:"connectors"`
|
||||
Web Web `yaml:"web"`
|
||||
OAuth2 OAuth2 `yaml:"oauth2"`
|
||||
GRPC GRPC `yaml:"grpc"`
|
||||
|
||||
Templates server.TemplateConfig `yaml:"templates"`
|
||||
|
||||
@@ -41,6 +42,14 @@ type Web struct {
|
||||
TLSKey string `yaml:"tlsKey"`
|
||||
}
|
||||
|
||||
// GRPC is the config for the gRPC API.
|
||||
type GRPC struct {
|
||||
// The port to listen on.
|
||||
Addr string `yaml:"addr"`
|
||||
TLSCert string `yaml:"tlsCert"`
|
||||
TLSKey string `yaml:"tlsKey"`
|
||||
}
|
||||
|
||||
// Storage holds app's storage configuration.
|
||||
type Storage struct {
|
||||
Type string `yaml:"type"`
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package main
|
||||
+36
-5
@@ -5,11 +5,15 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/coreos/dex/api"
|
||||
"github.com/coreos/dex/server"
|
||||
"github.com/coreos/dex/storage"
|
||||
)
|
||||
@@ -19,7 +23,7 @@ func commandServe() *cobra.Command {
|
||||
Use: "serve [ config file ]",
|
||||
Short: "Connect to the storage and begin serving requests.",
|
||||
Long: ``,
|
||||
Example: "dex serve c.yaml",
|
||||
Example: "dex serve config.yaml",
|
||||
RunE: serve,
|
||||
}
|
||||
}
|
||||
@@ -56,6 +60,9 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||
{c.Web.HTTP == "" && c.Web.HTTPS == "", "must supply a HTTP/HTTPS address to listen on"},
|
||||
{c.Web.HTTPS != "" && c.Web.TLSCert == "", "no cert specified for HTTPS"},
|
||||
{c.Web.HTTPS != "" && c.Web.TLSKey == "", "no private key specified for HTTPS"},
|
||||
{c.GRPC.TLSCert != "" && c.GRPC.Addr == "", "no address specified for gRPC"},
|
||||
{c.GRPC.TLSKey != "" && c.GRPC.Addr == "", "no address specified for gRPC"},
|
||||
{(c.GRPC.TLSCert == "") != (c.GRPC.TLSKey == ""), "must specific both a gRPC TLS cert and key"},
|
||||
}
|
||||
|
||||
for _, check := range checks {
|
||||
@@ -64,6 +71,15 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
var grpcOptions []grpc.ServerOption
|
||||
if c.GRPC.TLSCert != "" {
|
||||
opt, err := credentials.NewServerTLSFromFile(c.GRPC.TLSCert, c.GRPC.TLSKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load grpc certs: %v", err)
|
||||
}
|
||||
grpcOptions = append(grpcOptions, grpc.Creds(opt))
|
||||
}
|
||||
|
||||
connectors := make([]server.Connector, len(c.Connectors))
|
||||
for i, conn := range c.Connectors {
|
||||
if conn.Config == nil {
|
||||
@@ -96,22 +112,37 @@ func serve(cmd *cobra.Command, args []string) error {
|
||||
TemplateConfig: c.Templates,
|
||||
}
|
||||
|
||||
serv, err := server.New(serverConfig)
|
||||
serv, err := server.NewServer(serverConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing server: %v", err)
|
||||
}
|
||||
errc := make(chan error, 2)
|
||||
errc := make(chan error, 3)
|
||||
if c.Web.HTTP != "" {
|
||||
log.Printf("listening (http) on %s", c.Web.HTTP)
|
||||
go func() {
|
||||
log.Printf("listening on %s", c.Web.HTTP)
|
||||
errc <- http.ListenAndServe(c.Web.HTTP, serv)
|
||||
}()
|
||||
}
|
||||
if c.Web.HTTPS != "" {
|
||||
log.Printf("listening (https) on %s", c.Web.HTTPS)
|
||||
go func() {
|
||||
log.Printf("listening on %s", c.Web.HTTPS)
|
||||
errc <- http.ListenAndServeTLS(c.Web.HTTPS, c.Web.TLSCert, c.Web.TLSKey, serv)
|
||||
}()
|
||||
}
|
||||
if c.GRPC.Addr != "" {
|
||||
log.Printf("listening (grpc) on %s", c.GRPC.Addr)
|
||||
go func() {
|
||||
errc <- func() error {
|
||||
list, err := net.Listen("tcp", c.GRPC.Addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listen grpc: %v", err)
|
||||
}
|
||||
s := grpc.NewServer(grpcOptions...)
|
||||
api.RegisterDexServer(s, server.NewAPI(serverConfig.Storage))
|
||||
return s.Serve(list)
|
||||
}()
|
||||
}()
|
||||
}
|
||||
|
||||
return <-errc
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
issuer: http://127.0.0.1:5556
|
||||
storage:
|
||||
type: sqlite3
|
||||
config:
|
||||
file: examples/dex.db
|
||||
|
||||
web:
|
||||
http: 127.0.0.1:5556
|
||||
|
||||
grpc:
|
||||
addr: 127.0.0.1:5557
|
||||
|
||||
connectors:
|
||||
- type: mockCallback
|
||||
id: mock-callback
|
||||
name: Mock
|
||||
- type: mockPassword
|
||||
id: mock-password
|
||||
name: Password
|
||||
config:
|
||||
username: "admin"
|
||||
password: "PASSWORD"
|
||||
|
||||
staticClients:
|
||||
- id: example-app
|
||||
redirectURIs:
|
||||
- 'http://127.0.0.1:5555/callback'
|
||||
name: 'Example App'
|
||||
secret: ZXhhbXBsZS1hcHAtc2VjcmV0
|
||||
Generated
+18
-2
@@ -1,5 +1,5 @@
|
||||
hash: 149c717bc83cc279ab6192364776b8c1b6bad8a620ce9d64c56d946276630437
|
||||
updated: 2016-09-30T21:01:57.607704513-07:00
|
||||
hash: 8b7a5f94584ecd144fc3ce94bb0b09f8e96c94b5a8e10d5053bd24bb597367ce
|
||||
updated: 2016-10-03T23:25:41.280181088-07:00
|
||||
imports:
|
||||
- name: github.com/cockroachdb/cockroach-go
|
||||
version: 31611c0501c812f437d4861d87d117053967c955
|
||||
@@ -52,6 +52,11 @@ imports:
|
||||
version: 6a513affb38dc9788b449d59ffed099b8de18fa0
|
||||
subpackages:
|
||||
- context
|
||||
- http2
|
||||
- http2/hpack
|
||||
- internal/timeseries
|
||||
- lex/httplex
|
||||
- trace
|
||||
- name: golang.org/x/oauth2
|
||||
version: 08c8d727d2392d18286f9f88ad775ad98f09ab33
|
||||
subpackages:
|
||||
@@ -67,6 +72,17 @@ imports:
|
||||
- internal/remote_api
|
||||
- internal/urlfetch
|
||||
- urlfetch
|
||||
- name: google.golang.org/grpc
|
||||
version: b1a2821ca5a4fd6b6e48ddfbb7d6d7584d839d21
|
||||
subpackages:
|
||||
- codes
|
||||
- credentials
|
||||
- grpclog
|
||||
- internal
|
||||
- metadata
|
||||
- naming
|
||||
- peer
|
||||
- transport
|
||||
- name: gopkg.in/asn1-ber.v1
|
||||
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
|
||||
- name: gopkg.in/ldap.v2
|
||||
|
||||
+18
@@ -26,6 +26,11 @@ import:
|
||||
version: 6a513affb38dc9788b449d59ffed099b8de18fa0
|
||||
subpackages:
|
||||
- context
|
||||
- http2
|
||||
- http2/hpack
|
||||
- internal/timeseries
|
||||
- lex/httplex
|
||||
- trace
|
||||
|
||||
- package: gopkg.in/yaml.v2
|
||||
version: a83829b6f1293c91addabc89d0571c246397bbf4
|
||||
@@ -89,3 +94,16 @@ import:
|
||||
version: 31611c0501c812f437d4861d87d117053967c955
|
||||
subpackages:
|
||||
- crdb
|
||||
|
||||
# gRPC also imports protobuf and the x/net/http2 stack.
|
||||
- package: google.golang.org/grpc
|
||||
version: b1a2821ca5a4fd6b6e48ddfbb7d6d7584d839d21
|
||||
subpackages:
|
||||
- codes
|
||||
- credentials
|
||||
- grpclog
|
||||
- internal
|
||||
- metadata
|
||||
- naming
|
||||
- peer
|
||||
- transport
|
||||
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# This is a script to download protoc. Rather than depending on the version on
|
||||
# a developer's machine, always download a specific version.
|
||||
|
||||
VERSION="3.1.0"
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: ./get-protoc [dest]"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Use the go tool to determine OS.
|
||||
OS=$( go env GOOS )
|
||||
|
||||
if [ "$OS" = "darwin" ]; then
|
||||
OS="osx"
|
||||
fi
|
||||
|
||||
# TODO(ericchiang): Architectures other than amd64?
|
||||
ZIP="protoc-${VERSION}-${OS}-x86_64.zip"
|
||||
URL="https://github.com/google/protobuf/releases/download/v${VERSION}/${ZIP}"
|
||||
|
||||
wget ${URL}
|
||||
# Unpack the protoc binary. Later we might want to grab additional data.
|
||||
unzip -p ${ZIP} bin/protoc > $1
|
||||
chmod +x $1
|
||||
rm ${ZIP}
|
||||
@@ -0,0 +1,64 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/dex/api"
|
||||
"github.com/coreos/dex/storage"
|
||||
)
|
||||
|
||||
// NewAPI returns a server which implements the gRPC API interface.
|
||||
func NewAPI(s storage.Storage) api.DexServer {
|
||||
return dexAPI{s: s}
|
||||
}
|
||||
|
||||
type dexAPI struct {
|
||||
s storage.Storage
|
||||
}
|
||||
|
||||
func (d dexAPI) CreateClient(ctx context.Context, req *api.CreateClientReq) (*api.CreateClientResp, error) {
|
||||
if req.Client == nil {
|
||||
return nil, errors.New("no client supplied")
|
||||
}
|
||||
|
||||
if req.Client.Id == "" {
|
||||
req.Client.Id = storage.NewID()
|
||||
}
|
||||
if req.Client.Secret == "" {
|
||||
req.Client.Secret = storage.NewID() + storage.NewID()
|
||||
}
|
||||
|
||||
c := storage.Client{
|
||||
ID: req.Client.Id,
|
||||
Secret: req.Client.Secret,
|
||||
RedirectURIs: req.Client.RedirectUris,
|
||||
TrustedPeers: req.Client.TrustedPeers,
|
||||
Public: req.Client.Public,
|
||||
Name: req.Client.Name,
|
||||
LogoURL: req.Client.LogoUrl,
|
||||
}
|
||||
if err := d.s.CreateClient(c); err != nil {
|
||||
log.Printf("api: failed to create client: %v", err)
|
||||
// TODO(ericchiang): Surface "already exists" errors.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.CreateClientResp{
|
||||
Client: req.Client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d dexAPI) DeleteClient(ctx context.Context, req *api.DeleteClientReq) (*api.DeleteClientResp, error) {
|
||||
err := d.s.DeleteClient(req.Id)
|
||||
if err != nil {
|
||||
if err == storage.ErrNotFound {
|
||||
return &api.DeleteClientResp{NotFound: true}, nil
|
||||
}
|
||||
log.Printf("api: failed to delete client: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return &api.DeleteClientResp{}, nil
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package server
|
||||
+2
-2
@@ -78,8 +78,8 @@ type Server struct {
|
||||
idTokensValidFor time.Duration
|
||||
}
|
||||
|
||||
// New constructs a server from the provided config.
|
||||
func New(c Config) (*Server, error) {
|
||||
// NewServer constructs a server from the provided config.
|
||||
func NewServer(c Config) (*Server, error) {
|
||||
return newServer(c, defaultRotationStrategy(
|
||||
value(c.RotateKeysAfter, 6*time.Hour),
|
||||
value(c.IDTokensValidFor, 24*time.Hour),
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.5.4
|
||||
- 1.6.3
|
||||
- 1.7
|
||||
|
||||
go_import_path: google.golang.org/grpc
|
||||
|
||||
before_install:
|
||||
- go get -u golang.org/x/tools/cmd/goimports github.com/golang/lint/golint github.com/axw/gocov/gocov github.com/mattn/goveralls golang.org/x/tools/cmd/cover
|
||||
|
||||
script:
|
||||
- '! gofmt -s -d -l . 2>&1 | read'
|
||||
- '! goimports -l . | read'
|
||||
- '! golint ./... | grep -vE "(_string|\.pb)\.go:"'
|
||||
- '! go tool vet -all . 2>&1 | grep -vE "constant [0-9]+ not a string in call to Errorf" | grep -vF .pb.go:' # https://github.com/golang/protobuf/issues/214
|
||||
- make test testrace
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
# How to contribute
|
||||
|
||||
We definitely welcome patches and contribution to grpc! Here are some guidelines
|
||||
and information about how to do so.
|
||||
|
||||
## Sending patches
|
||||
|
||||
### Getting started
|
||||
|
||||
1. Check out the code:
|
||||
|
||||
$ go get google.golang.org/grpc
|
||||
$ cd $GOPATH/src/google.golang.org/grpc
|
||||
|
||||
1. Create a fork of the grpc-go repository.
|
||||
1. Add your fork as a remote:
|
||||
|
||||
$ git remote add fork git@github.com:$YOURGITHUBUSERNAME/grpc-go.git
|
||||
|
||||
1. Make changes, commit them.
|
||||
1. Run the test suite:
|
||||
|
||||
$ make test
|
||||
|
||||
1. Push your changes to your fork:
|
||||
|
||||
$ git push fork ...
|
||||
|
||||
1. Open a pull request.
|
||||
|
||||
## Legal requirements
|
||||
|
||||
In order to protect both you and ourselves, you will need to sign the
|
||||
[Contributor License Agreement](https://cla.developers.google.com/clas).
|
||||
|
||||
## Filing Issues
|
||||
When filing an issue, make sure to answer these five questions:
|
||||
|
||||
1. What version of Go are you using (`go version`)?
|
||||
2. What operating system and processor architecture are you using?
|
||||
3. What did you do?
|
||||
4. What did you expect to see?
|
||||
5. What did you see instead?
|
||||
|
||||
### Contributing code
|
||||
Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file.
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
# Authentication
|
||||
|
||||
As outlined in the [gRPC authentication guide](http://www.grpc.io/docs/guides/auth.html) there are a number of different mechanisms for asserting identity between an client and server. We'll present some code-samples here demonstrating how to provide TLS support encryption and identity assertions as well as passing OAuth2 tokens to services that support it.
|
||||
|
||||
# Enabling TLS on a gRPC client
|
||||
|
||||
```Go
|
||||
conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")))
|
||||
```
|
||||
|
||||
# Enabling TLS on a gRPC server
|
||||
|
||||
```Go
|
||||
creds, err := credentials.NewServerTLSFromFile(certFile, keyFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to generate credentials %v", err)
|
||||
}
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
server := grpc.NewServer(grpc.Creds(creds))
|
||||
...
|
||||
server.Serve(lis)
|
||||
```
|
||||
|
||||
# Authenticating with Google
|
||||
|
||||
## Google Compute Engine (GCE)
|
||||
|
||||
```Go
|
||||
conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, ""), grpc.WithPerRPCCredentials(oauth.NewComputeEngine())))
|
||||
```
|
||||
|
||||
## JWT
|
||||
|
||||
```Go
|
||||
jwtCreds, err := oauth.NewServiceAccountFromFile(*serviceAccountKeyFile, *oauthScope)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create JWT credentials: %v", err)
|
||||
}
|
||||
conn, err := grpc.Dial(serverAddr, grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, ""), grpc.WithPerRPCCredentials(jwtCreds)))
|
||||
```
|
||||
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
# Metadata
|
||||
|
||||
gRPC supports sending metadata between client and server.
|
||||
This doc shows how to send and receive metadata in gRPC-go.
|
||||
|
||||
## Background
|
||||
|
||||
Four kinds of service method:
|
||||
|
||||
- [Unary RPC](http://www.grpc.io/docs/guides/concepts.html#unary-rpc)
|
||||
- [Server streaming RPC](http://www.grpc.io/docs/guides/concepts.html#server-streaming-rpc)
|
||||
- [Client streaming RPC](http://www.grpc.io/docs/guides/concepts.html#client-streaming-rpc)
|
||||
- [Bidirectional streaming RPC](http://www.grpc.io/docs/guides/concepts.html#bidirectional-streaming-rpc)
|
||||
|
||||
And concept of [metadata](http://www.grpc.io/docs/guides/concepts.html#metadata).
|
||||
|
||||
## Constructing metadata
|
||||
|
||||
A metadata can be created using package [metadata](https://godoc.org/google.golang.org/grpc/metadata).
|
||||
The type MD is actually a map from string to a list of strings:
|
||||
|
||||
```go
|
||||
type MD map[string][]string
|
||||
```
|
||||
|
||||
Metadata can be read like a normal map.
|
||||
Note that the value type of this map is `[]string`,
|
||||
so that users can attach multiple values using a single key.
|
||||
|
||||
### Creating a new metadata
|
||||
|
||||
A metadata can be created from a `map[string]string` using function `New`:
|
||||
|
||||
```go
|
||||
md := metadata.New(map[string]string{"key1": "val1", "key2": "val2"})
|
||||
```
|
||||
|
||||
Another way is to use `Pairs`.
|
||||
Values with the same key will be merged into a list:
|
||||
|
||||
```go
|
||||
md := metadata.Pairs(
|
||||
"key1", "val1",
|
||||
"key1", "val1-2", // "key1" will have map value []string{"val1", "val1-2"}
|
||||
"key2", "val2",
|
||||
)
|
||||
```
|
||||
|
||||
__Note:__ all the keys will be automatically converted to lowercase,
|
||||
so "key1" and "kEy1" will be the same key and their values will be merged into the same list.
|
||||
This happens for both `New` and `Pairs`.
|
||||
|
||||
### Storing binary data in metadata
|
||||
|
||||
In metadata, keys are always strings. But values can be strings or binary data.
|
||||
To store binary data value in metadata, simply add "-bin" suffix to the key.
|
||||
The values with "-bin" suffixed keys will be encoded when creating the metadata:
|
||||
|
||||
```go
|
||||
md := metadata.Pairs(
|
||||
"key", "string value",
|
||||
"key-bin", string([]byte{96, 102}), // this binary data will be encoded (base64) before sending
|
||||
// and will be decoded after being transferred.
|
||||
)
|
||||
```
|
||||
|
||||
## Retrieving metadata from context
|
||||
|
||||
Metadata can be retrieved from context using `FromContext`:
|
||||
|
||||
```go
|
||||
func (s *server) SomeRPC(ctx context.Context, in *pb.SomeRequest) (*pb.SomeResponse, err) {
|
||||
md, ok := metadata.FromContext(ctx)
|
||||
// do something with metadata
|
||||
}
|
||||
```
|
||||
|
||||
## Sending and receiving metadata - client side
|
||||
|
||||
[//]: # "TODO: uncomment next line after example source added"
|
||||
[//]: # "Real metadata sending and receiving examples are available [here](TODO:example_dir)."
|
||||
|
||||
### Sending metadata
|
||||
|
||||
To send metadata to server, the client can wrap the metadata into a context using `NewContext`, and make the RPC with this context:
|
||||
|
||||
```go
|
||||
md := metadata.Pairs("key", "val")
|
||||
|
||||
// create a new context with this metadata
|
||||
ctx := metadata.NewContext(context.Background(), md)
|
||||
|
||||
// make unary RPC
|
||||
response, err := client.SomeRPC(ctx, someRequest)
|
||||
|
||||
// or make streaming RPC
|
||||
stream, err := client.SomeStreamingRPC(ctx)
|
||||
```
|
||||
### Receiving metadata
|
||||
|
||||
Metadata that a client can receive includes header and trailer.
|
||||
|
||||
#### Unary call
|
||||
|
||||
Header and trailer sent along with a unary call can be retrieved using function [Header](https://godoc.org/google.golang.org/grpc#Header) and [Trailer](https://godoc.org/google.golang.org/grpc#Trailer) in [CallOption](https://godoc.org/google.golang.org/grpc#CallOption):
|
||||
|
||||
```go
|
||||
var header, trailer metadata.MD // variable to store header and trailer
|
||||
r, err := client.SomeRPC(
|
||||
ctx,
|
||||
someRequest,
|
||||
grpc.Header(&header), // will retrieve header
|
||||
grpc.Trailer(&trailer), // will retrieve trailer
|
||||
)
|
||||
|
||||
// do something with header and trailer
|
||||
```
|
||||
|
||||
#### Streaming call
|
||||
|
||||
For streaming calls including:
|
||||
|
||||
- Server streaming RPC
|
||||
- Client streaming RPC
|
||||
- Bidirectional streaming RPC
|
||||
|
||||
Header and trailer can be retrieved from the returned stream using function `Header` and `Trailer` in interface [ClientStream](https://godoc.org/google.golang.org/grpc#ClientStream):
|
||||
|
||||
```go
|
||||
stream, err := client.SomeStreamingRPC(ctx)
|
||||
|
||||
// retrieve header
|
||||
header, err := stream.Header()
|
||||
|
||||
// retrieve trailer
|
||||
trailer := stream.Trailer()
|
||||
|
||||
```
|
||||
|
||||
## Sending and receiving metadata - server side
|
||||
|
||||
[//]: # "TODO: uncomment next line after example source added"
|
||||
[//]: # "Real metadata sending and receiving examples are available [here](TODO:example_dir)."
|
||||
|
||||
### Receiving metadata
|
||||
|
||||
To read metadata sent by the client, the server needs to retrieve it from RPC context.
|
||||
If it is a unary call, the RPC handler's context can be used.
|
||||
For streaming calls, the server needs to get context from the stream.
|
||||
|
||||
#### Unary call
|
||||
|
||||
```go
|
||||
func (s *server) SomeRPC(ctx context.Context, in *pb.someRequest) (*pb.someResponse, error) {
|
||||
md, ok := metadata.FromContext(ctx)
|
||||
// do something with metadata
|
||||
}
|
||||
```
|
||||
|
||||
#### Streaming call
|
||||
|
||||
```go
|
||||
func (s *server) SomeStreamingRPC(stream pb.Service_SomeStreamingRPCServer) error {
|
||||
md, ok := metadata.FromContext(stream.Context()) // get context from stream
|
||||
// do something with metadata
|
||||
}
|
||||
```
|
||||
|
||||
### Sending metadata
|
||||
|
||||
#### Unary call
|
||||
|
||||
To send header and trailer to client in unary call, the server can call [SendHeader](https://godoc.org/google.golang.org/grpc#SendHeader) and [SetTrailer](https://godoc.org/google.golang.org/grpc#SetTrailer) functions in module [grpc](https://godoc.org/google.golang.org/grpc).
|
||||
These two functions take a context as the first parameter.
|
||||
It should be the RPC handler's context or one derived from it:
|
||||
|
||||
```go
|
||||
func (s *server) SomeRPC(ctx context.Context, in *pb.someRequest) (*pb.someResponse, error) {
|
||||
// create and send header
|
||||
header := metadata.Pairs("header-key", "val")
|
||||
grpc.SendHeader(ctx, header)
|
||||
// create and set trailer
|
||||
trailer := metadata.Pairs("trailer-key", "val")
|
||||
grpc.SetTrailer(ctx, trailer)
|
||||
}
|
||||
```
|
||||
|
||||
#### Streaming call
|
||||
|
||||
For streaming calls, header and trailer can be sent using function `SendHeader` and `SetTrailer` in interface [ServerStream](https://godoc.org/google.golang.org/grpc#ServerStream):
|
||||
|
||||
```go
|
||||
func (s *server) SomeStreamingRPC(stream pb.Service_SomeStreamingRPCServer) error {
|
||||
// create and send header
|
||||
header := metadata.Pairs("header-key", "val")
|
||||
stream.SendHeader(header)
|
||||
// create and set trailer
|
||||
trailer := metadata.Pairs("trailer-key", "val")
|
||||
stream.SetTrailer(trailer)
|
||||
}
|
||||
```
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
Copyright 2014, Google Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
all: test testrace
|
||||
|
||||
deps:
|
||||
go get -d -v google.golang.org/grpc/...
|
||||
|
||||
updatedeps:
|
||||
go get -d -v -u -f google.golang.org/grpc/...
|
||||
|
||||
testdeps:
|
||||
go get -d -v -t google.golang.org/grpc/...
|
||||
|
||||
updatetestdeps:
|
||||
go get -d -v -t -u -f google.golang.org/grpc/...
|
||||
|
||||
build: deps
|
||||
go build google.golang.org/grpc/...
|
||||
|
||||
proto:
|
||||
@ if ! which protoc > /dev/null; then \
|
||||
echo "error: protoc not installed" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
go get -u -v github.com/golang/protobuf/protoc-gen-go
|
||||
# use $$dir as the root for all proto files in the same directory
|
||||
for dir in $$(git ls-files '*.proto' | xargs -n1 dirname | uniq); do \
|
||||
protoc -I $$dir --go_out=plugins=grpc:$$dir $$dir/*.proto; \
|
||||
done
|
||||
|
||||
test: testdeps
|
||||
go test -v -cpu 1,4 google.golang.org/grpc/...
|
||||
|
||||
testrace: testdeps
|
||||
go test -v -race -cpu 1,4 google.golang.org/grpc/...
|
||||
|
||||
clean:
|
||||
go clean -i google.golang.org/grpc/...
|
||||
|
||||
coverage: testdeps
|
||||
./coverage.sh --coveralls
|
||||
|
||||
.PHONY: \
|
||||
all \
|
||||
deps \
|
||||
updatedeps \
|
||||
testdeps \
|
||||
updatetestdeps \
|
||||
build \
|
||||
proto \
|
||||
test \
|
||||
testrace \
|
||||
clean \
|
||||
coverage
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user