Move service related filed to services folder

This commit is contained in:
mitchell 2019-07-10 22:33:22 -04:00
parent 347fbe7268
commit 7d770ef150
41 changed files with 50 additions and 50 deletions

View file

@ -0,0 +1,100 @@
package commands
import (
"context"
"fmt"
"os"
"sort"
"time"
"gopkg.in/AlecAivazis/survey.v1"
"github.com/mitchell/selfpass/services/credentials/types"
)
type CredentialClientInit func(ctx context.Context) (c types.CredentialClient)
func check(err error) {
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func selectCredential(client types.CredentialClient) types.Credential {
var (
idKey string
source string
prompt survey.Prompt
)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
mdch, errch := client.GetAllMetadata(ctx, "")
mds := map[string][]types.Metadata{}
fmt.Println()
receive:
for {
select {
case <-ctx.Done():
check(ctx.Err())
case err := <-errch:
check(err)
case md, ok := <-mdch:
if !ok {
break receive
}
mds[md.SourceHost] = append(mds[md.SourceHost], md)
}
}
sources := []string{}
for source := range mds {
sources = append(sources, source)
}
sort.Strings(sources)
prompt = &survey.Select{
Message: "Source host:",
Options: sources,
PageSize: 20,
VimMode: true,
}
check(survey.AskOne(prompt, &source, nil))
keys := []string{}
keyIDMap := map[string]string{}
for _, md := range mds[source] {
key := md.Primary
if md.Tag != "" {
key += "-" + md.Tag
}
keys = append(keys, key)
keyIDMap[key] = md.ID
}
prompt = &survey.Select{
Message: "Primary user key (and tag):",
Options: keys,
PageSize: 20,
VimMode: true,
}
check(survey.AskOne(prompt, &idKey, nil))
ctx, cancel = context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
cred, err := client.Get(ctx, keyIDMap[idKey])
check(err)
return cred
}

View file

@ -0,0 +1,155 @@
package commands
import (
"context"
"encoding/base64"
"fmt"
"os"
"time"
"github.com/atotto/clipboard"
"github.com/pquerna/otp/totp"
"github.com/spf13/cobra"
"gopkg.in/AlecAivazis/survey.v1"
clitypes "github.com/mitchell/selfpass/services/cli/types"
"github.com/mitchell/selfpass/services/credentials/types"
"github.com/mitchell/selfpass/services/crypto"
)
func MakeCreate(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
var length uint
var numbers bool
var specials bool
createCmd := &cobra.Command{
Use: "create",
Short: "Create a credential in Selfpass",
Long: `Create a credential in Selfpass, and save it to the server after encrypting the
password.`,
Run: func(_ *cobra.Command, args []string) {
var (
otp bool
cleancb bool
newpass bool
ci types.CredentialInput
)
masterpass, cfg, err := repo.OpenConfig()
check(err)
mdqs := []*survey.Question{
{
Name: "primary",
Prompt: &survey.Input{Message: "Primary user key:"},
},
{
Name: "sourceHost",
Prompt: &survey.Input{Message: "Source host:"},
},
{
Name: "loginURL",
Prompt: &survey.Input{Message: "Login url:"},
},
{
Name: "tag",
Prompt: &survey.Input{Message: "Tag:"},
},
}
cqs := []*survey.Question{
{
Name: "username",
Prompt: &survey.Input{Message: "Username:"},
},
{
Name: "email",
Prompt: &survey.Input{Message: "Email:"},
},
}
check(survey.Ask(mdqs, &ci.MetadataInput))
check(survey.Ask(cqs, &ci))
key := cfg.GetString(clitypes.KeyPrivateKey)
keypass := crypto.GeneratePBKDF2Key([]byte(masterpass), []byte(key))
prompt := &survey.Confirm{Message: "Do you want a random password?", Default: true}
check(survey.AskOne(prompt, &newpass, nil))
if newpass {
ci.Password = crypto.GeneratePassword(int(length), numbers, specials)
var copypass bool
prompt = &survey.Confirm{Message: "Copy new pass to clipboard?", Default: true}
check(survey.AskOne(prompt, &copypass, nil))
if copypass {
check(clipboard.WriteAll(ci.Password))
}
} else {
prompt := &survey.Password{Message: "Password: "}
check(survey.AskOne(prompt, &ci.Password, nil))
var cpass string
prompt = &survey.Password{Message: "Confirm password: "}
check(survey.AskOne(prompt, &cpass, nil))
if ci.Password != cpass {
fmt.Println("passwords didn't match")
os.Exit(1)
}
}
cipherpass, err := crypto.CBCEncrypt(keypass, []byte(ci.Password))
check(err)
ci.Password = base64.StdEncoding.EncodeToString(cipherpass)
prompt = &survey.Confirm{Message: "Do you have an OTP/MFA secret?", Default: true}
check(survey.AskOne(prompt, &otp, nil))
if otp {
var secret string
prompt := &survey.Password{Message: "OTP secret:"}
check(survey.AskOne(prompt, &secret, nil))
ciphersecret, err := crypto.CBCEncrypt(keypass, []byte(secret))
check(err)
ci.OTPSecret = base64.StdEncoding.EncodeToString(ciphersecret)
var copyotp bool
prompt2 := &survey.Confirm{Message: "Copy new OTP to clipboard?", Default: true}
check(survey.AskOne(prompt2, &copyotp, nil))
if copyotp {
otp, err := totp.GenerateCode(secret, time.Now())
check(err)
check(clipboard.WriteAll(otp))
}
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*25)
defer cancel()
c, err := initClient(ctx).Create(ctx, ci)
check(err)
fmt.Println(c)
prompt = &survey.Confirm{Message: "Do you want to clear the clipboard?", Default: true}
check(survey.AskOne(prompt, &cleancb, nil))
if cleancb {
check(clipboard.WriteAll(" "))
}
},
}
createCmd.Flags().BoolVarP(&numbers, "numbers", "n", true, "use numbers in the generated password")
createCmd.Flags().BoolVarP(&specials, "specials", "s", false, "use special characters in the generated password")
createCmd.Flags().UintVarP(&length, "length", "l", 32, "length of the generated password")
return createCmd
}

View file

@ -0,0 +1,42 @@
package commands
import (
"context"
"fmt"
"time"
"github.com/spf13/cobra"
"gopkg.in/AlecAivazis/survey.v1"
)
func MakeDelete(initClient CredentialClientInit) *cobra.Command {
deleteCmd := &cobra.Command{
Use: "delete",
Short: "Delete a credential using the given ID",
Long: `Delete a credential using the given ID, permanently. THERE IS NO UNDOING THIS ACTION.`,
Run: func(cmd *cobra.Command, args []string) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
defer cancel()
client := initClient(ctx)
cred := selectCredential(client)
fmt.Println(cred)
var confirmed bool
prompt := &survey.Confirm{Message: "Are you sure you want to permanently delete this credential?"}
check(survey.AskOne(prompt, &confirmed, nil))
if confirmed {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*25)
defer cancel()
check(initClient(ctx).Delete(ctx, cred.ID))
}
},
}
return deleteCmd
}

View file

