working changes

This commit is contained in:
Олег Бородин
2024-07-30 23:14:54 +02:00
parent f605a01b22
commit 42cd5f4800
18 changed files with 702 additions and 72 deletions

View File

@@ -12,12 +12,12 @@ GOFLAGS = -v -ldflags='-s -w -X helmet/certmanager/internal/config.buildVersion=
certmanagerd_SOURCES = cmd/certmanagerd/main.go certmanagerd_SOURCES = cmd/certmanagerd/main.go
certmanagerd$(EXEEXT): $(certmanagerd_SOURCES) $(EXTRA_certmanagerd_SOURCES) certmanagerd$(EXEEXT): $(certmanagerd_SOURCES) $(EXTRA_certmanagerd_SOURCES)
env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o certmanagerd$(EXEEXT) $(certmanagerd_SOURCES) env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o certmanagerd$(EXEEXT) $(certmanagerd_SOURCES)
certmanagerctl_SOURCES = cmd/certmanagerctl/main.go certmanagerctl_SOURCES = cmd/certmanagerctl/main.go
certmanagerctl$(EXEEXT): $(certmanagerctl_SOURCES) $(EXTRA_certmanagerd_SOURCES) certmanagerctl$(EXEEXT): $(certmanagerctl_SOURCES) $(EXTRA_certmanagerd_SOURCES)
env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o certmanagerctl$(EXEEXT) $(certmanagerctl_SOURCES) env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o certmanagerctl$(EXEEXT) $(certmanagerctl_SOURCES)
EXTRA_certmanagerd_SOURCES = EXTRA_certmanagerd_SOURCES =
@@ -29,8 +29,6 @@ grpc:
mkdir -p $(GENDIR) mkdir -p $(GENDIR)
protoc --proto_path=proto --go_out=$(GENDIR) --go-grpc_out=$(GENDIR) proto/certmanagercontrol.proto protoc --proto_path=proto --go_out=$(GENDIR) --go-grpc_out=$(GENDIR) proto/certmanagercontrol.proto
SYSTEMD_LIBDIR = /lib/systemd/system SYSTEMD_LIBDIR = /lib/systemd/system
install-data-local: install-data-local:
@@ -49,7 +47,10 @@ gformat:
done done
run: run:
env CGO_ENABLED=0 $(GO) run $(GOFLAGS) ./cmd/certmanagerd/... --daemon=false test -z $(DESTDIR)$(SRV_LOGDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_LOGDIR)
test -z $(DESTDIR)$(SRV_RUNDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_RUNDIR)
test -z $(DESTDIR)$(SRV_DATADIR) || $(MKDIR_P) $(DESTDIR)$(SRV_DATADIR)
env CGO_ENABLED=1 $(GO) run $(GOFLAGS) ./cmd/certmanagerd/... --daemon=false
distclean-local: clean distclean-local: clean
rm -rf autom4te.cache rm -rf autom4te.cache
@@ -58,4 +59,5 @@ clean-local:
rm -rf autom4te.cache rm -rf autom4te.cache
rm -f cmd/certmanagerd/certmanagerd rm -f cmd/certmanagerd/certmanagerd
rm -f cmd/certmanagerctl/certmanagerctl rm -f cmd/certmanagerctl/certmanagerctl
rm -rf tmp/ rm -rf tmp.*/

View File

