Secrets: Manage secure values inside any resource (#107803)
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
package resource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"slices"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
secrets "github.com/grafana/grafana/pkg/registry/apis/secret/contracts"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
)
|
||||
|
||||
// The "CanReference" check exists to avoid writing references to secrets
|
||||
// the user should not allow granting access. We only check it when the value changes
|
||||
func canReferenceSecureValues(ctx context.Context,
|
||||
obj utils.GrafanaMetaAccessor,
|
||||
old utils.GrafanaMetaAccessor,
|
||||
secrets secrets.InlineSecureValueSupport,
|
||||
) *resourcepb.ErrorResult {
|
||||
secure, err := obj.GetSecureValues()
|
||||
if err != nil || len(secure) == 0 {
|
||||
return AsErrorResult(err)
|
||||
}
|
||||
|
||||
if secrets == nil {
|
||||
return &resourcepb.ErrorResult{
|
||||
Message: "secure storage not configured",
|
||||
Code: http.StatusServiceUnavailable,
|
||||
Reason: string(metav1.StatusReasonServiceUnavailable),
|
||||
}
|
||||
}
|
||||
|
||||
// All references should only set a name
|
||||
names := make([]string, 0, len(secure))
|
||||
for k, v := range secure {
|
||||
if !v.Create.IsZero() {
|
||||
return newInvalidFieldError(obj,
|
||||
"unable to create values in unified storage",
|
||||
"secure", k, "create")
|
||||
}
|
||||
if v.Remove {
|
||||
return newInvalidFieldError(obj,
|
||||
"unable to save the remove command",
|
||||
"secure", k, "remove")
|
||||
}
|
||||
if v.Name == "" {
|
||||
return newRequiredFieldError(obj,
|
||||
"missing name",
|
||||
"secure", k, "name")
|
||||
}
|
||||
names = append(names, v.Name)
|
||||
}
|
||||
|
||||
// This will call the real service to check access, converting any errors to protobuf
|
||||
canReference := func() *resourcepb.ErrorResult {
|
||||
slices.Sort(names)
|
||||
names = slices.Compact(names) //
|
||||
if err := secrets.CanReference(ctx, utils.ToObjectReference(obj), names...); err != nil {
|
||||
return AsErrorResult(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Always check for create
|
||||
if old == nil {
|
||||
return canReference()
|
||||
}
|
||||
|
||||
oldSecureValues, err := old.GetSecureValues()
|
||||
if err != nil || len(secure) != len(oldSecureValues) {
|
||||
return canReference()
|
||||
}
|
||||
for k, v := range secure {
|
||||
if oldSecureValues[k].Name != v.Name {
|
||||
return canReference()
|
||||
}
|
||||
}
|
||||
return nil // no need to check if the values are the same
|
||||
}
|
||||
Reference in New Issue
Block a user