@ -0,0 +1,108 @@
package commands
import (
"context"
"encoding/base64"
"encoding/hex"
"fmt"
"time"
clitypes "github.com/mitchell/selfpass/services/cli/types"
"github.com/mitchell/selfpass/services/credentials/types"
"github.com/mitchell/selfpass/services/crypto"
"github.com/spf13/cobra"
)
func MakeGCMToCBC(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
gcmToCBC := &cobra.Command{
Use: "gcm-to-cbc",
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
masterpass, cfg, err := repo.OpenConfig()
check(err)
privKey := cfg.GetString(clitypes.KeyPrivateKey)
fmt.Println(privKey)
oldHex, err := hex.DecodeString(privKey)
check(err)
oldKey, err := crypto.CombinePasswordAndKey([]byte(masterpass), oldHex)
check(err)
key := crypto.GeneratePBKDF2Key([]byte(masterpass), []byte(privKey))
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()
client := initClient(ctx)
mdch, errch := client.GetAllMetadata(ctx, "")
receive:
for {
select {
case <-ctx.Done():
check(ctx.Err())
case err := <-errch:
check(err)
case md, ok := <-mdch:
if !ok {
break receive
}
cred, err := client.Get(ctx, md.ID)
check(err)
cipherpass, err := base64.StdEncoding.DecodeString(cred.Password)
check(err)
plainpass, err := crypto.GCMDecrypt(oldKey, cipherpass)
check(err)
cipherpass, err = crypto.CBCEncrypt(key, plainpass)
check(err)
password := base64.StdEncoding.EncodeToString(cipherpass)
var otpSecret string
if cred.OTPSecret != "" {
ciphersecret, err := base64.StdEncoding.DecodeString(cred.OTPSecret)
check(err)
plainsecret, err := crypto.GCMDecrypt(oldKey, ciphersecret)
check(err)
ciphersecret, err = crypto.CBCEncrypt(key, plainsecret)
check(err)
otpSecret = base64.StdEncoding.EncodeToString(ciphersecret)
}
credIn := types.CredentialInput{
MetadataInput: types.MetadataInput{
Primary: cred.Primary,
SourceHost: cred.SourceHost,
LoginURL: cred.LoginURL,
Tag: cred.Tag,
},
Username: cred.Username,
Email: cred.Email,
Password: password,
OTPSecret: otpSecret,
}
_, err = client.Update(ctx, cred.ID, credIn)
check(err)
}
}
},
}
return gcmToCBC
}

View file

@ -0,0 +1,94 @@
package commands
import (
"context"
"encoding/base64"
"fmt"
"time"
"github.com/atotto/clipboard"
"github.com/pquerna/otp/totp"
"github.com/spf13/cobra"
"gopkg.in/AlecAivazis/survey.v1"
clitypes "github.com/mitchell/selfpass/services/cli/types"
"github.com/mitchell/selfpass/services/crypto"
)
func MakeGet(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
getCmd := &cobra.Command{
Use: "get",
Short: "Get a credential info and copy password to clipboard",
Long: `Get a credential's info and copy password to clipboard, from Selfpass server, after
decrypting password.`,
Run: func(cmd *cobra.Command, args []string) {
var (
copyPass bool
cleancb bool
prompt survey.Prompt
)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
defer cancel()
client := initClient(ctx)
masterpass, cfg, err := repo.OpenConfig()
check(err)
cred := selectCredential(client)
fmt.Println(cred)
check(clipboard.WriteAll(string(cred.Primary)))
fmt.Println("Wrote primary user key to clipboard.")
key := cfg.GetString(clitypes.KeyPrivateKey)
passkey := crypto.GeneratePBKDF2Key([]byte(masterpass), []byte(key))
prompt = &survey.Confirm{Message: "Copy password to clipboard?", Default: true}
check(survey.AskOne(prompt, &copyPass, nil))
if copyPass {
passbytes, err := base64.StdEncoding.DecodeString(cred.Password)
check(err)
plainpass, err := crypto.CBCDecrypt(passkey, passbytes)
check(clipboard.WriteAll(string(plainpass)))
fmt.Println("Wrote password to clipboard.")
}
if cred.OTPSecret != "" {
var newOTP bool
prompt = &survey.Confirm{Message: "Generate one time password and copy to clipboard?", Default: true}
check(survey.AskOne(prompt, &newOTP, nil))
if newOTP {
secretbytes, err := base64.StdEncoding.DecodeString(cred.OTPSecret)
check(err)
plainsecret, err := crypto.CBCDecrypt(passkey, secretbytes)
otp, err := totp.GenerateCode(string(plainsecret), time.Now())
check(err)
check(clipboard.WriteAll(otp))
fmt.Println("Wrote one time password to clipboard.")
}
}
prompt = &survey.Confirm{Message: "Do you want to clear the clipboard?", Default: true}
check(survey.AskOne(prompt, &cleancb, nil))
if cleancb {
check(clipboard.WriteAll(" "))
}
},
}
return getCmd
}

View file

@ -0,0 +1,77 @@
package commands
import (
"context"
"fmt"
"sort"
"time"
"github.com/spf13/cobra"
"gopkg.in/AlecAivazis/survey.v1"
"github.com/mitchell/selfpass/services/credentials/types"
)
func MakeList(initClient CredentialClientInit) *cobra.Command {
var sourceHost string
listCmd := &cobra.Command{
Use: "list",
Short: "List the metadata for all credentials",
Long: `List the metadata for all credentials, with the option to filter by source host. Metadata
includes almost all the information but the most sensitive.`,
Run: func(cmd *cobra.Command, args []string) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
mdch, errch := initClient(ctx).GetAllMetadata(ctx, sourceHost)
mds := map[string][]types.Metadata{}
fmt.Println()
receive:
for {
select {
case <-ctx.Done():
check(ctx.Err())
case err := <-errch:
check(err)
case md, ok := <-mdch:
if !ok {
break receive
}
mds[md.SourceHost] = append(mds[md.SourceHost], md)
}
}
sources := []string{}
for source := range mds {
sources = append(sources, source)
}
sort.Strings(sources)
prompt := &survey.Select{
Message: "Source host:",
Options: sources,
PageSize: 20,
VimMode: true,
}
var source string
check(survey.AskOne(prompt, &source, nil))
for _, md := range mds[source] {
fmt.Println(md)
}
fmt.Println("Done listing.")
},
}
return listCmd
}

View file

