Implemented remaining transport layer methods; added logging middleware;

added Dockerfile; added gen cert Makefile cmds; added Redis repo
This commit is contained in:
mitchell 2019-05-05 17:56:27 -07:00
parent 719a462048
commit c289eecd54
20 changed files with 1977 additions and 143 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
.idea
bin
certs
db

22
Dockerfile Normal file
View File

@ -0,0 +1,22 @@
FROM golang:1.11.5 as build
WORKDIR /go/src/github.com/mitchell/selfpass
COPY . .
RUN go get -u golang.org/x/tools/cmd/goimports
ENV GO111MODULE=on
RUN make build
FROM debian:stable-20190326-slim
RUN printf "deb http://httpredir.debian.org/debian stretch-backports main non-free\ndeb-src http://httpredir.debian.org/debian stretch-backports main non-free" > /etc/apt/sources.list.d/backports.list
RUN apt-get update && apt-get install -t stretch-backports -y --no-install-recommends redis-server=5:5.0.3-3~bpo9+2 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /usr/bin/selfpass/
COPY --from=build /go/src/github.com/mitchell/selfpass/bin/server .
COPY --from=build /go/src/github.com/mitchell/selfpass/redis.conf .
COPY --from=build /go/src/github.com/mitchell/selfpass/db/dump.rdb ./db/dump.rdb
COPY --from=build /go/src/github.com/mitchell/selfpass/certs/ca.pem ./certs/ca.pem
COPY --from=build /go/src/github.com/mitchell/selfpass/certs/server.pem ./certs/server.pem
COPY --from=build /go/src/github.com/mitchell/selfpass/certs/server-key.pem ./certs/server-key.pem
COPY --from=build /go/src/github.com/mitchell/selfpass/dual-entry ./dual-entry
ENTRYPOINT ./dual-entry
EXPOSE 8080

View File

@ -1,14 +1,20 @@
.PHONY: all build clean format test
.PHONY: all build clean format test docker-build
build: clean format test
go build -o ./bin/server ./cmd/server/server.go
docker-build:
docker build -t selfpass .
clean:
rm -rf ./bin
go mod tidy
dev: build
./bin/server --dev
dev: docker-build
docker run -i -t -p 8080:8080 selfpass -v -dev
local: docker-build
docker run -i -t -p 8080:8080 selfpass
format:
goimports -w -l .
@ -17,5 +23,18 @@ gen-protoc:
protoc --go_out=plugins=grpc:. \
./credentials/protobuf/service.proto
gen-csr-json:
mkdir certs
cd certs && cfssl print-defaults csr > csr.json
gen-ca:
cd certs && cfssl genkey -initca csr.json | cfssljson -bare ca
gen-server-cert:
cd certs && cfssl gencert -ca ca.pem -ca-key ca-key.pem csr.json | cfssljson -bare server
gen-client-cert:
cd certs && cfssl gencert -ca ca.pem -ca-key ca-key.pem csr.json | cfssljson -bare client
test:
go test -cover ./...

View File

