feat(licenses): sync between portainer and license-server (#41)

* feat(license): add sync service

* feat(licenses): check license server

* chore(deps): update liblicense

* feat(license): revoke license if invalid

* feat(license): log revokation

* - removed retry logics
- removed license sync logging
* revert liblicense version

* - remove not used field

Co-authored-by: yi-portainer <yi.chen@portainer.io>
This commit is contained in:
Chaim Lev-Ari
2020-11-04 03:07:45 +02:00
committed by GitHub
parent 7e768a54d5
commit cec0ef17e0
5 changed files with 115 additions and 4 deletions
+6
View File
@@ -79,6 +79,12 @@ func (service *Service) AddLicense(licenseKey string, license *liblicense.Portai
})
}
// UpdateLicense updates a license.
func (service *Service) UpdateLicense(licenseKey string, license *liblicense.PortainerLicense) error {
identifier := []byte(licenseKey)
return internal.UpdateObject(service.db, BucketName, identifier, license)
}
// DeleteLicense deletes a License.
func (service *Service) DeleteLicense(licenseKey string) error {
identifier := []byte(licenseKey)
+5
View File
@@ -463,6 +463,11 @@ func main() {
log.Fatal(err)
}
err = licenseService.Start()
if err != nil {
log.Fatalf("failed starting license service: %w", err)
}
var server portainer.Server = &http.Server{
ReverseTunnelService: reverseTunnelService,
Status: applicationStatus,
+39 -4
View File
@@ -2,22 +2,33 @@ package license
import (
"errors"
"github.com/portainer/liblicense"
"github.com/portainer/liblicense/master"
"github.com/portainer/portainer/api"
"log"
"time"
"github.com/portainer/liblicense"
"github.com/portainer/liblicense/master"
portainer "github.com/portainer/portainer/api"
)
// Service represents a service for managing portainer licenses
type Service struct {
repository portainer.LicenseRepository
info *portainer.LicenseInfo
stopSignal chan struct{}
}
// NewService creates a new instance of Service
func NewService(repository portainer.LicenseRepository) *Service {
return &Service{repository: repository, info: nil}
return &Service{
repository: repository,
info: nil,
stopSignal: nil,
}
}
// Start starts the service
func (service *Service) Start() error {
return service.startSyncLoop()
}
// Info returns aggregation of the information about the existing licenses
@@ -120,6 +131,30 @@ func (service *Service) DeleteLicense(licenseKey string) error {
return nil
}
// revokeLicense revokes the license
func (service *Service) revokeLicense(licenseKey string) error {
license, err := service.repository.License(licenseKey)
if err != nil {
return err
}
license.Revoked = true
err = service.repository.UpdateLicense(licenseKey, license)
if err != nil {
return err
}
licenses, err := service.Licenses()
if err != nil {
return err
}
service.info = aggregate(licenses)
return nil
}
func aggregate(licenses []liblicense.PortainerLicense) *portainer.LicenseInfo {
nodes := 0
var expiresAt time.Time
+64
View File
@@ -0,0 +1,64 @@
package license
import (
"time"
"github.com/portainer/liblicense/master"
)
const (
syncInterval = 5 * time.Minute
)
func (service *Service) startSyncLoop() error {
if service.stopSignal != nil {
return nil
}
err := service.syncLicenses()
if err != nil {
return err
}
service.stopSignal = make(chan struct{})
ticker := time.NewTicker(syncInterval)
go (func() {
for {
select {
case <-service.stopSignal:
ticker.Stop()
return
case <-ticker.C:
service.syncLicenses()
}
}
})()
return nil
}
func (service *Service) syncLicenses() error {
licenses, err := service.Licenses()
if err != nil {
return err
}
licensesToRemove := []string{}
for _, license := range licenses {
valid, err := master.ValidateLicense(&license)
if err != nil || !valid {
licensesToRemove = append(licensesToRemove, license.LicenseKey)
}
}
for _, licenseKey := range licensesToRemove {
err := service.revokeLicense(licenseKey)
if err != nil {
return err
}
}
return nil
}
+1
View File
@@ -1058,6 +1058,7 @@ type (
Licenses() ([]liblicense.PortainerLicense, error)
License(licenseKey string) (*liblicense.PortainerLicense, error)
AddLicense(licenseKey string, license *liblicense.PortainerLicense) error
UpdateLicense(licenseKey string, license *liblicense.PortainerLicense) error
DeleteLicense(licenseKey string) error
}