@ -0,0 +1,190 @@
package commands
import (
"context"
"encoding/base64"
"fmt"
"os"
"time"
"github.com/atotto/clipboard"
"github.com/pquerna/otp/totp"
"github.com/spf13/cobra"
"gopkg.in/AlecAivazis/survey.v1"
clitypes "github.com/mitchell/selfpass/services/cli/types"
"github.com/mitchell/selfpass/services/credentials/types"
"github.com/mitchell/selfpass/services/crypto"
)
func MakeUpdate(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
var length uint
var numbers bool
var specials bool
updateCmd := &cobra.Command{
Use: "update",
Short: "Update a credential in Selfpass",
Long: `Update a credential in Selfpass, and save it to the server after encrypting the
password.`,
Run: func(_ *cobra.Command, args []string) {
var (
newpass bool
otp bool
cleancb bool
prompt survey.Prompt
ci types.CredentialInput
)
masterpass, cfg, err := repo.OpenConfig()
check(err)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
defer cancel()
client := initClient(ctx)
cred := selectCredential(client)
mdqs := []*survey.Question{
{
Name: "primary",
Prompt: &survey.Input{
Message: "Primary user key:",
Default: cred.Primary,
},
},
{
Name: "sourceHost",
Prompt: &survey.Input{
Message: "Source host:",
Default: cred.SourceHost,
},
},
{
Name: "loginURL",
Prompt: &survey.Input{
Message: "Login url:",
Default: cred.LoginURL,
},
},
{
Name: "tag",
Prompt: &survey.Input{
Message: "Tag:",
Default: cred.Tag,
},
},
}
cqs := []*survey.Question{
{
Name: "username",
Prompt: &survey.Input{
Message: "Username:",
Default: cred.Username,
},
},
{
Name: "email",
Prompt: &survey.Input{
Message: "Email:",
Default: cred.Email,
},
},
}
check(survey.Ask(mdqs, &ci.MetadataInput))
check(survey.Ask(cqs, &ci))
ci.Password = cred.Password
ci.OTPSecret = cred.OTPSecret
key := cfg.GetString(clitypes.KeyPrivateKey)
keypass := crypto.GeneratePBKDF2Key([]byte(masterpass), []byte(key))
prompt = &survey.Confirm{Message: "Do you want a new password?", Default: true}
check(survey.AskOne(prompt, &newpass, nil))
if newpass {
var randpass bool
prompt = &survey.Confirm{Message: "Do you want a random password?", Default: true}
check(survey.AskOne(prompt, &randpass, nil))
if randpass {
ci.Password = crypto.GeneratePassword(int(length), numbers, specials)
var copypass bool
prompt = &survey.Confirm{Message: "Copy new pass to clipboard?", Default: true}
check(survey.AskOne(prompt, &copypass, nil))
if copypass {
check(clipboard.WriteAll(ci.Password))
}
} else {
prompt := &survey.Password{Message: "Password: "}
check(survey.AskOne(prompt, &ci.Password, nil))
var cpass string
prompt = &survey.Password{Message: "Confirm password: "}
check(survey.AskOne(prompt, &cpass, nil))
if ci.Password != cpass {
fmt.Println("passwords didn't match")
os.Exit(1)
}
}
cipherpass, err := crypto.CBCEncrypt(keypass, []byte(ci.Password))
check(err)
ci.Password = base64.StdEncoding.EncodeToString(cipherpass)
}
prompt = &survey.Confirm{Message: "Do you want to set a new OTP/MFA secret?", Default: true}
check(survey.AskOne(prompt, &otp, nil))
if otp {
var secret string
prompt := &survey.Password{Message: "OTP secret:"}
check(survey.AskOne(prompt, &secret, nil))
ciphersecret, err := crypto.CBCEncrypt(keypass, []byte(secret))
check(err)
ci.OTPSecret = base64.StdEncoding.EncodeToString(ciphersecret)
var copyotp bool
prompt2 := &survey.Confirm{Message: "Copy new OTP to clipboard?", Default: true}
check(survey.AskOne(prompt2, &copyotp, nil))
if copyotp {
otp, err := totp.GenerateCode(secret, time.Now())
check(err)
check(clipboard.WriteAll(otp))
}
}
ctx, cancel = context.WithTimeout(context.Background(), time.Second*25)
defer cancel()
c, err := initClient(ctx).Update(ctx, cred.ID, ci)
check(err)
fmt.Println(c)
prompt = &survey.Confirm{Message: "Do you want to clear the clipboard?", Default: true}
check(survey.AskOne(prompt, &cleancb, nil))
if cleancb {
check(clipboard.WriteAll(" "))
}
},
}
updateCmd.Flags().BoolVarP(&numbers, "numbers", "n", true, "use numbers in the generated password")
updateCmd.Flags().BoolVarP(&specials, "specials", "s", false, "use special characters in the generated password")
updateCmd.Flags().UintVarP(&length, "length", "l", 32, "length of the generated password")
return updateCmd
}

View file

@ -0,0 +1,78 @@
package endpoints
import (
"context"
"github.com/go-kit/kit/endpoint"
"github.com/mitchell/selfpass/services/credentials/types"
)
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)
mdch, errch := svc.GetAllMetadata(ctx, r.SourceHost)
return MetadataStream{
Metadata: mdch,
Errors: errch,
}, nil
}
}
func MakeUpdateEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(UpdateRequest)
return svc.Update(ctx, r.ID, r.Credential)
}
}
func MakeDumpEndpoint(svc types.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
contents, err := svc.DumpDB(ctx)
return DumpResponse{Contents: contents}, err
}
}
type DumpResponse struct {
Contents []byte
}
type IDRequest struct {
ID string
}
type GetAllMetadataRequest struct {
SourceHost string
}
type MetadataStream struct {
Metadata <-chan types.Metadata
Errors chan error
}
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/services/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