@@ -795,9 +795,9 @@ uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS
.PRECIOUS: Makefile .PRECIOUS: Makefile
certmanagerd$(EXEEXT): $(certmanagerd_SOURCES) $(EXTRA_certmanagerd_SOURCES) certmanagerd$(EXEEXT): $(certmanagerd_SOURCES) $(EXTRA_certmanagerd_SOURCES)
env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o certmanagerd$(EXEEXT) $(certmanagerd_SOURCES) env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o certmanagerd$(EXEEXT) $(certmanagerd_SOURCES)
certmanagerctl$(EXEEXT): $(certmanagerctl_SOURCES) $(EXTRA_certmanagerd_SOURCES) certmanagerctl$(EXEEXT): $(certmanagerctl_SOURCES) $(EXTRA_certmanagerd_SOURCES)
env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o certmanagerctl$(EXEEXT) $(certmanagerctl_SOURCES) env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o certmanagerctl$(EXEEXT) $(certmanagerctl_SOURCES)
grpc: grpc:
mkdir -p $(GENDIR) mkdir -p $(GENDIR)
protoc --proto_path=proto --go_out=$(GENDIR) --go-grpc_out=$(GENDIR) proto/certmanagercontrol.proto protoc --proto_path=proto --go_out=$(GENDIR) --go-grpc_out=$(GENDIR) proto/certmanagercontrol.proto
@@ -817,7 +817,10 @@ gformat:
done done
run: run:
env CGO_ENABLED=0 $(GO) run $(GOFLAGS) ./cmd/certmanagerd/... --daemon=false test -z $(DESTDIR)$(SRV_LOGDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_LOGDIR)
test -z $(DESTDIR)$(SRV_RUNDIR) || $(MKDIR_P) $(DESTDIR)$(SRV_RUNDIR)
test -z $(DESTDIR)$(SRV_DATADIR) || $(MKDIR_P) $(DESTDIR)$(SRV_DATADIR)
env CGO_ENABLED=1 $(GO) run $(GOFLAGS) ./cmd/certmanagerd/... --daemon=false
distclean-local: clean distclean-local: clean
rm -rf autom4te.cache rm -rf autom4te.cache
@@ -826,7 +829,7 @@ clean-local:
rm -rf autom4te.cache rm -rf autom4te.cache
rm -f cmd/certmanagerd/certmanagerd rm -f cmd/certmanagerd/certmanagerd
rm -f cmd/certmanagerctl/certmanagerctl rm -f cmd/certmanagerctl/certmanagerctl
rm -rf tmp/ rm -rf tmp.*/
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.

3
go.mod
View File

