Skip to content

fix(server): fail if repo initialized by another instance #332

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions server/pkg/publisher/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ type RepositoryInterface interface {
StageTarget(ctx context.Context, pathInsideTargets string, data io.Reader) error
CommitStaged(ctx context.Context) error
GetTargets(ctx context.Context) ([]string, error)
GetRolePublicKeysFromS3Meta(file, role string) ([]string, error)
}
34 changes: 34 additions & 0 deletions server/pkg/publisher/publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package publisher
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"os"
"path"
"path/filepath"
"slices"
"strings"
"sync"
"unicode/utf8"
Expand All @@ -18,6 +20,7 @@ import (
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/sdk/logical"

"github.com/werf/logboek"
"github.com/werf/trdl/server/pkg/config"
"github.com/werf/trdl/server/pkg/pgp"
"github.com/werf/trdl/server/pkg/util"
Expand Down Expand Up @@ -94,6 +97,9 @@ type setRepositoryKeysOptions struct {
InitializeKeys bool
}

var TufRepoAlreadyInitializedMsg = `Tuf repository already initialized by another instance of vault-plugin.
Verify the project settings. If settings are correct, consider cleaning up the TUF repository by removing orphaned metadata.`

func (publisher *Publisher) setRepositoryKeys(ctx context.Context, storage logical.Storage, repository RepositoryInterface, opts setRepositoryKeysOptions) error {
entry, err := storage.Get(ctx, storageKeyTufRepositoryKeys)
if err != nil {
Expand All @@ -105,6 +111,16 @@ func (publisher *Publisher) setRepositoryKeys(ctx context.Context, storage logic
return ErrUninitializedRepositoryKeys
}

rootPublicKeysFromS3, err := repository.GetRolePublicKeysFromS3Meta("root.json", "root")
if err != nil {
return fmt.Errorf("unable to get root keys from repository: %w", err)
}
if len(rootPublicKeysFromS3) > 0 {
publisher.logger.Error(TufRepoAlreadyInitializedMsg)
logboek.Context(context.Background()).Default().LogF("%s\n", TufRepoAlreadyInitializedMsg)
return fmt.Errorf("tuf repository already initialized by another instance of vault-plugin")
}

publisher.logger.Debug("Will generate new repository private keys")

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

rootPublicKeysFromS3, err := repository.GetRolePublicKeysFromS3Meta("root.json", "root")
if err != nil {
return fmt.Errorf("unable to get root keys from repository: %w", err)
}

var data KeyVal
if err := json.Unmarshal(privKeys.Root.Value, &data); err != nil {
return err
}

if len(rootPublicKeysFromS3) > 0 {
if !slices.Contains(rootPublicKeysFromS3, data.Public) {
publisher.logger.Error(TufRepoAlreadyInitializedMsg)
logboek.Context(context.Background()).Default().LogF("%s\n", TufRepoAlreadyInitializedMsg)
return fmt.Errorf("tuf repository already initialized by another instance of vault-plugin")
}
}

if err := repository.SetPrivKeys(privKeys); err != nil {
return fmt.Errorf("unable to set private keys into repository: %w", err)
}
Expand Down
48 changes: 48 additions & 0 deletions server/pkg/publisher/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,51 @@ func (repository *S3Repository) GetTargets(ctx context.Context) ([]string, error
}
return res, nil
}

type RootMeta struct {
Signed Signed `json:"signed"`
}
type Signed struct {
Keys map[string]Key `json:"keys"`
Roles map[string]RoleDefinition `json:"roles"`
}

type Key struct {
KeyVal KeyVal `json:"keyval"`
}

type KeyVal struct {
Public string `json:"public"`
}

type RoleDefinition struct {
KeyIDs []string `json:"keyids"`
}

func (repository *S3Repository) GetRolePublicKeysFromS3Meta(file, role string) ([]string, error) {
meta, err := repository.TufRepo.GetMeta()
if err != nil {
return nil, fmt.Errorf("error getting metadata from TUF repo: %w", err)
}

var rootMeta RootMeta
if err := json.Unmarshal(meta[file], &rootMeta); err != nil {
return nil, fmt.Errorf("error unmarshalling %s: %w", file, err)
}

rootRole, ok := rootMeta.Signed.Roles[role]
if !ok {
return nil, nil
}

publicKeys := make([]string, 0, len(rootRole.KeyIDs))
for _, keyID := range rootRole.KeyIDs {
key, ok := rootMeta.Signed.Keys[keyID]
if !ok {
return nil, fmt.Errorf("key %q not found in keys section", keyID)
}
publicKeys = append(publicKeys, key.KeyVal.Public)
}

return publicKeys, nil
}
Loading