Compare commits
8 Commits
develop
...
feat/EE-18
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa0878a18a | ||
|
|
fa921f5ae8 | ||
|
|
ca91db6bd8 | ||
|
|
d6e8bf8d2b | ||
|
|
09cf63c63a | ||
|
|
71079a76f7 | ||
|
|
64c96e613c | ||
|
|
7e7e32932f |
@@ -42,7 +42,7 @@ func (service *Service) GetAPIKeysByUserID(userID portainer.UserID) ([]portainer
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var record portainer.APIKey
|
||||
err := internal.UnmarshalObject(v, &record)
|
||||
err := internal.UnmarshalObject(v, &record, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func (service *Service) GetAPIKeyByDigest(digest []byte) (*portainer.APIKey, err
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var record portainer.APIKey
|
||||
err := internal.UnmarshalObject(v, &record)
|
||||
err := internal.UnmarshalObject(v, &record, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func (service *Service) CreateAPIKey(record *portainer.APIKey) error {
|
||||
id, _ := bucket.NextSequence()
|
||||
record.ID = portainer.APIKeyID(id)
|
||||
|
||||
data, err := internal.MarshalObject(record)
|
||||
data, err := internal.MarshalObject(record, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (service *Service) GetAPIKey(keyID portainer.APIKeyID) (*portainer.APIKey,
|
||||
return errors.ErrObjectNotFound
|
||||
}
|
||||
|
||||
err := internal.UnmarshalObject(item, &apiKey)
|
||||
err := internal.UnmarshalObject(item, &apiKey, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func (service *Service) CustomTemplates() ([]portainer.CustomTemplate, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var customTemplate portainer.CustomTemplate
|
||||
err := internal.UnmarshalObjectWithJsoniter(v, &customTemplate)
|
||||
err := internal.UnmarshalObjectWithJsoniter(v, &customTemplate, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -81,7 +81,7 @@ func (service *Service) CreateCustomTemplate(customTemplate *portainer.CustomTem
|
||||
return service.connection.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket([]byte(BucketName))
|
||||
|
||||
data, err := internal.MarshalObject(customTemplate)
|
||||
data, err := internal.MarshalObject(customTemplate, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -92,12 +92,12 @@ func (store *Store) edition() portainer.SoftwareEdition {
|
||||
}
|
||||
|
||||
// NewStore initializes a new Store and the associated services
|
||||
func NewStore(storePath string, fileService portainer.FileService) *Store {
|
||||
func NewStore(storePath string, fileService portainer.FileService, encryptionKey string) *Store {
|
||||
return &Store{
|
||||
path: storePath,
|
||||
fileService: fileService,
|
||||
isNew: true,
|
||||
connection: &internal.DbConnection{},
|
||||
connection: &internal.DbConnection{EncryptionKey: encryptionKey},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ func (service *Service) EdgeGroups() ([]portainer.EdgeGroup, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var group portainer.EdgeGroup
|
||||
err := internal.UnmarshalObjectWithJsoniter(v, &group)
|
||||
err := internal.UnmarshalObjectWithJsoniter(v, &group, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (service *Service) CreateEdgeGroup(group *portainer.EdgeGroup) error {
|
||||
id, _ := bucket.NextSequence()
|
||||
group.ID = portainer.EdgeGroupID(id)
|
||||
|
||||
data, err := internal.MarshalObject(group)
|
||||
data, err := internal.MarshalObject(group, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func (service *Service) EdgeJobs() ([]portainer.EdgeJob, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var edgeJob portainer.EdgeJob
|
||||
err := internal.UnmarshalObject(v, &edgeJob)
|
||||
err := internal.UnmarshalObject(v, &edgeJob, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func (service *Service) CreateEdgeJob(edgeJob *portainer.EdgeJob) error {
|
||||
edgeJob.ID = portainer.EdgeJobID(id)
|
||||
}
|
||||
|
||||
data, err := internal.MarshalObject(edgeJob)
|
||||
data, err := internal.MarshalObject(edgeJob, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func (service *Service) EdgeStacks() ([]portainer.EdgeStack, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var stack portainer.EdgeStack
|
||||
err := internal.UnmarshalObject(v, &stack)
|
||||
err := internal.UnmarshalObject(v, &stack, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func (service *Service) CreateEdgeStack(edgeStack *portainer.EdgeStack) error {
|
||||
edgeStack.ID = portainer.EdgeStackID(id)
|
||||
}
|
||||
|
||||
data, err := internal.MarshalObject(edgeStack)
|
||||
data, err := internal.MarshalObject(edgeStack, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ func (service *Service) Endpoints() ([]portainer.Endpoint, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var endpoint portainer.Endpoint
|
||||
err := internal.UnmarshalObjectWithJsoniter(v, &endpoint)
|
||||
err := internal.UnmarshalObjectWithJsoniter(v, &endpoint, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -87,7 +87,7 @@ func (service *Service) CreateEndpoint(endpoint *portainer.Endpoint) error {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := internal.MarshalObject(endpoint)
|
||||
data, err := internal.MarshalObject(endpoint, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -110,7 +110,7 @@ func (service *Service) Synchronize(toCreate, toUpdate, toDelete []*portainer.En
|
||||
id, _ := bucket.NextSequence()
|
||||
endpoint.ID = portainer.EndpointID(id)
|
||||
|
||||
data, err := internal.MarshalObject(endpoint)
|
||||
data, err := internal.MarshalObject(endpoint, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func (service *Service) Synchronize(toCreate, toUpdate, toDelete []*portainer.En
|
||||
}
|
||||
|
||||
for _, endpoint := range toUpdate {
|
||||
data, err := internal.MarshalObject(endpoint)
|
||||
data, err := internal.MarshalObject(endpoint, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func (service *Service) EndpointGroups() ([]portainer.EndpointGroup, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var endpointGroup portainer.EndpointGroup
|
||||
err := internal.UnmarshalObject(v, &endpointGroup)
|
||||
err := internal.UnmarshalObject(v, &endpointGroup, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func (service *Service) CreateEndpointGroup(endpointGroup *portainer.EndpointGro
|
||||
id, _ := bucket.NextSequence()
|
||||
endpointGroup.ID = portainer.EndpointGroupID(id)
|
||||
|
||||
data, err := internal.MarshalObject(endpointGroup)
|
||||
data, err := internal.MarshalObject(endpointGroup, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func (service *Service) CreateEndpointRelation(endpointRelation *portainer.Endpo
|
||||
return service.connection.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket([]byte(BucketName))
|
||||
|
||||
data, err := internal.MarshalObject(endpointRelation)
|
||||
data, err := internal.MarshalObject(endpointRelation, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (service *Service) Extensions() ([]portainer.Extension, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var extension portainer.Extension
|
||||
err := internal.UnmarshalObject(v, &extension)
|
||||
err := internal.UnmarshalObject(v, &extension, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func (service *Service) Persist(extension *portainer.Extension) error {
|
||||
return service.connection.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket([]byte(BucketName))
|
||||
|
||||
data, err := internal.MarshalObject(extension)
|
||||
data, err := internal.MarshalObject(extension, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func (service *Service) HelmUserRepositoryByUserID(userID portainer.UserID) ([]p
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var record portainer.HelmUserRepository
|
||||
err := internal.UnmarshalObject(v, &record)
|
||||
err := internal.UnmarshalObject(v, &record, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func (service *Service) CreateHelmUserRepository(record *portainer.HelmUserRepos
|
||||
id, _ := bucket.NextSequence()
|
||||
record.ID = portainer.HelmUserRepositoryID(id)
|
||||
|
||||
data, err := internal.MarshalObject(record)
|
||||
data, err := internal.MarshalObject(record, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
)
|
||||
|
||||
type DbConnection struct {
|
||||
EncryptionKey string
|
||||
*bolt.DB
|
||||
}
|
||||
|
||||
@@ -52,7 +53,7 @@ func GetObject(connection *DbConnection, bucketName string, key []byte, object i
|
||||
return err
|
||||
}
|
||||
|
||||
return UnmarshalObject(data, object)
|
||||
return UnmarshalObject(data, object, connection.EncryptionKey)
|
||||
}
|
||||
|
||||
// UpdateObject is a generic function used to update an object inside a bolt database.
|
||||
@@ -60,7 +61,7 @@ func UpdateObject(connection *DbConnection, bucketName string, key []byte, objec
|
||||
return connection.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket([]byte(bucketName))
|
||||
|
||||
data, err := MarshalObject(object)
|
||||
data, err := MarshalObject(object, connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,25 +1,119 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var encryptedStringTooShort = fmt.Errorf("encrypted string too short")
|
||||
|
||||
// MarshalObject encodes an object to binary format
|
||||
func MarshalObject(object interface{}) ([]byte, error) {
|
||||
return json.Marshal(object)
|
||||
func MarshalObject(object interface{}, passphrase string) ([]byte, error) {
|
||||
data, err := json.Marshal(object)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Errorf("failed marshaling object")
|
||||
return data, err
|
||||
}
|
||||
if passphrase == "" {
|
||||
logrus.Infof("no encryption passphrase")
|
||||
return data, nil
|
||||
}
|
||||
return encrypt(data, passphrase)
|
||||
}
|
||||
|
||||
// UnmarshalObject decodes an object from binary data
|
||||
func UnmarshalObject(data []byte, object interface{}) error {
|
||||
func UnmarshalObject(data []byte, object interface{}, passphrase string) error {
|
||||
if passphrase == "" {
|
||||
logrus.Infof("no encryption passphrase")
|
||||
} else {
|
||||
var err error
|
||||
data, err = decrypt(data, passphrase)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Errorf("failed decrypting object")
|
||||
return err
|
||||
}
|
||||
}
|
||||
return json.Unmarshal(data, object)
|
||||
}
|
||||
|
||||
// UnmarshalObjectWithJsoniter decodes an object from binary data
|
||||
// using the jsoniter library. It is mainly used to accelerate environment(endpoint)
|
||||
// decoding at the moment.
|
||||
func UnmarshalObjectWithJsoniter(data []byte, object interface{}) error {
|
||||
func UnmarshalObjectWithJsoniter(data []byte, object interface{}, passphrase string) error {
|
||||
if passphrase == "" {
|
||||
logrus.Infof("no encryption passphrase")
|
||||
} else {
|
||||
var err error
|
||||
data, err = decrypt(data, passphrase)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Errorf("failed decrypting object")
|
||||
return err
|
||||
}
|
||||
}
|
||||
var jsoni = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
return jsoni.Unmarshal(data, &object)
|
||||
}
|
||||
|
||||
// mmm, don't have a KMS .... aes GCM seems the most likely from
|
||||
// https://gist.github.com/atoponce/07d8d4c833873be2f68c34f9afc5a78a#symmetric-encryption
|
||||
|
||||
func encrypt(plaintext []byte, passphrase string) (encrypted []byte, err error) {
|
||||
block, _ := aes.NewCipher([]byte(passphrase))
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return encrypted, err
|
||||
}
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
return encrypted, err
|
||||
}
|
||||
ciphertextByte := gcm.Seal(
|
||||
nonce,
|
||||
nonce,
|
||||
plaintext,
|
||||
nil)
|
||||
return ciphertextByte, nil
|
||||
}
|
||||
|
||||
// On error, return the original byte array - it might be unencrypted...
|
||||
func decrypt(encrypted []byte, passphrase string) (plaintextByte []byte, err error) {
|
||||
passphraseByte := []byte(passphrase)
|
||||
block, err := aes.NewCipher(passphraseByte)
|
||||
if err != nil {
|
||||
logrus.Infof("NOT decrypted")
|
||||
|
||||
return encrypted, err
|
||||
}
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
logrus.Infof("NOT decrypted")
|
||||
|
||||
return encrypted, err
|
||||
}
|
||||
nonceSize := gcm.NonceSize()
|
||||
if len(encrypted) < nonceSize {
|
||||
logrus.Infof("NOT decrypted")
|
||||
|
||||
return encrypted, encryptedStringTooShort
|
||||
}
|
||||
nonce, ciphertextByteClean := encrypted[:nonceSize], encrypted[nonceSize:]
|
||||
plaintextByte, err = gcm.Open(
|
||||
nil,
|
||||
nonce,
|
||||
ciphertextByteClean,
|
||||
nil)
|
||||
if err != nil {
|
||||
logrus.Infof("NOT decrypted")
|
||||
|
||||
return encrypted, err
|
||||
}
|
||||
logrus.Infof("decrypted")
|
||||
return plaintextByte, err
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package migrator
|
||||
|
||||
import (
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/internal"
|
||||
)
|
||||
|
||||
@@ -66,7 +66,7 @@ func (m *Migrator) retrieveLegacyResourceControls() ([]portainer.ResourceControl
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var resourceControl portainer.ResourceControl
|
||||
err := internal.UnmarshalObject(v, &resourceControl)
|
||||
err := internal.UnmarshalObject(v, &resourceControl, "") // TODO
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -78,7 +78,7 @@ func (m *Migrator) retrieveLegacyResourceControls() ([]portainer.ResourceControl
|
||||
cursor = bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var resourceControl portainer.ResourceControl
|
||||
err := internal.UnmarshalObject(v, &resourceControl)
|
||||
err := internal.UnmarshalObject(v, &resourceControl, "") // TODO
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -90,7 +90,7 @@ func (m *Migrator) retrieveLegacyResourceControls() ([]portainer.ResourceControl
|
||||
cursor = bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var resourceControl portainer.ResourceControl
|
||||
err := internal.UnmarshalObject(v, &resourceControl)
|
||||
err := internal.UnmarshalObject(v, &resourceControl, "") // TODO
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/internal"
|
||||
"github.com/portainer/portainer/api/bolt/stack"
|
||||
)
|
||||
@@ -113,7 +113,7 @@ func (m *Migrator) retrieveLegacyStacks() ([]legacyStack, error) {
|
||||
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var stack legacyStack
|
||||
err := internal.UnmarshalObject(v, &stack)
|
||||
err := internal.UnmarshalObject(v, &stack, "") // TODO
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (service *Service) Registries() ([]portainer.Registry, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var registry portainer.Registry
|
||||
err := internal.UnmarshalObject(v, ®istry)
|
||||
err := internal.UnmarshalObject(v, ®istry, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func (service *Service) CreateRegistry(registry *portainer.Registry) error {
|
||||
id, _ := bucket.NextSequence()
|
||||
registry.ID = portainer.RegistryID(id)
|
||||
|
||||
data, err := internal.MarshalObject(registry)
|
||||
data, err := internal.MarshalObject(registry, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func (service *Service) ResourceControlByResourceIDAndType(resourceID string, re
|
||||
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var rc portainer.ResourceControl
|
||||
err := internal.UnmarshalObject(v, &rc)
|
||||
err := internal.UnmarshalObject(v, &rc, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func (service *Service) ResourceControls() ([]portainer.ResourceControl, error)
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var resourceControl portainer.ResourceControl
|
||||
err := internal.UnmarshalObject(v, &resourceControl)
|
||||
err := internal.UnmarshalObject(v, &resourceControl, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func (service *Service) CreateResourceControl(resourceControl *portainer.Resourc
|
||||
id, _ := bucket.NextSequence()
|
||||
resourceControl.ID = portainer.ResourceControlID(id)
|
||||
|
||||
data, err := internal.MarshalObject(resourceControl)
|
||||
data, err := internal.MarshalObject(resourceControl, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (service *Service) Roles() ([]portainer.Role, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var set portainer.Role
|
||||
err := internal.UnmarshalObject(v, &set)
|
||||
err := internal.UnmarshalObject(v, &set, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func (service *Service) CreateRole(role *portainer.Role) error {
|
||||
id, _ := bucket.NextSequence()
|
||||
role.ID = portainer.RoleID(id)
|
||||
|
||||
data, err := internal.MarshalObject(role)
|
||||
data, err := internal.MarshalObject(role, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func (service *Service) Schedules() ([]portainer.Schedule, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var schedule portainer.Schedule
|
||||
err := internal.UnmarshalObject(v, &schedule)
|
||||
err := internal.UnmarshalObject(v, &schedule, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func (service *Service) SchedulesByJobType(jobType portainer.JobType) ([]portain
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var schedule portainer.Schedule
|
||||
err := internal.UnmarshalObject(v, &schedule)
|
||||
err := internal.UnmarshalObject(v, &schedule, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func (service *Service) CreateSchedule(schedule *portainer.Schedule) error {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := internal.MarshalObject(schedule)
|
||||
data, err := internal.MarshalObject(schedule, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func (service *Service) StackByName(name string) (*portainer.Stack, error) {
|
||||
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var t portainer.Stack
|
||||
err := internal.UnmarshalObject(v, &t)
|
||||
err := internal.UnmarshalObject(v, &t, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -86,7 +86,7 @@ func (service *Service) StacksByName(name string) ([]portainer.Stack, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var t portainer.Stack
|
||||
err := internal.UnmarshalObject(v, &t)
|
||||
err := internal.UnmarshalObject(v, &t, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (service *Service) Stacks() ([]portainer.Stack, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var stack portainer.Stack
|
||||
err := internal.UnmarshalObject(v, &stack)
|
||||
err := internal.UnmarshalObject(v, &stack, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func (service *Service) CreateStack(stack *portainer.Stack) error {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := internal.MarshalObject(stack)
|
||||
data, err := internal.MarshalObject(stack, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -182,14 +182,14 @@ func (service *Service) StackByWebhookID(id string) (*portainer.Stack, error) {
|
||||
} `json:"AutoUpdate"`
|
||||
}
|
||||
|
||||
err := internal.UnmarshalObject(v, &t)
|
||||
err := internal.UnmarshalObject(v, &t, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if t.AutoUpdate != nil && strings.EqualFold(t.AutoUpdate.WebhookID, id) {
|
||||
found = true
|
||||
err := internal.UnmarshalObject(v, &stack)
|
||||
err := internal.UnmarshalObject(v, &stack, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -219,7 +219,7 @@ func (service *Service) RefreshableStacks() ([]portainer.Stack, error) {
|
||||
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
stack := portainer.Stack{}
|
||||
err := internal.UnmarshalObject(v, &stack)
|
||||
err := internal.UnmarshalObject(v, &stack, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func (service *Service) Tags() ([]portainer.Tag, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var tag portainer.Tag
|
||||
err := internal.UnmarshalObject(v, &tag)
|
||||
err := internal.UnmarshalObject(v, &tag, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func (service *Service) CreateTag(tag *portainer.Tag) error {
|
||||
id, _ := bucket.NextSequence()
|
||||
tag.ID = portainer.TagID(id)
|
||||
|
||||
data, err := internal.MarshalObject(tag)
|
||||
data, err := internal.MarshalObject(tag, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (service *Service) TeamByName(name string) (*portainer.Team, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var t portainer.Team
|
||||
err := internal.UnmarshalObject(v, &t)
|
||||
err := internal.UnmarshalObject(v, &t, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -86,7 +86,7 @@ func (service *Service) Teams() ([]portainer.Team, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var team portainer.Team
|
||||
err := internal.UnmarshalObject(v, &team)
|
||||
err := internal.UnmarshalObject(v, &team, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -113,7 +113,7 @@ func (service *Service) CreateTeam(team *portainer.Team) error {
|
||||
id, _ := bucket.NextSequence()
|
||||
team.ID = portainer.TeamID(id)
|
||||
|
||||
data, err := internal.MarshalObject(team)
|
||||
data, err := internal.MarshalObject(team, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (service *Service) TeamMemberships() ([]portainer.TeamMembership, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var membership portainer.TeamMembership
|
||||
err := internal.UnmarshalObject(v, &membership)
|
||||
err := internal.UnmarshalObject(v, &membership, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -75,7 +75,7 @@ func (service *Service) TeamMembershipsByUserID(userID portainer.UserID) ([]port
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var membership portainer.TeamMembership
|
||||
err := internal.UnmarshalObject(v, &membership)
|
||||
err := internal.UnmarshalObject(v, &membership, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func (service *Service) TeamMembershipsByTeamID(teamID portainer.TeamID) ([]port
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var membership portainer.TeamMembership
|
||||
err := internal.UnmarshalObject(v, &membership)
|
||||
err := internal.UnmarshalObject(v, &membership, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -131,7 +131,7 @@ func (service *Service) CreateTeamMembership(membership *portainer.TeamMembershi
|
||||
id, _ := bucket.NextSequence()
|
||||
membership.ID = portainer.TeamMembershipID(id)
|
||||
|
||||
data, err := internal.MarshalObject(membership)
|
||||
data, err := internal.MarshalObject(membership, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -154,7 +154,7 @@ func (service *Service) DeleteTeamMembershipByUserID(userID portainer.UserID) er
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var membership portainer.TeamMembership
|
||||
err := internal.UnmarshalObject(v, &membership)
|
||||
err := internal.UnmarshalObject(v, &membership, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -179,7 +179,7 @@ func (service *Service) DeleteTeamMembershipByTeamID(teamID portainer.TeamID) er
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var membership portainer.TeamMembership
|
||||
err := internal.UnmarshalObject(v, &membership)
|
||||
err := internal.UnmarshalObject(v, &membership, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func NewTestStore(init bool) (*Store, func(), error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
store := NewStore(dataStorePath, fileService)
|
||||
store := NewStore(dataStorePath, fileService, "") // TODO: encryption key
|
||||
err = store.Open()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
@@ -57,7 +57,7 @@ func (service *Service) UserByUsername(username string) (*portainer.User, error)
|
||||
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var u portainer.User
|
||||
err := internal.UnmarshalObject(v, &u)
|
||||
err := internal.UnmarshalObject(v, &u, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -87,7 +87,7 @@ func (service *Service) Users() ([]portainer.User, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var user portainer.User
|
||||
err := internal.UnmarshalObject(v, &user)
|
||||
err := internal.UnmarshalObject(v, &user, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func (service *Service) UsersByRole(role portainer.UserRole) ([]portainer.User,
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var user portainer.User
|
||||
err := internal.UnmarshalObject(v, &user)
|
||||
err := internal.UnmarshalObject(v, &user, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -140,7 +140,7 @@ func (service *Service) CreateUser(user *portainer.User) error {
|
||||
user.ID = portainer.UserID(id)
|
||||
user.Username = strings.ToLower(user.Username)
|
||||
|
||||
data, err := internal.MarshalObject(user)
|
||||
data, err := internal.MarshalObject(user, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func (service *Service) Webhooks() ([]portainer.Webhook, error) {
|
||||
cursor := bucket.Cursor()
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var webhook portainer.Webhook
|
||||
err := internal.UnmarshalObject(v, &webhook)
|
||||
err := internal.UnmarshalObject(v, &webhook, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -76,7 +76,7 @@ func (service *Service) WebhookByResourceID(ID string) (*portainer.Webhook, erro
|
||||
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var w portainer.Webhook
|
||||
err := internal.UnmarshalObject(v, &w)
|
||||
err := internal.UnmarshalObject(v, &w, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -107,7 +107,7 @@ func (service *Service) WebhookByToken(token string) (*portainer.Webhook, error)
|
||||
|
||||
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||
var w portainer.Webhook
|
||||
err := internal.UnmarshalObject(v, &w)
|
||||
err := internal.UnmarshalObject(v, &w, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func (service *Service) CreateWebhook(webhook *portainer.Webhook) error {
|
||||
id, _ := bucket.NextSequence()
|
||||
webhook.ID = portainer.WebhookID(id)
|
||||
|
||||
data, err := internal.MarshalObject(webhook)
|
||||
data, err := internal.MarshalObject(webhook, service.connection.EncryptionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
|
||||
Labels: pairs(kingpin.Flag("hide-label", "Hide containers with a specific label in the UI").Short('l')),
|
||||
Logo: kingpin.Flag("logo", "URL for the logo displayed in the UI").String(),
|
||||
Templates: kingpin.Flag("templates", "URL to the templates definitions.").Short('t').String(),
|
||||
SecretKeyName: kingpin.Flag("secret-key-name", "Secret key name for encryption and will be used as /run/secrets/<secret-key-name>.").Default(defaultSecretKeyName).String(),
|
||||
BaseURL: kingpin.Flag("base-url", "Base URL parameter such as portainer if running portainer as http://yourdomain.com/portainer/.").Short('b').Default(defaultBaseURL).String(),
|
||||
}
|
||||
|
||||
|
||||
@@ -19,5 +19,6 @@ const (
|
||||
defaultSSLCertPath = "/certs/portainer.crt"
|
||||
defaultSSLKeyPath = "/certs/portainer.key"
|
||||
defaultSnapshotInterval = "5m"
|
||||
defaultSecretKeyName = "portainer"
|
||||
defaultBaseURL = "/"
|
||||
)
|
||||
|
||||
@@ -17,5 +17,6 @@ const (
|
||||
defaultSSLCertPath = "C:\\certs\\portainer.crt"
|
||||
defaultSSLKeyPath = "C:\\certs\\portainer.key"
|
||||
defaultSnapshotInterval = "5m"
|
||||
defaultSecretKeyName = "portainer"
|
||||
defaultBaseURL = "/"
|
||||
)
|
||||
|
||||
@@ -59,8 +59,8 @@ func initFileService(dataStorePath string) portainer.FileService {
|
||||
return fileService
|
||||
}
|
||||
|
||||
func initDataStore(dataStorePath string, rollback bool, fileService portainer.FileService, shutdownCtx context.Context) portainer.DataStore {
|
||||
store := bolt.NewStore(dataStorePath, fileService)
|
||||
func initDataStore(dataStorePath, encryptionKey string, rollback bool, fileService portainer.FileService, shutdownCtx context.Context) portainer.DataStore {
|
||||
store := bolt.NewStore(dataStorePath, fileService, encryptionKey)
|
||||
err := store.Open()
|
||||
if err != nil {
|
||||
log.Fatalf("failed opening store: %v", err)
|
||||
@@ -458,12 +458,32 @@ func initEndpoint(flags *portainer.CLIFlags, dataStore portainer.DataStore, snap
|
||||
return createUnsecuredEndpoint(*flags.EndpointURL, dataStore, snapshotService)
|
||||
}
|
||||
|
||||
func initSecretKey(fileName string) string {
|
||||
ok, _ := filesystem.FileExists("/run/secrets/" + fileName)
|
||||
if !ok {
|
||||
log.Println(fmt.Sprintf("encryption secret file `%s` does not exists", fileName))
|
||||
return ""
|
||||
}
|
||||
|
||||
content, err := os.ReadFile("/run/secrets/" + fileName)
|
||||
if err != nil {
|
||||
log.Println(fmt.Sprintf("error reading encryption key file: %s", err.Error()))
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.TrimSuffix(string(content), "\n")
|
||||
}
|
||||
|
||||
func buildServer(flags *portainer.CLIFlags) portainer.Server {
|
||||
shutdownCtx, shutdownTrigger := context.WithCancel(context.Background())
|
||||
|
||||
fileService := initFileService(*flags.Data)
|
||||
encryptionKey := initSecretKey(*flags.SecretKeyName)
|
||||
if encryptionKey == "" {
|
||||
log.Println("proceeding without encryption key")
|
||||
}
|
||||
|
||||
dataStore := initDataStore(*flags.Data, *flags.Rollback, fileService, shutdownCtx)
|
||||
dataStore := initDataStore(*flags.Data, encryptionKey, *flags.Rollback, fileService, shutdownCtx)
|
||||
|
||||
if err := dataStore.CheckCurrentEdition(); err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
@@ -95,6 +95,7 @@ type (
|
||||
SSLKey *string
|
||||
Rollback *bool
|
||||
SnapshotInterval *string
|
||||
SecretKeyName *string
|
||||
BaseURL *string
|
||||
}
|
||||
|
||||
@@ -612,7 +613,7 @@ type (
|
||||
ManagementConfiguration *RegistryManagementConfiguration `json:"ManagementConfiguration"`
|
||||
Gitlab GitlabRegistryData `json:"Gitlab"`
|
||||
Quay QuayRegistryData `json:"Quay"`
|
||||
Ecr EcrData `json:"Ecr"`
|
||||
Ecr EcrData `json:"Ecr"`
|
||||
RegistryAccesses RegistryAccesses `json:"RegistryAccesses"`
|
||||
|
||||
// Deprecated fields
|
||||
|
||||
Reference in New Issue
Block a user