@@ -7,6 +7,7 @@ require (
github.com/jmoiron/sqlx v1.4.0 github.com/jmoiron/sqlx v1.4.0
github.com/mattn/go-sqlite3 v1.14.22 github.com/mattn/go-sqlite3 v1.14.22
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
google.golang.org/grpc v1.65.0 google.golang.org/grpc v1.65.0
google.golang.org/protobuf v1.34.2 google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@@ -18,6 +19,7 @@ require (
github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect github.com/cloudwego/iasm v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
@@ -31,6 +33,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect

View File

@@ -1,9 +1,8 @@
package config package config
const ( const (
confdirPath = "/home/ziggi/projects/certman/etc/certmanager" confdirPath = "/home/ziggi/projects/certman/etc/certmanager"
rundirPath = "/home/ziggi/projects/certman/tmp.run" rundirPath = "/home/ziggi/projects/certman/tmp.run"
logdirPath = "/home/ziggi/projects/certman/tmp.log" logdirPath = "/home/ziggi/projects/certman/tmp.log"
datadirPath = "/home/ziggi/projects/certman/tmp.data" datadirPath = "/home/ziggi/projects/certman/tmp.data"
) )

View File

@@ -10,49 +10,51 @@ import (
) )
const schema = ` const schema = `
--- DROP TABLE IF EXISTS manifests; DROP TABLE IF EXISTS issuer;
CREATE TABLE IF NOT EXISTS manifests ( CREATE TABLE IF NOT EXISTS issuer (
id VARCHAR(255) NOT NULL, id INT NOT NULL,
name VARCHAR(255) NOT NULL, name TEXT NOT NULL,
reference VARCHAR(255) NOT NULL, cert TEXT NOT NULL,
contentType VARCHAR(255) NOT NULL, key TEXT NOT NULL,
payload VARCHAR(4096) NOT NULL revoked BOOL
); );
CREATE INDEX IF NOT EXISTS manifest_index CREATE INDEX IF NOT EXISTS issuer_index
ON manifests(name, reference); ON issuer(id, name);
CREATE TABLE IF NOT EXISTS blobs ( DROP TABLE IF EXISTS service;
id VARCHAR(255) NOT NULL, CREATE TABLE IF NOT EXISTS service (
name VARCHAR(255) NOT NULL, id INT NOT NULL,
digest VARCHAR(255) NOT NULL, issuer_id INT NOT NULL,
used INTEGER name TEXT NOT NULL,
cert TEXT NOT NULL,
key TEXT NOT NULL,
revoked BOOL
); );
CREATE INDEX IF NOT EXISTS service_index
CREATE INDEX IF NOT EXISTS blobs_index ON issuer(id, name);
ON blobs(name, digest);
` `
type Database struct { type Database struct {
datapath string datapath string
db *sqlx.DB db *sqlx.DB
log *logger.Logger log *logger.Logger
} }
func NewDatabase(datapath string) (*Database, error) { func NewDatabase(datapath string) (*Database, error) {
var err error var err error
db := &Database{ db := &Database{
datapath: datapath, datapath: datapath,
} }
db.log = logger.NewLogger("database") db.log = logger.NewLogger("database")
return db, err return db, err
} }
func (db *Database) InitDatabase() error { func (db *Database) InitDatabase() error {
var err error var err error
dbPath := filepath.Join(db.datapath, "certmanager.db") dbPath := filepath.Join(db.datapath, "certmanager.db")
db.log.Infof("Initialize database %s", dbPath)
db.db, err = sqlx.Open("sqlite3", dbPath) db.db, err = sqlx.Open("sqlite3", dbPath)
if err != nil { if err != nil {
return err return err

101
internal/database/issuer.go Normal file
View File

@@ -0,0 +1,101 @@
package database
import (
"context"
"certmanager/internal/descriptor"
"certmanager/pkg/auxid"
_ "github.com/mattn/go-sqlite3"
)
func (db *Database) InsertIssuer(ctx context.Context, issuer *descriptor.Issuer) (int64, error) {
var err error
var res int64
issuer.ID = auxid.GenID()
request := `INSERT INTO issuer(id, name, cert, key, revoked)
VALUES ($1, $2, $3, $4, $5)`
_, err = db.db.Exec(request, issuer.ID, issuer.Name, issuer.Cert, issuer.Key, issuer.Revoked)
if err != nil {
return res, err
}
res = issuer.ID
return res, err
}
func (db *Database) UpdateIssuerByID(ctx context.Context, issuerID int64, issuer *descriptor.Issuer) error {
var err error
request := `UPDATE issuer SET revoked = $1 WHERE id = $2`
_, err = db.db.Exec(request, issuer.Revoked, issuerID)
if err != nil {
return err
}
return err
}
func (db *Database) ListIssuers(ctx context.Context) ([]descriptor.Issuer, error) {
var err error
request := `SELECT id, name, revoked FROM issuer`
res := make([]descriptor.Issuer, 0)
err = db.db.Select(&res, request)
if err != nil {
return res, err
}
return res, err
}
func (db *Database) GetIssuerByID(ctx context.Context, issuerID int64) (bool, *descriptor.Issuer, error) {
var err error
var res *descriptor.Issuer
var exists bool
request := `SELECT id, name, cert, key, revoked FROM issuer WHERE id = $1 LiMIT 1`
dbRes := make([]descriptor.Issuer, 0)
err = db.db.Select(&dbRes, request, issuerID)
if err != nil {
return exists, res, err
}
if len(dbRes) == 0 {
return exists, res, err
}
exists = true
res = &dbRes[0]
return exists, res, err
}
func (db *Database) GetIssuerByName(ctx context.Context, issuerName string) (bool, *descriptor.Issuer, error) {
var err error
var res *descriptor.Issuer
var exists bool
request := `SELECT id, name, cert, key, revoked FROM issuer WHERE name = $1 LIMIT 1`
dbRes := make([]descriptor.Issuer, 0)
err = db.db.Select(&dbRes, request, issuerName)
if err != nil {
return exists, res, err
}
if len(dbRes) == 0 {
return exists, res, err
}
exists = true
res = &dbRes[0]
return exists, res, err
}
func (db *Database) DeleteIssuerByID(ctx context.Context, issuerID int64) error {
var err error
request := `DELETE FROM issuer WHERE id = $1`
_, err = db.db.Exec(request, issuerID)
if err != nil {
return err
}
return err
}
func (db *Database) DeleteIssuerByName(ctx context.Context, issuerName string) error {
var err error
request := `DELETE FROM issuer WHERE name = $1`
_, err = db.db.Exec(request, issuerName)
if err != nil {
return err
}
return err
}

View File

@@ -0,0 +1,102 @@
package database
import (
"context"
"certmanager/internal/descriptor"
"certmanager/pkg/auxid"
_ "github.com/mattn/go-sqlite3"
)
func (db *Database) InsertService(ctx context.Context, service *descriptor.Service) (int64, error) {
var err error
var res int64
service.ID = auxid.GenID()
request := `INSERT INTO service(id, issuer_id, name, cert, key, revoked)
VALUES ($1, $2, $3, $4, $5, $6)`
_, err = db.db.Exec(request, service.ID, service.IssuerID, service.Name, service.Cert,
service.Key, service.Revoked)
if err != nil {
return res, err
}
res = service.ID
return res, err
}
func (db *Database) UpdateServiceByID(ctx context.Context, serviceID int64, service *descriptor.Service) error {
var err error
request := `UPDATE service SET revoked = $1 WHERE id = $2`
_, err = db.db.Exec(request, service.Revoked, serviceID)
if err != nil {
return err
}
return err
}
func (db *Database) ListServices(ctx context.Context) ([]descriptor.Service, error) {
var err error
request := `SELECT id, name, revoked FROM service`
res := make([]descriptor.Service, 0)
err = db.db.Select(&res, request)
if err != nil {
return res, err
}
return res, err
}
func (db *Database) GetServiceByID(ctx context.Context, serviceID int64) (bool, *descriptor.Service, error) {
var err error
var res *descriptor.Service
var exists bool
request := `SELECT id, name, cert, key, revoked FROM service WHERE id = $1 LiMIT 1`
dbRes := make([]descriptor.Service, 0)
err = db.db.Select(&dbRes, request, serviceID)
if err != nil {
return exists, res, err
}
if len(dbRes) == 0 {
return exists, res, err
}
exists = true
res = &dbRes[0]
return exists, res, err
}
func (db *Database) GetServiceByName(ctx context.Context, serviceName string) (bool, *descriptor.Service, error) {
var err error
var res *descriptor.Service
var exists bool
request := `SELECT id, name, cert, key, revoked FROM service WHERE name = $1 LIMIT 1`
dbRes := make([]descriptor.Service, 0)
err = db.db.Select(&dbRes, request, serviceName)
if err != nil {
return exists, res, err
}
if len(dbRes) == 0 {
return exists, res, err
}
exists = true
res = &dbRes[0]
return exists, res, err
}
func (db *Database) DeleteServiceByID(ctx context.Context, serviceID int64) error {
var err error
request := `DELETE FROM service WHERE id = $1`
_, err = db.db.Exec(request, serviceID)
if err != nil {
return err
}
return err
}
func (db *Database) DeleteServiceByName(ctx context.Context, serviceName string) error {
var err error
request := `DELETE FROM service WHERE name = $1`
_, err = db.db.Exec(request, serviceName)
if err != nil {
return err
}
return err
}

View File

@@ -1,3 +1,18 @@
package descriptor package descriptor
type Issuer struct {
ID int64 `json:"id" yaml:"id" db:"id"`
Name string `json:"name" yaml:"name" db:"name"`
Cert string `json:"cert" yaml:"cert" db:"cert"`
Key string `json:"key" yaml:"key" db:"key"`
Revoked bool `json:"revoked" yaml:"revoked" db:"revoked"`
}
type Service struct {
ID int64 `json:"id" yaml:"id" db:"id"`
IssuerID int64 `json:"issuerId" yaml:"issuerId" db:"issuer_id"`
Name string `json:"name" yaml:"name" db:"name"`
Cert string `json:"cert" yaml:"cert" db:"cert"`
Key string `json:"key" yaml:"key" db:"key"`
Revoked bool `json:"revoked" yaml:"revoked" db:"revoked"`
}

View File

@@ -6,7 +6,6 @@ import (
"certmanager/api/certmanagercontrol" "certmanager/api/certmanagercontrol"
) )
func (hand *Handler) CreateIssuerPair(ctx context.Context, req *certmanagercontrol.CreateIssuerPairParams) (*certmanagercontrol.CreateIssuerPairResult, error) { func (hand *Handler) CreateIssuerPair(ctx context.Context, req *certmanagercontrol.CreateIssuerPairParams) (*certmanagercontrol.CreateIssuerPairResult, error) {
var err error var err error
hand.log.Debugf("Handle CreateIssuerPair request") hand.log.Debugf("Handle CreateIssuerPair request")

View File

@@ -2,66 +2,90 @@ package logic
import ( import (
"context" "context"
"encoding/base64"
"encoding/json"
"certmanager/api/certmanagercontrol" cmapi "certmanager/api/certmanagercontrol"
"certmanager/internal/descriptor"
//yaml "gopkg.in/yaml.v3"
) )
func (lg *Logic) CreateIssuerPair(ctx context.Context, params *certmanagercontrol.CreateIssuerPairParams) (*certmanagercontrol.CreateIssuerPairResult, error) { func (lg *Logic) CreateIssuerPair(ctx context.Context, params *cmapi.CreateIssuerPairParams) (*cmapi.CreateIssuerPairResult, error) {
var err error var err error
res := &certmanagercontrol.CreateIssuerPairResult{} res := &cmapi.CreateIssuerPairResult{}
paramsJson, err := json.Marshal(params)
if err != nil {
return res, err
}
lg.log.Debugf("params: \n%s\n", string(paramsJson))
certBytes, keyBytes, err := CreateX509SelfSignedCert(params.IssuerName)
certString := base64.StdEncoding.EncodeToString(certBytes)
keyString := base64.StdEncoding.EncodeToString(keyBytes)
issuer := &descriptor.Issuer{
Name: params.IssuerName,
Cert: certString,
Key: keyString,
}
issuerID, err := lg.db.InsertIssuer(ctx, issuer)
if err != nil {
return res, err
}
res.IssuerID = issuerID
return res, err return res, err
} }
func (lg *Logic) ImportIssuerPair(ctx context.Context, params *certmanagercontrol.ImportIssuerPairParams) (*certmanagercontrol.ImportIssuerPairResult, error) { func (lg *Logic) ImportIssuerPair(ctx context.Context, params *cmapi.ImportIssuerPairParams) (*cmapi.ImportIssuerPairResult, error) {
var err error var err error
res := &certmanagercontrol.ImportIssuerPairResult{} res := &cmapi.ImportIssuerPairResult{}
return res, err return res, err
} }
func (lg *Logic) RevokeIssuerPair(ctx context.Context, params *certmanagercontrol.RevokeIssuerPairParams) (*certmanagercontrol.RevokeIssuerPairResult, error) { func (lg *Logic) RevokeIssuerPair(ctx context.Context, params *cmapi.RevokeIssuerPairParams) (*cmapi.RevokeIssuerPairResult, error) {
var err error var err error
res := &certmanagercontrol.RevokeIssuerPairResult{} res := &cmapi.RevokeIssuerPairResult{}
return res, err return res, err
} }
func (lg *Logic) UnrevokeIssuerPair(ctx context.Context, params *certmanagercontrol.UnrevokeIssuerPairParams) (*certmanagercontrol.UnrevokeIssuerPairResult, error) { func (lg *Logic) UnrevokeIssuerPair(ctx context.Context, params *cmapi.UnrevokeIssuerPairParams) (*cmapi.UnrevokeIssuerPairResult, error) {
var err error var err error
res := &certmanagercontrol.UnrevokeIssuerPairResult{} res := &cmapi.UnrevokeIssuerPairResult{}
return res, err return res, err
} }
func (lg *Logic) ListIssuerPairs(ctx context.Context, params *certmanagercontrol.ListIssuerPairsParams) (*certmanagercontrol.ListIssuerPairsResult, error) { func (lg *Logic) ListIssuerPairs(ctx context.Context, params *cmapi.ListIssuerPairsParams) (*cmapi.ListIssuerPairsResult, error) {
var err error var err error
res := &certmanagercontrol.ListIssuerPairsResult{} res := &cmapi.ListIssuerPairsResult{}
return res, err return res, err
} }
func (lg *Logic) GetIssuerCertificate(ctx context.Context, params *certmanagercontrol.GetIssuerCertificateParams) (*certmanagercontrol.GetIssuerCertificateResult, error) { func (lg *Logic) GetIssuerCertificate(ctx context.Context, params *cmapi.GetIssuerCertificateParams) (*cmapi.GetIssuerCertificateResult, error) {
var err error var err error
res := &certmanagercontrol.GetIssuerCertificateResult{} res := &cmapi.GetIssuerCertificateResult{}
return res, err return res, err
} }
func (lg *Logic) CreateServicePair(ctx context.Context, params *certmanagercontrol.CreateServicePairParams) (*certmanagercontrol.CreateServicePairResult, error) { func (lg *Logic) CreateServicePair(ctx context.Context, params *cmapi.CreateServicePairParams) (*cmapi.CreateServicePairResult, error) {
var err error var err error
res := &certmanagercontrol.CreateServicePairResult{} res := &cmapi.CreateServicePairResult{}
return res, err return res, err
} }
func (lg *Logic) RevokeServicePair(ctx context.Context, params *certmanagercontrol.RevokeServicePairParams) (*certmanagercontrol.RevokeServicePairResult, error) { func (lg *Logic) RevokeServicePair(ctx context.Context, params *cmapi.RevokeServicePairParams) (*cmapi.RevokeServicePairResult, error) {
var err error var err error
res := &certmanagercontrol.RevokeServicePairResult{} res := &cmapi.RevokeServicePairResult{}
return res, err return res, err
} }
func (lg *Logic) ListServicePairs(ctx context.Context, params *certmanagercontrol.ListServicePairsParams) (*certmanagercontrol.ListServicePairsResult, error) { func (lg *Logic) ListServicePairs(ctx context.Context, params *cmapi.ListServicePairsParams) (*cmapi.ListServicePairsResult, error) {
var err error var err error
res := &certmanagercontrol.ListServicePairsResult{} res := &cmapi.ListServicePairsResult{}
return res, err return res, err
} }
func (lg *Logic) GetServicePair(ctx context.Context, params *certmanagercontrol.GetServicePairParams) (*certmanagercontrol.GetServicePairResult, error) { func (lg *Logic) GetServicePair(ctx context.Context, params *cmapi.GetServicePairParams) (*cmapi.GetServicePairResult, error) {
var err error var err error
res := &certmanagercontrol.GetServicePairResult{} res := &cmapi.GetServicePairResult{}
return res, err return res, err
} }

View File

@@ -7,21 +7,21 @@ import (
) )
type LogicConfig struct { type LogicConfig struct {
Database *database.Database Database *database.Database
Auths []config.AuthConfig Auths []config.AuthConfig
} }
type Logic struct { type Logic struct {
auths []config.AuthConfig auths []config.AuthConfig
log *logger.Logger log *logger.Logger
db *database.Database db *database.Database
} }
func NewLogic(conf *LogicConfig) (*Logic, error) { func NewLogic(conf *LogicConfig) (*Logic, error) {
var err error var err error
lg := &Logic{ lg := &Logic{
db: conf.Database, db: conf.Database,
auths: conf.Auths, auths: conf.Auths,
} }
lg.log = logger.NewLogger("logic") lg.log = logger.NewLogger("logic")
return lg, err return lg, err

176
internal/logic/x509.go Normal file
View File

@@ -0,0 +1,176 @@
package logic
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net"
"time"
)
func CreateX509SelfSignedCert(subject string, commonNames ...string) ([]byte, []byte, error) {
var err error
certPem := make([]byte, 0)
keyPem := make([]byte, 0)
now := time.Now()
const yearsAfter int = 10
const keySize int = 2048
key, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
err := fmt.Errorf("Can't create a private key: %v", err)
return certPem, keyPem, err
}
keyPemBlock := pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
}
keyPem = pem.EncodeToMemory(&keyPemBlock)
dnsNames := make([]string, 0)
dnsNames = append(dnsNames, subject)
dnsNames = append(dnsNames, commonNames...)
tml := x509.Certificate{
SerialNumber: big.NewInt(now.Unix()),
NotBefore: now,
NotAfter: now.AddDate(yearsAfter, 0, 0),
Subject: pkix.Name{
CommonName: subject,
},
DNSNames: dnsNames,
IPAddresses: []net.IP{net.ParseIP("192.168.57.1")},
BasicConstraintsValid: true,
}
certBytes, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key)
if err != nil {
return certPem, keyPem, fmt.Errorf("Can't create a certificate: %v", err)
}
certPemBlock := pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
certPem = pem.EncodeToMemory(&certPemBlock)
if err != nil {
return certPem, keyPem, err
}
return certPem, keyPem, err
}
func CreateX509CACert(commonName string) ([]byte, []byte, error) {
var err error
certPem := make([]byte, 0)
keyPem := make([]byte, 0)
now := time.Now()
const yearsAfter int = 10
const keySize int = 2048
key, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
err := fmt.Errorf("Can't create a private key: %v", err)
return certPem, keyPem, err
}
keyPemBlock := pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
}
keyPem = pem.EncodeToMemory(&keyPemBlock)
tml := x509.Certificate{
SerialNumber: big.NewInt(now.Unix()),
NotBefore: now,
NotAfter: now.AddDate(yearsAfter, 0, 0),
Subject: pkix.Name{
CommonName: commonName,
},
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
certBytes, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key)
if err != nil {
return certPem, keyPem, fmt.Errorf("Can't create a certificate: %v", err)
}
certPemBlock := pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
certPem = pem.EncodeToMemory(&certPemBlock)
if err != nil {
return certPem, keyPem, err
}
return certPem, keyPem, err
}
func CreateX509Cert(commonName string, caKeyPem []byte, dnsNames ...string) ([]byte, []byte, error) {
var err error
certPem := make([]byte, 0)
keyPem := make([]byte, 0)
now := time.Now()
const yearsAfter int = 10
const keySize int = 2048
key, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
err := fmt.Errorf("Can't create a private key: %v", err)
return certPem, keyPem, err
}
keyPemBlock := pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(key),
}
keyPem = pem.EncodeToMemory(&keyPemBlock)
pemBlock, _ := pem.Decode(caKeyPem)
if pemBlock == nil {
err := fmt.Errorf("Can't parse a CA private key block")
return certPem, keyPem, err
}
caKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
if err != nil {
err := fmt.Errorf("Can't parse a CA private key")
return certPem, keyPem, err
}
tml := x509.Certificate{
SerialNumber: big.NewInt(now.Unix()),
NotBefore: now,
NotAfter: now.AddDate(yearsAfter, 0, 0),
Subject: pkix.Name{
CommonName: commonName,
},
DNSNames: append([]string{commonName}, dnsNames...),
IsCA: false,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
}
certBytes, err := x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, caKey)
if err != nil {
return certPem, keyPem, fmt.Errorf("Can't create a certificate: %v", err)
}
certPemBlock := pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
}
certPem = pem.EncodeToMemory(&certPemBlock)
if err != nil {
return certPem, keyPem, err
}
return certPem, keyPem, err
}

