SecretsManager: Add ability to list all encrypted values (#108512)

* list all encrypted values and count

* separate interfaces

* add time filter to global queries

* fix lint
This commit is contained in:
Dana Axinte
2025-07-28 10:50:24 +01:00
committed by GitHub
parent f969eb0277
commit 2ea77a7c05
26 changed files with 502 additions and 20 deletions
@@ -206,3 +206,126 @@ func (s *encryptedValStorage) Delete(ctx context.Context, namespace, name string
return nil
}
type globalEncryptedValStorage struct {
db contracts.Database
dialect sqltemplate.Dialect
tracer trace.Tracer
}
func ProvideGlobalEncryptedValueStorage(
db contracts.Database,
tracer trace.Tracer,
) (contracts.GlobalEncryptedValueStorage, error) {
return &globalEncryptedValStorage{
db: db,
dialect: sqltemplate.DialectForDriver(db.DriverName()),
tracer: tracer,
}, nil
}
func (s *globalEncryptedValStorage) ListAll(ctx context.Context, opts contracts.ListOpts, untilTime *int64) ([]*contracts.EncryptedValue, error) {
attrs := []attribute.KeyValue{
attribute.Int64("limit", opts.Limit),
attribute.Int64("offset", opts.Offset),
}
if untilTime != nil {
attrs = append(attrs, attribute.Int64("untilTime", *untilTime))
}
ctx, span := s.tracer.Start(ctx, "GlobalEncryptedValueStorage.CountAll", trace.WithAttributes(attrs...))
defer span.End()
req := listAllEncryptedValues{
SQLTemplate: sqltemplate.New(s.dialect),
Limit: opts.Limit,
Offset: opts.Offset,
}
if untilTime != nil {
req.HasUntilTime = true
req.UntilTime = *untilTime
}
query, err := sqltemplate.Execute(sqlEncryptedValueListAll, req)
if err != nil {
return nil, fmt.Errorf("execute template %q: %w", sqlEncryptedValueListAll.Name(), err)
}
rows, err := s.db.QueryContext(ctx, query, req.GetArgs()...)
if err != nil {
return nil, fmt.Errorf("listing encrypted values %q: %w", sqlEncryptedValueListAll.Name(), err)
}
defer func() { _ = rows.Close() }()
encryptedValues := make([]*contracts.EncryptedValue, 0)
for rows.Next() {
var row EncryptedValue
err = rows.Scan(
&row.Namespace,
&row.Name,
&row.Version,
&row.EncryptedData,
&row.Created,
&row.Updated,
)
if err != nil {
return nil, fmt.Errorf("error reading data key row: %w", err)
}
encryptedValues = append(encryptedValues, &contracts.EncryptedValue{
Namespace: row.Namespace,
Name: row.Name,
Version: row.Version,
EncryptedData: row.EncryptedData,
Created: row.Created,
Updated: row.Updated,
})
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("read rows error: %w", err)
}
return encryptedValues, nil
}
func (s *globalEncryptedValStorage) CountAll(ctx context.Context, untilTime *int64) (int64, error) {
attrs := []attribute.KeyValue{}
if untilTime != nil {
attrs = append(attrs, attribute.Int64("untilTime", *untilTime))
}
ctx, span := s.tracer.Start(ctx, "GlobalEncryptedValueStorage.CountAll", trace.WithAttributes(attrs...))
defer span.End()
req := countAllEncryptedValues{
SQLTemplate: sqltemplate.New(s.dialect),
}
if untilTime != nil {
req.HasUntilTime = true
req.UntilTime = *untilTime
}
query, err := sqltemplate.Execute(sqlEncryptedValueCountAll, req)
if err != nil {
return 0, fmt.Errorf("execute template %q: %w", sqlEncryptedValueCountAll.Name(), err)
}
rows, err := s.db.QueryContext(ctx, query, req.GetArgs()...)
if err != nil {
return 0, fmt.Errorf("getting row: %w", err)
}
defer func() { _ = rows.Close() }()
if !rows.Next() {
return 0, fmt.Errorf("no rows returned when counting encrypted values")
}
var count int64
err = rows.Scan(&count)
if err != nil {
return 0, fmt.Errorf("failed to scan encrypted value row: %w", err)
}
if err := rows.Err(); err != nil {
return 0, fmt.Errorf("read rows error: %w", err)
}
return count, nil
}