Secrets: Save owner reference fields in secure value db table (#108905)
* Secrets: Save owner reference fields in secure value db table * Save api group and version separately
This commit is contained in:
@@ -20,6 +20,18 @@ INSERT INTO {{ .Ident "secret_secure_value" }} (
|
||||
{{ if .Row.Ref.Valid }}
|
||||
{{ .Ident "ref" }},
|
||||
{{ end }}
|
||||
{{ if .Row.OwnerReferenceAPIGroup.Valid }}
|
||||
{{ .Ident "owner_reference_api_group" }},
|
||||
{{ end }}
|
||||
{{ if .Row.OwnerReferenceAPIVersion.Valid }}
|
||||
{{ .Ident "owner_reference_api_version" }},
|
||||
{{ end }}
|
||||
{{ if .Row.OwnerReferenceKind.Valid }}
|
||||
{{ .Ident "owner_reference_kind" }},
|
||||
{{ end }}
|
||||
{{ if .Row.OwnerReferenceName.Valid }}
|
||||
{{ .Ident "owner_reference_name" }},
|
||||
{{ end }}
|
||||
{{ .Ident "external_id" }}
|
||||
) VALUES (
|
||||
{{ .Arg .Row.GUID }},
|
||||
@@ -43,5 +55,17 @@ INSERT INTO {{ .Ident "secret_secure_value" }} (
|
||||
{{ if .Row.Ref.Valid }}
|
||||
{{ .Arg .Row.Ref.String }},
|
||||
{{ end }}
|
||||
{{ if .Row.OwnerReferenceAPIGroup.Valid }}
|
||||
{{ .Arg .Row.OwnerReferenceAPIGroup.String }},
|
||||
{{ end }}
|
||||
{{ if .Row.OwnerReferenceAPIVersion.Valid }}
|
||||
{{ .Arg .Row.OwnerReferenceAPIVersion.String }},
|
||||
{{ end }}
|
||||
{{ if .Row.OwnerReferenceKind.Valid }}
|
||||
{{ .Arg .Row.OwnerReferenceKind.String }},
|
||||
{{ end }}
|
||||
{{ if .Row.OwnerReferenceName.Valid }}
|
||||
{{ .Arg .Row.OwnerReferenceName.String }},
|
||||
{{ end }}
|
||||
{{ .Arg .Row.ExternalID }}
|
||||
);
|
||||
@@ -14,7 +14,11 @@ SELECT
|
||||
{{ .Ident "ref" }},
|
||||
{{ .Ident "external_id" }},
|
||||
{{ .Ident "version" }},
|
||||
{{ .Ident "active" }}
|
||||
{{ .Ident "active" }},
|
||||
{{ .Ident "owner_reference_api_group" }},
|
||||
{{ .Ident "owner_reference_api_version" }},
|
||||
{{ .Ident "owner_reference_kind" }},
|
||||
{{ .Ident "owner_reference_name" }}
|
||||
FROM
|
||||
{{ .Ident "secret_secure_value" }}
|
||||
WHERE
|
||||
|
||||
@@ -14,7 +14,11 @@ SELECT
|
||||
{{ .Ident "ref" }},
|
||||
{{ .Ident "external_id" }},
|
||||
{{ .Ident "active" }},
|
||||
{{ .Ident "version" }}
|
||||
{{ .Ident "version" }},
|
||||
{{ .Ident "owner_reference_api_group" }},
|
||||
{{ .Ident "owner_reference_api_version" }},
|
||||
{{ .Ident "owner_reference_kind" }},
|
||||
{{ .Ident "owner_reference_name" }}
|
||||
FROM
|
||||
{{ .Ident "secret_secure_value" }}
|
||||
WHERE
|
||||
|
||||
@@ -177,21 +177,25 @@ func TestSecureValueQueries(t *testing.T) {
|
||||
Data: &createSecureValue{
|
||||
SQLTemplate: mocks.NewTestingSQLTemplate(),
|
||||
Row: &secureValueDB{
|
||||
GUID: "abc",
|
||||
Name: "name",
|
||||
Namespace: "ns",
|
||||
Annotations: `{"x":"XXXX"}`,
|
||||
Labels: `{"a":"AAA", "b", "BBBB"}`,
|
||||
Created: 1234,
|
||||
CreatedBy: "user:ryan",
|
||||
Updated: 5678,
|
||||
UpdatedBy: "user:cameron",
|
||||
Version: 1,
|
||||
Description: "description",
|
||||
Keeper: toNullString(nil),
|
||||
Decrypters: toNullString(nil),
|
||||
Ref: toNullString(nil),
|
||||
ExternalID: "extId",
|
||||
GUID: "abc",
|
||||
Name: "name",
|
||||
Namespace: "ns",
|
||||
Annotations: `{"x":"XXXX"}`,
|
||||
Labels: `{"a":"AAA", "b", "BBBB"}`,
|
||||
Created: 1234,
|
||||
CreatedBy: "user:ryan",
|
||||
Updated: 5678,
|
||||
UpdatedBy: "user:cameron",
|
||||
Version: 1,
|
||||
Description: "description",
|
||||
Keeper: toNullString(nil),
|
||||
Decrypters: toNullString(nil),
|
||||
Ref: toNullString(nil),
|
||||
ExternalID: "extId",
|
||||
OwnerReferenceAPIGroup: toNullString(nil),
|
||||
OwnerReferenceAPIVersion: toNullString(nil),
|
||||
OwnerReferenceKind: toNullString(nil),
|
||||
OwnerReferenceName: toNullString(nil),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -200,21 +204,25 @@ func TestSecureValueQueries(t *testing.T) {
|
||||
Data: &createSecureValue{
|
||||
SQLTemplate: mocks.NewTestingSQLTemplate(),
|
||||
Row: &secureValueDB{
|
||||
GUID: "abc",
|
||||
Name: "name",
|
||||
Namespace: "ns",
|
||||
Annotations: `{"x":"XXXX"}`,
|
||||
Labels: `{"a":"AAA", "b", "BBBB"}`,
|
||||
Created: 1234,
|
||||
CreatedBy: "user:ryan",
|
||||
Updated: 5678,
|
||||
UpdatedBy: "user:cameron",
|
||||
Version: 1,
|
||||
Description: "description",
|
||||
Keeper: toNullString(ptr.To("keeper_test")),
|
||||
Decrypters: toNullString(ptr.To("decrypters_test")),
|
||||
Ref: toNullString(ptr.To("ref_test")),
|
||||
ExternalID: "extId",
|
||||
GUID: "abc",
|
||||
Name: "name",
|
||||
Namespace: "ns",
|
||||
Annotations: `{"x":"XXXX"}`,
|
||||
Labels: `{"a":"AAA", "b", "BBBB"}`,
|
||||
Created: 1234,
|
||||
CreatedBy: "user:ryan",
|
||||
Updated: 5678,
|
||||
UpdatedBy: "user:cameron",
|
||||
Version: 1,
|
||||
Description: "description",
|
||||
Keeper: toNullString(ptr.To("keeper_test")),
|
||||
Decrypters: toNullString(ptr.To("decrypters_test")),
|
||||
Ref: toNullString(ptr.To("ref_test")),
|
||||
ExternalID: "extId",
|
||||
OwnerReferenceAPIGroup: toNullString(ptr.To("prometheus.datasource.grafana.app")),
|
||||
OwnerReferenceAPIVersion: toNullString(ptr.To("v0alpha1")),
|
||||
OwnerReferenceKind: toNullString(ptr.To("DataSource")),
|
||||
OwnerReferenceName: toNullString(ptr.To("prom-config")),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -10,22 +10,26 @@ import (
|
||||
secretv1beta1 "github.com/grafana/grafana/apps/secret/pkg/apis/secret/v1beta1"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/secret/xkube"
|
||||
"github.com/grafana/grafana/pkg/storage/secret/migrator"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
type secureValueDB struct {
|
||||
// Kubernetes Metadata
|
||||
GUID string
|
||||
Name string
|
||||
Namespace string
|
||||
Annotations string // map[string]string
|
||||
Labels string // map[string]string
|
||||
Created int64
|
||||
CreatedBy string
|
||||
Updated int64
|
||||
UpdatedBy string
|
||||
GUID string
|
||||
Name string
|
||||
Namespace string
|
||||
Annotations string // map[string]string
|
||||
Labels string // map[string]string
|
||||
Created int64
|
||||
CreatedBy string
|
||||
Updated int64
|
||||
UpdatedBy string
|
||||
OwnerReferenceAPIGroup sql.NullString
|
||||
OwnerReferenceAPIVersion sql.NullString
|
||||
OwnerReferenceKind sql.NullString
|
||||
OwnerReferenceName sql.NullString
|
||||
|
||||
// Kubernetes Status
|
||||
Active bool
|
||||
@@ -39,10 +43,6 @@ type secureValueDB struct {
|
||||
ExternalID string
|
||||
}
|
||||
|
||||
func (*secureValueDB) TableName() string {
|
||||
return migrator.TableNameSecureValue
|
||||
}
|
||||
|
||||
// toKubernetes maps a DB row into a Kubernetes resource (metadata + spec).
|
||||
func (sv *secureValueDB) toKubernetes() (*secretv1beta1.SecureValue, error) {
|
||||
annotations := make(map[string]string, 0)
|
||||
@@ -85,8 +85,6 @@ func (sv *secureValueDB) toKubernetes() (*secretv1beta1.SecureValue, error) {
|
||||
resource.Spec.Ref = &sv.Ref.String
|
||||
}
|
||||
|
||||
resource.Status.ExternalID = sv.ExternalID
|
||||
|
||||
// Set all meta fields here for consistency.
|
||||
meta, err := utils.MetaAccessor(resource)
|
||||
if err != nil {
|
||||
@@ -106,6 +104,20 @@ func (sv *secureValueDB) toKubernetes() (*secretv1beta1.SecureValue, error) {
|
||||
meta.SetUpdatedTimestamp(&updated)
|
||||
meta.SetResourceVersionInt64(sv.Updated)
|
||||
|
||||
hasOwnerReference := sv.OwnerReferenceAPIGroup.Valid && sv.OwnerReferenceAPIGroup.String != "" &&
|
||||
sv.OwnerReferenceAPIVersion.Valid && sv.OwnerReferenceAPIVersion.String != "" &&
|
||||
sv.OwnerReferenceKind.Valid && sv.OwnerReferenceKind.String != "" &&
|
||||
sv.OwnerReferenceName.Valid && sv.OwnerReferenceName.String != ""
|
||||
if hasOwnerReference {
|
||||
meta.SetOwnerReferences([]metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: schema.GroupVersion{Group: sv.OwnerReferenceAPIGroup.String, Version: sv.OwnerReferenceAPIVersion.String}.String(),
|
||||
Kind: sv.OwnerReferenceKind.String,
|
||||
Name: sv.OwnerReferenceName.String,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return resource, nil
|
||||
}
|
||||
|
||||
@@ -179,16 +191,48 @@ func toRow(sv *secretv1beta1.SecureValue, externalID string) (*secureValueDB, er
|
||||
return nil, fmt.Errorf("failed to get resource version: %w", err)
|
||||
}
|
||||
|
||||
var (
|
||||
ownerReferenceAPIGroup sql.NullString
|
||||
ownerReferenceAPIVersion sql.NullString
|
||||
ownerReferenceKind sql.NullString
|
||||
ownerReferenceName sql.NullString
|
||||
)
|
||||
|
||||
ownerReferences := meta.GetOwnerReferences()
|
||||
if len(ownerReferences) > 1 {
|
||||
return nil, fmt.Errorf("only one owner reference is supported, found %d", len(ownerReferences))
|
||||
}
|
||||
if len(ownerReferences) == 1 {
|
||||
ownerReference := ownerReferences[0]
|
||||
|
||||
gv, err := schema.ParseGroupVersion(ownerReference.APIVersion)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse owner reference API version %s: %w", ownerReference.APIVersion, err)
|
||||
}
|
||||
if gv.Group == "" {
|
||||
return nil, fmt.Errorf("malformed api version %s requires <group>/<version> format", ownerReference.APIVersion)
|
||||
}
|
||||
|
||||
ownerReferenceAPIGroup = toNullString(&gv.Group)
|
||||
ownerReferenceAPIVersion = toNullString(&gv.Version)
|
||||
ownerReferenceKind = toNullString(&ownerReference.Kind)
|
||||
ownerReferenceName = toNullString(&ownerReference.Name)
|
||||
}
|
||||
|
||||
return &secureValueDB{
|
||||
GUID: string(sv.UID),
|
||||
Name: sv.Name,
|
||||
Namespace: sv.Namespace,
|
||||
Annotations: annotations,
|
||||
Labels: labels,
|
||||
Created: meta.GetCreationTimestamp().UnixMilli(),
|
||||
CreatedBy: meta.GetCreatedBy(),
|
||||
Updated: updatedTimestamp,
|
||||
UpdatedBy: meta.GetUpdatedBy(),
|
||||
GUID: string(sv.UID),
|
||||
Name: sv.Name,
|
||||
Namespace: sv.Namespace,
|
||||
Annotations: annotations,
|
||||
Labels: labels,
|
||||
Created: meta.GetCreationTimestamp().UnixMilli(),
|
||||
CreatedBy: meta.GetCreatedBy(),
|
||||
Updated: updatedTimestamp,
|
||||
UpdatedBy: meta.GetUpdatedBy(),
|
||||
OwnerReferenceAPIGroup: ownerReferenceAPIGroup,
|
||||
OwnerReferenceAPIVersion: ownerReferenceAPIVersion,
|
||||
OwnerReferenceKind: ownerReferenceKind,
|
||||
OwnerReferenceName: ownerReferenceName,
|
||||
|
||||
Version: sv.Status.Version,
|
||||
|
||||
|
||||
@@ -243,7 +243,9 @@ func (s *secureValueMetadataStorage) readActiveVersion(ctx context.Context, name
|
||||
&secureValue.Annotations, &secureValue.Labels,
|
||||
&secureValue.Created, &secureValue.CreatedBy,
|
||||
&secureValue.Updated, &secureValue.UpdatedBy,
|
||||
&secureValue.Description, &secureValue.Keeper, &secureValue.Decrypters, &secureValue.Ref, &secureValue.ExternalID, &secureValue.Active, &secureValue.Version); err != nil {
|
||||
&secureValue.Description, &secureValue.Keeper, &secureValue.Decrypters, &secureValue.Ref, &secureValue.ExternalID, &secureValue.Active, &secureValue.Version,
|
||||
&secureValue.OwnerReferenceAPIGroup, &secureValue.OwnerReferenceAPIVersion, &secureValue.OwnerReferenceKind, &secureValue.OwnerReferenceName,
|
||||
); err != nil {
|
||||
return secureValueDB{}, fmt.Errorf("failed to scan secure value row: %w", err)
|
||||
}
|
||||
|
||||
@@ -320,6 +322,7 @@ func (s *secureValueMetadataStorage) List(ctx context.Context, namespace xkube.N
|
||||
&row.Updated, &row.UpdatedBy,
|
||||
&row.Description, &row.Keeper, &row.Decrypters,
|
||||
&row.Ref, &row.ExternalID, &row.Version, &row.Active,
|
||||
&row.OwnerReferenceAPIGroup, &row.OwnerReferenceAPIVersion, &row.OwnerReferenceKind, &row.OwnerReferenceName,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
|
||||
+8
@@ -14,6 +14,10 @@ INSERT INTO `secret_secure_value` (
|
||||
`keeper`,
|
||||
`decrypters`,
|
||||
`ref`,
|
||||
`owner_reference_api_group`,
|
||||
`owner_reference_api_version`,
|
||||
`owner_reference_kind`,
|
||||
`owner_reference_name`,
|
||||
`external_id`
|
||||
) VALUES (
|
||||
'abc',
|
||||
@@ -31,5 +35,9 @@ INSERT INTO `secret_secure_value` (
|
||||
'keeper_test',
|
||||
'decrypters_test',
|
||||
'ref_test',
|
||||
'prometheus.datasource.grafana.app',
|
||||
'v0alpha1',
|
||||
'DataSource',
|
||||
'prom-config',
|
||||
'extId'
|
||||
);
|
||||
|
||||
@@ -14,7 +14,11 @@ SELECT
|
||||
`ref`,
|
||||
`external_id`,
|
||||
`version`,
|
||||
`active`
|
||||
`active`,
|
||||
`owner_reference_api_group`,
|
||||
`owner_reference_api_version`,
|
||||
`owner_reference_kind`,
|
||||
`owner_reference_name`
|
||||
FROM
|
||||
`secret_secure_value`
|
||||
WHERE
|
||||
|
||||
+5
-1
@@ -14,7 +14,11 @@ SELECT
|
||||
`ref`,
|
||||
`external_id`,
|
||||
`active`,
|
||||
`version`
|
||||
`version`,
|
||||
`owner_reference_api_group`,
|
||||
`owner_reference_api_version`,
|
||||
`owner_reference_kind`,
|
||||
`owner_reference_name`
|
||||
FROM
|
||||
`secret_secure_value`
|
||||
WHERE
|
||||
|
||||
@@ -14,7 +14,11 @@ SELECT
|
||||
`ref`,
|
||||
`external_id`,
|
||||
`active`,
|
||||
`version`
|
||||
`version`,
|
||||
`owner_reference_api_group`,
|
||||
`owner_reference_api_version`,
|
||||
`owner_reference_kind`,
|
||||
`owner_reference_name`
|
||||
FROM
|
||||
`secret_secure_value`
|
||||
WHERE
|
||||
|
||||
+8
@@ -14,6 +14,10 @@ INSERT INTO "secret_secure_value" (
|
||||
"keeper",
|
||||
"decrypters",
|
||||
"ref",
|
||||
"owner_reference_api_group",
|
||||
"owner_reference_api_version",
|
||||
"owner_reference_kind",
|
||||
"owner_reference_name",
|
||||
"external_id"
|
||||
) VALUES (
|
||||
'abc',
|
||||
@@ -31,5 +35,9 @@ INSERT INTO "secret_secure_value" (
|
||||
'keeper_test',
|
||||
'decrypters_test',
|
||||
'ref_test',
|
||||
'prometheus.datasource.grafana.app',
|
||||
'v0alpha1',
|
||||
'DataSource',
|
||||
'prom-config',
|
||||
'extId'
|
||||
);
|
||||
|
||||
@@ -14,7 +14,11 @@ SELECT
|
||||
"ref",
|
||||
"external_id",
|
||||
"version",
|
||||
"active"
|
||||
"active",
|
||||
"owner_reference_api_group",
|
||||
"owner_reference_api_version",
|
||||
"owner_reference_kind",
|
||||
"owner_reference_name"
|
||||
FROM
|
||||
"secret_secure_value"
|
||||
WHERE
|
||||
|
||||
+5
-1
@@ -14,7 +14,11 @@ SELECT
|
||||
"ref",
|
||||
"external_id",
|
||||
"active",
|
||||
"version"
|
||||
"version",
|
||||
"owner_reference_api_group",
|
||||
"owner_reference_api_version",
|
||||
"owner_reference_kind",
|
||||
"owner_reference_name"
|
||||
FROM
|
||||
"secret_secure_value"
|
||||
WHERE
|
||||
|
||||
@@ -14,7 +14,11 @@ SELECT
|
||||
"ref",
|
||||
"external_id",
|
||||
"active",
|
||||
"version"
|
||||
"version",
|
||||
"owner_reference_api_group",
|
||||
"owner_reference_api_version",
|
||||
"owner_reference_kind",
|
||||
"owner_reference_name"
|
||||
FROM
|
||||
"secret_secure_value"
|
||||
WHERE
|
||||
|
||||
+8
@@ -14,6 +14,10 @@ INSERT INTO "secret_secure_value" (
|
||||
"keeper",
|
||||
"decrypters",
|
||||
"ref",
|
||||
"owner_reference_api_group",
|
||||
"owner_reference_api_version",
|
||||
"owner_reference_kind",
|
||||
"owner_reference_name",
|
||||
"external_id"
|
||||
) VALUES (
|
||||
'abc',
|
||||
@@ -31,5 +35,9 @@ INSERT INTO "secret_secure_value" (
|
||||
'keeper_test',
|
||||
'decrypters_test',
|
||||
'ref_test',
|
||||
'prometheus.datasource.grafana.app',
|
||||
'v0alpha1',
|
||||
'DataSource',
|
||||
'prom-config',
|
||||
'extId'
|
||||
);
|
||||
|
||||
@@ -14,7 +14,11 @@ SELECT
|
||||
"ref",
|
||||
"external_id",
|
||||
"version",
|
||||
"active"
|
||||
"active",
|
||||
"owner_reference_api_group",
|
||||
"owner_reference_api_version",
|
||||
"owner_reference_kind",
|
||||
"owner_reference_name"
|
||||
FROM
|
||||
"secret_secure_value"
|
||||
WHERE
|
||||
|
||||
+5
-1
@@ -14,7 +14,11 @@ SELECT
|
||||
"ref",
|
||||
"external_id",
|
||||
"active",
|
||||
"version"
|
||||
"version",
|
||||
"owner_reference_api_group",
|
||||
"owner_reference_api_version",
|
||||
"owner_reference_kind",
|
||||
"owner_reference_name"
|
||||
FROM
|
||||
"secret_secure_value"
|
||||
WHERE
|
||||
|
||||
@@ -14,7 +14,11 @@ SELECT
|
||||
"ref",
|
||||
"external_id",
|
||||
"active",
|
||||
"version"
|
||||
"version",
|
||||
"owner_reference_api_group",
|
||||
"owner_reference_api_version",
|
||||
"owner_reference_kind",
|
||||
"owner_reference_name"
|
||||
FROM
|
||||
"secret_secure_value"
|
||||
WHERE
|
||||
|
||||
@@ -152,4 +152,33 @@ func (*SecretDB) AddMigration(mg *migrator.Migrator) {
|
||||
Cols: []string{"namespace", "label", "active"},
|
||||
Type: migrator.IndexType,
|
||||
}))
|
||||
|
||||
// Owner Reference columns
|
||||
mg.AddMigration("add owner_reference_api_group column to "+TableNameSecureValue, migrator.NewAddColumnMigration(secureValueTable, &migrator.Column{
|
||||
Name: "owner_reference_api_group",
|
||||
Type: migrator.DB_NVarchar,
|
||||
Length: 253, // Limit enforced by K8s.
|
||||
Nullable: true,
|
||||
}))
|
||||
|
||||
mg.AddMigration("add owner_reference_api_version column to "+TableNameSecureValue, migrator.NewAddColumnMigration(secureValueTable, &migrator.Column{
|
||||
Name: "owner_reference_api_version",
|
||||
Type: migrator.DB_NVarchar,
|
||||
Length: 253, // Limit enforced by K8s.
|
||||
Nullable: true,
|
||||
}))
|
||||
|
||||
mg.AddMigration("add owner_reference_kind column to "+TableNameSecureValue, migrator.NewAddColumnMigration(secureValueTable, &migrator.Column{
|
||||
Name: "owner_reference_kind",
|
||||
Type: migrator.DB_NVarchar,
|
||||
Length: 253, // Limit enforced by K8s.
|
||||
Nullable: true,
|
||||
}))
|
||||
|
||||
mg.AddMigration("add owner_reference_name column to "+TableNameSecureValue, migrator.NewAddColumnMigration(secureValueTable, &migrator.Column{
|
||||
Name: "owner_reference_name",
|
||||
Type: migrator.DB_NVarchar,
|
||||
Length: 253, // Limit enforced by K8s.
|
||||
Nullable: true,
|
||||
}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user