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$(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$(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 =
@@ -29,8 +29,6 @@ grpc:
mkdir -p $(GENDIR)
protoc --proto_path=proto --go_out=$(GENDIR) --go-grpc_out=$(GENDIR) proto/certmanagercontrol.proto
SYSTEMD_LIBDIR = /lib/systemd/system
install-data-local:
@@ -49,7 +47,10 @@ gformat:
done
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
rm -rf autom4te.cache
@@ -58,4 +59,5 @@ clean-local:
rm -rf autom4te.cache
rm -f cmd/certmanagerd/certmanagerd
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
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)
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:
mkdir -p $(GENDIR)
protoc --proto_path=proto --go_out=$(GENDIR) --go-grpc_out=$(GENDIR) proto/certmanagercontrol.proto
@@ -817,7 +817,10 @@ gformat:
done
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
rm -rf autom4te.cache
@@ -826,7 +829,7 @@ clean-local:
rm -rf autom4te.cache
rm -f cmd/certmanagerd/certmanagerd
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.
# 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/mattn/go-sqlite3 v1.14.22
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
google.golang.org/grpc v1.65.0
google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v3 v3.0.1
@@ -18,6 +19,7 @@ require (
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // 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/gin-contrib/sse v0.1.0 // 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/reflect2 v1.0.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/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect

View File

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

View File

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

View File

@@ -2,66 +2,90 @@ package logic
import (
"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
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
}
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
res := &certmanagercontrol.ImportIssuerPairResult{}
res := &cmapi.ImportIssuerPairResult{}
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
res := &certmanagercontrol.RevokeIssuerPairResult{}
res := &cmapi.RevokeIssuerPairResult{}
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
res := &certmanagercontrol.UnrevokeIssuerPairResult{}
res := &cmapi.UnrevokeIssuerPairResult{}
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
res := &certmanagercontrol.ListIssuerPairsResult{}
res := &cmapi.ListIssuerPairsResult{}
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
res := &certmanagercontrol.GetIssuerCertificateResult{}
res := &cmapi.GetIssuerCertificateResult{}
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
res := &certmanagercontrol.CreateServicePairResult{}
res := &cmapi.CreateServicePairResult{}
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
res := &certmanagercontrol.RevokeServicePairResult{}
res := &cmapi.RevokeServicePairResult{}
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
res := &certmanagercontrol.ListServicePairsResult{}
res := &cmapi.ListServicePairsResult{}
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
res := &certmanagercontrol.GetServicePairResult{}
res := &cmapi.GetServicePairResult{}
return res, err
}

View File

@@ -7,21 +7,21 @@ import (
)
type LogicConfig struct {
Database *database.Database
Auths []config.AuthConfig
Database *database.Database
Auths []config.AuthConfig
}
type Logic struct {
auths []config.AuthConfig
log *logger.Logger
db *database.Database
auths []config.AuthConfig
log *logger.Logger
db *database.Database
}
func NewLogic(conf *LogicConfig) (*Logic, error) {
var err error
lg := &Logic{
db: conf.Database,
auths: conf.Auths,
db: conf.Database,
auths: conf.Auths,
}
lg.log = logger.NewLogger("logic")
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
logicConfig := &logic.LogicConfig{
Auths: srv.conf.Auths,
Database: srv.db,
Auths: srv.conf.Auths,
Database: srv.db,
}
srv.lg, err = logic.NewLogic(logicConfig)
if err != nil {
@@ -149,13 +149,19 @@ func (srv *Server) Run() error {
}
srv.log.Debugf("Server configuration:\n%s\n", yamlConfig)
// Show current user
// Show current user
currUser, err := user.Current()
if err != nil {
return err
}
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)
gdone := 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
}
type Control struct {
conn *grpc.ClientConn
client cmapi.ControlClient

View File

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