Add validation to config
This commit is contained in:
parent
cc9687b907
commit
195310282f
@ -62,30 +62,23 @@ func ActionServe(c *cli.Context) error {
|
|||||||
defer fileCloseFunc()
|
defer fileCloseFunc()
|
||||||
|
|
||||||
// Setup user store
|
// Setup user store
|
||||||
userStore, userCloseFunc, err := cfg.Server.UserStoreConfig.GetStore()
|
dataStore, userCloseFunc, err := cfg.Server.DataStoreConfig.GetStore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to initialize user store: %w", err)
|
return fmt.Errorf("unable to initialize user store: %w", err)
|
||||||
}
|
}
|
||||||
defer userCloseFunc()
|
defer userCloseFunc()
|
||||||
|
|
||||||
// Create initial admin-user if neccessary
|
// Create initial admin-user if neccessary
|
||||||
if err := initializeUsers(userStore, serverLogger); err != nil {
|
if err := initializeUsers(dataStore, serverLogger); err != nil {
|
||||||
return fmt.Errorf("error initializing store: %w", err)
|
return fmt.Errorf("error initializing store: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup cert store
|
|
||||||
// TODO: User proper store
|
|
||||||
certStore := store.NewMemoryStore()
|
|
||||||
|
|
||||||
// Setup cert-service
|
// Setup cert-service
|
||||||
certSvc, err := certs.NewCertService(certStore, caCertBytes, caKeyBytes)
|
certSvc, err := certs.NewCertService(dataStore, caCertBytes, caKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error initializing certificate service: %w", err)
|
return fmt.Errorf("error initializing certificate service: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup binary store
|
|
||||||
binaryStore := store.NewMemoryStore()
|
|
||||||
|
|
||||||
// Setup shutdown-handling
|
// Setup shutdown-handling
|
||||||
rootCtx, rootCancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
rootCtx, rootCancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||||
defer rootCancel()
|
defer rootCancel()
|
||||||
@ -114,14 +107,14 @@ func ActionServe(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup cert-service
|
// Setup cert-service
|
||||||
certServiceServer := server.NewCertServiceServer(certSvc, certStore, userStore)
|
certServiceServer := server.NewCertServiceServer(certSvc, dataStore, dataStore)
|
||||||
certServiceServer.Logger = certLogger
|
certServiceServer.Logger = certLogger
|
||||||
|
|
||||||
// Setup user-service
|
// Setup user-service
|
||||||
grpcUserServer := server.NewGRPCUserServiceServer(userStore, certSvc)
|
grpcUserServer := server.NewGRPCUserServiceServer(dataStore, certSvc)
|
||||||
grpcUserServer.Logger = logger.Named("USER")
|
grpcUserServer.Logger = logger.Named("USER")
|
||||||
|
|
||||||
binaryServer := server.NewBinaryServiceServer(binaryStore)
|
binaryServer := server.NewBinaryServiceServer(dataStore)
|
||||||
binaryServer.Logger = binsLogger
|
binaryServer.Logger = binsLogger
|
||||||
|
|
||||||
lis, err := net.Listen("tcp", grpcAddr)
|
lis, err := net.Listen("tcp", grpcAddr)
|
||||||
@ -150,7 +143,7 @@ func ActionServe(c *cli.Context) error {
|
|||||||
grpc.MaxRecvMsgSize(100*1024*1024),
|
grpc.MaxRecvMsgSize(100*1024*1024),
|
||||||
grpc.MaxSendMsgSize(100*1024*1024),
|
grpc.MaxSendMsgSize(100*1024*1024),
|
||||||
grpc.Creds(creds),
|
grpc.Creds(creds),
|
||||||
grpc.ChainUnaryInterceptor(interceptors.NewAuthInterceptor(userStore, certSvc, authLogger)),
|
grpc.ChainUnaryInterceptor(interceptors.NewAuthInterceptor(dataStore, certSvc, authLogger)),
|
||||||
)
|
)
|
||||||
pb.RegisterFileServiceServer(grpcServer, grpcFileServer)
|
pb.RegisterFileServiceServer(grpcServer, grpcFileServer)
|
||||||
pb.RegisterUserServiceServer(grpcServer, grpcUserServer)
|
pb.RegisterUserServiceServer(grpcServer, grpcUserServer)
|
||||||
@ -183,7 +176,7 @@ func ActionServe(c *cli.Context) error {
|
|||||||
if c.IsSet("http-addr") {
|
if c.IsSet("http-addr") {
|
||||||
httpAddr = c.String("http-addr")
|
httpAddr = c.String("http-addr")
|
||||||
}
|
}
|
||||||
httpServer := server.NewHTTPSever(s, binaryStore, srvCertBytes, cfg.Server.GRPCEndpoint)
|
httpServer := server.NewHTTPSever(s, dataStore, srvCertBytes, cfg.Server.GRPCEndpoint)
|
||||||
httpServer.Logger = httpLogger
|
httpServer.Logger = httpLogger
|
||||||
httpServer.Addr = httpAddr
|
httpServer.Addr = httpAddr
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ type ServerConfig struct {
|
|||||||
LogLevel string `toml:"LogLevel"`
|
LogLevel string `toml:"LogLevel"`
|
||||||
Hostname string `toml:"Hostname"`
|
Hostname string `toml:"Hostname"`
|
||||||
GRPCEndpoint string `toml:"GRPCEndpoint"`
|
GRPCEndpoint string `toml:"GRPCEndpoint"`
|
||||||
UserStoreConfig *ServerUserStoreConfig `toml:"UserStore"`
|
DataStoreConfig *ServerDataStoreConfig `toml:"DataStore"`
|
||||||
FileStoreConfig *ServerFileStoreConfig `toml:"FileStore"`
|
FileStoreConfig *ServerFileStoreConfig `toml:"FileStore"`
|
||||||
GRPC *ServerGRPCConfig `toml:"GRPC"`
|
GRPC *ServerGRPCConfig `toml:"GRPC"`
|
||||||
HTTP *ServerHTTPConfig `toml:"HTTP"`
|
HTTP *ServerHTTPConfig `toml:"HTTP"`
|
||||||
@ -47,7 +47,7 @@ type ServerFileStoreConfig struct {
|
|||||||
BoltStoreConfig *BoltStoreConfig `toml:"Bolt"`
|
BoltStoreConfig *BoltStoreConfig `toml:"Bolt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerUserStoreConfig struct {
|
type ServerDataStoreConfig struct {
|
||||||
Type string `toml:"Type"`
|
Type string `toml:"Type"`
|
||||||
BoltStoreConfig *BoltStoreConfig `toml:"Bolt"`
|
BoltStoreConfig *BoltStoreConfig `toml:"Bolt"`
|
||||||
}
|
}
|
||||||
@ -88,6 +88,8 @@ func FromDefault() *Config {
|
|||||||
HTTP: &ServerHTTPConfig{
|
HTTP: &ServerHTTPConfig{
|
||||||
ListenAddr: ":8089",
|
ListenAddr: ":8089",
|
||||||
},
|
},
|
||||||
|
DataStoreConfig: &ServerDataStoreConfig{},
|
||||||
|
FileStoreConfig: &ServerFileStoreConfig{},
|
||||||
},
|
},
|
||||||
Client: &ClientConfig{
|
Client: &ClientConfig{
|
||||||
Certs: &CertificatePaths{},
|
Certs: &CertificatePaths{},
|
||||||
@ -142,6 +144,87 @@ func FromDefaultLocations() (*Config, error) {
|
|||||||
return nil, fmt.Errorf("config not found")
|
return nil, fmt.Errorf("config not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) ValidForServer() error {
|
||||||
|
// Verify that grpc-endpoint is set
|
||||||
|
if c.Server.GRPCEndpoint == "" {
|
||||||
|
return fmt.Errorf("missing require config-value Server.GRPCEndpoint")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify loglevel
|
||||||
|
switch strings.ToUpper(c.Server.LogLevel) {
|
||||||
|
case "DEBUG", "INFO", "WARN", "ERROR", "FATAL":
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("config-value Server.LogLevel is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify datastore config
|
||||||
|
switch strings.ToLower(c.Server.DataStoreConfig.Type) {
|
||||||
|
case "memory":
|
||||||
|
break
|
||||||
|
case "bolt":
|
||||||
|
if c.Server.DataStoreConfig.BoltStoreConfig == nil || c.Server.DataStoreConfig.BoltStoreConfig.Path == "" {
|
||||||
|
return fmt.Errorf("server datastore is bolt, missing required config value Server.DataStore.Bolt.Path")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("config-value Server.DataStore.Type is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify filestore config
|
||||||
|
switch strings.ToLower(c.Server.FileStoreConfig.Type) {
|
||||||
|
case "memory":
|
||||||
|
break
|
||||||
|
case "filesystem":
|
||||||
|
if c.Server.FileStoreConfig.FSStoreConfig == nil || c.Server.FileStoreConfig.FSStoreConfig.Dir == "" {
|
||||||
|
return fmt.Errorf("server datastore is bolt, missing required config value Server.FileStore.FSStore.Path")
|
||||||
|
}
|
||||||
|
case "bolt":
|
||||||
|
if c.Server.FileStoreConfig.BoltStoreConfig == nil || c.Server.FileStoreConfig.BoltStoreConfig.Path == "" {
|
||||||
|
return fmt.Errorf("server datastore is bolt, missing required config value Server.DataStore.Bolt.Path")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify grpc-config
|
||||||
|
if c.Server.GRPC.ListenAddr == "" {
|
||||||
|
return fmt.Errorf("missing required config-value Server.GRPC.ListenAddr")
|
||||||
|
}
|
||||||
|
if c.Server.GRPC.CACerts.CertificateKeyPath == "" {
|
||||||
|
// TODO: Maybe return custom error, so we can create certs if missing
|
||||||
|
return fmt.Errorf("missing require value Server.GRPC.CACerts.CertificateKeyPath")
|
||||||
|
}
|
||||||
|
if c.Server.GRPC.CACerts.CertificatePath == "" {
|
||||||
|
// TODO: Maybe return custom error, so we can create certs if missing
|
||||||
|
return fmt.Errorf("missing require value Server.GRPC.CACerts.CertificatePath")
|
||||||
|
}
|
||||||
|
if c.Server.GRPC.Certs.CertificatePath == "" {
|
||||||
|
// TODO: Maybe return custom error, so we can create certs if missing
|
||||||
|
return fmt.Errorf("missing require value Server.GRPC.Certs.CertificatePath")
|
||||||
|
}
|
||||||
|
if c.Server.GRPC.Certs.CertificateKeyPath == "" {
|
||||||
|
// TODO: Maybe return custom error, so we can create certs if missing
|
||||||
|
return fmt.Errorf("missing require value Server.GRPC.Certs.CertificateKeyPath")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (c *Config) ValidForClient() error {
|
||||||
|
if c.Client.Certs.CertificateKeyPath == "" {
|
||||||
|
return fmt.Errorf("missing required value Client.Certs.CertificateKeyPath")
|
||||||
|
}
|
||||||
|
if c.Client.Certs.CertificatePath == "" {
|
||||||
|
return fmt.Errorf("missing required value Client.Certs.CertificatePath")
|
||||||
|
}
|
||||||
|
if c.Client.DefaultServer == "" {
|
||||||
|
// TODO: Should probably have its own custom error
|
||||||
|
return fmt.Errorf("missing required value Client.DefaultServer")
|
||||||
|
}
|
||||||
|
if c.Client.ServerCertPath == "" {
|
||||||
|
// TODO: Should probably have its own custom error
|
||||||
|
return fmt.Errorf("missing required value Client.ServerCertPath")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) Location() string {
|
func (c *Config) Location() string {
|
||||||
return c.location
|
return c.location
|
||||||
}
|
}
|
||||||
@ -293,7 +376,7 @@ func (sc *ServerFileStoreConfig) GetStore() (store.FileStore, func() error, erro
|
|||||||
return nil, nil, fmt.Errorf("invalid store config")
|
return nil, nil, fmt.Errorf("invalid store config")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *ServerUserStoreConfig) GetStore() (store.UserStore, func() error, error) {
|
func (sc *ServerDataStoreConfig) GetStore() (store.DataStore, func() error, error) {
|
||||||
nopCloseFunc := func() error { return nil }
|
nopCloseFunc := func() error { return nil }
|
||||||
if strings.EqualFold(sc.Type, "bolt") {
|
if strings.EqualFold(sc.Type, "bolt") {
|
||||||
s, err := store.NewBoltStore(sc.BoltStoreConfig.Path)
|
s, err := store.NewBoltStore(sc.BoltStoreConfig.Path)
|
||||||
|
209
config/config_test.go
Normal file
209
config/config_test.go
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
package config_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gitea.benny.dog/torjus/ezshare/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var configStrExample = `
|
||||||
|
########################
|
||||||
|
# Server configuration #
|
||||||
|
########################
|
||||||
|
[Server]
|
||||||
|
# Set server log-level
|
||||||
|
# Must be one of: DEBUG, INFO, WARN, ERROR
|
||||||
|
# Default: INFO
|
||||||
|
LogLevel = "INFO"
|
||||||
|
|
||||||
|
# Server hostname
|
||||||
|
# Used for generating links
|
||||||
|
# Required
|
||||||
|
Hostname = "localhost"
|
||||||
|
|
||||||
|
# Endpoint reachable by clients
|
||||||
|
# Fetched by clients for automatic setup
|
||||||
|
# Required
|
||||||
|
GRPCEndpoint = "localhost:50051"
|
||||||
|
|
||||||
|
# File store configuration
|
||||||
|
[Server.FileStore]
|
||||||
|
# How server stores file
|
||||||
|
# Must be one of: filesystem, memory, bolt
|
||||||
|
# Required
|
||||||
|
Type = "bolt"
|
||||||
|
|
||||||
|
[Server.FileStore.Bolt]
|
||||||
|
# Where the bolt-db is stored
|
||||||
|
# Required if store-type is bolt
|
||||||
|
Path = "/data/files.db"
|
||||||
|
|
||||||
|
[Server.FileStore.Filesystem]
|
||||||
|
# Where files are stored
|
||||||
|
# Required if store-type is filesystem
|
||||||
|
Dir = "/data"
|
||||||
|
|
||||||
|
[Server.DataStore]
|
||||||
|
# What store to use for users, certs and binaries
|
||||||
|
# Must be one of: memory, bolt
|
||||||
|
# Required
|
||||||
|
Type = "bolt"
|
||||||
|
|
||||||
|
[Server.DataStore.Bolt]
|
||||||
|
# Path to bolt database-file
|
||||||
|
# Required if Server.Datastore is bolt
|
||||||
|
Path = "/data/users.db"
|
||||||
|
|
||||||
|
# GRPC Configuration
|
||||||
|
[Server.GRPC]
|
||||||
|
# Address to listen to
|
||||||
|
# Default: :50051
|
||||||
|
ListenAddr = ":50051"
|
||||||
|
|
||||||
|
# GRPC Certificate Configuration
|
||||||
|
[Server.GRPC.CACerts]
|
||||||
|
# Path of PEM-encoded certificate file
|
||||||
|
CertificatePath = "/data/ca.pem"
|
||||||
|
# Path of PEM-encoded private key
|
||||||
|
# Must be of type ecdsa
|
||||||
|
CertificateKeyPath = "/data/ca.key"
|
||||||
|
|
||||||
|
[Server.GRPC.Certs]
|
||||||
|
# Path of PEM-encoded certificate file
|
||||||
|
CertificatePath = "/data/server.pem"
|
||||||
|
# Path of PEM-encoded private key
|
||||||
|
# Must be of type ecdsa
|
||||||
|
CertificateKeyPath = "/data/server.key"
|
||||||
|
|
||||||
|
[Server.HTTP]
|
||||||
|
# Address to listen to
|
||||||
|
# Default: :8089
|
||||||
|
ListenAddr = ":8089"
|
||||||
|
|
||||||
|
|
||||||
|
########################
|
||||||
|
# Client configuration #
|
||||||
|
########################
|
||||||
|
[Client]
|
||||||
|
# Server used if not specified using command-line
|
||||||
|
DefaultServer = "localhost:50051"
|
||||||
|
# Path to PEM-encoder server-certificate
|
||||||
|
ServerCertPath = "/data/server.pem"
|
||||||
|
|
||||||
|
[Client.Certs]
|
||||||
|
# Path of PEM-encoded certificate file
|
||||||
|
CertificatePath = "/data/client.pem"
|
||||||
|
# Path of PEM-encoded private key
|
||||||
|
# Must be of type ecdsa
|
||||||
|
CertificateKeyPath = "/data/client.key"
|
||||||
|
`
|
||||||
|
|
||||||
|
var configStrValidClient = `
|
||||||
|
[Client]
|
||||||
|
DefaultServer = "localhost:50051"
|
||||||
|
ServerCertPath = "/data/server.pem"
|
||||||
|
[Client.Certs]
|
||||||
|
CertificatePath = "/data/client.pem"
|
||||||
|
CertificateKeyPath = "/data/client.key"
|
||||||
|
`
|
||||||
|
|
||||||
|
var configStrValidServerMinimal = `
|
||||||
|
[Server]
|
||||||
|
LogLevel = "INFO"
|
||||||
|
Hostname = "localhost"
|
||||||
|
GRPCEndpoint = "localhost:50051"
|
||||||
|
[Server.FileStore]
|
||||||
|
Type = "memory"
|
||||||
|
[Server.DataStore]
|
||||||
|
Type = "memory"
|
||||||
|
[Server.GRPC]
|
||||||
|
ListenAddr = ":50051"
|
||||||
|
[Server.GRPC.CACerts]
|
||||||
|
CertificatePath = "/data/ca.pem"
|
||||||
|
CertificateKeyPath = "/data/ca.key"
|
||||||
|
[Server.GRPC.Certs]
|
||||||
|
CertificatePath = "/data/server.pem"
|
||||||
|
CertificateKeyPath = "/data/server.key"
|
||||||
|
[Server.HTTP]
|
||||||
|
ListenAddr = ":8089"
|
||||||
|
`
|
||||||
|
|
||||||
|
var configStrInvalidServerMissingStoreConfig = `
|
||||||
|
[Server]
|
||||||
|
LogLevel = "INFO"
|
||||||
|
Hostname = "localhost"
|
||||||
|
GRPCEndpoint = "localhost:50051"
|
||||||
|
[Server.FileStore]
|
||||||
|
Type = "bolt"
|
||||||
|
[Server.DataStore]
|
||||||
|
Type = "memory"
|
||||||
|
[Server.GRPC]
|
||||||
|
ListenAddr = ":50051"
|
||||||
|
[Server.GRPC.CACerts]
|
||||||
|
CertificatePath = "/data/ca.pem"
|
||||||
|
CertificateKeyPath = "/data/ca.key"
|
||||||
|
[Server.GRPC.Certs]
|
||||||
|
CertificatePath = "/data/server.pem"
|
||||||
|
CertificateKeyPath = "/data/server.key"
|
||||||
|
[Server.HTTP]
|
||||||
|
ListenAddr = ":8089"
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestConfig(t *testing.T) {
|
||||||
|
t.Run("TestValid", func(t *testing.T) {
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Name string
|
||||||
|
ConfigString string
|
||||||
|
ValidForClient bool
|
||||||
|
ValidForServer bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "ExampleConfig",
|
||||||
|
ConfigString: configStrExample,
|
||||||
|
ValidForClient: true,
|
||||||
|
ValidForServer: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ServerValidMinimal",
|
||||||
|
ConfigString: configStrValidServerMinimal,
|
||||||
|
ValidForServer: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ClientValidMinimal",
|
||||||
|
ConfigString: configStrValidClient,
|
||||||
|
ValidForClient: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ServerInvalidMissingStoreConfig",
|
||||||
|
ConfigString: configStrInvalidServerMissingStoreConfig,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range testCases {
|
||||||
|
t.Run(c.Name, func(t *testing.T) {
|
||||||
|
sr := strings.NewReader(c.ConfigString)
|
||||||
|
cfg, err := config.FromReader(sr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error reading config: %s", err)
|
||||||
|
}
|
||||||
|
clientErr := cfg.ValidForClient()
|
||||||
|
serverErr := cfg.ValidForServer()
|
||||||
|
|
||||||
|
if c.ValidForClient && !(clientErr == nil) {
|
||||||
|
t.Errorf("Valid config ValidClientConfig returned wrong result: %s", clientErr)
|
||||||
|
}
|
||||||
|
if !c.ValidForClient && (clientErr == nil) {
|
||||||
|
t.Errorf("Invalid config ValidClientConfig returned wrong result: %s", clientErr)
|
||||||
|
}
|
||||||
|
if c.ValidForServer && !(serverErr == nil) {
|
||||||
|
t.Errorf("Valid config ValidServerConfig returned wrong result: %s", clientErr)
|
||||||
|
}
|
||||||
|
if !c.ValidForServer && (serverErr == nil) {
|
||||||
|
t.Errorf("Invalid config ValidServerConfig returned wrong result: %s", clientErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -34,14 +34,15 @@ Path = "/data/files.db"
|
|||||||
# Required if store-type is filesystem
|
# Required if store-type is filesystem
|
||||||
Dir = "/data"
|
Dir = "/data"
|
||||||
|
|
||||||
[Server.UserStore]
|
[Server.DataStore]
|
||||||
# What store to use for users
|
# What store to use for users, certs and binaries
|
||||||
# Must be one of: memory, bolt
|
# Must be one of: memory, bolt
|
||||||
# Required
|
# Required
|
||||||
Type = "bolt"
|
Type = "bolt"
|
||||||
|
|
||||||
[Server.UserStore.Bolt]
|
[Server.DataStore.Bolt]
|
||||||
# Path to bolt database-file
|
# Path to bolt database-file
|
||||||
|
# Required if Server.Datastore is bolt
|
||||||
Path = "/data/users.db"
|
Path = "/data/users.db"
|
||||||
|
|
||||||
# GRPC Configuration
|
# GRPC Configuration
|
||||||
|
@ -17,6 +17,12 @@ type FileStore interface {
|
|||||||
ListFiles() ([]*pb.ListFilesResponse_ListFileInfo, error)
|
ListFiles() ([]*pb.ListFilesResponse_ListFileInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DataStore interface {
|
||||||
|
BinaryStore
|
||||||
|
CertificateStore
|
||||||
|
UserStore
|
||||||
|
}
|
||||||
|
|
||||||
type CertificateStore interface {
|
type CertificateStore interface {
|
||||||
GetCertificate(serial string) (*x509.Certificate, error)
|
GetCertificate(serial string) (*x509.Certificate, error)
|
||||||
StoreCertificate(cert *x509.Certificate) error
|
StoreCertificate(cert *x509.Certificate) error
|
||||||
|
Loading…
Reference in New Issue
Block a user