A pair credential is sealed to the operator key too
The secret the vault provides a module is the credential of the consumer↔vault pair, and so is every credential a provider grants; sealing only own secrets to the operator left exactly those unrecoverable. Same column, same call; the export and `secret recover` address a pair by consumer node, module and the provision's name, and say which kind each entry is.
This commit is contained in:
@@ -69,17 +69,21 @@ type Kept = catalogue.Kept
|
||||
// an export say what it does not cover, rather than being taken for complete.
|
||||
func (i *Inventory) KeptForOperator(ctx context.Context) (kept []Kept, unrecoverable []Kept, err error) {
|
||||
rows, err := i.store.Pool().Query(ctx,
|
||||
`select n.name, s.module, s.name, s.origin, coalesce(s.operator_sealed, ''),
|
||||
`select 'own', n.name, s.module, s.name, '', s.origin, coalesce(s.operator_sealed, ''),
|
||||
coalesce(s.operator_key, ''), s.made_at
|
||||
from module_secret s join node n on n.id = s.node
|
||||
order by n.name, s.module, s.name`)
|
||||
union all
|
||||
select 'pair', c.name, s.consumer_module, s.name, p.name, 'made', coalesce(s.operator_sealed, ''),
|
||||
coalesce(s.operator_key, ''), s.created_at
|
||||
from secret s join node c on c.id = s.consumer join node p on p.id = s.provider
|
||||
order by 1, 2, 3, 4`)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var k Kept
|
||||
if err := rows.Scan(&k.Node, &k.Module, &k.Name, &k.Origin, &k.Sealed, &k.Key, &k.MadeAt); err != nil {
|
||||
if err := rows.Scan(&k.Kind, &k.Node, &k.Module, &k.Name, &k.Provider, &k.Origin, &k.Sealed, &k.Key, &k.MadeAt); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if k.Sealed == "" {
|
||||
@@ -93,15 +97,25 @@ func (i *Inventory) KeptForOperator(ctx context.Context) (kept []Kept, unrecover
|
||||
|
||||
// KeptSecret is one secret's operator-sealed copy, for recovery.
|
||||
func (i *Inventory) KeptSecret(ctx context.Context, node, module, name string) (Kept, error) {
|
||||
// An own secret first, then a pair credential by the provision's name. A module whose own
|
||||
// secret and requirement share a name is refused at resolution, so the two cannot both answer.
|
||||
var k Kept
|
||||
err := i.store.Pool().QueryRow(ctx,
|
||||
`select n.name, s.module, s.name, s.origin, coalesce(s.operator_sealed, ''),
|
||||
`select 'own', n.name, s.module, s.name, '', s.origin, coalesce(s.operator_sealed, ''),
|
||||
coalesce(s.operator_key, ''), s.made_at
|
||||
from module_secret s join node n on n.id = s.node
|
||||
where n.name = $1 and s.module = $2 and s.name = $3`, node, module, name).
|
||||
Scan(&k.Node, &k.Module, &k.Name, &k.Origin, &k.Sealed, &k.Key, &k.MadeAt)
|
||||
Scan(&k.Kind, &k.Node, &k.Module, &k.Name, &k.Provider, &k.Origin, &k.Sealed, &k.Key, &k.MadeAt)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return Kept{}, fmt.Errorf("%s on %s holds nothing called %q", module, node, name)
|
||||
err = i.store.Pool().QueryRow(ctx,
|
||||
`select 'pair', c.name, s.consumer_module, s.name, p.name, 'made', coalesce(s.operator_sealed, ''),
|
||||
coalesce(s.operator_key, ''), s.created_at
|
||||
from secret s join node c on c.id = s.consumer join node p on p.id = s.provider
|
||||
where c.name = $1 and s.consumer_module = $2 and s.name = $3`, node, module, name).
|
||||
Scan(&k.Kind, &k.Node, &k.Module, &k.Name, &k.Provider, &k.Origin, &k.Sealed, &k.Key, &k.MadeAt)
|
||||
}
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return Kept{}, fmt.Errorf("%s on %s holds nothing called %q — neither a secret of its own nor a credential for a provision", module, node, name)
|
||||
}
|
||||
if err != nil {
|
||||
return Kept{}, err
|
||||
|
||||
Reference in New Issue
Block a user