@ -1,32 +1,43 @@
package main
import (
"crypto/tls"
"crypto/x509"
"flag"
"io"
"io/ioutil"
stdlog "log"
"net"
"os"
"os/signal"
"github.com/go-kit/kit/log"
"github.com/mitchell/selfpass/credentials/middleware"
"github.com/mitchell/selfpass/credentials/protobuf"
"github.com/mitchell/selfpass/credentials/repositories"
"github.com/mitchell/selfpass/credentials/service"
"github.com/mitchell/selfpass/credentials/transport"
"github.com/mitchell/selfpass/credentials/types"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
var logger log.Logger
func main() {
var (
stop = make(chan os.Signal)
stop = make(chan os.Signal, 1)
dev = flag.Bool("dev", false, "enables dev mode logging")
port = flag.String("port", "8080", "specify the port to listen on")
tableName = flag.String(
"credential-table-name",
"selfpass-credential",
"specify the credential table name on AWS",
)
crtFile = flag.String("cert", "./certs/server.pem", "specify the cert file")
keyFile = flag.String("key", "./certs/server-key.pem", "specify the private key file")
caFile = flag.String("ca", "./certs/ca.pem", "specify the ca cert file")
verbose = flag.Bool("v", false, "be more verbose")
// tableName = flag.String(
// "credential-table-name",
// "selfpass-credential",
// "specify the credential table name on AWS",
// )
)
signal.Notify(stop, os.Interrupt)
@ -34,30 +45,51 @@ func main() {
logger = newLogger(os.Stdout, *dev)
var (
db = repositories.NewDynamoTable(*tableName)
svc = service.NewCredentials(db)
gsrv = transport.NewGRPCServer(svc, logger)
srv = grpc.NewServer()
keypair, err := tls.LoadX509KeyPair(*crtFile, *keyFile)
check(err)
ca, err := ioutil.ReadFile(*caFile)
check(err)
caPool := x509.NewCertPool()
caPool.AppendCertsFromPEM(ca)
creds := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{keypair},
ClientCAs: caPool,
ClientAuth: tls.RequireAndVerifyClientCert,
})
// db := repositories.NewDynamoTable(*tableName)
db, err := repositories.NewRedisConn(
repositories.ConnConfig{NetworkType: "tcp", Address: "localhost:6379", Size: 2},
)
check(err)
var svc types.Service
svc = service.NewCredentials(db)
if *verbose {
svc = middleware.NewServiceLogger(logger, svc)
}
gsrv := transport.NewGRPCServer(svc, logger)
srv := grpc.NewServer(grpc.Creds(creds))
protobuf.RegisterCredentialServiceServer(srv, gsrv)
addr := "0.0.0.0:" + *port
addr := ":" + *port
lis, err := net.Listen("tcp", addr)
check(err)
go func() {
logger.Log(
_ = logger.Log(
"message", "serving",
"address", addr,
"credentialTable", tableName,
"dev", dev,
)
check(srv.Serve(lis))
}()
go func() { check(srv.Serve(lis)) }()
<-stop
logger.Log("message", "gracefully stopping")
_ = logger.Log("message", "gracefully stopping")
srv.GracefulStop()
}
@ -70,11 +102,11 @@ func newLogger(writer io.Writer, dev bool) log.Logger {
} else {
l = log.NewJSONLogger(writer)
}
l = log.WithPrefix(l, "caller", log.DefaultCaller, "timestamp", log.DefaultTimestamp)
l = log.WithPrefix(l, "caller", log.Caller(5), "timestamp", log.DefaultTimestamp)
lfunc := log.LoggerFunc(func(in ...interface{}) error {
if err := l.Log(in...); err != nil {
panic(err.Error())
stdlog.Println(err)
}
return nil
})
@ -84,7 +116,7 @@ func newLogger(writer io.Writer, dev bool) log.Logger {
func check(err error) {
if err != nil {
logger.Log("error", err)
_ = logger.Log("error", err)
os.Exit(1)
}
}

View File

@ -7,7 +7,27 @@ import (
"github.com/mitchell/selfpass/credentials/types"
)
// MakeGetAllMetadataEndpoint TODO
func MakeCreateEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(types.CredentialInput)
return svc.Create(ctx, r)
}
}
func MakeDeleteEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(IDRequest)
return nil, svc.Delete(ctx, r.ID)
}
}
func MakeGetEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(IDRequest)
return svc.Get(ctx, r.ID)
}
}
func MakeGetAllMetadataEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(GetAllMetadataRequest)
@ -21,15 +41,6 @@ func MakeGetAllMetadataEndpoint(svc types.Service) endpoint.Endpoint {
}
}
// MakeCreateEndpoint TODO
func MakeCreateEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(types.CredentialInput)
return svc.Create(ctx, r)
}
}
// MakeUpdateEndpoint TODO
func MakeUpdateEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(UpdateRequest)
@ -37,30 +48,30 @@ func MakeUpdateEndpoint(svc types.Service) endpoint.Endpoint {
}
}
func MakeDeleteEndpoint(svc types.Service) endpoint.Endpoint {
func MakeDumpEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(IDRequest)
return nil, svc.Delete(ctx, r.ID)
contents, err := svc.DumpDB(ctx)
return DumpResponse{Contents: contents}, err
}
}
// IDRequest TODO
type DumpResponse struct {
Contents []byte
}
type IDRequest struct {
ID string
}
// GetAllMetadataRequest TODO
type GetAllMetadataRequest struct {
SourceHost string
}
// MetadataStream TODO
type MetadataStream struct {
Metadata <-chan types.Metadata
Errors chan error
}
// UpdateRequest TODO
type UpdateRequest struct {
ID string
Credential types.CredentialInput

View File

@ -0,0 +1,114 @@
package middleware
import (
"context"
"time"
"github.com/go-kit/kit/log"
"github.com/mitchell/selfpass/credentials/types"
)
func NewServiceLogger(l log.Logger, next types.Service) ServiceLogger {
return ServiceLogger{
l: l,
next: next,
}
}
type ServiceLogger struct {
l log.Logger
next types.Service
}
func (svc ServiceLogger) GetAllMetadata(ctx context.Context, sourceHost string) (output <-chan types.Metadata, errch chan error) {
defer func(begin time.Time) {
_ = svc.l.Log(
"service", "Credentials",
"method", "GetAllMetadata",
"input", sourceHost,
"output", "channel",
"err", "channel",
"took", time.Since(begin),
)
}(time.Now())
return svc.next.GetAllMetadata(ctx, sourceHost)
}
func (svc ServiceLogger) Get(ctx context.Context, id string) (output types.Credential, err error) {
defer func(begin time.Time) {
_ = svc.l.Log(
"service", "Credentials",
"method", "Get",
"input", id,
"output", output,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
output, err = svc.next.Get(ctx, id)
return output, err
}
func (svc ServiceLogger) Create(ctx context.Context, ci types.CredentialInput) (output types.Credential, err error) {
defer func(begin time.Time) {
_ = svc.l.Log(
"service", "Credentials",
"method", "Create",
"input", ci,
"output", output,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
output, err = svc.next.Create(ctx, ci)
return output, err
}
func (svc ServiceLogger) Update(ctx context.Context, id string, ci types.CredentialInput) (output types.Credential, err error) {
defer func(begin time.Time) {
_ = svc.l.Log(
"service", "Credentials",
"method", "Update",
"input", []interface{}{id, ci},
"output", output,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
output, err = svc.next.Update(ctx, id, ci)
return output, err
}
func (svc ServiceLogger) Delete(ctx context.Context, id string) (err error) {
defer func(begin time.Time) {
_ = svc.l.Log(
"service", "Credentials",
"method", "Delete",
"input", id,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
err = svc.next.Delete(ctx, id)
return err
}
func (svc ServiceLogger) DumpDB(ctx context.Context) (output []byte, err error) {
defer func(begin time.Time) {
_ = svc.l.Log(
"service", "Credentials",
"method", "Dump",
"output", output,
"err", err,
"took", time.Since(begin),
)
}(time.Now())
output, err = svc.next.DumpDB(ctx)
return output, err
}

View File

@ -6,13 +6,12 @@ package protobuf
import (
context "context"
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
@ -190,6 +189,76 @@ func (m *UpdateRequest) GetCredential() *CredentialRequest {
return nil
}
type DumpResponse struct {
Contents []byte `protobuf:"bytes,1,opt,name=contents,proto3" json:"contents,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DumpResponse) Reset() { *m = DumpResponse{} }
func (m *DumpResponse) String() string { return proto.CompactTextString(m) }
func (*DumpResponse) ProtoMessage() {}
func (*DumpResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{4}
}
func (m *DumpResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DumpResponse.Unmarshal(m, b)
}
func (m *DumpResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DumpResponse.Marshal(b, m, deterministic)
}
func (m *DumpResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_DumpResponse.Merge(m, src)
}
func (m *DumpResponse) XXX_Size() int {
return xxx_messageInfo_DumpResponse.Size(m)
}
func (m *DumpResponse) XXX_DiscardUnknown() {
xxx_messageInfo_DumpResponse.DiscardUnknown(m)
}
var xxx_messageInfo_DumpResponse proto.InternalMessageInfo
func (m *DumpResponse) GetContents() []byte {
if m != nil {
return m.Contents
}
return nil
}
type EmptyRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *EmptyRequest) Reset() { *m = EmptyRequest{} }
func (m *EmptyRequest) String() string { return proto.CompactTextString(m) }
func (*EmptyRequest) ProtoMessage() {}
func (*EmptyRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{5}
}
func (m *EmptyRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EmptyRequest.Unmarshal(m, b)
}
func (m *EmptyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_EmptyRequest.Marshal(b, m, deterministic)
}
func (m *EmptyRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_EmptyRequest.Merge(m, src)
}
func (m *EmptyRequest) XXX_Size() int {
return xxx_messageInfo_EmptyRequest.Size(m)
}
func (m *EmptyRequest) XXX_DiscardUnknown() {
xxx_messageInfo_EmptyRequest.DiscardUnknown(m)
}
var xxx_messageInfo_EmptyRequest proto.InternalMessageInfo
type Metadata struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
CreatedAt *timestamp.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
@ -206,7 +275,7 @@ func (m *Metadata) Reset() { *m = Metadata{} }
func (m *Metadata) String() string { return proto.CompactTextString(m) }
func (*Metadata) ProtoMessage() {}
func (*Metadata) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{4}
return fileDescriptor_ad34efc7bbd96e69, []int{6}
}
func (m *Metadata) XXX_Unmarshal(b []byte) error {
@ -288,7 +357,7 @@ func (m *Credential) Reset() { *m = Credential{} }
func (m *Credential) String() string { return proto.CompactTextString(m) }
func (*Credential) ProtoMessage() {}
func (*Credential) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{5}
return fileDescriptor_ad34efc7bbd96e69, []int{7}
}
func (m *Credential) XXX_Unmarshal(b []byte) error {
@ -388,7 +457,7 @@ func (m *CredentialRequest) Reset() { *m = CredentialRequest{} }
func (m *CredentialRequest) String() string { return proto.CompactTextString(m) }
func (*CredentialRequest) ProtoMessage() {}
func (*CredentialRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{6}
return fileDescriptor_ad34efc7bbd96e69, []int{8}
}
func (m *CredentialRequest) XXX_Unmarshal(b []byte) error {
@ -456,6 +525,8 @@ func init() {
proto.RegisterType((*GetAllMetadataRequest)(nil), "selfpass.credentials.GetAllMetadataRequest")
proto.RegisterType((*IdRequest)(nil), "selfpass.credentials.IdRequest")
proto.RegisterType((*UpdateRequest)(nil), "selfpass.credentials.UpdateRequest")
proto.RegisterType((*DumpResponse)(nil), "selfpass.credentials.DumpResponse")
proto.RegisterType((*EmptyRequest)(nil), "selfpass.credentials.EmptyRequest")
proto.RegisterType((*Metadata)(nil), "selfpass.credentials.Metadata")
proto.RegisterType((*Credential)(nil), "selfpass.credentials.Credential")
proto.RegisterType((*CredentialRequest)(nil), "selfpass.credentials.CredentialRequest")
@ -464,38 +535,41 @@ func init() {
func init() { proto.RegisterFile("credentials/protobuf/service.proto", fileDescriptor_ad34efc7bbd96e69) }
var fileDescriptor_ad34efc7bbd96e69 = []byte{
// 493 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0x5d, 0x6b, 0xd4, 0x40,
0x14, 0x25, 0xd9, 0x76, 0x9b, 0xdc, 0xe2, 0x82, 0x43, 0x85, 0x90, 0x82, 0xbb, 0x44, 0xc1, 0xa2,
0x90, 0x4a, 0x7d, 0xd1, 0xc7, 0xb5, 0xc2, 0xd6, 0x07, 0x11, 0x52, 0xfb, 0xe2, 0xcb, 0x32, 0x4d,
0x6e, 0xb7, 0x81, 0xc9, 0x4e, 0x9c, 0x99, 0x28, 0xfe, 0x30, 0x41, 0xff, 0x91, 0x3f, 0x43, 0x32,
0xc9, 0xec, 0x47, 0x3a, 0xdb, 0x5d, 0xdf, 0xfa, 0x96, 0x3b, 0x39, 0x67, 0xe6, 0xdc, 0x33, 0x73,
0x2e, 0x44, 0xa9, 0xc0, 0x0c, 0xe7, 0x2a, 0xa7, 0x4c, 0x9e, 0x96, 0x82, 0x2b, 0x7e, 0x5d, 0xdd,
0x9c, 0x4a, 0x14, 0xdf, 0xf3, 0x14, 0x63, 0xbd, 0x40, 0x8e, 0x24, 0xb2, 0x9b, 0x92, 0x4a, 0x19,
0xaf, 0x80, 0xc3, 0xe1, 0x8c, 0xf3, 0x19, 0xc3, 0x25, 0x49, 0xe5, 0x05, 0x4a, 0x45, 0x8b, 0xb2,
0xa1, 0x45, 0x2f, 0x61, 0xf0, 0x01, 0x19, 0x2a, 0x4c, 0x50, 0x96, 0x7c, 0x2e, 0x91, 0x04, 0x70,
0x20, 0xab, 0x34, 0x45, 0x29, 0x03, 0x67, 0xe4, 0x9c, 0x78, 0x89, 0x29, 0xa3, 0xb7, 0xf0, 0x64,
0x82, 0x6a, 0xcc, 0xd8, 0x27, 0x54, 0x34, 0xa3, 0x8a, 0x26, 0xf8, 0xad, 0x42, 0xa9, 0xc8, 0x10,
0x0e, 0x25, 0xaf, 0x44, 0x8a, 0xd3, 0x5b, 0x2e, 0x95, 0xa6, 0xf9, 0x09, 0x34, 0x4b, 0x17, 0x5c,
0xaa, 0xe8, 0x18, 0xfc, 0x8f, 0x99, 0x41, 0x0f, 0xc0, 0xcd, 0xb3, 0x16, 0xe4, 0xe6, 0x59, 0x74,
0x0b, 0x8f, 0xae, 0xca, 0x8c, 0xd6, 0x12, 0xac, 0x00, 0x32, 0x01, 0x58, 0xf6, 0x14, 0xb8, 0x23,
0xe7, 0xe4, 0xf0, 0xec, 0x45, 0x6c, 0xeb, 0x37, 0x3e, 0x5f, 0x7c, 0xb7, 0x9b, 0x25, 0x2b, 0xd4,
0xe8, 0xaf, 0x03, 0x9e, 0xd1, 0x7e, 0xe7, 0x94, 0x77, 0xfa, 0x14, 0xaa, 0x30, 0x9b, 0x52, 0xd5,
0x9e, 0x12, 0xc6, 0x8d, 0x7f, 0xb1, 0xf1, 0x2f, 0xfe, 0x62, 0xfc, 0x4b, 0xfc, 0x16, 0x3d, 0x56,
0x35, 0xb5, 0xd2, 0x1d, 0x68, 0x6a, 0x6f, 0x3b, 0xb5, 0x45, 0x8f, 0x55, 0xed, 0x76, 0x29, 0xf2,
0x82, 0x8a, 0x9f, 0xc1, 0x9e, 0x96, 0x62, 0xca, 0xae, 0xa9, 0xfb, 0x5d, 0x53, 0xc9, 0x31, 0xf8,
0x8c, 0xcf, 0xf2, 0xf9, 0xb4, 0x12, 0x2c, 0xe8, 0xeb, 0xdf, 0x9e, 0x5e, 0xb8, 0x12, 0x2c, 0xfa,
0xed, 0x02, 0x2c, 0xcd, 0x78, 0xf0, 0xcd, 0x86, 0xe0, 0x55, 0x12, 0xc5, 0x9c, 0x16, 0xd8, 0x76,
0xba, 0xa8, 0xc9, 0x11, 0xec, 0x63, 0x41, 0x73, 0xd3, 0x63, 0x53, 0xd4, 0x8c, 0xfa, 0xf6, 0x7f,
0x70, 0x91, 0x05, 0x07, 0x0d, 0xc3, 0xd4, 0x5d, 0xeb, 0xbc, 0xfb, 0xad, 0xf3, 0x3b, 0xd6, 0xfd,
0x71, 0xe0, 0xf1, 0x9d, 0x77, 0xb4, 0xaa, 0xdd, 0xd9, 0xac, 0xdd, 0xdd, 0xa4, 0xbd, 0xb7, 0x49,
0xfb, 0xde, 0xfd, 0xda, 0xff, 0xef, 0xda, 0xcf, 0x7e, 0xf5, 0x56, 0xb5, 0x5f, 0x36, 0x13, 0x82,
0x4c, 0x61, 0xb0, 0x1e, 0x5c, 0xf2, 0xca, 0x1e, 0x1f, 0x6b, 0xbc, 0xc3, 0xa7, 0x76, 0xb0, 0x81,
0xbd, 0x76, 0xc8, 0x05, 0xf4, 0x26, 0xa8, 0xc8, 0xd0, 0x0e, 0x5c, 0x44, 0x3f, 0x1c, 0x6d, 0x4b,
0x2d, 0xb9, 0x84, 0xfe, 0xb9, 0x7e, 0x6a, 0x64, 0xd7, 0x84, 0xef, 0xb0, 0xe9, 0x67, 0xe8, 0x37,
0x13, 0x86, 0x3c, 0xb3, 0x63, 0xd7, 0xe6, 0xcf, 0x6e, 0x1b, 0x36, 0x53, 0x73, 0x7b, 0xcb, 0xcf,
0xed, 0x80, 0xf5, 0xa1, 0xfb, 0x1e, 0xbe, 0x7a, 0x26, 0x3a, 0xd7, 0x7d, 0xfd, 0xf5, 0xe6, 0x5f,
0x00, 0x00, 0x00, 0xff, 0xff, 0x8f, 0xb2, 0x15, 0xd8, 0xf6, 0x05, 0x00, 0x00,
// 539 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xc1, 0x6e, 0xd3, 0x40,
0x10, 0x95, 0x93, 0x34, 0x75, 0xa6, 0x21, 0x12, 0xab, 0x22, 0x59, 0xae, 0x44, 0xa2, 0x05, 0x89,
0xaa, 0x48, 0x2e, 0x2a, 0x17, 0x38, 0x86, 0x16, 0xa5, 0x1c, 0x00, 0xc9, 0xa5, 0x17, 0x2e, 0xd1,
0xd6, 0x9e, 0xa6, 0x96, 0x6c, 0xaf, 0xd9, 0x5d, 0x83, 0xfa, 0x01, 0xfc, 0x13, 0xfc, 0x11, 0x9f,
0x81, 0xbc, 0xf6, 0x26, 0xae, 0xeb, 0x34, 0xe1, 0xc6, 0xcd, 0xb3, 0x7e, 0x6f, 0xf5, 0xde, 0xcc,
0xce, 0x03, 0x1a, 0x08, 0x0c, 0x31, 0x55, 0x11, 0x8b, 0xe5, 0x71, 0x26, 0xb8, 0xe2, 0x57, 0xf9,
0xf5, 0xb1, 0x44, 0xf1, 0x3d, 0x0a, 0xd0, 0xd3, 0x07, 0x64, 0x5f, 0x62, 0x7c, 0x9d, 0x31, 0x29,
0xbd, 0x1a, 0xd8, 0x1d, 0x2f, 0x38, 0x5f, 0xc4, 0xb8, 0x22, 0xa9, 0x28, 0x41, 0xa9, 0x58, 0x92,
0x95, 0x34, 0x7a, 0x04, 0xa3, 0x33, 0x8c, 0x51, 0xa1, 0x8f, 0x32, 0xe3, 0xa9, 0x44, 0xe2, 0xc0,
0xae, 0xcc, 0x83, 0x00, 0xa5, 0x74, 0xac, 0x89, 0x75, 0x68, 0xfb, 0xa6, 0xa4, 0x6f, 0xe0, 0xc9,
0x0c, 0xd5, 0x34, 0x8e, 0x3f, 0xa2, 0x62, 0x21, 0x53, 0xcc, 0xc7, 0x6f, 0x39, 0x4a, 0x45, 0xc6,
0xb0, 0x27, 0x79, 0x2e, 0x02, 0x9c, 0xdf, 0x70, 0xa9, 0x34, 0x6d, 0xe0, 0x43, 0x79, 0x74, 0xce,
0xa5, 0xa2, 0x07, 0x30, 0xf8, 0x10, 0x1a, 0xf4, 0x08, 0x3a, 0x51, 0x58, 0x81, 0x3a, 0x51, 0x48,
0x6f, 0xe0, 0xd1, 0x65, 0x16, 0xb2, 0x42, 0x42, 0x2b, 0x80, 0xcc, 0x00, 0x56, 0x9e, 0x9c, 0xce,
0xc4, 0x3a, 0xdc, 0x3b, 0x79, 0xe1, 0xb5, 0xf9, 0xf5, 0x4e, 0x97, 0xdf, 0xd5, 0x65, 0x7e, 0x8d,
0x4a, 0x8f, 0x60, 0x78, 0x96, 0x27, 0xd9, 0xd2, 0xaa, 0x0b, 0x76, 0xc0, 0x53, 0x85, 0xa9, 0x2a,
0xbd, 0x0e, 0xfd, 0x65, 0x4d, 0x47, 0x30, 0x7c, 0x9f, 0x64, 0xea, 0xb6, 0xba, 0x87, 0xfe, 0xb1,
0xc0, 0x36, 0xbe, 0xef, 0x29, 0x7c, 0xab, 0x15, 0x32, 0x85, 0xe1, 0x9c, 0xa9, 0x4a, 0xa1, 0xeb,
0x95, 0xbd, 0xf7, 0x4c, 0xef, 0xbd, 0x2f, 0xa6, 0xf7, 0xfe, 0xa0, 0x42, 0x4f, 0x55, 0x41, 0xcd,
0xb5, 0x7b, 0x4d, 0xed, 0x6e, 0xa6, 0x56, 0xe8, 0xa9, 0x2a, 0x26, 0x95, 0x89, 0x28, 0x61, 0xe2,
0xd6, 0xe9, 0x69, 0x29, 0xa6, 0x6c, 0x0e, 0x64, 0xa7, 0x39, 0x10, 0x72, 0x00, 0x83, 0x98, 0x2f,
0xa2, 0x74, 0x9e, 0x8b, 0xd8, 0xe9, 0xeb, 0xdf, 0xb6, 0x3e, 0xb8, 0x14, 0x31, 0xfd, 0xd5, 0x01,
0x58, 0x35, 0xf2, 0xbf, 0x37, 0xeb, 0x82, 0x9d, 0x4b, 0x14, 0x29, 0x4b, 0xb0, 0x72, 0xba, 0xac,
0xc9, 0x3e, 0xec, 0x60, 0xc2, 0x22, 0xe3, 0xb1, 0x2c, 0x0a, 0x46, 0xf1, 0x72, 0x7e, 0x70, 0x11,
0x3a, 0xbb, 0x25, 0xc3, 0xd4, 0xcd, 0xd6, 0xd9, 0x0f, 0xb7, 0x6e, 0xd0, 0x68, 0xdd, 0x6f, 0x0b,
0x1e, 0xdf, 0x7b, 0x83, 0x75, 0xed, 0xd6, 0x7a, 0xed, 0x9d, 0x75, 0xda, 0xbb, 0xeb, 0xb4, 0xf7,
0x1e, 0xd6, 0xfe, 0x6f, 0x63, 0x3f, 0xf9, 0xd9, 0xab, 0x6b, 0xbf, 0x28, 0xd3, 0x85, 0xcc, 0x61,
0x74, 0x77, 0xe9, 0xc9, 0xcb, 0xf6, 0xd5, 0x6b, 0x8d, 0x06, 0xf7, 0x69, 0x3b, 0xd8, 0xc0, 0x5e,
0x59, 0xe4, 0x1c, 0xba, 0x33, 0x54, 0x64, 0xdc, 0x0e, 0x5c, 0xc6, 0x86, 0x3b, 0xd9, 0xb4, 0xf1,
0xe4, 0x02, 0xfa, 0xa7, 0xfa, 0xa9, 0x91, 0x6d, 0xd3, 0x61, 0x8b, 0x4b, 0x3f, 0x43, 0xbf, 0x4c,
0x27, 0xf2, 0xac, 0x1d, 0x7b, 0x27, 0xbb, 0xb6, 0xbb, 0xb0, 0x4c, 0xdc, 0xcd, 0x96, 0x9f, 0xb7,
0x03, 0x1a, 0x81, 0xfd, 0x09, 0x7a, 0x45, 0xaa, 0x11, 0xda, 0x8e, 0xae, 0xa7, 0x98, 0xbb, 0x06,
0x53, 0x4f, 0xc5, 0x77, 0xf0, 0xd5, 0x36, 0xab, 0x78, 0xd5, 0xd7, 0x5f, 0xaf, 0xff, 0x06, 0x00,
0x00, 0xff, 0xff, 0x39, 0xb2, 0x93, 0x8d, 0x82, 0x06, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -515,6 +589,7 @@ type CredentialServiceClient interface {
Create(ctx context.Context, in *CredentialRequest, opts ...grpc.CallOption) (*Credential, error)
Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Credential, error)
Delete(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
Dump(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*DumpResponse, error)
}
type credentialServiceClient struct {
@ -593,6 +668,15 @@ func (c *credentialServiceClient) Delete(ctx context.Context, in *IdRequest, opt
return out, nil
}
func (c *credentialServiceClient) Dump(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*DumpResponse, error) {
out := new(DumpResponse)
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Dump", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// CredentialServiceServer is the server API for CredentialService service.
type CredentialServiceServer interface {
GetAllMetadata(*GetAllMetadataRequest, CredentialService_GetAllMetadataServer) error
@ -600,6 +684,7 @@ type CredentialServiceServer interface {
Create(context.Context, *CredentialRequest) (*Credential, error)
Update(context.Context, *UpdateRequest) (*Credential, error)
Delete(context.Context, *IdRequest) (*DeleteResponse, error)
Dump(context.Context, *EmptyRequest) (*DumpResponse, error)
}
// UnimplementedCredentialServiceServer can be embedded to have forward compatible implementations.
@ -621,6 +706,9 @@ func (*UnimplementedCredentialServiceServer) Update(ctx context.Context, req *Up
func (*UnimplementedCredentialServiceServer) Delete(ctx context.Context, req *IdRequest) (*DeleteResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
}
func (*UnimplementedCredentialServiceServer) Dump(ctx context.Context, req *EmptyRequest) (*DumpResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Dump not implemented")
}
func RegisterCredentialServiceServer(s *grpc.Server, srv CredentialServiceServer) {
s.RegisterService(&_CredentialService_serviceDesc, srv)
@ -719,6 +807,24 @@ func _CredentialService_Delete_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _CredentialService_Dump_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(EmptyRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CredentialServiceServer).Dump(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/selfpass.credentials.CredentialService/Dump",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CredentialServiceServer).Dump(ctx, req.(*EmptyRequest))
}
return interceptor(ctx, in, info, handler)
}
var _CredentialService_serviceDesc = grpc.ServiceDesc{
ServiceName: "selfpass.credentials.CredentialService",
HandlerType: (*CredentialServiceServer)(nil),
@ -739,6 +845,10 @@ var _CredentialService_serviceDesc = grpc.ServiceDesc{
MethodName: "Delete",
Handler: _CredentialService_Delete_Handler,
},
{
MethodName: "Dump",
Handler: _CredentialService_Dump_Handler,
},
},
Streams: []grpc.StreamDesc{
{

View File

@ -12,6 +12,7 @@ service CredentialService {
rpc Create (CredentialRequest) returns (Credential);
rpc Update (UpdateRequest) returns (Credential);
rpc Delete (IdRequest) returns (DeleteResponse);
rpc Dump (EmptyRequest) returns (DumpResponse);
}
message DeleteResponse {
@ -31,6 +32,13 @@ message UpdateRequest {
CredentialRequest credential = 2;
}
message DumpResponse {
bytes contents = 1;
}
message EmptyRequest {
}
message Metadata {
string id = 1;
google.protobuf.Timestamp created_at = 2;

View File

@ -9,7 +9,6 @@ import (
"github.com/mitchell/selfpass/credentials/types"
)
// NewDynamoTable TODO
func NewDynamoTable(name string) DynamoTable {
cfg, err := external.LoadDefaultAWSConfig()
if err != nil {
@ -21,22 +20,20 @@ func NewDynamoTable(name string) DynamoTable {
}
}
// DynamoTable TODO
type DynamoTable struct {
name string
svc *dynamodb.DynamoDB
}
// GetAllMetadata TODO
func (t DynamoTable) GetAllMetadata(ctx context.Context, sourceService string, errch chan<- error) (output <-chan types.Metadata) {
func (t DynamoTable) GetAllMetadata(ctx context.Context, sourceHost string, errch chan<- error) (output <-chan types.Metadata) {
mdch := make(chan types.Metadata, 1)
in := &dynamodb.ScanInput{TableName: &t.name}
if sourceService != "" {
if sourceHost != "" {
filterExpr := "SourceHost = :sh"
in.FilterExpression = &filterExpr
in.ExpressionAttributeValues = map[string]dynamodb.AttributeValue{
":sh": {S: &sourceService},
":sh": {S: &sourceHost},
}
}
@ -68,7 +65,6 @@ func (t DynamoTable) GetAllMetadata(ctx context.Context, sourceService string, e
return mdch
}
// Get TODO
func (t DynamoTable) Get(ctx context.Context, id string) (output types.Credential, err error) {
req := t.svc.GetItemRequest(&dynamodb.GetItemInput{
TableName: &t.name,
@ -86,7 +82,6 @@ func (t DynamoTable) Get(ctx context.Context, id string) (output types.Credentia
return output, err
}
// Put TODO
func (t DynamoTable) Put(ctx context.Context, c types.Credential) (err error) {
item, err := dynamodbattribute.MarshalMap(c)
if err != nil {
@ -104,7 +99,6 @@ func (t DynamoTable) Put(ctx context.Context, c types.Credential) (err error) {
return err
}
// Delete TODO
func (t DynamoTable) Delete(ctx context.Context, id string) (err error) {
req := t.svc.DeleteItemRequest(&dynamodb.DeleteItemInput{
TableName: &t.name,

View File

@ -0,0 +1,111 @@
package repositories
import (
"context"
"github.com/mediocregopher/radix/v3"
"github.com/mitchell/selfpass/credentials/types"
)
func NewRedisConn(cfg ConnConfig) (c RedisConn, err error) {
p, err := radix.NewPool(cfg.NetworkType, cfg.Address, int(cfg.Size), cfg.Options...)
return RedisConn{p: p}, err
}
type ConnConfig struct {
NetworkType string
Address string
Size uint
Options []radix.PoolOpt
}
type RedisConn struct {
p *radix.Pool
}
func (conn RedisConn) GetAllMetadata(ctx context.Context, sourceHost string, errch chan<- error) (output <-chan types.Metadata) {
mdch := make(chan types.Metadata, 1)
go func() {
defer close(mdch)
var key string
scr := radix.NewScanner(conn.p, radix.ScanOpts{Command: scan, Pattern: sourceHost + star})
for scr.Next(&key) {
select {
case <-ctx.Done():
return
default:
var md types.Metadata
if err := conn.p.Do(radix.Cmd(&md, hGetAll, key)); err != nil {
errch <- err
return
}
mdch <- md
}
}
}()
return mdch
}
func (conn RedisConn) Get(ctx context.Context, id string) (output types.Credential, err error) {
var key string
scr := radix.NewScanner(conn.p, radix.ScanOpts{Command: scan, Pattern: star + id, Count: 1})
if !scr.Next(&key) {
return output, nil
}
if err = scr.Close(); err != nil {
return output, err
}
err = conn.p.Do(radix.Cmd(&output, hGetAll, key))
return output, err
}
func (conn RedisConn) Put(ctx context.Context, c types.Credential) (err error) {
err = conn.p.Do(radix.FlatCmd(nil, hMSet, c.SourceHost+dash+c.ID, c))
return err
}
func (conn RedisConn) Delete(ctx context.Context, id string) (err error) {
var key string
scr := radix.NewScanner(conn.p, radix.ScanOpts{Command: scan, Pattern: star + id, Count: 1})
if !scr.Next(&key) {
return nil
}
if err = scr.Close(); err != nil {
return err
}
err = conn.p.Do(radix.Cmd(nil, del, key))
return err
}
func (conn RedisConn) DumpDB(ctx context.Context) (bs []byte, err error) {
bs = []byte{}
if err := conn.p.Do(radix.Cmd(&bs, "DUMP")); err != nil {
return nil, err
}
return bs, nil
}
const (
dash = "-"
star = "*"
scan = "SCAN"
hGetAll = "HGETALL"
hMSet = "HMSET"
del = "DEL"
)

View File

@ -2,45 +2,42 @@ package service
import (
"context"
"fmt"
"time"
"github.com/google/uuid"
"github.com/mitchell/selfpass/credentials/types"
)
// NewCredentials TODO
func NewCredentials(repo types.CredentialRepo) Credentials {
return Credentials{
repo: repo,
}
}
// Credentials TODO
type Credentials struct {
repo types.CredentialRepo
}
// GetAllMetadata TODO
func (svc Credentials) GetAllMetadata(ctx context.Context, sourceService string) (output <-chan types.Metadata, errch chan error) {
func (svc Credentials) GetAllMetadata(ctx context.Context, sourceHost string) (output <-chan types.Metadata, errch chan error) {
errch = make(chan error, 1)
output = svc.repo.GetAllMetadata(ctx, sourceService, errch)
output = svc.repo.GetAllMetadata(ctx, sourceHost, errch)
return output, errch
}
// Get TODO
func (svc Credentials) Get(ctx context.Context, id string) (output types.Credential, err error) {
return svc.repo.Get(nil, id)
if id == "" {
return output, fmt.Errorf("%s must specify an id", types.InvalidArgument)
}
return svc.repo.Get(ctx, id)
}
// Create TODO
func (svc Credentials) Create(ctx context.Context, ci types.CredentialInput) (output types.Credential, err error) {
if err = validateCreate(ci); err != nil {
if err = validateCredentialInput(ci); err != nil {
return output, err
}
var c types.Credential
c.ID = "cred-" + uuid.New().String()
c.CreatedAt = time.Now()
c.UpdatedAt = time.Now()
@ -56,12 +53,26 @@ func (svc Credentials) Create(ctx context.Context, ci types.CredentialInput) (ou
return c, err
}
func validateCreate(c types.CredentialInput) (err error) {
func validateCredentialInput(c types.CredentialInput) (err error) {
switch {
case c.SourceHost == "":
return fmt.Errorf("%s must specify source host", types.InvalidArgument)
case c.Password == "":
return fmt.Errorf("%s must specify password", types.InvalidArgument)
}
return err
}
// Update TODO
func (svc Credentials) Update(ctx context.Context, id string, ci types.CredentialInput) (output types.Credential, err error) {
if err = validateCredentialInput(ci); err != nil {
return output, err
}
if id == "" {
return output, fmt.Errorf("%s must specify an id", types.InvalidArgument)
}
c, err := svc.repo.Get(ctx, id)
if err != nil {
return output, err
@ -78,7 +89,13 @@ func (svc Credentials) Update(ctx context.Context, id string, ci types.Credentia
return c, svc.repo.Put(ctx, c)
}
// Delete TODO
func (svc Credentials) Delete(ctx context.Context, id string) (err error) {
return svc.repo.Delete(nil, id)
if id == "" {
return fmt.Errorf("%s must specify an id", types.InvalidArgument)
}
return svc.repo.Delete(ctx, id)
}
func (svc Credentials) DumpDB(ctx context.Context) (bs []byte, err error) {
return svc.repo.DumpDB(ctx)
}

View File

@ -16,6 +16,13 @@ func decodeGetAllMetadataRequest(ctx context.Context, request interface{}) (inte
}, nil
}
func encodeDumpResponse(ctx context.Context, response interface{}) (interface{}, error) {
r := response.(endpoints.DumpResponse)
return protobuf.DumpResponse{
Contents: r.Contents,
}, nil
}
func encodeMetadataStreamResponse(ctx context.Context, response interface{}) (interface{}, error) {
r := response.(endpoints.MetadataStream)
pbmdch := make(chan protobuf.Metadata, 1)
@ -122,6 +129,6 @@ func decodeIdRequest(ctx context.Context, request interface{}) (interface{}, err
}, nil
}
func noOpEncode(ctx context.Context, request interface{}) (interface{}, error) {
func noOp(ctx context.Context, request interface{}) (interface{}, error) {
return nil, nil
}

View File

@ -2,7 +2,6 @@ package transport
import (
"context"
"fmt"
"strings"
"github.com/go-kit/kit/log"
@ -15,7 +14,6 @@ import (
"github.com/mitchell/selfpass/credentials/types"
)
// NewGRPCServer TODO
func NewGRPCServer(svc types.Service, logger log.Logger) GRPCServer {
return GRPCServer{
getAllMetadata: grpc.NewServer(
@ -24,6 +22,12 @@ func NewGRPCServer(svc types.Service, logger log.Logger) GRPCServer {
encodeMetadataStreamResponse,
grpc.ServerErrorLogger(logger),
),
get: grpc.NewServer(
endpoints.MakeGetEndpoint(svc),
decodeIdRequest,
encodeCredentialResponse,
grpc.ServerErrorLogger(logger),
),
create: grpc.NewServer(
endpoints.MakeCreateEndpoint(svc),
decodeCredentialRequest,
@ -39,25 +43,29 @@ func NewGRPCServer(svc types.Service, logger log.Logger) GRPCServer {
delete: grpc.NewServer(
endpoints.MakeDeleteEndpoint(svc),
decodeIdRequest,
noOpEncode,
noOp,
grpc.ServerErrorLogger(logger),
),
dump: grpc.NewServer(
endpoints.MakeDumpEndpoint(svc),
noOp,
encodeDumpResponse,
grpc.ServerErrorLogger(logger),
),
}
}
// GRPCServer TODO
type GRPCServer struct {
getAllMetadata *grpc.Server
get *grpc.Server
create *grpc.Server
update *grpc.Server
delete *grpc.Server
dump *grpc.Server
}
// GetAllMetadata TODO
func (s GRPCServer) GetAllMetadata(r *protobuf.GetAllMetadataRequest, srv protobuf.CredentialService_GetAllMetadataServer) (err error) {
defer func() {
err = handlerGRPCError(err)
}()
defer func() { err = handlerGRPCError(err) }()
var i interface{}
ctx := srv.Context()
@ -80,7 +88,6 @@ receiveLoop:
if !ok {
break receiveLoop
}
fmt.Println(md)
if err = srv.Send(&md); err != nil {
break receiveLoop
}
@ -90,14 +97,20 @@ receiveLoop:
return err
}
// Get TODO
func (s GRPCServer) Get(context.Context, *protobuf.IdRequest) (*protobuf.Credential, error) {
panic("implement me")
}
// Create TODO
func (s GRPCServer) Create(ctx context.Context, ci *protobuf.CredentialRequest) (*protobuf.Credential, error) {
ctx, i, err := s.create.ServeGRPC(ctx, *ci)
func (s GRPCServer) Get(ctx context.Context, r *protobuf.IdRequest) (*protobuf.Credential, error) {
ctx, i, err := s.get.ServeGRPC(ctx, *r)
if err != nil {
err = handlerGRPCError(err)
return nil, err
}
c := &protobuf.Credential{}
*c = i.(protobuf.Credential)
return c, nil
}
func (s GRPCServer) Create(ctx context.Context, r *protobuf.CredentialRequest) (*protobuf.Credential, error) {
ctx, i, err := s.create.ServeGRPC(ctx, *r)
if err != nil {
err = handlerGRPCError(err)
return nil, err
@ -108,7 +121,6 @@ func (s GRPCServer) Create(ctx context.Context, ci *protobuf.CredentialRequest)
return c, nil
}
// Update TODO
func (s GRPCServer) Update(ctx context.Context, r *protobuf.UpdateRequest) (*protobuf.Credential, error) {
ctx, i, err := s.update.ServeGRPC(ctx, *r)
if err != nil {
@ -121,16 +133,28 @@ func (s GRPCServer) Update(ctx context.Context, r *protobuf.UpdateRequest) (*pro
return c, nil
}
// Delete TODO
func (s GRPCServer) Delete(ctx context.Context, r *protobuf.IdRequest) (*protobuf.DeleteResponse, error) {
ctx, _, err := s.delete.ServeGRPC(ctx, *r)
if err != nil {
err = handlerGRPCError(err)
return nil, err
}
return &protobuf.DeleteResponse{Success: true}, nil
}
func (s GRPCServer) Dump(ctx context.Context, r *protobuf.EmptyRequest) (*protobuf.DumpResponse, error) {
ctx, i, err := s.dump.ServeGRPC(ctx, *r)
if err != nil {
err = handlerGRPCError(err)
return nil, err
}
res := &protobuf.DumpResponse{}
*res = i.(protobuf.DumpResponse)
return res, nil
}
func handlerGRPCError(err error) error {
if err != nil {
switch {

View File

@ -1,8 +1,9 @@
package types
import "time"
import (
"time"
)
// Credential TODO
type Credential struct {
Metadata
Username string
@ -10,7 +11,6 @@ type Credential struct {
Password string
}
// CredentialInput TODO
type CredentialInput struct {
MetadataInput
Username string
@ -18,17 +18,15 @@ type CredentialInput struct {
Password string
}
// Metadata TODO
type Metadata struct {
ID string
ID string // primary key
SourceHost string // sort key
CreatedAt time.Time
UpdatedAt time.Time
Primary string
SourceHost string
LoginURL string
}
// MetadataInput TODO
type MetadataInput struct {
Primary string
SourceHost string

View File

@ -2,19 +2,19 @@ package types
import "context"
// Service TODO
type Service interface {
GetAllMetadata(ctx context.Context, sourceService string) (output <-chan Metadata, errch chan error)
GetAllMetadata(ctx context.Context, sourceHost string) (output <-chan Metadata, errch chan error)
Get(ctx context.Context, id string) (output Credential, err error)
Create(ctx context.Context, ci CredentialInput) (output Credential, err error)
Update(ctx context.Context, id string, ci CredentialInput) (output Credential, err error)
Delete(ctx context.Context, id string) (err error)
DumpDB(ctx context.Context) (bs []byte, err error)
}
// CredentialRepo TODO
type CredentialRepo interface {
GetAllMetadata(ctx context.Context, sourceService string, errch chan<- error) (output <-chan Metadata)
GetAllMetadata(ctx context.Context, sourceHost string, errch chan<- error) (output <-chan Metadata)
Get(ctx context.Context, id string) (output Credential, err error)
Put(ctx context.Context, c Credential) (err error)
Delete(ctx context.Context, id string) (err error)
DumpDB(ctx context.Context) (bs []byte, err error)
}

36
dual-entry Executable file
View File

@ -0,0 +1,36 @@
#!/bin/bash
# Start the first process
redis-server ./redis.conf &
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start my_first_process: $status"
exit $status
fi
# Start the second process
./server --dev -v &
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start my_second_process: $status"
exit $status
fi
# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container exits with an error
# if it detects that either of the processes has exited.
# Otherwise it loops forever, waking up every 60 seconds
while sleep 60; do
ps aux |grep my_first_process |grep -q -v grep
PROCESS_1_STATUS=$?
ps aux |grep my_second_process |grep -q -v grep
PROCESS_2_STATUS=$?
# If the greps above find anything, they exit with 0 status
# If they are not both 0, then something is wrong
if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
echo "One of the processes has already exited."
exit 1
fi
done

3
go.mod
View File

@ -7,8 +7,9 @@ require (
github.com/go-stack/stack v1.8.0 // indirect
github.com/golang/protobuf v1.3.1
github.com/google/uuid v1.1.1
github.com/mediocregopher/radix/v3 v3.2.3
github.com/stretchr/testify v1.3.0 // indirect
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect
golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect
golang.org/x/sys v0.0.0-20190416152802-12500544f89f // indirect
google.golang.org/grpc v1.20.0
)

9
go.sum
View File

@ -30,6 +30,10 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed h1:3dQJqqDouawQgl3gBE1PNHKFkJYGEuFb1DbSlaxdosE=
github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg=
github.com/mediocregopher/radix/v3 v3.2.3 h1:TbcGCZdo9zfPYPgevsqRn+OjvCyfOK6TzuXhqzWdCt0=
github.com/mediocregopher/radix/v3 v3.2.3/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -38,6 +42,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -50,8 +55,8 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190416152802-12500544f89f h1:1ZH9RnjNgLzh6YrsRp/c6ddZ8Lq0fq9xztNOoWJ2sz4=
golang.org/x/sys v0.0.0-20190416152802-12500544f89f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=

6
grpcurl.sh Normal file
View File

@ -0,0 +1,6 @@
grpcurl -cacert ./certs/ca.pem \
-cert ./certs/client.pem \
-key ./certs/client-key.pem \
-proto ./credentials/protobuf/service.proto \
localhost:8080 \
selfpass.credentials.CredentialService/Dump

1317
redis.conf Normal file

File diff suppressed because it is too large Load Diff