mirror of
https://github.com/grafana/grafana.git
synced 2025-08-03 02:42:22 +08:00
Plugins: Remove support for secrets manager plugins (#101467)
* remove secrets manager code * remove unused struct * add test toggles back * rollback golden file changes * add missing TestMain * update betterer
This commit is contained in:
@ -4776,10 +4776,9 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "2"],
|
||||
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "3"],
|
||||
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "4"],
|
||||
[0, 0, 0, "No untranslated strings in text props. Wrap text with <Trans /> or use t()", "5"],
|
||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "5"],
|
||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "6"],
|
||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "7"],
|
||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "8"]
|
||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "7"]
|
||||
],
|
||||
"public/app/features/plugins/admin/components/InstallControls/index.tsx:5381": [
|
||||
[0, 0, 0, "Do not re-export imported variable (\`./InstallControlsButton\`)", "0"],
|
||||
|
1
Makefile
1
Makefile
@ -441,7 +441,6 @@ protobuf: ## Compile protobuf definitions
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.4.0
|
||||
buf generate pkg/plugins/backendplugin/pluginextensionv2 --template pkg/plugins/backendplugin/pluginextensionv2/buf.gen.yaml
|
||||
buf generate pkg/plugins/backendplugin/secretsmanagerplugin --template pkg/plugins/backendplugin/secretsmanagerplugin/buf.gen.yaml
|
||||
buf generate pkg/apis/secret/v0alpha1/decrypt --template pkg/apis/secret/v0alpha1/decrypt/buf.gen.yaml
|
||||
buf generate pkg/storage/unified/resource --template pkg/storage/unified/resource/buf.gen.yaml
|
||||
buf generate pkg/services/authz/proto/v1 --template pkg/services/authz/proto/v1/buf.gen.yaml
|
||||
|
@ -10,12 +10,12 @@
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique name of the plugin. If the plugin is published on grafana.com, then the plugin `id` has to follow the naming conventions.",
|
||||
"pattern": "^[0-9a-z]+\\-([0-9a-z]+\\-)?(app|panel|datasource|secretsmanager)$"
|
||||
"pattern": "^[0-9a-z]+\\-([0-9a-z]+\\-)?(app|panel|datasource)$"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Plugin type.",
|
||||
"enum": ["app", "datasource", "panel", "renderer", "secretsmanager"]
|
||||
"enum": ["app", "datasource", "panel", "renderer"]
|
||||
},
|
||||
"info": {
|
||||
"type": "object",
|
||||
@ -183,11 +183,11 @@
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-z]+\\-([0-9a-z]+\\-)?(app|panel|datasource|secretsmanager)$"
|
||||
"pattern": "^[0-9a-z]+\\-([0-9a-z]+\\-)?(app|panel|datasource)$"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["app", "datasource", "panel", "secretsmanager"]
|
||||
"enum": ["app", "datasource", "panel"]
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
@ -280,7 +280,7 @@
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["dashboard", "page", "panel", "datasource", "secretsmanager"]
|
||||
"enum": ["dashboard", "page", "panel", "datasource"]
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
@ -647,7 +647,7 @@
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "A unique identifier for your exposed component. This is used to reference the component in other plugins. It must be in the following format: '{PLUGIN_ID}/name-of-component/v1'.",
|
||||
"pattern": "^[0-9a-z]+-([0-9a-z]+-)?(app|panel|datasource|secretsmanager)\\/[a-zA-Z0-9_-]+\\/v[0-9_.-]+$"
|
||||
"pattern": "^[0-9a-z]+-([0-9a-z]+-)?(app|panel|datasource)\\/[a-zA-Z0-9_-]+\\/v[0-9_.-]+$"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
@ -670,7 +670,7 @@
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "A unique identifier for your extension point. This is used to reference the extension point in other plugins. It must be in the following format: '{PLUGIN_ID}/name-of-my-extension-point/v1'.",
|
||||
"pattern": "^[0-9a-z]+-([0-9a-z]+-)?(app|panel|datasource|secretsmanager)\\/[a-zA-Z0-9_-]+\\/v[0-9_.-]+$"
|
||||
"pattern": "^[0-9a-z]+-([0-9a-z]+-)?(app|panel|datasource)\\/[a-zA-Z0-9_-]+\\/v[0-9_.-]+$"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
|
@ -215,7 +215,6 @@ export interface GrafanaConfig {
|
||||
unifiedAlerting: UnifiedAlertingConfig;
|
||||
angularSupportEnabled: boolean;
|
||||
feedbackLinksEnabled: boolean;
|
||||
secretsManagerPluginEnabled: boolean;
|
||||
supportBundlesEnabled: boolean;
|
||||
secureSocksDSProxyEnabled: boolean;
|
||||
googleAnalyticsId: string | undefined;
|
||||
|
@ -17,7 +17,6 @@ export enum PluginType {
|
||||
datasource = 'datasource',
|
||||
app = 'app',
|
||||
renderer = 'renderer',
|
||||
secretsmanager = 'secretsmanager',
|
||||
}
|
||||
|
||||
/** Describes status of {@link https://grafana.com/docs/grafana/latest/plugins/plugin-signatures/ | plugin signature} */
|
||||
|
@ -119,7 +119,6 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
||||
rendererDefaultImageWidth = 1000;
|
||||
rendererDefaultImageHeight = 500;
|
||||
rendererDefaultImageScale = 1;
|
||||
secretsManagerPluginEnabled = false;
|
||||
supportBundlesEnabled = false;
|
||||
http2Enabled = false;
|
||||
dateFormats?: SystemDateFormatSettings;
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
skv "github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) AdminRotateDataEncryptionKeys(c *contextmodel.ReqContext) response.Response {
|
||||
@ -50,51 +49,3 @@ func (hs *HTTPServer) AdminRollbackSecrets(c *contextmodel.ReqContext) response.
|
||||
|
||||
return response.Respond(http.StatusOK, "Secrets rolled back successfully")
|
||||
}
|
||||
|
||||
// To migrate to the plugin, it must be installed and configured
|
||||
// so as not to lose access to migrated secrets
|
||||
func (hs *HTTPServer) AdminMigrateSecretsToPlugin(c *contextmodel.ReqContext) response.Response {
|
||||
if skv.EvaluateRemoteSecretsPlugin(c.Req.Context(), hs.secretsPluginManager, hs.Cfg) != nil {
|
||||
hs.log.Warn("Received secrets plugin migration request while plugin is not available")
|
||||
return response.Respond(http.StatusBadRequest, "Secrets plugin is not available")
|
||||
}
|
||||
err := hs.secretsPluginMigrator.TriggerPluginMigration(c.Req.Context(), true)
|
||||
if err != nil {
|
||||
hs.log.Error("Failed to trigger secret migration to plugin", "error", err.Error())
|
||||
return response.Respond(http.StatusInternalServerError, "Secret migration to plugin failed")
|
||||
}
|
||||
return response.Respond(http.StatusOK, "Secret migration to plugin triggered successfully")
|
||||
}
|
||||
|
||||
// To migrate from the plugin, it must be installed only
|
||||
// as it is possible the user disabled it and then wants to migrate
|
||||
func (hs *HTTPServer) AdminMigrateSecretsFromPlugin(c *contextmodel.ReqContext) response.Response {
|
||||
if hs.secretsPluginManager.SecretsManager(c.Req.Context()) == nil {
|
||||
hs.log.Warn("Received secrets plugin migration request while plugin is not installed")
|
||||
return response.Respond(http.StatusBadRequest, "Secrets plugin is not installed")
|
||||
}
|
||||
err := hs.secretsPluginMigrator.TriggerPluginMigration(c.Req.Context(), false)
|
||||
if err != nil {
|
||||
hs.log.Error("Failed to trigger secret migration from plugin", "error", err.Error())
|
||||
return response.Respond(http.StatusInternalServerError, "Secret migration from plugin failed")
|
||||
}
|
||||
return response.Respond(http.StatusOK, "Secret migration from plugin triggered successfully")
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) AdminDeleteAllSecretsManagerPluginSecrets(c *contextmodel.ReqContext) response.Response {
|
||||
if hs.secretsPluginManager.SecretsManager(c.Req.Context()) == nil {
|
||||
hs.log.Warn("Received secrets plugin deletion request while plugin is not installed")
|
||||
return response.Respond(http.StatusBadRequest, "Secrets plugin is not installed")
|
||||
}
|
||||
items, err := hs.secretsStore.GetAll(c.Req.Context())
|
||||
if err != nil {
|
||||
return response.Respond(http.StatusInternalServerError, "an error occurred while retrieving secrets")
|
||||
}
|
||||
for _, item := range items {
|
||||
err := hs.secretsStore.Del(c.Req.Context(), *item.OrgId, *item.Namespace, *item.Type)
|
||||
if err != nil {
|
||||
return response.Respond(http.StatusInternalServerError, fmt.Sprintf("error deleting key with org=%v namespace=%v type=%v. error=%v", *item.OrgId, *item.Namespace, *item.Type, err.Error()))
|
||||
}
|
||||
}
|
||||
return response.Respond(http.StatusOK, fmt.Sprintf("All %d Secrets Manager plugin secrets deleted", len(items)))
|
||||
}
|
||||
|
@ -573,9 +573,6 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
adminRoute.Post("/encryption/reencrypt-data-keys", reqGrafanaAdmin, routing.Wrap(hs.AdminReEncryptEncryptionKeys))
|
||||
adminRoute.Post("/encryption/reencrypt-secrets", reqGrafanaAdmin, routing.Wrap(hs.AdminReEncryptSecrets))
|
||||
adminRoute.Post("/encryption/rollback-secrets", reqGrafanaAdmin, routing.Wrap(hs.AdminRollbackSecrets))
|
||||
adminRoute.Post("/encryption/migrate-secrets/to-plugin", reqGrafanaAdmin, routing.Wrap(hs.AdminMigrateSecretsToPlugin))
|
||||
adminRoute.Post("/encryption/migrate-secrets/from-plugin", reqGrafanaAdmin, routing.Wrap(hs.AdminMigrateSecretsFromPlugin))
|
||||
adminRoute.Post("/encryption/delete-secretsmanagerplugin-secrets", reqGrafanaAdmin, routing.Wrap(hs.AdminDeleteAllSecretsManagerPluginSecrets))
|
||||
|
||||
adminRoute.Post("/provisioning/dashboards/reload", authorize(ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersDashboards)), routing.Wrap(hs.AdminProvisioningReloadDashboards))
|
||||
adminRoute.Post("/provisioning/plugins/reload", authorize(ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersPlugins)), routing.Wrap(hs.AdminProvisioningReloadPlugins))
|
||||
|
@ -26,7 +26,6 @@ import (
|
||||
)
|
||||
|
||||
var datasourcesLogger = log.New("datasources")
|
||||
var secretsPluginError datasources.ErrDatasourceSecretsPluginUserFriendly
|
||||
|
||||
// swagger:route GET /datasources datasources getDataSources
|
||||
//
|
||||
@ -178,9 +177,6 @@ func (hs *HTTPServer) DeleteDataSourceById(c *contextmodel.ReqContext) response.
|
||||
|
||||
err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
|
||||
if err != nil {
|
||||
if errors.As(err, &secretsPluginError) {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to delete datasource: "+err.Error(), err)
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "Failed to delete datasource", err)
|
||||
}
|
||||
|
||||
@ -257,9 +253,6 @@ func (hs *HTTPServer) DeleteDataSourceByUID(c *contextmodel.ReqContext) response
|
||||
|
||||
err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
|
||||
if err != nil {
|
||||
if errors.As(err, &secretsPluginError) {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to delete datasource: "+err.Error(), err)
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "Failed to delete datasource", err)
|
||||
}
|
||||
|
||||
@ -307,9 +300,6 @@ func (hs *HTTPServer) DeleteDataSourceByName(c *contextmodel.ReqContext) respons
|
||||
cmd := &datasources.DeleteDataSourceCommand{Name: name, OrgID: c.SignedInUser.GetOrgID()}
|
||||
err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
|
||||
if err != nil {
|
||||
if errors.As(err, &secretsPluginError) {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to delete datasource: "+err.Error(), err)
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "Failed to delete datasource", err)
|
||||
}
|
||||
|
||||
@ -405,10 +395,6 @@ func (hs *HTTPServer) AddDataSource(c *contextmodel.ReqContext) response.Respons
|
||||
return response.Error(http.StatusConflict, err.Error(), err)
|
||||
}
|
||||
|
||||
if errors.As(err, &secretsPluginError) {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to add datasource: "+err.Error(), err)
|
||||
}
|
||||
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "Failed to add datasource", err)
|
||||
}
|
||||
|
||||
@ -532,10 +518,6 @@ func (hs *HTTPServer) updateDataSourceByID(c *contextmodel.ReqContext, ds *datas
|
||||
return response.Error(http.StatusConflict, "Datasource has already been updated by someone else. Please reload and try again", err)
|
||||
}
|
||||
|
||||
if errors.As(err, &secretsPluginError) {
|
||||
return response.Error(http.StatusInternalServerError, "Failed to update datasource: "+err.Error(), err)
|
||||
}
|
||||
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "Failed to update datasource", err)
|
||||
}
|
||||
|
||||
|
@ -29,11 +29,6 @@ func (hs *HTTPServer) handleQueryMetricsError(err error) *response.NormalRespons
|
||||
return response.Error(http.StatusNotFound, "Data source not found", err)
|
||||
}
|
||||
|
||||
var secretsPlugin datasources.ErrDatasourceSecretsPluginUserFriendly
|
||||
if errors.As(err, &secretsPlugin) {
|
||||
return response.Error(http.StatusInternalServerError, fmt.Sprint("Secrets Plugin error: ", err.Error()), err)
|
||||
}
|
||||
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "Query data error", err)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@ -25,7 +24,6 @@ import (
|
||||
fakeDatasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
pluginSettings "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/query"
|
||||
@ -40,11 +38,6 @@ type fakeDataSourceRequestValidator struct {
|
||||
err error
|
||||
}
|
||||
|
||||
type secretsErrorResponseBody struct {
|
||||
Error string `json:"error"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (rv *fakeDataSourceRequestValidator) Validate(ds *datasources.DataSource, req *http.Request) error {
|
||||
return rv.err
|
||||
}
|
||||
@ -93,64 +86,6 @@ func TestAPIEndpoint_Metrics_QueryMetricsV2(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAPIEndpoint_Metrics_PluginDecryptionFailure(t *testing.T) {
|
||||
cfg := setting.NewCfg()
|
||||
ds := &fakeDatasources.FakeDataSourceService{SimulatePluginFailure: true}
|
||||
db := &dbtest.FakeDB{ExpectedError: pluginsettings.ErrPluginSettingNotFound}
|
||||
pcp := plugincontext.ProvideService(cfg, localcache.ProvideService(),
|
||||
&pluginstore.FakePluginStore{
|
||||
PluginList: []pluginstore.Plugin{
|
||||
{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "grafana",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&fakeDatasources.FakeCacheService{},
|
||||
ds, pluginSettings.ProvideService(db, secretstest.NewFakeSecretsService()), pluginconfig.NewFakePluginRequestConfigProvider(),
|
||||
)
|
||||
qds := query.ProvideService(
|
||||
cfg,
|
||||
nil,
|
||||
nil,
|
||||
&fakeDataSourceRequestValidator{},
|
||||
&fakePluginClient{
|
||||
QueryDataHandlerFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
resp := backend.Responses{
|
||||
"A": backend.DataResponse{
|
||||
Error: errors.New("query failed"),
|
||||
},
|
||||
}
|
||||
return &backend.QueryDataResponse{Responses: resp}, nil
|
||||
},
|
||||
},
|
||||
pcp,
|
||||
)
|
||||
httpServer := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||
hs.queryDataService = qds
|
||||
hs.QuotaService = quotatest.New(false, nil)
|
||||
hs.pluginContextProvider = pcp
|
||||
})
|
||||
|
||||
t.Run("Status code is 500 and a secrets plugin error is returned if there is a problem getting secrets from the remote plugin", func(t *testing.T) {
|
||||
req := httpServer.NewPostRequest("/api/ds/query", strings.NewReader(reqValid))
|
||||
webtest.RequestWithSignedInUser(req, &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {datasources.ActionQuery: []string{datasources.ScopeAll}}}})
|
||||
resp, err := httpServer.SendJSON(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, http.StatusInternalServerError, resp.StatusCode)
|
||||
buf := new(bytes.Buffer)
|
||||
_, err = buf.ReadFrom(resp.Body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, resp.Body.Close())
|
||||
var resObj secretsErrorResponseBody
|
||||
err = json.Unmarshal(buf.Bytes(), &resObj)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "", resObj.Error)
|
||||
require.Contains(t, resObj.Message, "Secrets Plugin error:")
|
||||
})
|
||||
}
|
||||
|
||||
var reqValid = `{
|
||||
"from": "",
|
||||
"to": "",
|
||||
|
@ -228,7 +228,6 @@ type FrontendSettingsDTO struct {
|
||||
RendererDefaultImageWidth int `json:"rendererDefaultImageWidth"`
|
||||
RendererDefaultImageHeight int `json:"rendererDefaultImageHeight"`
|
||||
RendererDefaultImageScale float64 `json:"rendererDefaultImageScale"`
|
||||
SecretsManagerPluginEnabled bool `json:"secretsManagerPluginEnabled"`
|
||||
Http2Enabled bool `json:"http2Enabled"`
|
||||
GrafanaJavascriptAgent setting.GrafanaJavascriptAgent `json:"grafanaJavascriptAgent"`
|
||||
PluginCatalogURL string `json:"pluginCatalogURL"`
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/licensing"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tsdb/grafanads"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -174,7 +173,6 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
|
||||
}
|
||||
|
||||
hasAccess := accesscontrol.HasAccess(hs.AccessControl, c)
|
||||
secretsManagerPluginEnabled := kvstore.EvaluateRemoteSecretsPlugin(c.Req.Context(), hs.secretsPluginManager, hs.Cfg) == nil
|
||||
trustedTypesDefaultPolicyEnabled := (hs.Cfg.CSPEnabled && strings.Contains(hs.Cfg.CSPTemplate, "require-trusted-types-for")) || (hs.Cfg.CSPReportOnlyEnabled && strings.Contains(hs.Cfg.CSPReportOnlyTemplate, "require-trusted-types-for"))
|
||||
isCloudMigrationTarget := hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagOnPremToCloudMigrations) && hs.Cfg.CloudMigration.IsTarget
|
||||
featureToggles := hs.Features.GetEnabled(c.Req.Context())
|
||||
@ -279,7 +277,6 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
|
||||
RendererDefaultImageWidth: hs.Cfg.RendererDefaultImageWidth,
|
||||
RendererDefaultImageHeight: hs.Cfg.RendererDefaultImageHeight,
|
||||
RendererDefaultImageScale: hs.Cfg.RendererDefaultImageScale,
|
||||
SecretsManagerPluginEnabled: secretsManagerPluginEnabled,
|
||||
Http2Enabled: hs.Cfg.Protocol == setting.HTTP2Scheme,
|
||||
GrafanaJavascriptAgent: hs.Cfg.GrafanaJavascriptAgent,
|
||||
PluginCatalogURL: hs.Cfg.PluginCatalogURL,
|
||||
|
@ -169,10 +169,9 @@ type HTTPServer struct {
|
||||
Listener net.Listener
|
||||
EncryptionService encryption.Internal
|
||||
SecretsService secrets.Service
|
||||
secretsPluginManager plugins.SecretsPluginManager
|
||||
secretsStore secretsKV.SecretsKVStore
|
||||
secretsMigrator secrets.Migrator
|
||||
secretsPluginMigrator spm.SecretMigrationProvider
|
||||
secretMigrationProvider spm.SecretMigrationProvider
|
||||
DataSourcesService datasources.DataSourceService
|
||||
cleanUpService *cleanup.CleanUpService
|
||||
tracer tracing.Tracer
|
||||
@ -264,8 +263,8 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
dashboardPermissionsService accesscontrol.DashboardPermissionsService, dashboardVersionService dashver.Service,
|
||||
starService star.Service, csrfService csrf.Service, managedPlugins managedplugins.Manager,
|
||||
playlistService playlist.Service, apiKeyService apikey.Service, kvStore kvstore.KVStore,
|
||||
secretsMigrator secrets.Migrator, secretsPluginManager plugins.SecretsPluginManager, secretsService secrets.Service,
|
||||
secretsPluginMigrator spm.SecretMigrationProvider, secretsStore secretsKV.SecretsKVStore,
|
||||
secretsMigrator secrets.Migrator, secretsService secrets.Service,
|
||||
secretMigrationProvider spm.SecretMigrationProvider, secretsStore secretsKV.SecretsKVStore,
|
||||
publicDashboardsApi *publicdashboardsApi.Api, userService user.Service, tempUserService tempUser.Service,
|
||||
loginAttemptService loginAttempt.Service, orgService org.Service, orgDeletionService org.DeletionService, teamService team.Service,
|
||||
accesscontrolService accesscontrol.Service, navTreeService navtree.Service,
|
||||
@ -329,9 +328,8 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
SocialService: socialService,
|
||||
EncryptionService: encryptionService,
|
||||
SecretsService: secretsService,
|
||||
secretsPluginManager: secretsPluginManager,
|
||||
secretsMigrator: secretsMigrator,
|
||||
secretsPluginMigrator: secretsPluginMigrator,
|
||||
secretMigrationProvider: secretMigrationProvider,
|
||||
secretsStore: secretsStore,
|
||||
DataSourcesService: dataSourcesService,
|
||||
searchUsersService: searchUsersService,
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
)
|
||||
|
||||
@ -31,14 +30,13 @@ var handshake = goplugin.HandshakeConfig{
|
||||
// pluginSet is list of plugins supported on v2.
|
||||
var pluginSet = map[int]goplugin.PluginSet{
|
||||
grpcplugin.ProtocolVersion: {
|
||||
"diagnostics": &grpcplugin.DiagnosticsGRPCPlugin{},
|
||||
"resource": &grpcplugin.ResourceGRPCPlugin{},
|
||||
"data": &grpcplugin.DataGRPCPlugin{},
|
||||
"stream": &grpcplugin.StreamGRPCPlugin{},
|
||||
"admission": &grpcplugin.AdmissionGRPCPlugin{},
|
||||
"conversion": &grpcplugin.ConversionGRPCPlugin{},
|
||||
"renderer": &pluginextensionv2.RendererGRPCPlugin{},
|
||||
"secretsmanager": &secretsmanagerplugin.SecretsManagerGRPCPlugin{},
|
||||
"diagnostics": &grpcplugin.DiagnosticsGRPCPlugin{},
|
||||
"resource": &grpcplugin.ResourceGRPCPlugin{},
|
||||
"data": &grpcplugin.DataGRPCPlugin{},
|
||||
"stream": &grpcplugin.StreamGRPCPlugin{},
|
||||
"admission": &grpcplugin.AdmissionGRPCPlugin{},
|
||||
"conversion": &grpcplugin.ConversionGRPCPlugin{},
|
||||
"renderer": &pluginextensionv2.RendererGRPCPlugin{},
|
||||
},
|
||||
}
|
||||
|
||||
@ -84,19 +82,15 @@ func newClientConfig(executablePath string, args []string, env []string, skipHos
|
||||
// StartRendererFunc callback function called when a renderer plugin is started.
|
||||
type StartRendererFunc func(pluginID string, renderer pluginextensionv2.RendererPlugin, logger log.Logger) error
|
||||
|
||||
// StartSecretsManagerFunc callback function called when a secrets manager plugin is started.
|
||||
type StartSecretsManagerFunc func(pluginID string, secretsmanager secretsmanagerplugin.SecretsManagerPlugin, logger log.Logger) error
|
||||
|
||||
// PluginDescriptor is a descriptor used for registering backend plugins.
|
||||
type PluginDescriptor struct {
|
||||
pluginID string
|
||||
executablePath string
|
||||
executableArgs []string
|
||||
skipHostEnvVars bool
|
||||
managed bool
|
||||
versionedPlugins map[int]goplugin.PluginSet
|
||||
startRendererFn StartRendererFunc
|
||||
startSecretsManagerFn StartSecretsManagerFunc
|
||||
pluginID string
|
||||
executablePath string
|
||||
executableArgs []string
|
||||
skipHostEnvVars bool
|
||||
managed bool
|
||||
versionedPlugins map[int]goplugin.PluginSet
|
||||
startRendererFn StartRendererFunc
|
||||
}
|
||||
|
||||
// NewBackendPlugin creates a new backend plugin factory used for registering a backend plugin.
|
||||
@ -131,14 +125,3 @@ func NewRendererPlugin(pluginID, executablePath string, startFn StartRendererFun
|
||||
startRendererFn: startFn,
|
||||
})
|
||||
}
|
||||
|
||||
// NewSecretsManagerPlugin creates a new secrets manager plugin factory used for registering a backend secrets manager plugin.
|
||||
func NewSecretsManagerPlugin(pluginID, executablePath string, startFn StartSecretsManagerFunc) backendplugin.PluginFactoryFunc {
|
||||
return newPlugin(PluginDescriptor{
|
||||
pluginID: pluginID,
|
||||
executablePath: executablePath,
|
||||
managed: false,
|
||||
versionedPlugins: pluginSet,
|
||||
startSecretsManagerFn: startFn,
|
||||
})
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
)
|
||||
|
||||
@ -32,7 +31,6 @@ type ClientV2 struct {
|
||||
grpcplugin.AdmissionClient
|
||||
grpcplugin.ConversionClient
|
||||
pluginextensionv2.RendererPlugin
|
||||
secretsmanagerplugin.SecretsManagerPlugin
|
||||
}
|
||||
|
||||
func newClientV2(descriptor PluginDescriptor, logger log.Logger, rpcClient plugin.ClientProtocol) (*ClientV2, error) {
|
||||
@ -71,11 +69,6 @@ func newClientV2(descriptor PluginDescriptor, logger log.Logger, rpcClient plugi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawSecretsManager, err := rpcClient.Dispense("secretsmanager")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &ClientV2{}
|
||||
if rawDiagnostics != nil {
|
||||
if diagnosticsClient, ok := rawDiagnostics.(grpcplugin.DiagnosticsClient); ok {
|
||||
@ -119,24 +112,12 @@ func newClientV2(descriptor PluginDescriptor, logger log.Logger, rpcClient plugi
|
||||
}
|
||||
}
|
||||
|
||||
if rawSecretsManager != nil {
|
||||
if secretsManagerPlugin, ok := rawSecretsManager.(secretsmanagerplugin.SecretsManagerPlugin); ok {
|
||||
c.SecretsManagerPlugin = secretsManagerPlugin
|
||||
}
|
||||
}
|
||||
|
||||
if descriptor.startRendererFn != nil {
|
||||
if err := descriptor.startRendererFn(descriptor.pluginID, c.RendererPlugin, logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if descriptor.startSecretsManagerFn != nil {
|
||||
if err := descriptor.startSecretsManagerFn(descriptor.pluginID, c.SecretsManagerPlugin, logger); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/grpcplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
)
|
||||
|
||||
@ -21,7 +20,7 @@ type Service struct {
|
||||
|
||||
func New(providers ...PluginBackendProvider) *Service {
|
||||
if len(providers) == 0 {
|
||||
return New(SecretsManagerProvider, DefaultProvider)
|
||||
return New(DefaultProvider)
|
||||
}
|
||||
return &Service{
|
||||
providerChain: providers,
|
||||
@ -29,7 +28,7 @@ func New(providers ...PluginBackendProvider) *Service {
|
||||
}
|
||||
|
||||
func ProvideService(coreRegistry *coreplugin.Registry) *Service {
|
||||
return New(coreRegistry.BackendFactoryProvider(), SecretsManagerProvider, DefaultProvider)
|
||||
return New(coreRegistry.BackendFactoryProvider(), DefaultProvider)
|
||||
}
|
||||
|
||||
func (s *Service) BackendFactory(ctx context.Context, p *plugins.Plugin) backendplugin.PluginFactoryFunc {
|
||||
@ -53,18 +52,6 @@ var RendererProvider PluginBackendProvider = func(_ context.Context, p *plugins.
|
||||
)
|
||||
}
|
||||
|
||||
var SecretsManagerProvider PluginBackendProvider = func(_ context.Context, p *plugins.Plugin) backendplugin.PluginFactoryFunc {
|
||||
if !p.IsSecretsManager() {
|
||||
return nil
|
||||
}
|
||||
return grpcplugin.NewSecretsManagerPlugin(p.ID, p.ExecutablePath(),
|
||||
func(pluginID string, secretsmanager secretsmanagerplugin.SecretsManagerPlugin, logger log.Logger) error {
|
||||
p.SecretsManager = secretsmanager
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
var DefaultProvider = PluginBackendProvider(func(_ context.Context, p *plugins.Plugin) backendplugin.PluginFactoryFunc {
|
||||
return grpcplugin.NewBackendPlugin(p.ID, p.ExecutablePath(), p.SkipHostEnvVars)
|
||||
})
|
||||
|
@ -1,9 +0,0 @@
|
||||
version: v1
|
||||
plugins:
|
||||
- plugin: go
|
||||
out: pkg/plugins/backendplugin/secretsmanagerplugin
|
||||
opt: paths=source_relative
|
||||
- plugin: go-grpc
|
||||
out: pkg/plugins/backendplugin/secretsmanagerplugin
|
||||
opt:
|
||||
- paths=source_relative
|
@ -1,7 +0,0 @@
|
||||
version: v1
|
||||
breaking:
|
||||
use:
|
||||
- FILE
|
||||
lint:
|
||||
use:
|
||||
- DEFAULT
|
@ -1,921 +0,0 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.5
|
||||
// protoc (unknown)
|
||||
// source: secretsmanager.proto
|
||||
|
||||
package secretsmanagerplugin
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Key struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
OrgId int64 `protobuf:"varint,1,opt,name=orgId,proto3" json:"orgId,omitempty"`
|
||||
Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"`
|
||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Key) Reset() {
|
||||
*x = Key{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Key) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Key) ProtoMessage() {}
|
||||
|
||||
func (x *Key) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Key.ProtoReflect.Descriptor instead.
|
||||
func (*Key) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Key) GetOrgId() int64 {
|
||||
if x != nil {
|
||||
return x.OrgId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Key) GetNamespace() string {
|
||||
if x != nil {
|
||||
return x.Namespace
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Key) GetType() string {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Key *Key `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Item) Reset() {
|
||||
*x = Item{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Item) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Item) ProtoMessage() {}
|
||||
|
||||
func (x *Item) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Item.ProtoReflect.Descriptor instead.
|
||||
func (*Item) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Item) GetKey() *Key {
|
||||
if x != nil {
|
||||
return x.Key
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Item) GetValue() string {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GetSecretRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
KeyDescriptor *Key `protobuf:"bytes,1,opt,name=keyDescriptor,proto3" json:"keyDescriptor,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetSecretRequest) Reset() {
|
||||
*x = GetSecretRequest{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetSecretRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetSecretRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetSecretRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetSecretRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetSecretRequest) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *GetSecretRequest) GetKeyDescriptor() *Key {
|
||||
if x != nil {
|
||||
return x.KeyDescriptor
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetSecretResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserFriendlyError string `protobuf:"bytes,1,opt,name=userFriendlyError,proto3" json:"userFriendlyError,omitempty"`
|
||||
DecryptedValue string `protobuf:"bytes,2,opt,name=decryptedValue,proto3" json:"decryptedValue,omitempty"`
|
||||
Exists bool `protobuf:"varint,3,opt,name=exists,proto3" json:"exists,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetSecretResponse) Reset() {
|
||||
*x = GetSecretResponse{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetSecretResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetSecretResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetSecretResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetSecretResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetSecretResponse) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *GetSecretResponse) GetUserFriendlyError() string {
|
||||
if x != nil {
|
||||
return x.UserFriendlyError
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetSecretResponse) GetDecryptedValue() string {
|
||||
if x != nil {
|
||||
return x.DecryptedValue
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetSecretResponse) GetExists() bool {
|
||||
if x != nil {
|
||||
return x.Exists
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type SetSecretRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
KeyDescriptor *Key `protobuf:"bytes,1,opt,name=keyDescriptor,proto3" json:"keyDescriptor,omitempty"`
|
||||
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *SetSecretRequest) Reset() {
|
||||
*x = SetSecretRequest{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *SetSecretRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SetSecretRequest) ProtoMessage() {}
|
||||
|
||||
func (x *SetSecretRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SetSecretRequest.ProtoReflect.Descriptor instead.
|
||||
func (*SetSecretRequest) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *SetSecretRequest) GetKeyDescriptor() *Key {
|
||||
if x != nil {
|
||||
return x.KeyDescriptor
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SetSecretRequest) GetValue() string {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type SetSecretResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserFriendlyError string `protobuf:"bytes,1,opt,name=userFriendlyError,proto3" json:"userFriendlyError,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *SetSecretResponse) Reset() {
|
||||
*x = SetSecretResponse{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *SetSecretResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SetSecretResponse) ProtoMessage() {}
|
||||
|
||||
func (x *SetSecretResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SetSecretResponse.ProtoReflect.Descriptor instead.
|
||||
func (*SetSecretResponse) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *SetSecretResponse) GetUserFriendlyError() string {
|
||||
if x != nil {
|
||||
return x.UserFriendlyError
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type DeleteSecretRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
KeyDescriptor *Key `protobuf:"bytes,1,opt,name=keyDescriptor,proto3" json:"keyDescriptor,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DeleteSecretRequest) Reset() {
|
||||
*x = DeleteSecretRequest{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DeleteSecretRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DeleteSecretRequest) ProtoMessage() {}
|
||||
|
||||
func (x *DeleteSecretRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DeleteSecretRequest.ProtoReflect.Descriptor instead.
|
||||
func (*DeleteSecretRequest) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *DeleteSecretRequest) GetKeyDescriptor() *Key {
|
||||
if x != nil {
|
||||
return x.KeyDescriptor
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeleteSecretResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserFriendlyError string `protobuf:"bytes,1,opt,name=userFriendlyError,proto3" json:"userFriendlyError,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DeleteSecretResponse) Reset() {
|
||||
*x = DeleteSecretResponse{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DeleteSecretResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DeleteSecretResponse) ProtoMessage() {}
|
||||
|
||||
func (x *DeleteSecretResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[7]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DeleteSecretResponse.ProtoReflect.Descriptor instead.
|
||||
func (*DeleteSecretResponse) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *DeleteSecretResponse) GetUserFriendlyError() string {
|
||||
if x != nil {
|
||||
return x.UserFriendlyError
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ListSecretsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
KeyDescriptor *Key `protobuf:"bytes,1,opt,name=keyDescriptor,proto3" json:"keyDescriptor,omitempty"`
|
||||
AllOrganizations bool `protobuf:"varint,2,opt,name=allOrganizations,proto3" json:"allOrganizations,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListSecretsRequest) Reset() {
|
||||
*x = ListSecretsRequest{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListSecretsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListSecretsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ListSecretsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[8]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListSecretsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ListSecretsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *ListSecretsRequest) GetKeyDescriptor() *Key {
|
||||
if x != nil {
|
||||
return x.KeyDescriptor
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ListSecretsRequest) GetAllOrganizations() bool {
|
||||
if x != nil {
|
||||
return x.AllOrganizations
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ListSecretsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserFriendlyError string `protobuf:"bytes,1,opt,name=userFriendlyError,proto3" json:"userFriendlyError,omitempty"`
|
||||
Keys []*Key `protobuf:"bytes,2,rep,name=keys,proto3" json:"keys,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListSecretsResponse) Reset() {
|
||||
*x = ListSecretsResponse{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListSecretsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListSecretsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListSecretsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[9]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListSecretsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListSecretsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
func (x *ListSecretsResponse) GetUserFriendlyError() string {
|
||||
if x != nil {
|
||||
return x.UserFriendlyError
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ListSecretsResponse) GetKeys() []*Key {
|
||||
if x != nil {
|
||||
return x.Keys
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetAllSecretsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetAllSecretsRequest) Reset() {
|
||||
*x = GetAllSecretsRequest{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[10]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetAllSecretsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetAllSecretsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetAllSecretsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[10]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetAllSecretsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetAllSecretsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{10}
|
||||
}
|
||||
|
||||
type GetAllSecretsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserFriendlyError string `protobuf:"bytes,1,opt,name=userFriendlyError,proto3" json:"userFriendlyError,omitempty"`
|
||||
Items []*Item `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetAllSecretsResponse) Reset() {
|
||||
*x = GetAllSecretsResponse{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[11]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetAllSecretsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetAllSecretsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetAllSecretsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[11]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetAllSecretsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetAllSecretsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{11}
|
||||
}
|
||||
|
||||
func (x *GetAllSecretsResponse) GetUserFriendlyError() string {
|
||||
if x != nil {
|
||||
return x.UserFriendlyError
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetAllSecretsResponse) GetItems() []*Item {
|
||||
if x != nil {
|
||||
return x.Items
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RenameSecretRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
KeyDescriptor *Key `protobuf:"bytes,1,opt,name=keyDescriptor,proto3" json:"keyDescriptor,omitempty"`
|
||||
NewNamespace string `protobuf:"bytes,2,opt,name=newNamespace,proto3" json:"newNamespace,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RenameSecretRequest) Reset() {
|
||||
*x = RenameSecretRequest{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[12]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RenameSecretRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RenameSecretRequest) ProtoMessage() {}
|
||||
|
||||
func (x *RenameSecretRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[12]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RenameSecretRequest.ProtoReflect.Descriptor instead.
|
||||
func (*RenameSecretRequest) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{12}
|
||||
}
|
||||
|
||||
func (x *RenameSecretRequest) GetKeyDescriptor() *Key {
|
||||
if x != nil {
|
||||
return x.KeyDescriptor
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RenameSecretRequest) GetNewNamespace() string {
|
||||
if x != nil {
|
||||
return x.NewNamespace
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RenameSecretResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserFriendlyError string `protobuf:"bytes,1,opt,name=userFriendlyError,proto3" json:"userFriendlyError,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RenameSecretResponse) Reset() {
|
||||
*x = RenameSecretResponse{}
|
||||
mi := &file_secretsmanager_proto_msgTypes[13]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RenameSecretResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RenameSecretResponse) ProtoMessage() {}
|
||||
|
||||
func (x *RenameSecretResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_secretsmanager_proto_msgTypes[13]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RenameSecretResponse.ProtoReflect.Descriptor instead.
|
||||
func (*RenameSecretResponse) Descriptor() ([]byte, []int) {
|
||||
return file_secretsmanager_proto_rawDescGZIP(), []int{13}
|
||||
}
|
||||
|
||||
func (x *RenameSecretResponse) GetUserFriendlyError() string {
|
||||
if x != nil {
|
||||
return x.UserFriendlyError
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_secretsmanager_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_secretsmanager_proto_rawDesc = string([]byte{
|
||||
0x0a, 0x14, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x22, 0x4d, 0x0a, 0x03,
|
||||
0x4b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x49, 0x0a, 0x04, 0x49,
|
||||
0x74, 0x65, 0x6d, 0x12, 0x2b, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x19, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x53, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x63,
|
||||
0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0d, 0x6b, 0x65,
|
||||
0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67,
|
||||
0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x6b, 0x65,
|
||||
0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x22, 0x81, 0x01, 0x0a, 0x11,
|
||||
0x47, 0x65, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x2c, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c,
|
||||
0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73,
|
||||
0x65, 0x72, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12,
|
||||
0x26, 0x0a, 0x0e, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74,
|
||||
0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x69, 0x73, 0x74,
|
||||
0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22,
|
||||
0x69, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0d, 0x6b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x63,
|
||||
0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69,
|
||||
0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x6b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x41, 0x0a, 0x11, 0x53, 0x65,
|
||||
0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x2c, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x45,
|
||||
0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x65, 0x72,
|
||||
0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x56, 0x0a,
|
||||
0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0d, 0x6b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65,
|
||||
0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67,
|
||||
0x69, 0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x6b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x6f, 0x72, 0x22, 0x44, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53,
|
||||
0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a,
|
||||
0x11, 0x75, 0x73, 0x65, 0x72, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x45, 0x72, 0x72,
|
||||
0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x65, 0x72, 0x46, 0x72,
|
||||
0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x81, 0x01, 0x0a, 0x12,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0d, 0x6b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x63, 0x72,
|
||||
0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
|
||||
0x2e, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x6b, 0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x6f, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x61, 0x6c, 0x6c, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69,
|
||||
0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x61,
|
||||
0x6c, 0x6c, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22,
|
||||
0x72, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x46, 0x72,
|
||||
0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x11, 0x75, 0x73, 0x65, 0x72, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x45,
|
||||
0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61,
|
||||
0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x6b,
|
||||
0x65, 0x79, 0x73, 0x22, 0x16, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x53, 0x65, 0x63,
|
||||
0x72, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x77, 0x0a, 0x15, 0x47,
|
||||
0x65, 0x74, 0x41, 0x6c, 0x6c, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x46, 0x72, 0x69, 0x65,
|
||||
0x6e, 0x64, 0x6c, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x11, 0x75, 0x73, 0x65, 0x72, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x45, 0x72, 0x72,
|
||||
0x6f, 0x72, 0x12, 0x30, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67,
|
||||
0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x73, 0x22, 0x7a, 0x0a, 0x13, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65,
|
||||
0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x0d, 0x6b,
|
||||
0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61,
|
||||
0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x0d, 0x6b,
|
||||
0x65, 0x79, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x22, 0x0a, 0x0c,
|
||||
0x6e, 0x65, 0x77, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x77, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
||||
0x22, 0x44, 0x0a, 0x14, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72,
|
||||
0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x65, 0x72, 0x46, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c,
|
||||
0x79, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xe8, 0x04, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x72, 0x65,
|
||||
0x74, 0x73, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x5c, 0x0a, 0x09, 0x47, 0x65, 0x74,
|
||||
0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x26, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73,
|
||||
0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x47, 0x65,
|
||||
0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27,
|
||||
0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70,
|
||||
0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x53, 0x65,
|
||||
0x63, 0x72, 0x65, 0x74, 0x12, 0x26, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61,
|
||||
0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x53,
|
||||
0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x73,
|
||||
0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75,
|
||||
0x67, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53,
|
||||
0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x29, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x44, 0x65, 0x6c,
|
||||
0x65, 0x74, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x2a, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65,
|
||||
0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0b,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x28, 0x2e, 0x73, 0x65,
|
||||
0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67,
|
||||
0x69, 0x6e, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x65, 0x0a, 0x0c, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74,
|
||||
0x12, 0x29, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65,
|
||||
0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65,
|
||||
0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x73, 0x65,
|
||||
0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67,
|
||||
0x69, 0x6e, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x6c,
|
||||
0x6c, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x2a, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65,
|
||||
0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d, 0x61,
|
||||
0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x41,
|
||||
0x6c, 0x6c, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x42, 0x19, 0x5a, 0x17, 0x2e, 0x2f, 0x3b, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x6d,
|
||||
0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
})
|
||||
|
||||
var (
|
||||
file_secretsmanager_proto_rawDescOnce sync.Once
|
||||
file_secretsmanager_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_secretsmanager_proto_rawDescGZIP() []byte {
|
||||
file_secretsmanager_proto_rawDescOnce.Do(func() {
|
||||
file_secretsmanager_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_secretsmanager_proto_rawDesc), len(file_secretsmanager_proto_rawDesc)))
|
||||
})
|
||||
return file_secretsmanager_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_secretsmanager_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
|
||||
var file_secretsmanager_proto_goTypes = []any{
|
||||
(*Key)(nil), // 0: secretsmanagerplugin.Key
|
||||
(*Item)(nil), // 1: secretsmanagerplugin.Item
|
||||
(*GetSecretRequest)(nil), // 2: secretsmanagerplugin.GetSecretRequest
|
||||
(*GetSecretResponse)(nil), // 3: secretsmanagerplugin.GetSecretResponse
|
||||
(*SetSecretRequest)(nil), // 4: secretsmanagerplugin.SetSecretRequest
|
||||
(*SetSecretResponse)(nil), // 5: secretsmanagerplugin.SetSecretResponse
|
||||
(*DeleteSecretRequest)(nil), // 6: secretsmanagerplugin.DeleteSecretRequest
|
||||
(*DeleteSecretResponse)(nil), // 7: secretsmanagerplugin.DeleteSecretResponse
|
||||
(*ListSecretsRequest)(nil), // 8: secretsmanagerplugin.ListSecretsRequest
|
||||
(*ListSecretsResponse)(nil), // 9: secretsmanagerplugin.ListSecretsResponse
|
||||
(*GetAllSecretsRequest)(nil), // 10: secretsmanagerplugin.GetAllSecretsRequest
|
||||
(*GetAllSecretsResponse)(nil), // 11: secretsmanagerplugin.GetAllSecretsResponse
|
||||
(*RenameSecretRequest)(nil), // 12: secretsmanagerplugin.RenameSecretRequest
|
||||
(*RenameSecretResponse)(nil), // 13: secretsmanagerplugin.RenameSecretResponse
|
||||
}
|
||||
var file_secretsmanager_proto_depIdxs = []int32{
|
||||
0, // 0: secretsmanagerplugin.Item.key:type_name -> secretsmanagerplugin.Key
|
||||
0, // 1: secretsmanagerplugin.GetSecretRequest.keyDescriptor:type_name -> secretsmanagerplugin.Key
|
||||
0, // 2: secretsmanagerplugin.SetSecretRequest.keyDescriptor:type_name -> secretsmanagerplugin.Key
|
||||
0, // 3: secretsmanagerplugin.DeleteSecretRequest.keyDescriptor:type_name -> secretsmanagerplugin.Key
|
||||
0, // 4: secretsmanagerplugin.ListSecretsRequest.keyDescriptor:type_name -> secretsmanagerplugin.Key
|
||||
0, // 5: secretsmanagerplugin.ListSecretsResponse.keys:type_name -> secretsmanagerplugin.Key
|
||||
1, // 6: secretsmanagerplugin.GetAllSecretsResponse.items:type_name -> secretsmanagerplugin.Item
|
||||
0, // 7: secretsmanagerplugin.RenameSecretRequest.keyDescriptor:type_name -> secretsmanagerplugin.Key
|
||||
2, // 8: secretsmanagerplugin.SecretsManager.GetSecret:input_type -> secretsmanagerplugin.GetSecretRequest
|
||||
4, // 9: secretsmanagerplugin.SecretsManager.SetSecret:input_type -> secretsmanagerplugin.SetSecretRequest
|
||||
6, // 10: secretsmanagerplugin.SecretsManager.DeleteSecret:input_type -> secretsmanagerplugin.DeleteSecretRequest
|
||||
8, // 11: secretsmanagerplugin.SecretsManager.ListSecrets:input_type -> secretsmanagerplugin.ListSecretsRequest
|
||||
12, // 12: secretsmanagerplugin.SecretsManager.RenameSecret:input_type -> secretsmanagerplugin.RenameSecretRequest
|
||||
10, // 13: secretsmanagerplugin.SecretsManager.GetAllSecrets:input_type -> secretsmanagerplugin.GetAllSecretsRequest
|
||||
3, // 14: secretsmanagerplugin.SecretsManager.GetSecret:output_type -> secretsmanagerplugin.GetSecretResponse
|
||||
5, // 15: secretsmanagerplugin.SecretsManager.SetSecret:output_type -> secretsmanagerplugin.SetSecretResponse
|
||||
7, // 16: secretsmanagerplugin.SecretsManager.DeleteSecret:output_type -> secretsmanagerplugin.DeleteSecretResponse
|
||||
9, // 17: secretsmanagerplugin.SecretsManager.ListSecrets:output_type -> secretsmanagerplugin.ListSecretsResponse
|
||||
13, // 18: secretsmanagerplugin.SecretsManager.RenameSecret:output_type -> secretsmanagerplugin.RenameSecretResponse
|
||||
11, // 19: secretsmanagerplugin.SecretsManager.GetAllSecrets:output_type -> secretsmanagerplugin.GetAllSecretsResponse
|
||||
14, // [14:20] is the sub-list for method output_type
|
||||
8, // [8:14] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
8, // [8:8] is the sub-list for extension extendee
|
||||
0, // [0:8] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_secretsmanager_proto_init() }
|
||||
func file_secretsmanager_proto_init() {
|
||||
if File_secretsmanager_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_secretsmanager_proto_rawDesc), len(file_secretsmanager_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 14,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_secretsmanager_proto_goTypes,
|
||||
DependencyIndexes: file_secretsmanager_proto_depIdxs,
|
||||
MessageInfos: file_secretsmanager_proto_msgTypes,
|
||||
}.Build()
|
||||
File_secretsmanager_proto = out.File
|
||||
file_secretsmanager_proto_goTypes = nil
|
||||
file_secretsmanager_proto_depIdxs = nil
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
syntax = "proto3";
|
||||
package secretsmanagerplugin;
|
||||
|
||||
option go_package = "./;secretsmanagerplugin";
|
||||
|
||||
message Key {
|
||||
int64 orgId = 1;
|
||||
string namespace = 2;
|
||||
string type = 3;
|
||||
}
|
||||
|
||||
message Item {
|
||||
Key key = 1;
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
message GetSecretRequest {
|
||||
Key keyDescriptor = 1;
|
||||
}
|
||||
|
||||
message GetSecretResponse {
|
||||
string userFriendlyError = 1;
|
||||
string decryptedValue = 2;
|
||||
bool exists = 3;
|
||||
}
|
||||
|
||||
message SetSecretRequest {
|
||||
Key keyDescriptor = 1;
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
message SetSecretResponse {
|
||||
string userFriendlyError = 1;
|
||||
}
|
||||
|
||||
message DeleteSecretRequest {
|
||||
Key keyDescriptor = 1;
|
||||
}
|
||||
|
||||
message DeleteSecretResponse {
|
||||
string userFriendlyError = 1;
|
||||
}
|
||||
|
||||
message ListSecretsRequest {
|
||||
Key keyDescriptor = 1;
|
||||
bool allOrganizations = 2;
|
||||
}
|
||||
|
||||
message ListSecretsResponse {
|
||||
string userFriendlyError = 1;
|
||||
repeated Key keys = 2;
|
||||
}
|
||||
|
||||
message GetAllSecretsRequest {
|
||||
}
|
||||
|
||||
message GetAllSecretsResponse {
|
||||
string userFriendlyError = 1;
|
||||
repeated Item items = 2;
|
||||
}
|
||||
|
||||
message RenameSecretRequest {
|
||||
Key keyDescriptor = 1;
|
||||
string newNamespace = 2;
|
||||
}
|
||||
|
||||
message RenameSecretResponse {
|
||||
string userFriendlyError = 1;
|
||||
}
|
||||
|
||||
service SecretsManager {
|
||||
rpc GetSecret(GetSecretRequest) returns (GetSecretResponse);
|
||||
rpc SetSecret(SetSecretRequest) returns (SetSecretResponse);
|
||||
rpc DeleteSecret(DeleteSecretRequest) returns (DeleteSecretResponse);
|
||||
rpc ListSecrets(ListSecretsRequest) returns (ListSecretsResponse);
|
||||
rpc RenameSecret(RenameSecretRequest) returns (RenameSecretResponse);
|
||||
rpc GetAllSecrets(GetAllSecretsRequest) returns (GetAllSecretsResponse);
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package secretsmanagerplugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/go-plugin"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type SecretsManagerPlugin interface {
|
||||
SecretsManagerClient
|
||||
}
|
||||
|
||||
type SecretsManagerGRPCPlugin struct {
|
||||
plugin.NetRPCUnsupportedPlugin
|
||||
}
|
||||
|
||||
func (p *SecretsManagerGRPCPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *SecretsManagerGRPCPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (any, error) {
|
||||
return &SecretsManagerGRPCClient{NewSecretsManagerClient(c)}, nil
|
||||
}
|
||||
|
||||
type SecretsManagerGRPCClient struct {
|
||||
SecretsManagerClient
|
||||
}
|
||||
|
||||
// Get an item from the store
|
||||
func (sm *SecretsManagerGRPCClient) GetSecret(ctx context.Context, req *GetSecretRequest, opts ...grpc.CallOption) (*GetSecretResponse, error) {
|
||||
return sm.SecretsManagerClient.GetSecret(ctx, req)
|
||||
}
|
||||
|
||||
// Set an item in the store
|
||||
func (sm *SecretsManagerGRPCClient) SetSecret(ctx context.Context, req *SetSecretRequest, opts ...grpc.CallOption) (*SetSecretResponse, error) {
|
||||
return sm.SecretsManagerClient.SetSecret(ctx, req)
|
||||
}
|
||||
|
||||
// Del deletes an item from the store.
|
||||
func (sm *SecretsManagerGRPCClient) DeleteSecret(ctx context.Context, req *DeleteSecretRequest, opts ...grpc.CallOption) (*DeleteSecretResponse, error) {
|
||||
return sm.SecretsManagerClient.DeleteSecret(ctx, req)
|
||||
}
|
||||
|
||||
// Keys get all keys for a given namespace.
|
||||
func (sm *SecretsManagerGRPCClient) ListSecrets(ctx context.Context, req *ListSecretsRequest, opts ...grpc.CallOption) (*ListSecretsResponse, error) {
|
||||
return sm.SecretsManagerClient.ListSecrets(ctx, req)
|
||||
}
|
||||
|
||||
// Rename an item in the store
|
||||
func (sm *SecretsManagerGRPCClient) RenameSecret(ctx context.Context, req *RenameSecretRequest, opts ...grpc.CallOption) (*RenameSecretResponse, error) {
|
||||
return sm.SecretsManagerClient.RenameSecret(ctx, req)
|
||||
}
|
||||
|
||||
// Get all items from the store
|
||||
func (sm *SecretsManagerGRPCClient) GetAllSecrets(ctx context.Context, req *GetAllSecretsRequest, opts ...grpc.CallOption) (*GetAllSecretsResponse, error) {
|
||||
return sm.SecretsManagerClient.GetAllSecrets(ctx, req)
|
||||
}
|
||||
|
||||
var _ SecretsManagerClient = &SecretsManagerGRPCClient{}
|
||||
var _ plugin.GRPCPlugin = &SecretsManagerGRPCPlugin{}
|
@ -1,300 +0,0 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.4.0
|
||||
// - protoc (unknown)
|
||||
// source: secretsmanager.proto
|
||||
|
||||
package secretsmanagerplugin
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.62.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion8
|
||||
|
||||
const (
|
||||
SecretsManager_GetSecret_FullMethodName = "/secretsmanagerplugin.SecretsManager/GetSecret"
|
||||
SecretsManager_SetSecret_FullMethodName = "/secretsmanagerplugin.SecretsManager/SetSecret"
|
||||
SecretsManager_DeleteSecret_FullMethodName = "/secretsmanagerplugin.SecretsManager/DeleteSecret"
|
||||
SecretsManager_ListSecrets_FullMethodName = "/secretsmanagerplugin.SecretsManager/ListSecrets"
|
||||
SecretsManager_RenameSecret_FullMethodName = "/secretsmanagerplugin.SecretsManager/RenameSecret"
|
||||
SecretsManager_GetAllSecrets_FullMethodName = "/secretsmanagerplugin.SecretsManager/GetAllSecrets"
|
||||
)
|
||||
|
||||
// SecretsManagerClient is the client API for SecretsManager service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type SecretsManagerClient interface {
|
||||
GetSecret(ctx context.Context, in *GetSecretRequest, opts ...grpc.CallOption) (*GetSecretResponse, error)
|
||||
SetSecret(ctx context.Context, in *SetSecretRequest, opts ...grpc.CallOption) (*SetSecretResponse, error)
|
||||
DeleteSecret(ctx context.Context, in *DeleteSecretRequest, opts ...grpc.CallOption) (*DeleteSecretResponse, error)
|
||||
ListSecrets(ctx context.Context, in *ListSecretsRequest, opts ...grpc.CallOption) (*ListSecretsResponse, error)
|
||||
RenameSecret(ctx context.Context, in *RenameSecretRequest, opts ...grpc.CallOption) (*RenameSecretResponse, error)
|
||||
GetAllSecrets(ctx context.Context, in *GetAllSecretsRequest, opts ...grpc.CallOption) (*GetAllSecretsResponse, error)
|
||||
}
|
||||
|
||||
type secretsManagerClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewSecretsManagerClient(cc grpc.ClientConnInterface) SecretsManagerClient {
|
||||
return &secretsManagerClient{cc}
|
||||
}
|
||||
|
||||
func (c *secretsManagerClient) GetSecret(ctx context.Context, in *GetSecretRequest, opts ...grpc.CallOption) (*GetSecretResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetSecretResponse)
|
||||
err := c.cc.Invoke(ctx, SecretsManager_GetSecret_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *secretsManagerClient) SetSecret(ctx context.Context, in *SetSecretRequest, opts ...grpc.CallOption) (*SetSecretResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(SetSecretResponse)
|
||||
err := c.cc.Invoke(ctx, SecretsManager_SetSecret_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *secretsManagerClient) DeleteSecret(ctx context.Context, in *DeleteSecretRequest, opts ...grpc.CallOption) (*DeleteSecretResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(DeleteSecretResponse)
|
||||
err := c.cc.Invoke(ctx, SecretsManager_DeleteSecret_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *secretsManagerClient) ListSecrets(ctx context.Context, in *ListSecretsRequest, opts ...grpc.CallOption) (*ListSecretsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ListSecretsResponse)
|
||||
err := c.cc.Invoke(ctx, SecretsManager_ListSecrets_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *secretsManagerClient) RenameSecret(ctx context.Context, in *RenameSecretRequest, opts ...grpc.CallOption) (*RenameSecretResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(RenameSecretResponse)
|
||||
err := c.cc.Invoke(ctx, SecretsManager_RenameSecret_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *secretsManagerClient) GetAllSecrets(ctx context.Context, in *GetAllSecretsRequest, opts ...grpc.CallOption) (*GetAllSecretsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetAllSecretsResponse)
|
||||
err := c.cc.Invoke(ctx, SecretsManager_GetAllSecrets_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// SecretsManagerServer is the server API for SecretsManager service.
|
||||
// All implementations must embed UnimplementedSecretsManagerServer
|
||||
// for forward compatibility
|
||||
type SecretsManagerServer interface {
|
||||
GetSecret(context.Context, *GetSecretRequest) (*GetSecretResponse, error)
|
||||
SetSecret(context.Context, *SetSecretRequest) (*SetSecretResponse, error)
|
||||
DeleteSecret(context.Context, *DeleteSecretRequest) (*DeleteSecretResponse, error)
|
||||
ListSecrets(context.Context, *ListSecretsRequest) (*ListSecretsResponse, error)
|
||||
RenameSecret(context.Context, *RenameSecretRequest) (*RenameSecretResponse, error)
|
||||
GetAllSecrets(context.Context, *GetAllSecretsRequest) (*GetAllSecretsResponse, error)
|
||||
mustEmbedUnimplementedSecretsManagerServer()
|
||||
}
|
||||
|
||||
// UnimplementedSecretsManagerServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedSecretsManagerServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedSecretsManagerServer) GetSecret(context.Context, *GetSecretRequest) (*GetSecretResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetSecret not implemented")
|
||||
}
|
||||
func (UnimplementedSecretsManagerServer) SetSecret(context.Context, *SetSecretRequest) (*SetSecretResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetSecret not implemented")
|
||||
}
|
||||
func (UnimplementedSecretsManagerServer) DeleteSecret(context.Context, *DeleteSecretRequest) (*DeleteSecretResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteSecret not implemented")
|
||||
}
|
||||
func (UnimplementedSecretsManagerServer) ListSecrets(context.Context, *ListSecretsRequest) (*ListSecretsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListSecrets not implemented")
|
||||
}
|
||||
func (UnimplementedSecretsManagerServer) RenameSecret(context.Context, *RenameSecretRequest) (*RenameSecretResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RenameSecret not implemented")
|
||||
}
|
||||
func (UnimplementedSecretsManagerServer) GetAllSecrets(context.Context, *GetAllSecretsRequest) (*GetAllSecretsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAllSecrets not implemented")
|
||||
}
|
||||
func (UnimplementedSecretsManagerServer) mustEmbedUnimplementedSecretsManagerServer() {}
|
||||
|
||||
// UnsafeSecretsManagerServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to SecretsManagerServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeSecretsManagerServer interface {
|
||||
mustEmbedUnimplementedSecretsManagerServer()
|
||||
}
|
||||
|
||||
func RegisterSecretsManagerServer(s grpc.ServiceRegistrar, srv SecretsManagerServer) {
|
||||
s.RegisterService(&SecretsManager_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _SecretsManager_GetSecret_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetSecretRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SecretsManagerServer).GetSecret(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: SecretsManager_GetSecret_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SecretsManagerServer).GetSecret(ctx, req.(*GetSecretRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SecretsManager_SetSecret_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SetSecretRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SecretsManagerServer).SetSecret(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: SecretsManager_SetSecret_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SecretsManagerServer).SetSecret(ctx, req.(*SetSecretRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SecretsManager_DeleteSecret_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DeleteSecretRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SecretsManagerServer).DeleteSecret(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: SecretsManager_DeleteSecret_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SecretsManagerServer).DeleteSecret(ctx, req.(*DeleteSecretRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SecretsManager_ListSecrets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListSecretsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SecretsManagerServer).ListSecrets(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: SecretsManager_ListSecrets_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SecretsManagerServer).ListSecrets(ctx, req.(*ListSecretsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SecretsManager_RenameSecret_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RenameSecretRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SecretsManagerServer).RenameSecret(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: SecretsManager_RenameSecret_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SecretsManagerServer).RenameSecret(ctx, req.(*RenameSecretRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SecretsManager_GetAllSecrets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetAllSecretsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SecretsManagerServer).GetAllSecrets(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: SecretsManager_GetAllSecrets_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SecretsManagerServer).GetAllSecrets(ctx, req.(*GetAllSecretsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// SecretsManager_ServiceDesc is the grpc.ServiceDesc for SecretsManager service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var SecretsManager_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "secretsmanagerplugin.SecretsManager",
|
||||
HandlerType: (*SecretsManagerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetSecret",
|
||||
Handler: _SecretsManager_GetSecret_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SetSecret",
|
||||
Handler: _SecretsManager_SetSecret_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "DeleteSecret",
|
||||
Handler: _SecretsManager_DeleteSecret_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListSecrets",
|
||||
Handler: _SecretsManager_ListSecrets_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "RenameSecret",
|
||||
Handler: _SecretsManager_RenameSecret_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetAllSecrets",
|
||||
Handler: _SecretsManager_GetAllSecrets_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "secretsmanager.proto",
|
||||
}
|
@ -98,11 +98,6 @@ type BackendFactoryProvider interface {
|
||||
BackendFactory(ctx context.Context, p *Plugin) backendplugin.PluginFactoryFunc
|
||||
}
|
||||
|
||||
type SecretsPluginManager interface {
|
||||
// SecretsManager returns a secretsmanager plugin
|
||||
SecretsManager(ctx context.Context) *Plugin
|
||||
}
|
||||
|
||||
type StaticRouteResolver interface {
|
||||
Routes(ctx context.Context) []*StaticRoute
|
||||
}
|
||||
|
@ -64,30 +64,6 @@ func TestInitializer_Initialize(t *testing.T) {
|
||||
require.NotNil(t, c)
|
||||
})
|
||||
|
||||
t.Run("secretsmanager", func(t *testing.T) {
|
||||
p := &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
ID: "test",
|
||||
Type: plugins.TypeSecretsManager,
|
||||
Dependencies: plugins.Dependencies{
|
||||
GrafanaVersion: ">=8.x",
|
||||
},
|
||||
Backend: true,
|
||||
},
|
||||
Class: plugins.ClassExternal,
|
||||
}
|
||||
|
||||
stepFunc := BackendClientInitStep(&fakeEnvVarsProvider{}, &fakeBackendProvider{plugin: p}, fakes.InitializeNoopTracerForTest())
|
||||
|
||||
var err error
|
||||
p, err = stepFunc(context.Background(), p)
|
||||
require.NoError(t, err)
|
||||
|
||||
c, exists := p.Client()
|
||||
require.True(t, exists)
|
||||
require.NotNil(t, c)
|
||||
})
|
||||
|
||||
t.Run("non backend plugin app", func(t *testing.T) {
|
||||
p := &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
|
@ -17,7 +17,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/auth"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -58,10 +57,9 @@ type Plugin struct {
|
||||
|
||||
ExternalService *auth.ExternalService
|
||||
|
||||
Renderer pluginextensionv2.RendererPlugin
|
||||
SecretsManager secretsmanagerplugin.SecretsManagerPlugin
|
||||
client backendplugin.Plugin
|
||||
log log.Logger
|
||||
Renderer pluginextensionv2.RendererPlugin
|
||||
client backendplugin.Plugin
|
||||
log log.Logger
|
||||
|
||||
SkipHostEnvVars bool
|
||||
|
||||
@ -126,7 +124,7 @@ type JSONData struct {
|
||||
SDK bool `json:"sdk,omitempty"`
|
||||
MultiValueFilterOperators bool `json:"multiValueFilterOperators,omitempty"`
|
||||
|
||||
// Backend (Datasource + Renderer + SecretsManager)
|
||||
// Backend (Datasource + Renderer)
|
||||
Executable string `json:"executable,omitempty"`
|
||||
|
||||
// App Service Auth Registration
|
||||
@ -442,10 +440,6 @@ func (p *Plugin) ExecutablePath() string {
|
||||
return p.executablePath("plugin_start")
|
||||
}
|
||||
|
||||
if p.IsSecretsManager() {
|
||||
return p.executablePath("secrets_plugin_start")
|
||||
}
|
||||
|
||||
return p.executablePath(p.Executable)
|
||||
}
|
||||
|
||||
@ -486,10 +480,6 @@ func (p *Plugin) IsRenderer() bool {
|
||||
return p.Type == TypeRenderer
|
||||
}
|
||||
|
||||
func (p *Plugin) IsSecretsManager() bool {
|
||||
return p.Type == TypeSecretsManager
|
||||
}
|
||||
|
||||
func (p *Plugin) IsApp() bool {
|
||||
return p.Type == TypeApp
|
||||
}
|
||||
@ -519,22 +509,20 @@ var PluginTypes = []Type{
|
||||
TypePanel,
|
||||
TypeApp,
|
||||
TypeRenderer,
|
||||
TypeSecretsManager,
|
||||
}
|
||||
|
||||
type Type string
|
||||
|
||||
const (
|
||||
TypeDataSource Type = "datasource"
|
||||
TypePanel Type = "panel"
|
||||
TypeApp Type = "app"
|
||||
TypeRenderer Type = "renderer"
|
||||
TypeSecretsManager Type = "secretsmanager"
|
||||
TypeDataSource Type = "datasource"
|
||||
TypePanel Type = "panel"
|
||||
TypeApp Type = "app"
|
||||
TypeRenderer Type = "renderer"
|
||||
)
|
||||
|
||||
func (pt Type) IsValid() bool {
|
||||
switch pt {
|
||||
case TypeDataSource, TypePanel, TypeApp, TypeRenderer, TypeSecretsManager:
|
||||
case TypeDataSource, TypePanel, TypeApp, TypeRenderer:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -4,25 +4,6 @@ package semconv
|
||||
|
||||
import "go.opentelemetry.io/otel/attribute"
|
||||
|
||||
// Describes Grafana service attributes.
|
||||
const (
|
||||
// GrafanaServiceNameKey is the attribute Key conforming to the
|
||||
// "grafana.service.name" semantic conventions. It represents the service
|
||||
// name.
|
||||
//
|
||||
// Type: string
|
||||
// RequirementLevel: Optional
|
||||
// Stability: stable
|
||||
// Examples: 'grafana-apiserver'
|
||||
grafanaServiceNameKey = attribute.Key("grafana.service.name")
|
||||
)
|
||||
|
||||
// GrafanaServiceName returns an attribute KeyValue conforming to the
|
||||
// "grafana.service.name" semantic conventions. It represents the service name.
|
||||
func GrafanaServiceName(val string) attribute.KeyValue {
|
||||
return grafanaServiceNameKey.String(val)
|
||||
}
|
||||
|
||||
// Describes Grafana datasource attributes.
|
||||
const (
|
||||
// GrafanaDatasourceTypeKey is the attribute Key conforming to the
|
||||
@ -131,8 +112,6 @@ var (
|
||||
GrafanaPluginTypeApp = grafanaPluginTypeKey.String("app")
|
||||
// Renderer Plugin
|
||||
GrafanaPluginTypeRenderer = grafanaPluginTypeKey.String("renderer")
|
||||
// Secret Manager Plugin
|
||||
GrafanaPluginTypeSecretmanager = grafanaPluginTypeKey.String("secretmanager")
|
||||
)
|
||||
|
||||
// GrafanaPluginId returns an attribute KeyValue conforming to the
|
||||
@ -140,3 +119,22 @@ var (
|
||||
func GrafanaPluginId(val string) attribute.KeyValue {
|
||||
return grafanaPluginIdKey.String(val)
|
||||
}
|
||||
|
||||
// Describes Grafana service attributes.
|
||||
const (
|
||||
// GrafanaServiceNameKey is the attribute Key conforming to the
|
||||
// "grafana.service.name" semantic conventions. It represents the service
|
||||
// name.
|
||||
//
|
||||
// Type: string
|
||||
// RequirementLevel: Optional
|
||||
// Stability: stable
|
||||
// Examples: 'grafana-apiserver'
|
||||
grafanaServiceNameKey = attribute.Key("grafana.service.name")
|
||||
)
|
||||
|
||||
// GrafanaServiceName returns an attribute KeyValue conforming to the
|
||||
// "grafana.service.name" semantic conventions. It represents the service name.
|
||||
func GrafanaServiceName(val string) attribute.KeyValue {
|
||||
return grafanaServiceNameKey.String(val)
|
||||
}
|
||||
|
@ -31,10 +31,6 @@ groups:
|
||||
value: "renderer"
|
||||
brief: 'Renderer Plugin'
|
||||
stability: stable
|
||||
- id: secretmanager
|
||||
value: "secretmanager"
|
||||
brief: 'Secret Manager Plugin'
|
||||
stability: stable
|
||||
brief: The plugin type.
|
||||
examples: datasource
|
||||
stability: stable
|
@ -363,8 +363,6 @@ var wireBasicSet = wire.NewSet(
|
||||
loginattemptimpl.ProvideService,
|
||||
wire.Bind(new(loginattempt.Service), new(*loginattemptimpl.Service)),
|
||||
secretsMigrations.ProvideDataSourceMigrationService,
|
||||
secretsMigrations.ProvideMigrateToPluginService,
|
||||
secretsMigrations.ProvideMigrateFromPluginService,
|
||||
secretsMigrations.ProvideSecretMigrationProvider,
|
||||
wire.Bind(new(secretsMigrations.SecretMigrationProvider), new(*secretsMigrations.SecretMigrationProviderImpl)),
|
||||
resourcepermissions.NewActionSetService,
|
||||
|
@ -122,11 +122,7 @@ func (s *FakeDataSourceService) GetHTTPTransport(ctx context.Context, ds *dataso
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) DecryptedValues(ctx context.Context, ds *datasources.DataSource) (map[string]string, error) {
|
||||
if s.SimulatePluginFailure {
|
||||
return nil, datasources.ErrDatasourceSecretsPluginUserFriendly{Err: "unknown error"}
|
||||
}
|
||||
values := make(map[string]string)
|
||||
return values, nil
|
||||
return make(map[string]string), nil
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) DecryptedValue(ctx context.Context, ds *datasources.DataSource, key string) (string, bool, error) {
|
||||
|
@ -145,15 +145,6 @@ func (ds DataSource) AllowedCookies() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// Specific error type for grpc secrets management so that we can show more detailed plugin errors to users
|
||||
type ErrDatasourceSecretsPluginUserFriendly struct {
|
||||
Err string
|
||||
}
|
||||
|
||||
func (e ErrDatasourceSecretsPluginUserFriendly) Error() string {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// COMMANDS
|
||||
|
||||
|
@ -27,7 +27,7 @@ func ProvideDiscoveryStage(cfg *config.PluginManagementCfg, pf finder.Finder, pr
|
||||
FindFunc: pf.Find,
|
||||
FindFilterFuncs: []discovery.FindFilterFunc{
|
||||
discovery.NewPermittedPluginTypesFilterStep([]plugins.Type{
|
||||
plugins.TypeDataSource, plugins.TypeApp, plugins.TypePanel, plugins.TypeSecretsManager,
|
||||
plugins.TypeDataSource, plugins.TypeApp, plugins.TypePanel,
|
||||
}),
|
||||
func(ctx context.Context, _ plugins.Class, b []*plugins.FoundBundle) ([]*plugins.FoundBundle, error) {
|
||||
return NewDuplicatePluginIDFilterStep(pr).Filter(ctx, b)
|
||||
|
@ -70,7 +70,6 @@ var WireSet = wire.NewSet(
|
||||
wire.Bind(new(pluginconfig.PluginRequestConfigProvider), new(*pluginconfig.RequestConfigProvider)),
|
||||
pluginstore.ProvideService,
|
||||
wire.Bind(new(pluginstore.Store), new(*pluginstore.Service)),
|
||||
wire.Bind(new(plugins.SecretsPluginManager), new(*pluginstore.Service)),
|
||||
wire.Bind(new(plugins.StaticRouteResolver), new(*pluginstore.Service)),
|
||||
process.ProvideService,
|
||||
wire.Bind(new(process.Manager), new(*process.Service)),
|
||||
|
@ -94,15 +94,6 @@ func (s *Service) Plugins(ctx context.Context, pluginTypes ...plugins.Type) []Pl
|
||||
return pluginsList
|
||||
}
|
||||
|
||||
func (s *Service) SecretsManager(ctx context.Context) *plugins.Plugin {
|
||||
for _, p := range s.availablePlugins(ctx) {
|
||||
if p.IsSecretsManager() {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// plugin finds a plugin with `pluginID` from the registry that is not decommissioned
|
||||
func (s *Service) plugin(ctx context.Context, pluginID string) (*plugins.Plugin, bool) {
|
||||
p, exists := s.pluginRegistry.Plugin(ctx, pluginID, "") // version is not required since Grafana only supports single versions of a plugin
|
||||
|
@ -120,7 +120,6 @@ func TestStore_Routes(t *testing.T) {
|
||||
t.Run("Routes returns all static routes for non-decommissioned plugins", func(t *testing.T) {
|
||||
p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "a-test-renderer", Type: plugins.TypeRenderer}, FS: fakes.NewFakePluginFS("/some/dir")}
|
||||
p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "b-test-panel", Type: plugins.TypePanel}, FS: fakes.NewFakePluginFS("/grafana/")}
|
||||
p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "c-test-secrets", Type: plugins.TypeSecretsManager}, FS: fakes.NewFakePluginFS("./secrets"), Class: plugins.ClassCore}
|
||||
p4 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "d-test-datasource", Type: plugins.TypeDataSource}, FS: fakes.NewFakePluginFS("../test")}
|
||||
p5 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "e-test-app", Type: plugins.TypeApp}, FS: fakes.NewFakePluginFS("any/path")}
|
||||
p6 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "f-test-app", Type: plugins.TypeApp}}
|
||||
@ -130,7 +129,6 @@ func TestStore_Routes(t *testing.T) {
|
||||
Store: map[string]*plugins.Plugin{
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
p3.ID: p3,
|
||||
p4.ID: p4,
|
||||
p5.ID: p5,
|
||||
p6.ID: p6,
|
||||
@ -146,27 +144,6 @@ func TestStore_Routes(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_SecretsManager(t *testing.T) {
|
||||
t.Run("Renderer returns a single (non-decommissioned) secrets manager plugin", func(t *testing.T) {
|
||||
p1 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-renderer", Type: plugins.TypeRenderer}}
|
||||
p2 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-panel", Type: plugins.TypePanel}}
|
||||
p3 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-secrets", Type: plugins.TypeSecretsManager}}
|
||||
p4 := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-datasource", Type: plugins.TypeDataSource}}
|
||||
|
||||
ps := New(&fakes.FakePluginRegistry{
|
||||
Store: map[string]*plugins.Plugin{
|
||||
p1.ID: p1,
|
||||
p2.ID: p2,
|
||||
p3.ID: p3,
|
||||
p4.ID: p4,
|
||||
},
|
||||
}, &fakes.FakeLoader{})
|
||||
|
||||
r := ps.SecretsManager(context.Background())
|
||||
require.Equal(t, p3, r)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProcessManager_shutdown(t *testing.T) {
|
||||
p := &plugins.Plugin{JSONData: plugins.JSONData{ID: "test-datasource", Type: plugins.TypeDataSource}} // Backend: true
|
||||
backend := &fakes.FakeBackendPlugin{}
|
||||
|
@ -39,7 +39,7 @@ func TestRenderer(t *testing.T) {
|
||||
|
||||
r, exists := m.Renderer(context.Background())
|
||||
require.False(t, exists)
|
||||
require.Equal(t, 4, numLoaded)
|
||||
require.Equal(t, 3, numLoaded)
|
||||
require.Equal(t, 0, numUnloaded)
|
||||
require.Nil(t, r)
|
||||
})
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"type": "secretsmanager"
|
||||
}
|
@ -5,13 +5,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -22,45 +17,8 @@ const (
|
||||
func ProvideService(
|
||||
sqlStore db.DB,
|
||||
secretsService secrets.Service,
|
||||
pluginsManager plugins.SecretsPluginManager,
|
||||
kvstore kvstore.KVStore,
|
||||
features featuremgmt.FeatureToggles,
|
||||
cfg *setting.Cfg,
|
||||
) (SecretsKVStore, error) {
|
||||
var logger = log.New("secrets.kvstore")
|
||||
var store SecretsKVStore
|
||||
ctx := context.Background()
|
||||
store = NewSQLSecretsKVStore(sqlStore, secretsService, logger)
|
||||
err := EvaluateRemoteSecretsPlugin(ctx, pluginsManager, cfg)
|
||||
if err != nil {
|
||||
logger.Debug("secrets manager evaluator returned false", "reason", err.Error())
|
||||
} else {
|
||||
// Attempt to start the plugin
|
||||
var secretsPlugin secretsmanagerplugin.SecretsManagerPlugin
|
||||
secretsPlugin, err = StartAndReturnPlugin(pluginsManager, ctx)
|
||||
namespacedKVStore := GetNamespacedKVStore(kvstore)
|
||||
if err != nil || secretsPlugin == nil {
|
||||
logger.Error("failed to start remote secrets management plugin")
|
||||
if isFatal, readErr := IsPluginStartupErrorFatal(ctx, namespacedKVStore); isFatal || readErr != nil {
|
||||
// plugin error was fatal or there was an error determining if the error was fatal
|
||||
logger.Error("secrets management plugin is required to start -- exiting app")
|
||||
if readErr != nil {
|
||||
return nil, readErr
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// as the plugin is installed, SecretsKVStoreSQL is now replaced with
|
||||
// an instance of SecretsKVStorePlugin with the sql store as a fallback
|
||||
// (used for migration and in case a secret is not found).
|
||||
store = NewPluginSecretsKVStore(secretsPlugin, secretsService, namespacedKVStore, features, WithCache(store, 5*time.Second, 5*time.Minute), logger)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.Debug("secrets kvstore is using the default (SQL) implementation for secrets management")
|
||||
}
|
||||
|
||||
store := NewSQLSecretsKVStore(sqlStore, secretsService, log.New("secrets.kvstore"))
|
||||
return WithCache(store, 5*time.Second, 5*time.Minute), nil
|
||||
}
|
||||
|
||||
|
@ -1,108 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
secretskvs "github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var errPluginUnavailable = errors.New("remote secret management plugin is unavailable")
|
||||
|
||||
// MigrateFromPluginService This migrator will handle migration of the configured plugin secrets back to Grafana unified secrets
|
||||
type MigrateFromPluginService struct {
|
||||
cfg *setting.Cfg
|
||||
sqlStore db.DB
|
||||
secretsService secrets.Service
|
||||
manager plugins.SecretsPluginManager
|
||||
kvstore kvstore.KVStore
|
||||
}
|
||||
|
||||
func ProvideMigrateFromPluginService(
|
||||
cfg *setting.Cfg,
|
||||
sqlStore db.DB,
|
||||
secretsService secrets.Service,
|
||||
manager plugins.SecretsPluginManager,
|
||||
kvstore kvstore.KVStore,
|
||||
|
||||
) *MigrateFromPluginService {
|
||||
return &MigrateFromPluginService{
|
||||
cfg: cfg,
|
||||
sqlStore: sqlStore,
|
||||
secretsService: secretsService,
|
||||
manager: manager,
|
||||
kvstore: kvstore,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MigrateFromPluginService) Migrate(ctx context.Context) error {
|
||||
logger.Debug("starting migration of plugin secrets to unified secrets")
|
||||
// access the plugin directly
|
||||
plugin, err := secretskvs.StartAndReturnPlugin(s.manager, context.Background())
|
||||
if err != nil {
|
||||
return errPluginUnavailable
|
||||
}
|
||||
// Get full list of secrets from the plugin
|
||||
res, err := plugin.GetAllSecrets(ctx, &secretsmanagerplugin.GetAllSecretsRequest{})
|
||||
if err != nil {
|
||||
logger.Error("Failed to retrieve all secrets from plugin")
|
||||
return err
|
||||
}
|
||||
totalSecrets := len(res.Items)
|
||||
logger.Debug("retrieved all secrets from plugin", "num secrets", totalSecrets)
|
||||
// create a secret sql store manually
|
||||
secretsSql := secretskvs.NewSQLSecretsKVStore(s.sqlStore, s.secretsService, logger)
|
||||
for i, item := range res.Items {
|
||||
logger.Debug(fmt.Sprintf("Migrating secret %d of %d", i+1, totalSecrets), "current", i+1, "secretCount", totalSecrets)
|
||||
// Add to sql store
|
||||
err = secretsSql.Set(ctx, item.Key.OrgId, item.Key.Namespace, item.Key.Type, item.Value)
|
||||
if err != nil {
|
||||
logger.Error("Error adding secret to unified secrets", "orgId", item.Key.OrgId,
|
||||
"namespace", item.Key.Namespace, "type", item.Key.Type)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for i, item := range res.Items {
|
||||
logger.Debug(fmt.Sprintf("Cleaning secret %d of %d", i+1, totalSecrets), "current", i+1, "secretCount", totalSecrets)
|
||||
// Delete from the plugin
|
||||
_, err := plugin.DeleteSecret(ctx, &secretsmanagerplugin.DeleteSecretRequest{
|
||||
KeyDescriptor: &secretsmanagerplugin.Key{
|
||||
OrgId: item.Key.OrgId,
|
||||
Namespace: item.Key.Namespace,
|
||||
Type: item.Key.Type,
|
||||
}})
|
||||
if err != nil {
|
||||
logger.Error("Error deleting secret from plugin after migration", "orgId", item.Key.OrgId,
|
||||
"namespace", item.Key.Namespace, "type", item.Key.Type)
|
||||
continue
|
||||
}
|
||||
}
|
||||
logger.Debug("Completed migration of secrets from plugin")
|
||||
|
||||
// The plugin is no longer needed at the moment
|
||||
err = secretskvs.SetPluginStartupErrorFatal(ctx, secretskvs.GetNamespacedKVStore(s.kvstore), false)
|
||||
if err != nil {
|
||||
logger.Error("Failed to remove plugin error fatal flag", "error", err.Error())
|
||||
}
|
||||
// Reset the fatal flag setter in case another secret is created on the plugin
|
||||
secretskvs.ResetPlugin()
|
||||
|
||||
logger.Debug("Shutting down secrets plugin now that migration is complete")
|
||||
// if `use_plugin` wasn't set, stop the plugin after migration
|
||||
if !s.cfg.SectionWithEnvOverrides("secrets").Key("use_plugin").MustBool(false) {
|
||||
err := s.manager.SecretsManager(ctx).Stop(ctx)
|
||||
if err != nil {
|
||||
// Log a warning but don't throw an error
|
||||
logger.Error("Error stopping secrets plugin after migration", "error", err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretskvs "github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
// This tests will create a mock sql database and an inmemory
|
||||
// implementation of the secret manager to simulate the plugin.
|
||||
func TestPluginSecretMigrationService_MigrateFromPlugin(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("migrate secrets from secrets plugin to Grafana", func(t *testing.T) {
|
||||
// --- SETUP
|
||||
migratorService, plugin, sqlStore := setupTestMigrateFromPluginService(t)
|
||||
|
||||
addSecretToPluginStore(t, plugin, ctx, 1, "secret-1", "bogus", "value-1")
|
||||
addSecretToPluginStore(t, plugin, ctx, 1, "secret-2", "bogus", "value-2")
|
||||
|
||||
// --- EXECUTION
|
||||
err := migratorService.Migrate(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// --- VALIDATIONS
|
||||
validatePluginSecretsWereDeleted(t, plugin, ctx)
|
||||
|
||||
validateSecretWasStoredInSql(t, sqlStore, ctx, 1, "secret-1", "bogus", "value-1")
|
||||
validateSecretWasStoredInSql(t, sqlStore, ctx, 1, "secret-2", "bogus", "value-2")
|
||||
})
|
||||
}
|
||||
|
||||
// Set up services used in migration
|
||||
func setupTestMigrateFromPluginService(t *testing.T) (*MigrateFromPluginService, secretsmanagerplugin.SecretsManagerPlugin, *secretskvs.SecretsKVStoreSQL) {
|
||||
t.Helper()
|
||||
|
||||
// this is to init the sql secret store inside the migration
|
||||
sqlStore := db.InitTestDB(t)
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
manager := secretskvs.NewFakeSecretsPluginManager(t, false)
|
||||
migratorService := ProvideMigrateFromPluginService(
|
||||
setting.NewCfg(),
|
||||
sqlStore,
|
||||
secretsService,
|
||||
manager,
|
||||
kvstore.ProvideService(sqlStore),
|
||||
)
|
||||
|
||||
secretsSql := secretskvs.NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger"))
|
||||
|
||||
return migratorService, manager.SecretsManager(context.Background()).SecretsManager, secretsSql
|
||||
}
|
||||
|
||||
func addSecretToPluginStore(t *testing.T, plugin secretsmanagerplugin.SecretsManagerPlugin, ctx context.Context, orgId int64, namespace string, typ string, value string) {
|
||||
t.Helper()
|
||||
_, err := plugin.SetSecret(ctx, &secretsmanagerplugin.SetSecretRequest{
|
||||
KeyDescriptor: &secretsmanagerplugin.Key{
|
||||
OrgId: orgId,
|
||||
Namespace: namespace,
|
||||
Type: typ,
|
||||
},
|
||||
Value: value,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// validates that secrets on the plugin were deleted
|
||||
func validatePluginSecretsWereDeleted(t *testing.T, plugin secretsmanagerplugin.SecretsManagerPlugin, ctx context.Context) {
|
||||
t.Helper()
|
||||
res, err := plugin.GetAllSecrets(ctx, &secretsmanagerplugin.GetAllSecretsRequest{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(res.Items))
|
||||
}
|
||||
|
||||
// validates that secrets are in sql
|
||||
func validateSecretWasStoredInSql(t *testing.T, sqlStore *secretskvs.SecretsKVStoreSQL, ctx context.Context, orgId int64, namespace string, typ string, expectedValue string) {
|
||||
t.Helper()
|
||||
res, exists, err := sqlStore.Get(ctx, orgId, namespace, typ)
|
||||
require.NoError(t, err)
|
||||
require.True(t, exists)
|
||||
require.Equal(t, expectedValue, res)
|
||||
}
|
@ -8,7 +8,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/serverlock"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var logger = log.New("secret.migration")
|
||||
@ -22,40 +21,20 @@ type SecretMigrationService interface {
|
||||
|
||||
type SecretMigrationProvider interface {
|
||||
registry.BackgroundService
|
||||
TriggerPluginMigration(ctx context.Context, toPlugin bool) error
|
||||
}
|
||||
|
||||
type SecretMigrationProviderImpl struct {
|
||||
services []SecretMigrationService
|
||||
ServerLockService *serverlock.ServerLockService
|
||||
migrateToPluginService *MigrateToPluginService
|
||||
migrateFromPluginService *MigrateFromPluginService
|
||||
services []SecretMigrationService
|
||||
ServerLockService *serverlock.ServerLockService
|
||||
}
|
||||
|
||||
func ProvideSecretMigrationProvider(
|
||||
cfg *setting.Cfg,
|
||||
serverLockService *serverlock.ServerLockService,
|
||||
dataSourceSecretMigrationService *DataSourceSecretMigrationService,
|
||||
migrateToPluginService *MigrateToPluginService,
|
||||
migrateFromPluginService *MigrateFromPluginService,
|
||||
) *SecretMigrationProviderImpl {
|
||||
services := make([]SecretMigrationService, 0)
|
||||
services = append(services, dataSourceSecretMigrationService)
|
||||
// Plugin migration should always be last; should either migrate to or from, not both
|
||||
// This is because the migrateTo checks for use_plugin = true, in which case we should always
|
||||
// migrate by default to ensure users don't lose access to secrets. If migration has
|
||||
// already occurred, the migrateTo function will be called but it won't do anything
|
||||
if cfg.SectionWithEnvOverrides("secrets").Key("migrate_from_plugin").MustBool(false) {
|
||||
services = append(services, migrateFromPluginService)
|
||||
} else {
|
||||
services = append(services, migrateToPluginService)
|
||||
}
|
||||
|
||||
return &SecretMigrationProviderImpl{
|
||||
ServerLockService: serverLockService,
|
||||
services: services,
|
||||
migrateToPluginService: migrateToPluginService,
|
||||
migrateFromPluginService: migrateFromPluginService,
|
||||
ServerLockService: serverLockService,
|
||||
services: []SecretMigrationService{dataSourceSecretMigrationService},
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,23 +62,3 @@ func (s *SecretMigrationProviderImpl) Migrate(ctx context.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerPluginMigration Kick off a migration to or from the plugin. This will block until all services have exited.
|
||||
func (s *SecretMigrationProviderImpl) TriggerPluginMigration(ctx context.Context, toPlugin bool) error {
|
||||
// Don't migrate if there is already one happening
|
||||
return s.ServerLockService.LockExecuteAndRelease(ctx, actionName, time.Minute*10, func(context.Context) {
|
||||
var err error
|
||||
if toPlugin {
|
||||
err = s.migrateToPluginService.Migrate(ctx)
|
||||
} else {
|
||||
err = s.migrateFromPluginService.Migrate(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
direction := "from_plugin"
|
||||
if toPlugin {
|
||||
direction = "to_plugin"
|
||||
}
|
||||
logger.Error("Failed to migrate plugin secrets", "direction", direction, "error", err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,120 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
secretskvs "github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var errSecretStoreIsNotPlugin = errors.New("SecretsKVStore is not a SecretsKVStorePlugin")
|
||||
|
||||
// MigrateToPluginService This migrator will handle migration of datasource secrets (aka Unified secrets)
|
||||
// into the plugin secrets configured
|
||||
type MigrateToPluginService struct {
|
||||
secretsStore secretskvs.SecretsKVStore
|
||||
cfg *setting.Cfg
|
||||
sqlStore db.DB
|
||||
secretsService secrets.Service
|
||||
kvstore kvstore.KVStore
|
||||
manager plugins.SecretsPluginManager
|
||||
}
|
||||
|
||||
func ProvideMigrateToPluginService(
|
||||
secretsStore secretskvs.SecretsKVStore,
|
||||
cfg *setting.Cfg,
|
||||
sqlStore db.DB,
|
||||
secretsService secrets.Service,
|
||||
kvstore kvstore.KVStore,
|
||||
manager plugins.SecretsPluginManager,
|
||||
) *MigrateToPluginService {
|
||||
return &MigrateToPluginService{
|
||||
secretsStore: secretsStore,
|
||||
cfg: cfg,
|
||||
sqlStore: sqlStore,
|
||||
secretsService: secretsService,
|
||||
kvstore: kvstore,
|
||||
manager: manager,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MigrateToPluginService) Migrate(ctx context.Context) error {
|
||||
err := secretskvs.EvaluateRemoteSecretsPlugin(ctx, s.manager, s.cfg)
|
||||
hasStarted := secretskvs.HasPluginStarted(ctx, s.manager)
|
||||
if err == nil && hasStarted {
|
||||
logger.Debug("starting migration of unified secrets to the plugin")
|
||||
// we need to get the fallback store since in this scenario the secrets store would be the plugin.
|
||||
tmpStore, err := secretskvs.GetUnwrappedStoreFromCache(s.secretsStore)
|
||||
if err != nil {
|
||||
tmpStore = s.secretsStore
|
||||
logger.Warn("secret store is not cached, this is unexpected - continuing migration anyway.")
|
||||
}
|
||||
pluginStore, ok := tmpStore.(*secretskvs.SecretsKVStorePlugin)
|
||||
if !ok {
|
||||
return errSecretStoreIsNotPlugin
|
||||
}
|
||||
fallbackStore := pluginStore.Fallback()
|
||||
|
||||
// before we start migrating, check see if plugin startup failures were already fatal
|
||||
namespacedKVStore := secretskvs.GetNamespacedKVStore(s.kvstore)
|
||||
wasFatal, err := secretskvs.IsPluginStartupErrorFatal(ctx, namespacedKVStore)
|
||||
if err != nil {
|
||||
logger.Warn("unable to determine whether plugin startup failures are fatal - continuing migration anyway.")
|
||||
}
|
||||
|
||||
var allSec []secretskvs.Item
|
||||
var totalSec int
|
||||
// during migration we need to have fallback enabled while we move secrets to plugin
|
||||
err = pluginStore.WithFallbackEnabled(func() error {
|
||||
// get all secrets in the fallback store
|
||||
allSec, err = fallbackStore.GetAll(ctx)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
totalSec := len(allSec)
|
||||
logger.Debug(fmt.Sprintf("Total amount of secrets to migrate: %d", totalSec))
|
||||
|
||||
// We just set it again as the current secret store should be the plugin secret
|
||||
for i, sec := range allSec {
|
||||
logger.Debug(fmt.Sprintf("Migrating secret %d of %d", i+1, totalSec), "current", i+1, "secretCount", totalSec)
|
||||
err = pluginStore.Set(ctx, *sec.OrgId, *sec.Namespace, *sec.Type, sec.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// as no err was returned, when we delete all the secrets from the sql store
|
||||
logger.Debug("migrated unified secrets to plugin", "number of secrets", totalSec)
|
||||
for index, sec := range allSec {
|
||||
logger.Debug(fmt.Sprintf("Cleaning secret %d of %d", index+1, totalSec), "current", index+1, "secretCount", totalSec)
|
||||
|
||||
err = fallbackStore.Del(ctx, *sec.OrgId, *sec.Namespace, *sec.Type)
|
||||
if err != nil {
|
||||
logger.Error("plugin migrator encountered error while deleting unified secrets")
|
||||
if index == 0 && !wasFatal {
|
||||
// old unified secrets still exists, so plugin startup errors are still not fatal, unless they were before we started
|
||||
err := secretskvs.SetPluginStartupErrorFatal(ctx, namespacedKVStore, false)
|
||||
if err != nil {
|
||||
logger.Error("error reverting plugin failure fatal status", "error", err.Error())
|
||||
} else {
|
||||
logger.Debug("application will continue to function without the secrets plugin")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
logger.Debug("deleted unified secrets after migration", "number of secrets", totalSec)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/db/dbtest"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretskvs "github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
// This tests will create a mock sql database and an inmemory
|
||||
// implementation of the secret manager to simulate the plugin.
|
||||
func TestPluginSecretMigrationService_MigrateToPlugin(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("migration run ok - 2 secrets migrated", func(t *testing.T) {
|
||||
// --- SETUP
|
||||
migratorService, secretsStore, sqlSecretStore := setupTestMigrateToPluginService(t)
|
||||
var orgId int64 = 1
|
||||
namespace1, namespace2 := "namespace-test", "namespace-test2"
|
||||
typ := "type-test"
|
||||
value := "SUPER_SECRET"
|
||||
|
||||
addSecretToSqlStore(t, sqlSecretStore, ctx, orgId, namespace1, typ, value)
|
||||
addSecretToSqlStore(t, sqlSecretStore, ctx, orgId, namespace2, typ, value)
|
||||
|
||||
// --- EXECUTION
|
||||
err := migratorService.Migrate(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// --- VALIDATIONS
|
||||
validateSqlSecretWasDeleted(t, sqlSecretStore, ctx, orgId, namespace1, typ)
|
||||
validateSqlSecretWasDeleted(t, sqlSecretStore, ctx, orgId, namespace2, typ)
|
||||
|
||||
validateSecretWasStoredInPlugin(t, secretsStore, ctx, orgId, namespace1, typ)
|
||||
validateSecretWasStoredInPlugin(t, secretsStore, ctx, orgId, namespace1, typ)
|
||||
})
|
||||
}
|
||||
|
||||
// With fatal flag unset, do a migration with backwards compatibility disabled. When unified secrets are deleted, return an error on the first deletion
|
||||
// Should result in the fatal flag remaining unset
|
||||
func TestFatalPluginErr_MigrationTestWithErrorDeletingUnifiedSecrets(t *testing.T) {
|
||||
p, err := secretskvs.SetupFatalCrashTest(t, false, false, true)
|
||||
assert.NoError(t, err)
|
||||
|
||||
migration := setupTestMigratorServiceWithDeletionError(t, p.SecretsKVStore, &dbtest.FakeDB{
|
||||
ExpectedError: errors.New("random error"),
|
||||
}, p.KVStore)
|
||||
err = migration.Migrate(context.Background())
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "mocked del error", err.Error())
|
||||
|
||||
isFatal, err := secretskvs.IsPluginStartupErrorFatal(context.Background(), secretskvs.GetNamespacedKVStore(p.KVStore))
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, isFatal)
|
||||
}
|
||||
|
||||
func addSecretToSqlStore(t *testing.T, sqlSecretStore secretskvs.SecretsKVStore, ctx context.Context, orgId int64, namespace1 string, typ string, value string) {
|
||||
t.Helper()
|
||||
err := sqlSecretStore.Set(ctx, orgId, namespace1, typ, value)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// validates that secrets on the sql store were deleted.
|
||||
func validateSqlSecretWasDeleted(t *testing.T, sqlSecretStore secretskvs.SecretsKVStore, ctx context.Context, orgId int64, namespace1 string, typ string) {
|
||||
t.Helper()
|
||||
res, err := sqlSecretStore.Keys(ctx, orgId, namespace1, typ)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(res))
|
||||
}
|
||||
|
||||
// validates that secrets should be on the plugin
|
||||
func validateSecretWasStoredInPlugin(t *testing.T, secretsStore secretskvs.SecretsKVStore, ctx context.Context, orgId int64, namespace1 string, typ string) {
|
||||
t.Helper()
|
||||
resPlugin, err := secretsStore.Keys(ctx, orgId, namespace1, typ)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(resPlugin))
|
||||
}
|
||||
|
||||
// Set up services used in migration
|
||||
func setupTestMigrateToPluginService(t *testing.T) (*MigrateToPluginService, secretskvs.SecretsKVStore, secretskvs.SecretsKVStore) {
|
||||
t.Helper()
|
||||
|
||||
rawCfg := `
|
||||
[secrets]
|
||||
use_plugin = true
|
||||
`
|
||||
raw, err := ini.Load([]byte(rawCfg))
|
||||
require.NoError(t, err)
|
||||
cfg := &setting.Cfg{Raw: raw}
|
||||
sqlStore := db.InitTestDB(t)
|
||||
|
||||
// this would be the plugin - mocked at the moment
|
||||
fallbackStore := secretskvs.WithCache(secretskvs.NewFakeSQLSecretsKVStore(t, sqlStore), time.Minute*5, time.Minute*5)
|
||||
secretsStoreForPlugin := secretskvs.WithCache(secretskvs.NewFakePluginSecretsKVStore(t, featuremgmt.WithFeatures(), fallbackStore), time.Minute*5, time.Minute*5)
|
||||
|
||||
// this is to init the sql secret store inside the migration
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
manager := secretskvs.NewFakeSecretsPluginManager(t, false)
|
||||
migratorService := ProvideMigrateToPluginService(
|
||||
secretsStoreForPlugin,
|
||||
cfg,
|
||||
sqlStore,
|
||||
secretsService,
|
||||
kvstore.ProvideService(sqlStore),
|
||||
manager,
|
||||
)
|
||||
|
||||
return migratorService, secretsStoreForPlugin, fallbackStore
|
||||
}
|
||||
|
||||
func setupTestMigratorServiceWithDeletionError(
|
||||
t *testing.T,
|
||||
secretskv secretskvs.SecretsKVStore,
|
||||
sqlStore db.DB,
|
||||
kvstore kvstore.KVStore,
|
||||
) *MigrateToPluginService {
|
||||
t.Helper()
|
||||
t.Cleanup(secretskvs.ResetPlugin)
|
||||
cfg := secretskvs.SetupTestConfig(t)
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
manager := secretskvs.NewFakeSecretsPluginManager(t, false)
|
||||
migratorService := ProvideMigrateToPluginService(
|
||||
secretskv,
|
||||
cfg,
|
||||
sqlStore,
|
||||
secretsService,
|
||||
kvstore,
|
||||
manager,
|
||||
)
|
||||
fallback := secretskvs.NewFakeSecretsKVStore()
|
||||
var orgId int64 = 1
|
||||
str := "random string"
|
||||
err := fallback.Set(context.Background(), orgId, str, str, "bogus")
|
||||
require.NoError(t, err)
|
||||
fallback.DeletionError(true)
|
||||
err = secretskvs.ReplaceFallback(t, secretskv, fallback)
|
||||
require.NoError(t, err)
|
||||
return migratorService
|
||||
}
|
@ -5,9 +5,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
QuitOnPluginStartupFailureKey = "quit_on_secrets_plugin_startup_failure"
|
||||
PluginNamespace = "secretsmanagerplugin"
|
||||
DataSourceSecretType = "datasource"
|
||||
DataSourceSecretType = "datasource"
|
||||
)
|
||||
|
||||
// Item stored in k/v store.
|
||||
|
@ -1,288 +0,0 @@
|
||||
package kvstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
smp "github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var (
|
||||
fatalFlagOnce sync.Once
|
||||
startupOnce sync.Once
|
||||
errPluginDisabledByConfig = errors.New("remote secret management plugin disabled because the property `secrets.use_plugin` is not set to `true`")
|
||||
errPluginNotInstalled = errors.New("remote secret management plugin disabled because there is no installed plugin of type `secretsmanager`")
|
||||
)
|
||||
|
||||
// SecretsKVStorePlugin provides a key/value store backed by the Grafana plugin gRPC interface
|
||||
type SecretsKVStorePlugin struct {
|
||||
sync.Mutex
|
||||
log log.Logger
|
||||
secretsPlugin smp.SecretsManagerPlugin
|
||||
secretsService secrets.Service
|
||||
kvstore *kvstore.NamespacedKVStore
|
||||
backwardsCompatibilityDisabled bool
|
||||
fallbackEnabled bool
|
||||
fallbackStore SecretsKVStore
|
||||
}
|
||||
|
||||
func NewPluginSecretsKVStore(
|
||||
secretsPlugin smp.SecretsManagerPlugin,
|
||||
secretsService secrets.Service,
|
||||
kvstore *kvstore.NamespacedKVStore,
|
||||
features featuremgmt.FeatureToggles,
|
||||
fallback SecretsKVStore,
|
||||
logger log.Logger,
|
||||
) *SecretsKVStorePlugin {
|
||||
return &SecretsKVStorePlugin{
|
||||
secretsPlugin: secretsPlugin,
|
||||
secretsService: secretsService,
|
||||
log: logger,
|
||||
kvstore: kvstore,
|
||||
backwardsCompatibilityDisabled: features.IsEnabledGlobally(featuremgmt.FlagDisableSecretsCompatibility),
|
||||
fallbackStore: fallback,
|
||||
}
|
||||
}
|
||||
|
||||
// Get an item from the store
|
||||
// If it is the first time a secret has been retrieved and backwards compatibility is disabled, mark plugin startup errors fatal
|
||||
func (kv *SecretsKVStorePlugin) Get(ctx context.Context, orgId int64, namespace string, typ string) (string, bool, error) {
|
||||
req := &smp.GetSecretRequest{
|
||||
KeyDescriptor: &smp.Key{
|
||||
OrgId: orgId,
|
||||
Namespace: namespace,
|
||||
Type: typ,
|
||||
},
|
||||
}
|
||||
|
||||
res, err := kv.secretsPlugin.GetSecret(ctx, req)
|
||||
if res.UserFriendlyError != "" {
|
||||
err = wrapUserFriendlySecretError(res.UserFriendlyError)
|
||||
}
|
||||
|
||||
if res.Exists {
|
||||
updateFatalFlag(ctx, kv)
|
||||
}
|
||||
|
||||
if kv.fallbackEnabled {
|
||||
if err != nil || res.UserFriendlyError != "" || !res.Exists {
|
||||
res.DecryptedValue, res.Exists, err = kv.fallbackStore.Get(ctx, orgId, namespace, typ)
|
||||
}
|
||||
}
|
||||
|
||||
return res.DecryptedValue, res.Exists, err
|
||||
}
|
||||
|
||||
// Set an item in the store
|
||||
// If it is the first time a secret has been set and backwards compatibility is disabled, mark plugin startup errors fatal
|
||||
func (kv *SecretsKVStorePlugin) Set(ctx context.Context, orgId int64, namespace string, typ string, value string) error {
|
||||
req := &smp.SetSecretRequest{
|
||||
KeyDescriptor: &smp.Key{
|
||||
OrgId: orgId,
|
||||
Namespace: namespace,
|
||||
Type: typ,
|
||||
},
|
||||
Value: value,
|
||||
}
|
||||
|
||||
res, err := kv.secretsPlugin.SetSecret(ctx, req)
|
||||
if err == nil && res.UserFriendlyError != "" {
|
||||
err = wrapUserFriendlySecretError(res.UserFriendlyError)
|
||||
}
|
||||
|
||||
updateFatalFlag(ctx, kv)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Del deletes an item from the store.
|
||||
func (kv *SecretsKVStorePlugin) Del(ctx context.Context, orgId int64, namespace string, typ string) error {
|
||||
req := &smp.DeleteSecretRequest{
|
||||
KeyDescriptor: &smp.Key{
|
||||
OrgId: orgId,
|
||||
Namespace: namespace,
|
||||
Type: typ,
|
||||
},
|
||||
}
|
||||
|
||||
res, err := kv.secretsPlugin.DeleteSecret(ctx, req)
|
||||
if err == nil && res.UserFriendlyError != "" {
|
||||
err = wrapUserFriendlySecretError(res.UserFriendlyError)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Keys get all keys for a given namespace. To query for all
|
||||
// organizations the constant 'kvstore.AllOrganizations' can be passed as orgId.
|
||||
func (kv *SecretsKVStorePlugin) Keys(ctx context.Context, orgId int64, namespace string, typ string) ([]Key, error) {
|
||||
req := &smp.ListSecretsRequest{
|
||||
KeyDescriptor: &smp.Key{
|
||||
OrgId: orgId,
|
||||
Namespace: namespace,
|
||||
Type: typ,
|
||||
},
|
||||
AllOrganizations: orgId == AllOrganizations,
|
||||
}
|
||||
|
||||
res, err := kv.secretsPlugin.ListSecrets(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if res.UserFriendlyError != "" {
|
||||
err = wrapUserFriendlySecretError(res.UserFriendlyError)
|
||||
}
|
||||
|
||||
return parseKeys(res.Keys), err
|
||||
}
|
||||
|
||||
// Rename an item in the store
|
||||
func (kv *SecretsKVStorePlugin) Rename(ctx context.Context, orgId int64, namespace string, typ string, newNamespace string) error {
|
||||
req := &smp.RenameSecretRequest{
|
||||
KeyDescriptor: &smp.Key{
|
||||
OrgId: orgId,
|
||||
Namespace: namespace,
|
||||
Type: typ,
|
||||
},
|
||||
NewNamespace: newNamespace,
|
||||
}
|
||||
|
||||
res, err := kv.secretsPlugin.RenameSecret(ctx, req)
|
||||
if err == nil && res.UserFriendlyError != "" {
|
||||
err = wrapUserFriendlySecretError(res.UserFriendlyError)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (kv *SecretsKVStorePlugin) GetAll(ctx context.Context) ([]Item, error) {
|
||||
req := &smp.GetAllSecretsRequest{}
|
||||
|
||||
res, err := kv.secretsPlugin.GetAllSecrets(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if res.UserFriendlyError != "" {
|
||||
err = wrapUserFriendlySecretError(res.UserFriendlyError)
|
||||
}
|
||||
|
||||
return parseItems(res.Items), err
|
||||
}
|
||||
|
||||
func (kv *SecretsKVStorePlugin) Fallback() SecretsKVStore {
|
||||
return kv.fallbackStore
|
||||
}
|
||||
|
||||
func (kv *SecretsKVStorePlugin) WithFallbackEnabled(fn func() error) error {
|
||||
kv.Lock()
|
||||
defer kv.Unlock()
|
||||
kv.fallbackEnabled = true
|
||||
err := fn()
|
||||
kv.fallbackEnabled = false
|
||||
return err
|
||||
}
|
||||
|
||||
func parseKeys(keys []*smp.Key) []Key {
|
||||
newKeys := make([]Key, 0, len(keys))
|
||||
|
||||
for _, k := range keys {
|
||||
newKey := Key{OrgId: k.OrgId, Namespace: k.Namespace, Type: k.Type}
|
||||
newKeys = append(newKeys, newKey)
|
||||
}
|
||||
|
||||
return newKeys
|
||||
}
|
||||
|
||||
func parseItems(items []*smp.Item) []Item {
|
||||
newItems := make([]Item, 0, len(items))
|
||||
|
||||
for _, i := range items {
|
||||
newItem := Item{OrgId: &i.Key.OrgId, Namespace: &i.Key.Namespace, Type: &i.Key.Type, Value: i.Value}
|
||||
newItems = append(newItems, newItem)
|
||||
}
|
||||
|
||||
return newItems
|
||||
}
|
||||
|
||||
func updateFatalFlag(ctx context.Context, skv *SecretsKVStorePlugin) {
|
||||
// This function makes the most sense in here because it handles all possible scenarios:
|
||||
// - User changed backwards compatibility flag, so we have to migrate secrets either to or from the plugin (get or set)
|
||||
// - Migration is on, so we migrate secrets to the plugin (set)
|
||||
// - User doesn't migrate, but stores a new secret in the plugin (set)
|
||||
// Rather than updating the flag in several places, it is cleaner to just do this check once
|
||||
// Very early on. Once backwards compatibility to legacy secrets is gone in Grafana 10, this can go away as well
|
||||
fatalFlagOnce.Do(func() {
|
||||
skv.log.Debug("Updating plugin startup error fatal flag")
|
||||
var err error
|
||||
if isFatal, _ := IsPluginStartupErrorFatal(ctx, skv.kvstore); !isFatal && skv.backwardsCompatibilityDisabled {
|
||||
err = SetPluginStartupErrorFatal(ctx, skv.kvstore, true)
|
||||
} else if isFatal && !skv.backwardsCompatibilityDisabled {
|
||||
err = SetPluginStartupErrorFatal(ctx, skv.kvstore, false)
|
||||
}
|
||||
if err != nil {
|
||||
skv.log.Error("failed to set plugin error fatal flag", err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func wrapUserFriendlySecretError(ufe string) datasources.ErrDatasourceSecretsPluginUserFriendly {
|
||||
return datasources.ErrDatasourceSecretsPluginUserFriendly{Err: ufe}
|
||||
}
|
||||
|
||||
func GetNamespacedKVStore(kv kvstore.KVStore) *kvstore.NamespacedKVStore {
|
||||
return kvstore.WithNamespace(kv, kvstore.AllOrganizations, PluginNamespace)
|
||||
}
|
||||
|
||||
func IsPluginStartupErrorFatal(ctx context.Context, kvstore *kvstore.NamespacedKVStore) (bool, error) {
|
||||
_, exists, err := kvstore.Get(ctx, QuitOnPluginStartupFailureKey)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error retrieving key %s from kvstore. error: %w", QuitOnPluginStartupFailureKey, err)
|
||||
}
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
func SetPluginStartupErrorFatal(ctx context.Context, kvstore *kvstore.NamespacedKVStore, isFatal bool) error {
|
||||
if !isFatal {
|
||||
return kvstore.Del(ctx, QuitOnPluginStartupFailureKey)
|
||||
}
|
||||
return kvstore.Set(ctx, QuitOnPluginStartupFailureKey, "true")
|
||||
}
|
||||
|
||||
func EvaluateRemoteSecretsPlugin(ctx context.Context, mg plugins.SecretsPluginManager, cfg *setting.Cfg) error {
|
||||
usePlugin := cfg.SectionWithEnvOverrides("secrets").Key("use_plugin").MustBool()
|
||||
if !usePlugin {
|
||||
return errPluginDisabledByConfig
|
||||
}
|
||||
pluginInstalled := mg.SecretsManager(ctx) != nil
|
||||
if !pluginInstalled {
|
||||
return errPluginNotInstalled
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func HasPluginStarted(ctx context.Context, mg plugins.SecretsPluginManager) bool {
|
||||
return mg.SecretsManager(ctx) != nil && mg.SecretsManager(ctx).SecretsManager != nil
|
||||
}
|
||||
|
||||
func StartAndReturnPlugin(mg plugins.SecretsPluginManager, ctx context.Context) (smp.SecretsManagerPlugin, error) {
|
||||
var err error
|
||||
startupOnce.Do(func() {
|
||||
err = mg.SecretsManager(ctx).Start(ctx)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mg.SecretsManager(ctx).SecretsManager, nil
|
||||
}
|
||||
|
||||
func ResetPlugin() {
|
||||
fatalFlagOnce = sync.Once{}
|
||||
startupOnce = sync.Once{}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
package kvstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/tests/testsuite"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testsuite.Run(m)
|
||||
}
|
||||
|
||||
// Set fatal flag to true, then simulate a plugin start failure
|
||||
// Should result in an error from the secret store provider
|
||||
func TestFatalPluginErr_PluginFailsToStartWithFatalFlagSet(t *testing.T) {
|
||||
p, err := SetupFatalCrashTest(t, true, true, false)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "mocked failed to start", err.Error())
|
||||
assert.Nil(t, p.SecretsKVStore)
|
||||
}
|
||||
|
||||
// Set fatal flag to false, then simulate a plugin start failure
|
||||
// Should result in the secret store provider returning the sql impl
|
||||
func TestFatalPluginErr_PluginFailsToStartWithFatalFlagNotSet(t *testing.T) {
|
||||
p, err := SetupFatalCrashTest(t, true, false, false)
|
||||
assert.NoError(t, err)
|
||||
require.IsType(t, &CachedKVStore{}, p.SecretsKVStore)
|
||||
|
||||
cachedKv, _ := p.SecretsKVStore.(*CachedKVStore)
|
||||
store, err := GetUnwrappedStoreFromCache(cachedKv)
|
||||
require.NoError(t, err)
|
||||
assert.IsType(t, &SecretsKVStoreSQL{}, store)
|
||||
}
|
||||
|
||||
// With fatal flag not set, store a secret in the plugin while backwards compatibility is disabled
|
||||
// Should result in the fatal flag going from unset -> set to true
|
||||
func TestFatalPluginErr_FatalFlagGetsSetWithBackwardsCompatDisabled(t *testing.T) {
|
||||
p, err := SetupFatalCrashTest(t, false, false, true)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, p.SecretsKVStore)
|
||||
|
||||
err = p.SecretsKVStore.Set(context.Background(), 0, "datasource", "postgres", "my secret")
|
||||
assert.NoError(t, err)
|
||||
|
||||
isFatal, err := IsPluginStartupErrorFatal(context.Background(), GetNamespacedKVStore(p.KVStore))
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, isFatal)
|
||||
}
|
||||
|
||||
// With fatal flag set, retrieve a secret from the plugin while backwards compatibility is enabled
|
||||
// Should result in the fatal flag going from set to true -> unset
|
||||
func TestFatalPluginErr_FatalFlagGetsUnSetWithBackwardsCompatEnabled(t *testing.T) {
|
||||
p, err := SetupFatalCrashTest(t, false, true, false)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, p.SecretsKVStore)
|
||||
|
||||
// setup - store secret and manually bypassing the remote plugin impl
|
||||
_, err = p.PluginManager.SecretsManager(context.Background()).SecretsManager.SetSecret(context.Background(), &secretsmanagerplugin.SetSecretRequest{
|
||||
KeyDescriptor: &secretsmanagerplugin.Key{
|
||||
OrgId: 0,
|
||||
Namespace: "postgres",
|
||||
Type: "datasource",
|
||||
},
|
||||
Value: "bogus",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// retrieve the secret and check values
|
||||
val, exists, err := p.SecretsKVStore.Get(context.Background(), 0, "postgres", "datasource")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, val)
|
||||
assert.True(t, exists)
|
||||
|
||||
isFatal, err := IsPluginStartupErrorFatal(context.Background(), GetNamespacedKVStore(p.KVStore))
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, isFatal)
|
||||
}
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
"github.com/grafana/grafana/pkg/tests/testsuite"
|
||||
)
|
||||
|
||||
type TestCase struct {
|
||||
@ -25,6 +26,10 @@ func (t *TestCase) Value() string {
|
||||
return fmt.Sprintf("%d:%s:%s:%d", t.OrgId, t.Namespace, t.Type, t.Revision)
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testsuite.Run(m)
|
||||
}
|
||||
|
||||
func TestSecretsKVStoreSQL(t *testing.T) {
|
||||
sqlStore := db.InitTestDB(t)
|
||||
secretsService := manager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
|
@ -3,25 +3,13 @@ package kvstore
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
pluginsLogger "github.com/grafana/grafana/pkg/plugins/log"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretsmng "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func NewFakeSQLSecretsKVStore(t *testing.T, sqlStore *sqlstore.SQLStore) *SecretsKVStoreSQL {
|
||||
@ -30,17 +18,6 @@ func NewFakeSQLSecretsKVStore(t *testing.T, sqlStore *sqlstore.SQLStore) *Secret
|
||||
return NewSQLSecretsKVStore(sqlStore, secretsService, log.New("test.logger"))
|
||||
}
|
||||
|
||||
func NewFakePluginSecretsKVStore(t *testing.T, features featuremgmt.FeatureToggles, fallback SecretsKVStore) *SecretsKVStorePlugin {
|
||||
t.Helper()
|
||||
sqlStore := db.InitTestDB(t)
|
||||
secretsService := secretsmng.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
store := kvstore.ProvideService(sqlStore)
|
||||
namespacedKVStore := GetNamespacedKVStore(store)
|
||||
manager := NewFakeSecretsPluginManager(t, false)
|
||||
plugin := manager.SecretsManager(context.Background()).SecretsManager
|
||||
return NewPluginSecretsKVStore(plugin, secretsService, namespacedKVStore, features, fallback, log.New("test.logger"))
|
||||
}
|
||||
|
||||
// In memory kv store used for testing
|
||||
type FakeSecretsKVStore struct {
|
||||
store map[Key]string
|
||||
@ -127,14 +104,6 @@ func buildKey(orgId int64, namespace string, typ string) Key {
|
||||
}
|
||||
}
|
||||
|
||||
func internalToProtoKey(k Key) *secretsmanagerplugin.Key {
|
||||
return &secretsmanagerplugin.Key{
|
||||
OrgId: k.OrgId,
|
||||
Namespace: k.Namespace,
|
||||
Type: k.Type,
|
||||
}
|
||||
}
|
||||
|
||||
// Fake feature toggle - only need to check the backwards compatibility disabled flag
|
||||
type fakeFeatureToggles struct {
|
||||
returnValue bool
|
||||
@ -158,172 +127,3 @@ func (f fakeFeatureToggles) IsEnabled(ctx context.Context, feature string) bool
|
||||
func (f fakeFeatureToggles) GetEnabled(ctx context.Context) map[string]bool {
|
||||
return map[string]bool{}
|
||||
}
|
||||
|
||||
// Fake grpc secrets plugin impl
|
||||
type fakeGRPCSecretsPlugin struct {
|
||||
kv map[Key]string
|
||||
}
|
||||
|
||||
func (c *fakeGRPCSecretsPlugin) GetSecret(ctx context.Context, in *secretsmanagerplugin.GetSecretRequest, opts ...grpc.CallOption) (*secretsmanagerplugin.GetSecretResponse, error) {
|
||||
val, ok := c.kv[buildKey(in.KeyDescriptor.OrgId, in.KeyDescriptor.Namespace, in.KeyDescriptor.Type)]
|
||||
return &secretsmanagerplugin.GetSecretResponse{
|
||||
DecryptedValue: val,
|
||||
Exists: ok,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *fakeGRPCSecretsPlugin) SetSecret(ctx context.Context, in *secretsmanagerplugin.SetSecretRequest, opts ...grpc.CallOption) (*secretsmanagerplugin.SetSecretResponse, error) {
|
||||
c.kv[buildKey(in.KeyDescriptor.OrgId, in.KeyDescriptor.Namespace, in.KeyDescriptor.Type)] = in.Value
|
||||
return &secretsmanagerplugin.SetSecretResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeGRPCSecretsPlugin) DeleteSecret(ctx context.Context, in *secretsmanagerplugin.DeleteSecretRequest, opts ...grpc.CallOption) (*secretsmanagerplugin.DeleteSecretResponse, error) {
|
||||
delete(c.kv, buildKey(in.KeyDescriptor.OrgId, in.KeyDescriptor.Namespace, in.KeyDescriptor.Type))
|
||||
return &secretsmanagerplugin.DeleteSecretResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeGRPCSecretsPlugin) ListSecrets(ctx context.Context, in *secretsmanagerplugin.ListSecretsRequest, opts ...grpc.CallOption) (*secretsmanagerplugin.ListSecretsResponse, error) {
|
||||
res := make([]*secretsmanagerplugin.Key, 0)
|
||||
for k := range c.kv {
|
||||
if in.KeyDescriptor.OrgId == AllOrganizations && in.KeyDescriptor.Namespace == "" && in.KeyDescriptor.Type == "" {
|
||||
res = append(res, internalToProtoKey(k))
|
||||
} else if k.OrgId == in.KeyDescriptor.OrgId && k.Namespace == in.KeyDescriptor.Namespace && k.Type == in.KeyDescriptor.Type {
|
||||
res = append(res, internalToProtoKey(k))
|
||||
}
|
||||
}
|
||||
return &secretsmanagerplugin.ListSecretsResponse{
|
||||
Keys: res,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *fakeGRPCSecretsPlugin) RenameSecret(ctx context.Context, in *secretsmanagerplugin.RenameSecretRequest, opts ...grpc.CallOption) (*secretsmanagerplugin.RenameSecretResponse, error) {
|
||||
oldKey := buildKey(in.KeyDescriptor.OrgId, in.KeyDescriptor.Namespace, in.KeyDescriptor.Type)
|
||||
val := c.kv[oldKey]
|
||||
delete(c.kv, oldKey)
|
||||
c.kv[buildKey(in.KeyDescriptor.OrgId, in.NewNamespace, in.KeyDescriptor.Type)] = val
|
||||
return &secretsmanagerplugin.RenameSecretResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeGRPCSecretsPlugin) GetAllSecrets(ctx context.Context, in *secretsmanagerplugin.GetAllSecretsRequest, opts ...grpc.CallOption) (*secretsmanagerplugin.GetAllSecretsResponse, error) {
|
||||
items := make([]*secretsmanagerplugin.Item, 0)
|
||||
for k, v := range c.kv {
|
||||
items = append(items, &secretsmanagerplugin.Item{
|
||||
Key: internalToProtoKey(k),
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
return &secretsmanagerplugin.GetAllSecretsResponse{
|
||||
Items: items,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ SecretsKVStore = &FakeSecretsKVStore{}
|
||||
var _ secretsmanagerplugin.SecretsManagerPlugin = &fakeGRPCSecretsPlugin{}
|
||||
|
||||
// Fake plugin manager
|
||||
type fakePluginManager struct {
|
||||
shouldFailOnStart bool
|
||||
plugin *plugins.Plugin
|
||||
}
|
||||
|
||||
func (mg *fakePluginManager) SecretsManager(_ context.Context) *plugins.Plugin {
|
||||
if mg.plugin != nil {
|
||||
return mg.plugin
|
||||
}
|
||||
p := &plugins.Plugin{
|
||||
SecretsManager: &fakeGRPCSecretsPlugin{
|
||||
kv: make(map[Key]string),
|
||||
},
|
||||
}
|
||||
p.RegisterClient(&fakePluginClient{
|
||||
shouldFailOnStart: mg.shouldFailOnStart,
|
||||
})
|
||||
mg.plugin = p
|
||||
return p
|
||||
}
|
||||
|
||||
func NewFakeSecretsPluginManager(t *testing.T, shouldFailOnStart bool) plugins.SecretsPluginManager {
|
||||
t.Helper()
|
||||
return &fakePluginManager{
|
||||
shouldFailOnStart: shouldFailOnStart,
|
||||
}
|
||||
}
|
||||
|
||||
// Fake plugin client
|
||||
type fakePluginClient struct {
|
||||
shouldFailOnStart bool
|
||||
backendplugin.Plugin
|
||||
}
|
||||
|
||||
func (pc *fakePluginClient) Start(_ context.Context) error {
|
||||
if pc.shouldFailOnStart {
|
||||
return errors.New("mocked failed to start")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pc *fakePluginClient) Stop(_ context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pc *fakePluginClient) Logger() pluginsLogger.Logger {
|
||||
return pluginsLogger.NewTestLogger()
|
||||
}
|
||||
|
||||
func SetupFatalCrashTest(
|
||||
t *testing.T,
|
||||
shouldFailOnStart bool,
|
||||
isPluginErrorFatal bool,
|
||||
isBackwardsCompatDisabled bool,
|
||||
) (fatalCrashTestFields, error) {
|
||||
t.Helper()
|
||||
fatalFlagOnce = sync.Once{}
|
||||
startupOnce = sync.Once{}
|
||||
cfg := SetupTestConfig(t)
|
||||
sqlStore := db.InitTestDB(t)
|
||||
secretService := fakes.FakeSecretsService{}
|
||||
kvstore := kvstore.ProvideService(sqlStore)
|
||||
if isPluginErrorFatal {
|
||||
_ = SetPluginStartupErrorFatal(context.Background(), GetNamespacedKVStore(kvstore), true)
|
||||
}
|
||||
features := NewFakeFeatureToggles(t, isBackwardsCompatDisabled)
|
||||
manager := NewFakeSecretsPluginManager(t, shouldFailOnStart)
|
||||
svc, err := ProvideService(sqlStore, secretService, manager, kvstore, features, cfg)
|
||||
t.Cleanup(ResetPlugin)
|
||||
return fatalCrashTestFields{
|
||||
SecretsKVStore: svc,
|
||||
PluginManager: manager,
|
||||
KVStore: kvstore,
|
||||
SqlStore: sqlStore,
|
||||
}, err
|
||||
}
|
||||
|
||||
type fatalCrashTestFields struct {
|
||||
SecretsKVStore SecretsKVStore
|
||||
PluginManager plugins.SecretsPluginManager
|
||||
KVStore kvstore.KVStore
|
||||
SqlStore db.DB
|
||||
}
|
||||
|
||||
func SetupTestConfig(t *testing.T) *setting.Cfg {
|
||||
t.Helper()
|
||||
rawCfg := `
|
||||
[secrets]
|
||||
use_plugin = true
|
||||
`
|
||||
raw, err := ini.Load([]byte(rawCfg))
|
||||
require.NoError(t, err)
|
||||
return &setting.Cfg{Raw: raw}
|
||||
}
|
||||
|
||||
func ReplaceFallback(t *testing.T, kv SecretsKVStore, fb SecretsKVStore) error {
|
||||
t.Helper()
|
||||
if store, ok := kv.(*CachedKVStore); ok {
|
||||
kv = store.store
|
||||
}
|
||||
if store, ok := kv.(*SecretsKVStorePlugin); ok {
|
||||
store.fallbackStore = fb
|
||||
return nil
|
||||
}
|
||||
return errors.New("not a plugin store")
|
||||
}
|
||||
|
@ -88,4 +88,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -33,16 +33,6 @@ export const InstallControlsWarning = ({ plugin, pluginStatus, latestCompatibleV
|
||||
);
|
||||
}
|
||||
|
||||
if (plugin.type === PluginType.secretsmanager) {
|
||||
return (
|
||||
<Alert
|
||||
severity="warning"
|
||||
title="Secrets manager plugins cannot be managed by the Plugin Catalog."
|
||||
className={styles.alert}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (plugin.isEnterprise && !featureEnabled('enterprise.plugins')) {
|
||||
return (
|
||||
<Alert severity="warning" title="" className={styles.alert}>
|
||||
|
@ -24,12 +24,6 @@ describe('PluginDetailsBody', () => {
|
||||
type: PluginType.renderer,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'secrets manager type plugin',
|
||||
plugin: {
|
||||
type: PluginType.secretsmanager,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'enterprise plugin type without enterprise license',
|
||||
plugin: {
|
||||
|
@ -124,7 +124,7 @@ export function mapRemoteToCatalog(plugin: RemotePlugin, error?: PluginError): C
|
||||
url,
|
||||
} = plugin;
|
||||
|
||||
const isDisabled = !!error || isDisabledSecretsPlugin(typeCode);
|
||||
const isDisabled = !!error;
|
||||
return {
|
||||
description,
|
||||
downloads,
|
||||
@ -178,7 +178,7 @@ export function mapLocalToCatalog(plugin: LocalPlugin, error?: PluginError): Cat
|
||||
angularDetected,
|
||||
} = plugin;
|
||||
|
||||
const isDisabled = !!error || isDisabledSecretsPlugin(type);
|
||||
const isDisabled = !!error;
|
||||
return {
|
||||
description,
|
||||
downloads: 0,
|
||||
@ -218,7 +218,7 @@ export function mapToCatalogPlugin(local?: LocalPlugin, remote?: RemotePlugin, e
|
||||
const installedVersion = local?.info.version;
|
||||
const id = remote?.slug || local?.id || '';
|
||||
const type = local?.type || remote?.typeCode;
|
||||
const isDisabled = !!error || isDisabledSecretsPlugin(type);
|
||||
const isDisabled = !!error;
|
||||
const keywords = remote?.keywords || local?.info.keywords || [];
|
||||
|
||||
let logos = {
|
||||
@ -370,7 +370,6 @@ export const hasInstallControlWarning = (
|
||||
const isCompatible = Boolean(latestCompatibleVersion);
|
||||
return (
|
||||
plugin.type === PluginType.renderer ||
|
||||
plugin.type === PluginType.secretsmanager ||
|
||||
(plugin.isEnterprise && !featureEnabled('enterprise.plugins')) ||
|
||||
plugin.isDev ||
|
||||
(!hasPermission && !isExternallyManaged) ||
|
||||
@ -403,10 +402,6 @@ export function isPreinstalledPlugin(id: string): { found: boolean; withVersion:
|
||||
return { found: !!plugin?.id, withVersion: !!plugin?.version };
|
||||
}
|
||||
|
||||
function isDisabledSecretsPlugin(type?: PluginType): boolean {
|
||||
return type === PluginType.secretsmanager && !config.secretsManagerPluginEnabled;
|
||||
}
|
||||
|
||||
export function isLocalCorePlugin(local?: LocalPlugin): boolean {
|
||||
return Boolean(local?.signature === 'internal');
|
||||
}
|
||||
@ -469,7 +464,6 @@ export function isPluginUpdatable(plugin: CatalogPlugin) {
|
||||
export function shouldDisablePluginInstall(plugin: CatalogPlugin) {
|
||||
if (
|
||||
!isPluginModifiable(plugin) ||
|
||||
plugin.type === PluginType.secretsmanager ||
|
||||
(plugin.isEnterprise && !featureEnabled('enterprise.plugins')) ||
|
||||
!plugin.isPublished ||
|
||||
plugin.isDisabled ||
|
||||
|
@ -24,7 +24,6 @@ export enum PluginIconName {
|
||||
datasource = 'database',
|
||||
panel = 'credit-card',
|
||||
renderer = 'capture',
|
||||
secretsmanager = 'key-skeleton-alt',
|
||||
}
|
||||
|
||||
export interface CatalogPlugin extends WithAccessControlMetadata {
|
||||
|
Reference in New Issue
Block a user