Skip to content

Commit be8092d

Browse files
committed
fix(server): fail if repository already initialized by other instance
Signed-off-by: Yaroslav Pershin <[email protected]>
1 parent f8be573 commit be8092d

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

server/pkg/publisher/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ type RepositoryInterface interface {
3030
StageTarget(ctx context.Context, pathInsideTargets string, data io.Reader) error
3131
CommitStaged(ctx context.Context) error
3232
GetTargets(ctx context.Context) ([]string, error)
33+
GetRolePublicKeysFromS3Meta(file, role string) ([]string, error)
3334
}

server/pkg/publisher/publisher.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package publisher
33
import (
44
"bytes"
55
"context"
6+
"encoding/json"
67
"errors"
78
"fmt"
89
"io"
910
"os"
1011
"path"
1112
"path/filepath"
13+
"slices"
1214
"strings"
1315
"sync"
1416
"unicode/utf8"
@@ -18,6 +20,7 @@ import (
1820
"github.com/hashicorp/go-hclog"
1921
"github.com/hashicorp/vault/sdk/logical"
2022

23+
"github.com/werf/logboek"
2124
"github.com/werf/trdl/server/pkg/config"
2225
"github.com/werf/trdl/server/pkg/pgp"
2326
"github.com/werf/trdl/server/pkg/util"
@@ -94,6 +97,9 @@ type setRepositoryKeysOptions struct {
9497
InitializeKeys bool
9598
}
9699

100+
var TufRepoAlreadyInitializedMsg = `Tuf repository already initialized by another instance of vault-plugin.
101+
Verify the project settings. If settings are correct, consider cleaning up the TUF repository by removing orphaned metadata.`
102+
97103
func (publisher *Publisher) setRepositoryKeys(ctx context.Context, storage logical.Storage, repository RepositoryInterface, opts setRepositoryKeysOptions) error {
98104
entry, err := storage.Get(ctx, storageKeyTufRepositoryKeys)
99105
if err != nil {
@@ -105,6 +111,16 @@ func (publisher *Publisher) setRepositoryKeys(ctx context.Context, storage logic
105111
return ErrUninitializedRepositoryKeys
106112
}
107113

114+
rootPublicKeysFromS3, err := repository.GetRolePublicKeysFromS3Meta("root.json", "root")
115+
if err != nil {
116+
return fmt.Errorf("unable to get root keys from repository: %w", err)
117+
}
118+
if len(rootPublicKeysFromS3) > 0 {
119+
publisher.logger.Error(TufRepoAlreadyInitializedMsg)
120+
logboek.Context(context.Background()).Default().LogF("%s\n", TufRepoAlreadyInitializedMsg)
121+
return fmt.Errorf("tuf repository already initialized by another instance of vault-plugin")
122+
}
123+
108124
publisher.logger.Debug("Will generate new repository private keys")
109125

110126
if err := repository.GenPrivKeys(); err != nil {
@@ -132,6 +148,24 @@ func (publisher *Publisher) setRepositoryKeys(ctx context.Context, storage logic
132148
return fmt.Errorf("unable to decode keys json by the %q storage key:\n%s---\n%w", storageKeyTufRepositoryKeys, entry.Value, err)
133149
}
134150

151+
rootPublicKeysFromS3, err := repository.GetRolePublicKeysFromS3Meta("root.json", "root")
152+
if err != nil {
153+
return fmt.Errorf("unable to get root keys from repository: %w", err)
154+
}
155+
156+
var data KeyVal
157+
if err := json.Unmarshal(privKeys.Root.Value, &data); err != nil {
158+
return err
159+
}
160+
161+
if len(rootPublicKeysFromS3) > 0 {
162+
if !slices.Contains(rootPublicKeysFromS3, data.Public) {
163+
publisher.logger.Error(TufRepoAlreadyInitializedMsg)
164+
logboek.Context(context.Background()).Default().LogF("%s\n", TufRepoAlreadyInitializedMsg)
165+
return fmt.Errorf("tuf repository already initialized by another instance of vault-plugin")
166+
}
167+
}
168+
135169
if err := repository.SetPrivKeys(privKeys); err != nil {
136170
return fmt.Errorf("unable to set private keys into repository: %w", err)
137171
}

server/pkg/publisher/repository.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,51 @@ func (repository *S3Repository) GetTargets(ctx context.Context) ([]string, error
160160
}
161161
return res, nil
162162
}
163+
164+
type RootMeta struct {
165+
Signed Signed `json:"signed"`
166+
}
167+
type Signed struct {
168+
Keys map[string]Key `json:"keys"`
169+
Roles map[string]RoleDefinition `json:"roles"`
170+
}
171+
172+
type Key struct {
173+
KeyVal KeyVal `json:"keyval"`
174+
}
175+
176+
type KeyVal struct {
177+
Public string `json:"public"`
178+
}
179+
180+
type RoleDefinition struct {
181+
KeyIDs []string `json:"keyids"`
182+
}
183+
184+
func (repository *S3Repository) GetRolePublicKeysFromS3Meta(file, role string) ([]string, error) {
185+
meta, err := repository.TufRepo.GetMeta()
186+
if err != nil {
187+
return nil, fmt.Errorf("error getting metadata from TUF repo: %w", err)
188+
}
189+
190+
var rootMeta RootMeta
191+
if err := json.Unmarshal(meta[file], &rootMeta); err != nil {
192+
return nil, fmt.Errorf("error unmarshalling %s: %w", file, err)
193+
}
194+
195+
rootRole, ok := rootMeta.Signed.Roles[role]
196+
if !ok {
197+
return nil, nil
198+
}
199+
200+
publicKeys := make([]string, 0, len(rootRole.KeyIDs))
201+
for _, keyID := range rootRole.KeyIDs {
202+
key, ok := rootMeta.Signed.Keys[keyID]
203+
if !ok {
204+
return nil, fmt.Errorf("key %q not found in keys section", keyID)
205+
}
206+
publicKeys = append(publicKeys, key.KeyVal.Public)
207+
}
208+
209+
return publicKeys, nil
210+
}

0 commit comments

Comments
 (0)