@ -0,0 +1,867 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: credentials/protobuf/service.proto
package protobuf
import (
context "context"
fmt "fmt"
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.
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.ProtoPackageIsVersion3 // please upgrade the proto package
type DeleteResponse struct {
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DeleteResponse) Reset() { *m = DeleteResponse{} }
func (m *DeleteResponse) String() string { return proto.CompactTextString(m) }
func (*DeleteResponse) ProtoMessage() {}
func (*DeleteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{0}
}
func (m *DeleteResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DeleteResponse.Unmarshal(m, b)
}
func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DeleteResponse.Marshal(b, m, deterministic)
}
func (m *DeleteResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_DeleteResponse.Merge(m, src)
}
func (m *DeleteResponse) XXX_Size() int {
return xxx_messageInfo_DeleteResponse.Size(m)
}
func (m *DeleteResponse) XXX_DiscardUnknown() {
xxx_messageInfo_DeleteResponse.DiscardUnknown(m)
}
var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo
func (m *DeleteResponse) GetSuccess() bool {
if m != nil {
return m.Success
}
return false
}
type GetAllMetadataRequest struct {
SourceHost string `protobuf:"bytes,1,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetAllMetadataRequest) Reset() { *m = GetAllMetadataRequest{} }
func (m *GetAllMetadataRequest) String() string { return proto.CompactTextString(m) }
func (*GetAllMetadataRequest) ProtoMessage() {}
func (*GetAllMetadataRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{1}
}
func (m *GetAllMetadataRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetAllMetadataRequest.Unmarshal(m, b)
}
func (m *GetAllMetadataRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetAllMetadataRequest.Marshal(b, m, deterministic)
}
func (m *GetAllMetadataRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetAllMetadataRequest.Merge(m, src)
}
func (m *GetAllMetadataRequest) XXX_Size() int {
return xxx_messageInfo_GetAllMetadataRequest.Size(m)
}
func (m *GetAllMetadataRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetAllMetadataRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetAllMetadataRequest proto.InternalMessageInfo
func (m *GetAllMetadataRequest) GetSourceHost() string {
if m != nil {
return m.SourceHost
}
return ""
}
type IdRequest struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *IdRequest) Reset() { *m = IdRequest{} }
func (m *IdRequest) String() string { return proto.CompactTextString(m) }
func (*IdRequest) ProtoMessage() {}
func (*IdRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{2}
}
func (m *IdRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_IdRequest.Unmarshal(m, b)
}
func (m *IdRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_IdRequest.Marshal(b, m, deterministic)
}
func (m *IdRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_IdRequest.Merge(m, src)
}
func (m *IdRequest) XXX_Size() int {
return xxx_messageInfo_IdRequest.Size(m)
}
func (m *IdRequest) XXX_DiscardUnknown() {
xxx_messageInfo_IdRequest.DiscardUnknown(m)
}
var xxx_messageInfo_IdRequest proto.InternalMessageInfo
func (m *IdRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
type UpdateRequest struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Credential *CredentialRequest `protobuf:"bytes,2,opt,name=credential,proto3" json:"credential,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *UpdateRequest) Reset() { *m = UpdateRequest{} }
func (m *UpdateRequest) String() string { return proto.CompactTextString(m) }
func (*UpdateRequest) ProtoMessage() {}
func (*UpdateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ad34efc7bbd96e69, []int{3}
}
func (m *UpdateRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UpdateRequest.Unmarshal(m, b)
}
func (m *UpdateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_UpdateRequest.Marshal(b, m, deterministic)
}
func (m *UpdateRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_UpdateRequest.Merge(m, src)
}
func (m *UpdateRequest) XXX_Size() int {
return xxx_messageInfo_UpdateRequest.Size(m)
}
func (m *UpdateRequest) XXX_DiscardUnknown() {
xxx_messageInfo_UpdateRequest.DiscardUnknown(m)
}
var xxx_messageInfo_UpdateRequest proto.InternalMessageInfo
func (m *UpdateRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *UpdateRequest) GetCredential() *CredentialRequest {
if m != nil {
return m.Credential
}
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"`
UpdatedAt *timestamp.Timestamp `protobuf:"bytes,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
Primary string `protobuf:"bytes,4,opt,name=primary,proto3" json:"primary,omitempty"`
SourceHost string `protobuf:"bytes,5,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
LoginUrl string `protobuf:"bytes,6,opt,name=login_url,json=loginUrl,proto3" json:"login_url,omitempty"`
Tag string `protobuf:"bytes,7,opt,name=tag,proto3" json:"tag,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
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{6}
}
func (m *Metadata) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Metadata.Unmarshal(m, b)
}
func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Metadata.Marshal(b, m, deterministic)
}
func (m *Metadata) XXX_Merge(src proto.Message) {
xxx_messageInfo_Metadata.Merge(m, src)
}
func (m *Metadata) XXX_Size() int {
return xxx_messageInfo_Metadata.Size(m)
}
func (m *Metadata) XXX_DiscardUnknown() {
xxx_messageInfo_Metadata.DiscardUnknown(m)
}
var xxx_messageInfo_Metadata proto.InternalMessageInfo
func (m *Metadata) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *Metadata) GetCreatedAt() *timestamp.Timestamp {
if m != nil {
return m.CreatedAt
}
return nil
}
func (m *Metadata) GetUpdatedAt() *timestamp.Timestamp {
if m != nil {
return m.UpdatedAt
}
return nil
}
func (m *Metadata) GetPrimary() string {
if m != nil {
return m.Primary
}
return ""
}
func (m *Metadata) GetSourceHost() string {
if m != nil {
return m.SourceHost
}
return ""
}
func (m *Metadata) GetLoginUrl() string {
if m != nil {
return m.LoginUrl
}
return ""
}
func (m *Metadata) GetTag() string {
if m != nil {
return m.Tag
}
return ""
}
type Credential 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"`
UpdatedAt *timestamp.Timestamp `protobuf:"bytes,3,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
Primary string `protobuf:"bytes,4,opt,name=primary,proto3" json:"primary,omitempty"`
Username string `protobuf:"bytes,5,opt,name=username,proto3" json:"username,omitempty"`
Email string `protobuf:"bytes,6,opt,name=email,proto3" json:"email,omitempty"`
Password string `protobuf:"bytes,7,opt,name=password,proto3" json:"password,omitempty"`
SourceHost string `protobuf:"bytes,8,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
LoginUrl string `protobuf:"bytes,9,opt,name=login_url,json=loginUrl,proto3" json:"login_url,omitempty"`
Tag string `protobuf:"bytes,10,opt,name=tag,proto3" json:"tag,omitempty"`
OtpSecret string `protobuf:"bytes,11,opt,name=otp_secret,json=otpSecret,proto3" json:"otp_secret,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
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{7}
}
func (m *Credential) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Credential.Unmarshal(m, b)
}
func (m *Credential) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Credential.Marshal(b, m, deterministic)
}
func (m *Credential) XXX_Merge(src proto.Message) {
xxx_messageInfo_Credential.Merge(m, src)
}
func (m *Credential) XXX_Size() int {
return xxx_messageInfo_Credential.Size(m)
}
func (m *Credential) XXX_DiscardUnknown() {
xxx_messageInfo_Credential.DiscardUnknown(m)
}
var xxx_messageInfo_Credential proto.InternalMessageInfo
func (m *Credential) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *Credential) GetCreatedAt() *timestamp.Timestamp {
if m != nil {
return m.CreatedAt
}
return nil
}
func (m *Credential) GetUpdatedAt() *timestamp.Timestamp {
if m != nil {
return m.UpdatedAt
}
return nil
}
func (m *Credential) GetPrimary() string {
if m != nil {
return m.Primary
}
return ""
}
func (m *Credential) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *Credential) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *Credential) GetPassword() string {
if m != nil {
return m.Password
}
return ""
}
func (m *Credential) GetSourceHost() string {
if m != nil {
return m.SourceHost
}
return ""
}
func (m *Credential) GetLoginUrl() string {
if m != nil {
return m.LoginUrl
}
return ""
}
func (m *Credential) GetTag() string {
if m != nil {
return m.Tag
}
return ""
}
func (m *Credential) GetOtpSecret() string {
if m != nil {
return m.OtpSecret
}
return ""
}
type CredentialRequest struct {
Primary string `protobuf:"bytes,1,opt,name=primary,proto3" json:"primary,omitempty"`
Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
SourceHost string `protobuf:"bytes,5,opt,name=source_host,json=sourceHost,proto3" json:"source_host,omitempty"`
LoginUrl string `protobuf:"bytes,6,opt,name=login_url,json=loginUrl,proto3" json:"login_url,omitempty"`
Tag string `protobuf:"bytes,7,opt,name=tag,proto3" json:"tag,omitempty"`
OtpSecret string `protobuf:"bytes,8,opt,name=otp_secret,json=otpSecret,proto3" json:"otp_secret,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
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{8}
}
func (m *CredentialRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CredentialRequest.Unmarshal(m, b)
}
func (m *CredentialRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CredentialRequest.Marshal(b, m, deterministic)
}
func (m *CredentialRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CredentialRequest.Merge(m, src)
}
func (m *CredentialRequest) XXX_Size() int {
return xxx_messageInfo_CredentialRequest.Size(m)
}
func (m *CredentialRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CredentialRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CredentialRequest proto.InternalMessageInfo
func (m *CredentialRequest) GetPrimary() string {
if m != nil {
return m.Primary
}
return ""
}
func (m *CredentialRequest) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *CredentialRequest) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *CredentialRequest) GetPassword() string {
if m != nil {
return m.Password
}
return ""
}
func (m *CredentialRequest) GetSourceHost() string {
if m != nil {
return m.SourceHost
}
return ""
}
func (m *CredentialRequest) GetLoginUrl() string {
if m != nil {
return m.LoginUrl
}
return ""
}
func (m *CredentialRequest) GetTag() string {
if m != nil {
return m.Tag
}
return ""
}
func (m *CredentialRequest) GetOtpSecret() string {
if m != nil {
return m.OtpSecret
}
return ""
}
func init() {
proto.RegisterType((*DeleteResponse)(nil), "selfpass.credentials.DeleteResponse")
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")
}
func init() { proto.RegisterFile("credentials/protobuf/service.proto", fileDescriptor_ad34efc7bbd96e69) }
var fileDescriptor_ad34efc7bbd96e69 = []byte{
// 561 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x95, 0x4d, 0x6f, 0xd3, 0x4c,
0x10, 0xc7, 0xe5, 0xa4, 0x4d, 0xed, 0x69, 0x9f, 0xe8, 0x61, 0x55, 0x24, 0xcb, 0x15, 0x24, 0x32,
0x48, 0x54, 0x45, 0x72, 0x51, 0xb9, 0xc0, 0x31, 0xb4, 0x28, 0xe5, 0x80, 0x90, 0x1c, 0x7a, 0xe1,
0x12, 0x6d, 0xed, 0x69, 0x6a, 0xc9, 0xf6, 0x9a, 0xdd, 0x31, 0xa8, 0x1f, 0x8c, 0x0f, 0x05, 0x1f,
0x81, 0x13, 0xf2, 0xfa, 0x25, 0x2f, 0x75, 0x9a, 0x48, 0x5c, 0xb8, 0xed, 0x8c, 0xff, 0xb3, 0x9a,
0xdf, 0xec, 0xee, 0xdf, 0xe0, 0x06, 0x12, 0x43, 0x4c, 0x29, 0xe2, 0xb1, 0x3a, 0xcd, 0xa4, 0x20,
0x71, 0x9d, 0xdf, 0x9c, 0x2a, 0x94, 0xdf, 0xa2, 0x00, 0x3d, 0x9d, 0x60, 0x87, 0x0a, 0xe3, 0x9b,
0x8c, 0x2b, 0xe5, 0x2d, 0x88, 0x9d, 0xc1, 0x4c, 0x88, 0x59, 0x8c, 0xf3, 0x22, 0x8a, 0x12, 0x54,
0xc4, 0x93, 0xac, 0x2c, 0x73, 0x4f, 0xa0, 0x7f, 0x81, 0x31, 0x12, 0xfa, 0xa8, 0x32, 0x91, 0x2a,
0x64, 0x36, 0xec, 0xa9, 0x3c, 0x08, 0x50, 0x29, 0xdb, 0x18, 0x1a, 0xc7, 0xa6, 0x5f, 0x87, 0xee,
0x1b, 0x78, 0x3c, 0x46, 0x1a, 0xc5, 0xf1, 0x47, 0x24, 0x1e, 0x72, 0xe2, 0x3e, 0x7e, 0xcd, 0x51,
0x11, 0x1b, 0xc0, 0xbe, 0x12, 0xb9, 0x0c, 0x70, 0x7a, 0x2b, 0x14, 0xe9, 0x32, 0xcb, 0x87, 0x32,
0x75, 0x29, 0x14, 0xb9, 0x47, 0x60, 0x7d, 0x08, 0x6b, 0x75, 0x1f, 0x3a, 0x51, 0x58, 0x89, 0x3a,
0x51, 0xe8, 0xde, 0xc2, 0x7f, 0x57, 0x59, 0xc8, 0x8b, 0x16, 0x5a, 0x05, 0x6c, 0x0c, 0x30, 0x67,
0xb2, 0x3b, 0x43, 0xe3, 0x78, 0xff, 0xec, 0x85, 0xd7, 0xc6, 0xeb, 0x9d, 0x37, 0xeb, 0x6a, 0x33,
0x7f, 0xa1, 0xd4, 0x3d, 0x81, 0x83, 0x8b, 0x3c, 0xc9, 0x1a, 0x54, 0x07, 0xcc, 0x40, 0xa4, 0x84,
0x29, 0x95, 0xac, 0x07, 0x7e, 0x13, 0xbb, 0x7d, 0x38, 0x78, 0x9f, 0x64, 0x74, 0x57, 0xed, 0xe3,
0xfe, 0x36, 0xc0, 0xac, 0xb9, 0xef, 0x75, 0xf8, 0x56, 0x77, 0xc8, 0x09, 0xc3, 0x29, 0xa7, 0xaa,
0x43, 0xc7, 0x2b, 0x67, 0xef, 0xd5, 0xb3, 0xf7, 0x3e, 0xd7, 0xb3, 0xf7, 0xad, 0x4a, 0x3d, 0xa2,
0xa2, 0x34, 0xd7, 0xf4, 0xba, 0xb4, 0xbb, 0xb9, 0xb4, 0x52, 0x8f, 0xa8, 0x38, 0xa9, 0x4c, 0x46,
0x09, 0x97, 0x77, 0xf6, 0x8e, 0x6e, 0xa5, 0x0e, 0x57, 0x0f, 0x64, 0x77, 0xf5, 0x40, 0xd8, 0x11,
0x58, 0xb1, 0x98, 0x45, 0xe9, 0x34, 0x97, 0xb1, 0xdd, 0xd3, 0x9f, 0x4d, 0x9d, 0xb8, 0x92, 0x31,
0xfb, 0x1f, 0xba, 0xc4, 0x67, 0xf6, 0x9e, 0x4e, 0x17, 0x4b, 0xf7, 0x67, 0x07, 0x60, 0x3e, 0xda,
0x7f, 0x1e, 0xdf, 0x01, 0x33, 0x57, 0x28, 0x53, 0x9e, 0x60, 0xc5, 0xde, 0xc4, 0xec, 0x10, 0x76,
0x31, 0xe1, 0x51, 0x4d, 0x5d, 0x06, 0x45, 0x45, 0x71, 0x97, 0xbe, 0x0b, 0x19, 0x56, 0xdc, 0x4d,
0xbc, 0x3a, 0x4c, 0xf3, 0xe1, 0x61, 0x5a, 0xed, 0xc3, 0x84, 0x66, 0x98, 0xec, 0x09, 0x80, 0xa0,
0x6c, 0xaa, 0x30, 0x90, 0x48, 0xf6, 0xbe, 0xfe, 0x60, 0x09, 0xca, 0x26, 0x3a, 0xe1, 0xfe, 0x32,
0xe0, 0xd1, 0xbd, 0x6b, 0xbc, 0x08, 0x6b, 0xac, 0x87, 0xed, 0xac, 0x83, 0xed, 0xae, 0x83, 0xdd,
0x79, 0x18, 0xf6, 0x6f, 0x6f, 0xce, 0x0a, 0xac, 0xb9, 0x02, 0x7b, 0xf6, 0xa3, 0xbb, 0x08, 0x3b,
0x29, 0x1d, 0x8d, 0x4d, 0xa1, 0xbf, 0x6c, 0x34, 0xec, 0x65, 0xfb, 0x73, 0x6f, 0xb5, 0x23, 0xe7,
0x69, 0xbb, 0xb8, 0x96, 0xbd, 0x32, 0xd8, 0x25, 0x74, 0xc7, 0x48, 0x6c, 0xd0, 0x2e, 0x6c, 0xac,
0xca, 0x19, 0x6e, 0x72, 0x19, 0x36, 0x81, 0xde, 0xb9, 0xbe, 0xcc, 0x6c, 0x5b, 0x47, 0xda, 0x62,
0xd3, 0x4f, 0xd0, 0x2b, 0x1d, 0x91, 0x3d, 0x6b, 0xd7, 0x2e, 0xf9, 0xe5, 0x76, 0x1b, 0x96, 0x2e,
0xbf, 0x19, 0xf9, 0x79, 0xbb, 0x60, 0xf9, 0x27, 0xf1, 0x0e, 0xbe, 0x98, 0xf5, 0xe3, 0xbc, 0xee,
0xe9, 0xd5, 0xeb, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xde, 0x03, 0x4f, 0xb2, 0xa6, 0x06, 0x00,
0x00,
}
// 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
// CredentialServiceClient is the client API for CredentialService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type CredentialServiceClient interface {
GetAllMetadata(ctx context.Context, in *GetAllMetadataRequest, opts ...grpc.CallOption) (CredentialService_GetAllMetadataClient, error)
Get(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*Credential, error)
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)
}
type credentialServiceClient struct {
cc *grpc.ClientConn
}
func NewCredentialServiceClient(cc *grpc.ClientConn) CredentialServiceClient {
return &credentialServiceClient{cc}
}
func (c *credentialServiceClient) GetAllMetadata(ctx context.Context, in *GetAllMetadataRequest, opts ...grpc.CallOption) (CredentialService_GetAllMetadataClient, error) {
stream, err := c.cc.NewStream(ctx, &_CredentialService_serviceDesc.Streams[0], "/selfpass.credentials.CredentialService/GetAllMetadata", opts...)
if err != nil {
return nil, err
}
x := &credentialServiceGetAllMetadataClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type CredentialService_GetAllMetadataClient interface {
Recv() (*Metadata, error)
grpc.ClientStream
}
type credentialServiceGetAllMetadataClient struct {
grpc.ClientStream
}
func (x *credentialServiceGetAllMetadataClient) Recv() (*Metadata, error) {
m := new(Metadata)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *credentialServiceClient) Get(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*Credential, error) {
out := new(Credential)
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Get", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *credentialServiceClient) Create(ctx context.Context, in *CredentialRequest, opts ...grpc.CallOption) (*Credential, error) {
out := new(Credential)
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Create", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *credentialServiceClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Credential, error) {
out := new(Credential)
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Update", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *credentialServiceClient) Delete(ctx context.Context, in *IdRequest, opts ...grpc.CallOption) (*DeleteResponse, error) {
out := new(DeleteResponse)
err := c.cc.Invoke(ctx, "/selfpass.credentials.CredentialService/Delete", 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
Get(context.Context, *IdRequest) (*Credential, error)
Create(context.Context, *CredentialRequest) (*Credential, error)
Update(context.Context, *UpdateRequest) (*Credential, error)
Delete(context.Context, *IdRequest) (*DeleteResponse, error)
}
// UnimplementedCredentialServiceServer can be embedded to have forward compatible implementations.
type UnimplementedCredentialServiceServer struct {
}
func (*UnimplementedCredentialServiceServer) GetAllMetadata(req *GetAllMetadataRequest, srv CredentialService_GetAllMetadataServer) error {
return status.Errorf(codes.Unimplemented, "method GetAllMetadata not implemented")
}
func (*UnimplementedCredentialServiceServer) Get(ctx context.Context, req *IdRequest) (*Credential, error) {
return nil, status.Errorf(codes.Unimplemented, "method Get not implemented")
}
func (*UnimplementedCredentialServiceServer) Create(ctx context.Context, req *CredentialRequest) (*Credential, error) {
return nil, status.Errorf(codes.Unimplemented, "method Create not implemented")
}
func (*UnimplementedCredentialServiceServer) Update(ctx context.Context, req *UpdateRequest) (*Credential, error) {
return nil, status.Errorf(codes.Unimplemented, "method Update not implemented")
}
func (*UnimplementedCredentialServiceServer) Delete(ctx context.Context, req *IdRequest) (*DeleteResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
}
func RegisterCredentialServiceServer(s *grpc.Server, srv CredentialServiceServer) {
s.RegisterService(&_CredentialService_serviceDesc, srv)
}
func _CredentialService_GetAllMetadata_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(GetAllMetadataRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(CredentialServiceServer).GetAllMetadata(m, &credentialServiceGetAllMetadataServer{stream})
}
type CredentialService_GetAllMetadataServer interface {
Send(*Metadata) error
grpc.ServerStream
}
type credentialServiceGetAllMetadataServer struct {
grpc.ServerStream
}
func (x *credentialServiceGetAllMetadataServer) Send(m *Metadata) error {
return x.ServerStream.SendMsg(m)
}
func _CredentialService_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CredentialServiceServer).Get(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/selfpass.credentials.CredentialService/Get",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CredentialServiceServer).Get(ctx, req.(*IdRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CredentialService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CredentialRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CredentialServiceServer).Create(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/selfpass.credentials.CredentialService/Create",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CredentialServiceServer).Create(ctx, req.(*CredentialRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CredentialService_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CredentialServiceServer).Update(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/selfpass.credentials.CredentialService/Update",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CredentialServiceServer).Update(ctx, req.(*UpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CredentialService_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CredentialServiceServer).Delete(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/selfpass.credentials.CredentialService/Delete",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CredentialServiceServer).Delete(ctx, req.(*IdRequest))
}
return interceptor(ctx, in, info, handler)
}
var _CredentialService_serviceDesc = grpc.ServiceDesc{
ServiceName: "selfpass.credentials.CredentialService",
HandlerType: (*CredentialServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Get",
Handler: _CredentialService_Get_Handler,
},
{
MethodName: "Create",
Handler: _CredentialService_Create_Handler,
},
{
MethodName: "Update",
Handler: _CredentialService_Update_Handler,
},
{
MethodName: "Delete",
Handler: _CredentialService_Delete_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "GetAllMetadata",
Handler: _CredentialService_GetAllMetadata_Handler,
ServerStreams: true,
},
},
Metadata: "credentials/protobuf/service.proto",
}

