Compare commits

...

8 Commits

Author SHA1 Message Date
Prabhat Khera
fa0878a18a cleaned 2021-12-06 22:12:58 +13:00
Prabhat Khera
fa921f5ae8 time new line char from encryption key 2021-12-06 21:44:10 +13:00
Prabhat Khera
ca91db6bd8 key logged 2021-12-06 19:21:08 +13:00
Prabhat Khera
d6e8bf8d2b pass encryption key in db connection 2021-12-06 16:37:32 +13:00
Prabhat Khera
09cf63c63a Merge branch 'develop' of github.com:portainer/portainer into feat/EE-1852/EE-1983/encryption-key 2021-12-06 15:15:10 +13:00
Prabhat Khera
71079a76f7 Add db encryption 2021-12-06 15:10:54 +13:00
Prabhat Khera
64c96e613c Review comments incorporated 2021-12-06 15:06:28 +13:00
Prabhat Khera
7e7e32932f wip: bootstrap encryption key 2021-12-02 16:42:14 +13:00
31 changed files with 197 additions and 78 deletions

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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},
}
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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, &registry)
err := internal.UnmarshalObject(v, &registry, 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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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(),
}

View File

@@ -19,5 +19,6 @@ const (
defaultSSLCertPath = "/certs/portainer.crt"
defaultSSLKeyPath = "/certs/portainer.key"
defaultSnapshotInterval = "5m"
defaultSecretKeyName = "portainer"
defaultBaseURL = "/"
)

View File

@@ -17,5 +17,6 @@ const (
defaultSSLCertPath = "C:\\certs\\portainer.crt"
defaultSSLKeyPath = "C:\\certs\\portainer.key"
defaultSnapshotInterval = "5m"
defaultSecretKeyName = "portainer"
defaultBaseURL = "/"
)

View File

@@ -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)

View File

@@ -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