View File

@@ -85,8 +85,8 @@ func (srv *Server) Build() error {
// Create logic // Create logic
logicConfig := &logic.LogicConfig{ logicConfig := &logic.LogicConfig{
Auths: srv.conf.Auths, Auths: srv.conf.Auths,
Database: srv.db, Database: srv.db,
} }
srv.lg, err = logic.NewLogic(logicConfig) srv.lg, err = logic.NewLogic(logicConfig)
if err != nil { if err != nil {
@@ -149,13 +149,19 @@ func (srv *Server) Run() error {
} }
srv.log.Debugf("Server configuration:\n%s\n", yamlConfig) srv.log.Debugf("Server configuration:\n%s\n", yamlConfig)
// Show current user // Show current user
currUser, err := user.Current() currUser, err := user.Current()
if err != nil { if err != nil {
return err return err
} }
srv.log.Infof("Running server as user %s", currUser.Username) srv.log.Infof("Running server as user %s", currUser.Username)
// Show current user
err = srv.db.InitDatabase()
if err != nil {
return err
}
sigs := make(chan os.Signal, 1) sigs := make(chan os.Signal, 1)
gdone := make(chan error, 1) gdone := make(chan error, 1)
wdone := make(chan error, 1) wdone := make(chan error, 1)

View File

@@ -0,0 +1,118 @@
package test
import (
"context"
"fmt"
"testing"
"time"
"certmanager/internal/config"
"certmanager/internal/database"
"certmanager/internal/descriptor"
"github.com/stretchr/testify/require"
yaml "gopkg.in/yaml.v3"
)
func TestDatabaseIssuer(t *testing.T) {
var err error
conf := config.NewConfig()
err = conf.ReadFile()
require.NoError(t, err)
db, err := database.NewDatabase(conf.DataDir)
require.NoError(t, err)
require.NotNil(t, db)
err = db.InitDatabase()
require.NoError(t, err)
ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
issuer := &descriptor.Issuer{
Name: "foo.bar",
Cert: "ASDFF",
Key: "QWERT",
Revoked: true,
}
issuerID, err := db.InsertIssuer(ctx, issuer)
require.NoError(t, err)
fmt.Printf("issuerId: %d\n", issuerID)
issuer.Revoked = true
err = db.UpdateIssuerByID(ctx, issuerID, issuer)
require.NoError(t, err)
issuerExists, issuer, err := db.GetIssuerByID(ctx, issuerID)
require.NoError(t, err)
require.True(t, issuerExists)
require.NotNil(t, issuer)
require.True(t, issuer.Revoked)
issuerYAML, err := yaml.Marshal(issuer)
require.NoError(t, err)
fmt.Printf("Issuer: \n%s\n---\n", string(issuerYAML))
listIssuers, err := db.ListIssuers(ctx)
require.NoError(t, err)
require.NotNil(t, listIssuers)
listIssuersYAML, err := yaml.Marshal(listIssuers)
require.NoError(t, err)
fmt.Printf("listIssuers: \n%s\n", string(listIssuersYAML))
err = db.DeleteIssuerByID(ctx, issuerID)
require.NoError(t, err)
}
func TestDatabaseService(t *testing.T) {
var err error
conf := config.NewConfig()
err = conf.ReadFile()
require.NoError(t, err)
db, err := database.NewDatabase(conf.DataDir)
require.NoError(t, err)
require.NotNil(t, db)
err = db.InitDatabase()
require.NoError(t, err)
ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
service := &descriptor.Service{
Name: "foo.bar",
IssuerID: 123456,
Cert: "ASDFF",
Key: "QWERT",
Revoked: true,
}
serviceID, err := db.InsertService(ctx, service)
require.NoError(t, err)
fmt.Printf("serviceId: %d\n", serviceID)
service.Revoked = true
err = db.UpdateServiceByID(ctx, serviceID, service)
require.NoError(t, err)
serviceExists, service, err := db.GetServiceByID(ctx, serviceID)
require.NoError(t, err)
require.True(t, serviceExists)
require.NotNil(t, service)
require.True(t, service.Revoked)
serviceYAML, err := yaml.Marshal(service)
require.NoError(t, err)
fmt.Printf("Service: \n%s\n---\n", string(serviceYAML))
listServices, err := db.ListServices(ctx)
require.NoError(t, err)
require.NotNil(t, listServices)
listServicesYAML, err := yaml.Marshal(listServices)
require.NoError(t, err)
fmt.Printf("listServices: \n%s\n", string(listServicesYAML))
err = db.DeleteServiceByID(ctx, serviceID)
require.NoError(t, err)
}

View File

@@ -0,0 +1,50 @@
package test
import (
"context"
"fmt"
"testing"
"time"
cmapi "certmanager/api/certmanagercontrol"
"certmanager/internal/config"
"certmanager/internal/database"
"certmanager/internal/logic"
"github.com/stretchr/testify/require"
)
func TestLogicIssuer(t *testing.T) {
var err error
conf := config.NewConfig()
err = conf.ReadFile()
require.NoError(t, err)
db, err := database.NewDatabase(conf.DataDir)
require.NoError(t, err)
require.NotNil(t, db)
err = db.InitDatabase()
require.NoError(t, err)
logicConfig := &logic.LogicConfig{
Auths: conf.Auths,
Database: db,
}
lg, err := logic.NewLogic(logicConfig)
require.NoError(t, err)
require.NotNil(t, lg)
ctx, _ := context.WithTimeout(context.Background(), 1*time.Second)
createIssuerPairParams := &cmapi.CreateIssuerPairParams{
SelfSigned: true,
IssuerName: "foo.bar",
}
createIssuerPairRes, err := lg.CreateIssuerPair(ctx, createIssuerPairParams)
require.NoError(t, err)
require.NotNil(t, createIssuerPairRes)
fmt.Printf("issuerId: %d\n", createIssuerPairRes.IssuerID)
}

32
pkg/auxid/genid.go Normal file
View File

@@ -0,0 +1,32 @@
package auxid
import (
"math/rand"
"sync"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
var (
idMtx sync.Mutex
lastID int64
)
func GenID() int64 {
// 53 bit limit for js
// See https://stackoverflow.com/questions/1379934/large-numbers-erroneously-rounded-in-javascript
idMtx.Lock()
defer idMtx.Unlock()
for {
id := (time.Now().UnixNano() / 1000) // - 10000000000000
if id != lastID {
lastID = id
return id
}
time.Sleep(1 * time.Microsecond)
}
//10467328383814
}

View File

@@ -24,7 +24,6 @@ type Access struct {
Password string Password string
} }
type Control struct { type Control struct {
conn *grpc.ClientConn conn *grpc.ClientConn
client cmapi.ControlClient client cmapi.ControlClient

View File

@@ -1,2 +1 @@
package common package common