View file

@ -0,0 +1,75 @@
syntax = "proto3";
package selfpass.credentials;
option go_package = "protobuf";
import "google/protobuf/timestamp.proto";
service CredentialService {
rpc GetAllMetadata (GetAllMetadataRequest) returns (stream Metadata);
rpc Get (IdRequest) returns (Credential);
rpc Create (CredentialRequest) returns (Credential);
rpc Update (UpdateRequest) returns (Credential);
rpc Delete (IdRequest) returns (DeleteResponse);
// rpc Dump (EmptyRequest) returns (DumpResponse);
}
message DeleteResponse {
bool success = 1;
}
message GetAllMetadataRequest {
string source_host = 1;
}
message IdRequest {
string id = 1;
}
message UpdateRequest {
string id = 1;
CredentialRequest credential = 2;
}
message DumpResponse {
bytes contents = 1;
}
message EmptyRequest {
}
message Metadata {
string id = 1;
google.protobuf.Timestamp created_at = 2;
google.protobuf.Timestamp updated_at = 3;
string primary = 4;
string source_host = 5;
string login_url = 6;
string tag = 7;
}
message Credential {
string id = 1;
google.protobuf.Timestamp created_at = 2;
google.protobuf.Timestamp updated_at = 3;
string primary = 4;
string username = 5;
string email = 6;
string password = 7;
string source_host = 8;
string login_url = 9;
string tag = 10;
string otp_secret = 11;
}
message CredentialRequest {
string primary = 1;
string username = 2;
string email = 3;
string password = 4;
string source_host = 5;
string login_url = 6;
string tag = 7;
string otp_secret = 8;
}

View file

@ -0,0 +1,136 @@
package repositories
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"github.com/mitchell/selfpass/services/credentials/endpoints"
"github.com/mitchell/selfpass/services/credentials/protobuf"
"github.com/mitchell/selfpass/services/credentials/transport"
"github.com/mitchell/selfpass/services/credentials/types"
)
func NewCredentialServiceClient(ctx context.Context, target, ca, cert, key string) (types.CredentialClient, error) {
keypair, err := tls.X509KeyPair([]byte(cert), []byte(key))
if err != nil {
return nil, err
}
capool := x509.NewCertPool()
capool.AppendCertsFromPEM([]byte(ca))
creds := credentials.NewTLS(&tls.Config{
RootCAs: capool,
Certificates: []tls.Certificate{keypair},
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{
tls.CurveP256,
},
})
conn, err := grpc.DialContext(ctx, target, grpc.WithTransportCredentials(creds), grpc.WithBlock())
if err != nil {
return nil, err
}
return credentialServiceClient{
client: protobuf.NewCredentialServiceClient(conn),
}, nil
}
type credentialServiceClient struct {
client protobuf.CredentialServiceClient
}
func (c credentialServiceClient) GetAllMetadata(ctx context.Context, sourceHost string) (output <-chan types.Metadata, errch chan error) {
pbmdch := make(chan protobuf.Metadata, 1)
errch = make(chan error, 1)
stream, err := transport.DecodeMetdataStreamResponse(ctx, transport.ProtobufMetadataStream{
Metadata: pbmdch,
Errors: errch,
})
srv, err := c.client.GetAllMetadata(ctx, &protobuf.GetAllMetadataRequest{SourceHost: sourceHost})
if err != nil {
errch <- err
return nil, errch
}
go func() {
defer close(pbmdch)
for {
select {
case <-ctx.Done():
errch <- fmt.Errorf("context timeout")
return
default:
}
pbmd, err := srv.Recv()
if err == io.EOF {
return
} else if err != nil {
errch <- err
return
}
pbmdch <- *pbmd
}
}()
return stream.Metadata, stream.Errors
}
func (c credentialServiceClient) Get(ctx context.Context, id string) (output types.Credential, err error) {
req := transport.EncodeIdRequest(endpoints.IDRequest{ID: id})
res, err := c.client.Get(ctx, &req)
if err != nil {
return output, err
}
return transport.DecodeCredential(*res)
}
func (c credentialServiceClient) Create(ctx context.Context, ci types.CredentialInput) (output types.Credential, err error) {
req := transport.EncodeCredentialRequest(ci)
res, err := c.client.Create(ctx, &req)
if err != nil {
return output, err
}
return transport.DecodeCredential(*res)
}
func (c credentialServiceClient) Update(ctx context.Context, id string, ci types.CredentialInput) (output types.Credential, err error) {
req := transport.EncodeUpdateRequest(endpoints.UpdateRequest{ID: id, Credential: ci})
res, err := c.client.Update(ctx, &req)
if err != nil {
return output, err
}
return transport.DecodeCredential(*res)
}
func (c credentialServiceClient) Delete(ctx context.Context, id string) (err error) {
req := transport.EncodeIdRequest(endpoints.IDRequest{ID: id})
res, err := c.client.Delete(ctx, &req)
if err != nil {
return err
}
if !res.Success {
return fmt.Errorf("delete unsuccessful")
}
return nil
}

View file

@ -0,0 +1,81 @@
package repositories
import (
"context"
"github.com/mediocregopher/radix/v3"
"github.com/mitchell/selfpass/services/credentials/types"
)
func NewRedisConn(networkType, address string, connCount uint, options ...radix.PoolOpt) (c RedisConn, err error) {
p, err := radix.NewPool(networkType, address, int(connCount), options...)
return RedisConn{p: p}, err
}
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: types.TypePrefixCred + dash + 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) {
err = conn.p.Do(radix.Cmd(&output, hGetAll, id))
return output, err
}
func (conn RedisConn) Put(ctx context.Context, c types.Credential) (err error) {
err = conn.p.Do(radix.FlatCmd(nil, hMSet, c.ID, c))
return err
}
func (conn RedisConn) Delete(ctx context.Context, id string) (err error) {
err = conn.p.Do(radix.Cmd(nil, del, id))
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

@ -0,0 +1,118 @@
package service
import (
"context"
"fmt"
"time"
"github.com/mitchell/selfpass/services/credentials/types"
)
func NewCredentials(repo types.CredentialRepo) Credentials {
return Credentials{
repo: repo,
}
}
type Credentials struct {
repo types.CredentialRepo
}
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, sourceHost, errch)
return output, errch
}
func (svc Credentials) Get(ctx context.Context, id string) (output types.Credential, err error) {
if id == "" {
return output, fmt.Errorf("%s must specify an id", types.InvalidArgument)
}
return svc.repo.Get(ctx, id)
}
func (svc Credentials) Create(ctx context.Context, ci types.CredentialInput) (output types.Credential, err error) {
if err = validateCredentialInput(ci); err != nil {
return output, err
}
var c types.Credential
c.ID = generateID(ci)
c.CreatedAt = time.Now()
c.UpdatedAt = time.Now()
c.Primary = ci.Primary
c.LoginURL = ci.LoginURL
c.SourceHost = ci.SourceHost
c.Username = ci.Username
c.Email = ci.Email
c.Password = ci.Password
c.OTPSecret = ci.OTPSecret
c.Tag = ci.Tag
err = svc.repo.Put(ctx, c)
return c, err
}
func validateCredentialInput(c types.CredentialInput) (err error) {
switch {
case c.SourceHost == "":
return fmt.Errorf("%s must specify source host", types.InvalidArgument)
case c.Primary == "":
return fmt.Errorf("%s must specify primary user key", types.InvalidArgument)
case c.Password == "":
return fmt.Errorf("%s must specify password", types.InvalidArgument)
}
return err
}
func generateID(ci types.CredentialInput) string {
idFormat := types.TypePrefixCred + "-%s-%s"
if ci.Tag != "" {
idFormat += "-%s"
return fmt.Sprintf(idFormat, ci.SourceHost, ci.Primary, ci.Tag)
}
return fmt.Sprintf(idFormat, ci.SourceHost, ci.Primary)
}
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
}
c.ID = generateID(ci)
c.UpdatedAt = time.Now()
c.Primary = ci.Primary
c.LoginURL = ci.LoginURL
c.SourceHost = ci.SourceHost
c.Password = ci.Password
c.OTPSecret = ci.OTPSecret
c.Email = ci.Email
c.Username = ci.Username
c.Tag = ci.Tag
return c, svc.repo.Put(ctx, c)
}
func (svc Credentials) Delete(ctx context.Context, id string) (err error) {
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

@ -0,0 +1,254 @@
package transport
import (
"context"
"github.com/golang/protobuf/ptypes"
"github.com/mitchell/selfpass/services/credentials/endpoints"
"github.com/mitchell/selfpass/services/credentials/protobuf"
"github.com/mitchell/selfpass/services/credentials/types"
)
func decodeGetAllMetadataRequest(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(protobuf.GetAllMetadataRequest)
return endpoints.GetAllMetadataRequest{
SourceHost: r.SourceHost,
}, nil
}
func EncodeGetAllMetadataRequest(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(endpoints.GetAllMetadataRequest)
return protobuf.GetAllMetadataRequest{
SourceHost: r.SourceHost,
}, 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)
go func() {
defer close(pbmdch)
for md := range r.Metadata {
createdAt, err := ptypes.TimestampProto(md.CreatedAt)
if err != nil {
r.Errors <- err
return
}
updatedAt, err := ptypes.TimestampProto(md.UpdatedAt)
if err != nil {
r.Errors <- err
return
}
pbmdch <- protobuf.Metadata{
Id: md.ID,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
SourceHost: md.SourceHost,
Primary: md.Primary,
LoginUrl: md.LoginURL,
Tag: md.Tag,
}
}
}()
return ProtobufMetadataStream{
Metadata: pbmdch,
Errors: r.Errors,
}, nil
}
func DecodeMetdataStreamResponse(ctx context.Context, r ProtobufMetadataStream) (endpoints.MetadataStream, error) {
mdch := make(chan types.Metadata, 1)
errch := make(chan error, 1)
go func() {
defer close(mdch)
for pbmd := range r.Metadata {
createdAt, err := ptypes.Timestamp(pbmd.CreatedAt)
if err != nil {
errch <- err
return
}
updatedAt, err := ptypes.Timestamp(pbmd.UpdatedAt)
if err != nil {
errch <- err
return
}
mdch <- types.Metadata{
ID: pbmd.Id,
SourceHost: pbmd.SourceHost,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
Primary: pbmd.Primary,
LoginURL: pbmd.LoginUrl,
Tag: pbmd.Tag,
}
}
}()
return endpoints.MetadataStream{
Metadata: mdch,
Errors: errch,
}, nil
}
type ProtobufMetadataStream struct {
Metadata <-chan protobuf.Metadata
Errors chan error
}
func decodeCredentialRequest(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(protobuf.CredentialRequest)
return types.CredentialInput{
MetadataInput: types.MetadataInput{
Primary: r.Primary,
LoginURL: r.LoginUrl,
SourceHost: r.SourceHost,
Tag: r.Tag,
},
Username: r.Username,
Email: r.Email,
Password: r.Password,
OTPSecret: r.OtpSecret,
}, nil
}
func EncodeCredentialRequest(r types.CredentialInput) protobuf.CredentialRequest {
return protobuf.CredentialRequest{
Primary: r.Primary,
Username: r.Username,
Email: r.Email,
Password: r.Password,
OtpSecret: r.OTPSecret,
SourceHost: r.SourceHost,
LoginUrl: r.LoginURL,
Tag: r.Tag,
}
}
func encodeCredentialResponse(ctx context.Context, response interface{}) (interface{}, error) {
r := response.(types.Credential)
createdAt, err := ptypes.TimestampProto(r.CreatedAt)
if err != nil {
return nil, err
}
updatedAt, err := ptypes.TimestampProto(r.UpdatedAt)
if err != nil {
return nil, err
}
return protobuf.Credential{
Id: r.ID,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
Primary: r.Primary,
SourceHost: r.SourceHost,
LoginUrl: r.LoginURL,
Tag: r.Tag,
Username: r.Username,
Email: r.Email,
Password: r.Password,
OtpSecret: r.OTPSecret,
}, nil
}
func DecodeCredential(r protobuf.Credential) (c types.Credential, err error) {
createdAt, err := ptypes.Timestamp(r.CreatedAt)
if err != nil {
return c, err
}
updatedAt, err := ptypes.Timestamp(r.UpdatedAt)
if err != nil {
return c, err
}
return types.Credential{
Metadata: types.Metadata{
ID: r.Id,
SourceHost: r.SourceHost,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
Primary: r.Primary,
LoginURL: r.LoginUrl,
Tag: r.Tag,
},
Username: r.Username,
Email: r.Email,
Password: r.Password,
OTPSecret: r.OtpSecret,
}, nil
}
func decodeUpdateRequest(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(protobuf.UpdateRequest)
return endpoints.UpdateRequest{
ID: r.Id,
Credential: types.CredentialInput{
MetadataInput: types.MetadataInput{
Primary: r.Credential.Primary,
SourceHost: r.Credential.SourceHost,
LoginURL: r.Credential.LoginUrl,
Tag: r.Credential.Tag,
},
Username: r.Credential.Username,
Email: r.Credential.Email,
Password: r.Credential.Password,
OTPSecret: r.Credential.OtpSecret,
},
}, nil
}
func EncodeUpdateRequest(r endpoints.UpdateRequest) protobuf.UpdateRequest {
c := r.Credential
return protobuf.UpdateRequest{
Id: r.ID,
Credential: &protobuf.CredentialRequest{
Primary: c.Primary,
Username: c.Username,
Email: c.Email,
Password: c.Password,
OtpSecret: c.OTPSecret,
SourceHost: c.SourceHost,
LoginUrl: c.LoginURL,
Tag: c.Tag,
},
}
}
func decodeIdRequest(ctx context.Context, request interface{}) (interface{}, error) {
r := request.(protobuf.IdRequest)
return endpoints.IDRequest{
ID: r.Id,
}, nil
}
func EncodeIdRequest(r endpoints.IDRequest) protobuf.IdRequest {
return protobuf.IdRequest{
Id: r.ID,
}
}
func noOp(context.Context, interface{}) (interface{}, error) {
return nil, nil
}

View file

@ -0,0 +1,170 @@
package transport
import (
"context"
"strings"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/transport/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/mitchell/selfpass/services/credentials/endpoints"
"github.com/mitchell/selfpass/services/credentials/protobuf"
"github.com/mitchell/selfpass/services/credentials/types"
)
func NewGRPCServer(svc types.Service, logger log.Logger) GRPCServer {
return GRPCServer{
getAllMetadata: grpc.NewServer(
endpoints.MakeGetAllMetadataEndpoint(svc),
decodeGetAllMetadataRequest,
encodeMetadataStreamResponse,
grpc.ServerErrorLogger(logger),
),
get: grpc.NewServer(
endpoints.MakeGetEndpoint(svc),
decodeIdRequest,
encodeCredentialResponse,
grpc.ServerErrorLogger(logger),
),
create: grpc.NewServer(
endpoints.MakeCreateEndpoint(svc),
decodeCredentialRequest,
encodeCredentialResponse,
grpc.ServerErrorLogger(logger),
),
update: grpc.NewServer(
endpoints.MakeUpdateEndpoint(svc),
decodeUpdateRequest,
encodeCredentialResponse,
grpc.ServerErrorLogger(logger),
),
delete: grpc.NewServer(
endpoints.MakeDeleteEndpoint(svc),
decodeIdRequest,
noOp,
grpc.ServerErrorLogger(logger),
),
dump: grpc.NewServer(
endpoints.MakeDumpEndpoint(svc),
noOp,
encodeDumpResponse,
grpc.ServerErrorLogger(logger),
),
}
}
type GRPCServer struct {
getAllMetadata *grpc.Server
get *grpc.Server
create *grpc.Server
update *grpc.Server
delete *grpc.Server
dump *grpc.Server
}
func (s GRPCServer) GetAllMetadata(r *protobuf.GetAllMetadataRequest, srv protobuf.CredentialService_GetAllMetadataServer) (err error) {
defer func() { err = handlerGRPCError(err) }()
var i interface{}
ctx := srv.Context()
ctx, i, err = s.getAllMetadata.ServeGRPC(ctx, *r)
if err != nil {
return err
}
mds := i.(ProtobufMetadataStream)
receiveLoop:
for {
select {
case <-ctx.Done():
break receiveLoop
case err = <-mds.Errors:
break receiveLoop
case md, ok := <-mds.Metadata:
if !ok {
break receiveLoop
}
if err = srv.Send(&md); err != nil {
break receiveLoop
}
}
}
return err
}
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
}
c := &protobuf.Credential{}
*c = i.(protobuf.Credential)
return c, nil
}
func (s GRPCServer) Update(ctx context.Context, r *protobuf.UpdateRequest) (*protobuf.Credential, error) {
ctx, i, err := s.update.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) 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 {
case strings.HasPrefix(err.Error(), types.InvalidArgument):
err = status.Error(codes.InvalidArgument, err.Error())
case strings.HasPrefix(err.Error(), types.NotFound):
err = status.Error(codes.NotFound, err.Error())
default:
err = status.Error(codes.Internal, "an internal error has occurred")
}
}
return err
}

View file

@ -0,0 +1,75 @@
package types
import (
"fmt"
"time"
)
const TypePrefixCred = "cred"
type Credential struct {
Metadata
Username string
Email string
Password string `json:"-"`
OTPSecret string `json:"-"`
}
func (c Credential) String() string {
format := "%s"
args := []interface{}{c.Metadata}
if c.Username != "" {
format += "username = %s\n"
args = append(args, c.Username)
}
if c.Email != "" {
format += "email = %s\n"
args = append(args, c.Email)
}
return fmt.Sprintf(format, args...)
}
type CredentialInput struct {
MetadataInput
Username string
Email string
Password string
OTPSecret string
}
type Metadata struct {
ID string // primary key
SourceHost string // sort key
CreatedAt time.Time
UpdatedAt time.Time
Primary string
LoginURL string
Tag string
}
func (m Metadata) String() string {
format := "id = %s\ncreatedAt = %s\nupdatedAt = %s\nsourceHost = %s\nprimary = %s\n"
args := []interface{}{m.ID, m.CreatedAt, m.UpdatedAt, m.SourceHost, m.Primary}
if m.LoginURL != "" {
format += "loginUrl = %s\n"
args = append(args, m.LoginURL)
}
if m.Tag != "" {
format += "tag = %s\n"
args = append(args, m.Tag)
}
return fmt.Sprintf(format, args...)
}
type MetadataInput struct {
Primary string
SourceHost string
LoginURL string
Tag string
}

View file

@ -0,0 +1,8 @@
package types
// These constants are the prefixes of errors that should be exposed to the client.
// All error encoders should check for them.
const (
NotFound = "not found:"
InvalidArgument = "invalid argument:"
)

View file

@ -0,0 +1,30 @@
package types
import "context"
type Service interface {
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)
}
type CredentialRepo interface {
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)
}
type CredentialClientInit func(ctx context.Context, target, ca, cert, key string) (c CredentialClient, err error)
type CredentialClient interface {
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)
}