From 88644482ac7af12bc1c6d5ffb116a09b695a44a7 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Thu, 14 Dec 2023 23:31:34 +0530 Subject: [PATCH 01/23] chore: Vuln Scanning Signed-off-by: jay-dee7 --- Makefile | 7 + config/config.go | 92 +- config/yaml.go | 4 +- dfs/mock/memMappedSystem.go | 10 +- go.mod | 3 +- orgmode/admin.go | 38 +- orgmode/orgmode.go | 62 +- protos/services/yor/clair/v1/clair.proto | 121 + router/github.go | 11 +- router/orgmode.go | 1 + router/router.go | 3 +- router/vuln_scanning_routes.go | 30 + .../kon/github_actions/v1/server/server.go | 4 +- services/yor/clair/v1/clair.pb.go | 1708 +++++++++++++ services/yor/clair/v1/clair.pb.validate.go | 2269 +++++++++++++++++ .../clair/v1/clairconnect/clair.connect.go | 132 + services/yor/clair/v1/server/clair.go | 155 ++ services/yor/clair/v1/server/server.go | 46 + store/v1/permissions/permissions.go | 2 +- store/v1/permissions/permissions_impl.go | 41 +- store/v1/types/permissions.go | 25 +- store/v1/types/users.go | 15 +- store/v1/users/store.go | 2 + store/v1/users/users_impl.go | 35 +- vcs/github/github.go | 6 +- vcs/github/handlers.go | 4 + 26 files changed, 4750 insertions(+), 76 deletions(-) create mode 100644 protos/services/yor/clair/v1/clair.proto create mode 100644 router/vuln_scanning_routes.go create mode 100644 services/yor/clair/v1/clair.pb.go create mode 100644 services/yor/clair/v1/clair.pb.validate.go create mode 100644 services/yor/clair/v1/clairconnect/clair.connect.go create mode 100644 services/yor/clair/v1/server/clair.go create mode 100644 services/yor/clair/v1/server/server.go diff --git a/Makefile b/Makefile index 71efa572..80732244 100644 --- a/Makefile +++ b/Makefile @@ -14,3 +14,10 @@ certs: mkdir .certs openssl req -x509 -newkey rsa:4096 -keyout .certs/registry.local -out .certs/registry.local.crt -sha256 -days 365 \ -subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=registry.local" -nodes + +reset: + psql -c 'drop database open_registry' && \ + psql -c 'drop role open_registry_user' && \ + go build && \ + ./OpenRegistry migrations init --database="open_registry" --admin-db="postgres" --admin-db-username="postgres" --host="0.0.0.0" --password="Qwerty@123" --insecure=true && \ + ./OpenRegistry start diff --git a/config/config.go b/config/config.go index c6630fc3..4cb90030 100644 --- a/config/config.go +++ b/config/config.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/fatih/color" "github.com/go-playground/locales/en" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" @@ -13,6 +14,7 @@ import ( "github.com/hashicorp/go-multierror" "github.com/labstack/echo/v4" "github.com/spf13/viper" + "gopkg.in/yaml.v3" ) type ( @@ -75,7 +77,7 @@ type ( MockStorageBackend int // just so that we can retrieve values easily - Integrations []*Integration + Integrations map[string]any Registry struct { DNSAddress string `yaml:"dns_address" mapstructure:"dns_address" validate:"required"` @@ -133,7 +135,8 @@ type ( Enabled bool `yaml:"enabled" mapstructure:"enabled"` Timeout time.Duration `yaml:"timeout" mapstructure:"timeout"` } - Integration struct { + + GithubIntegration struct { Name string `yaml:"name" mapstructure:"name"` ClientSecret string `yaml:"client_secret" mapstructure:"client_secret"` ClientID string `yaml:"client_id" mapstructure:"client_id"` @@ -147,6 +150,14 @@ type ( Enabled bool `yaml:"enabled" mapstructure:"enabled"` } + ClairIntegration struct { + ClairEndpoint string `yaml:"clair_endpoint" mapstructure:"clair_endpoint"` + AuthToken string `yaml:"auth_token" mapstructure:"auth_token"` + Host string `yaml:"host" mapstructure:"host"` + Port int `yaml:"port" mapstructure:"port"` + Enabled bool `yaml:"enabled" mapstructure:"enabled"` + } + Auth struct { JWTSigningPrivateKey *rsa.PrivateKey `yaml:"priv_key" mapstructure:"priv_key"` JWTSigningPubKey *rsa.PublicKey `yaml:"pub_key" mapstructure:"pub_key"` @@ -289,23 +300,70 @@ func (oc *OpenRegistryConfig) Endpoint() string { } } -func (itg Integrations) GetGithubConfig() *Integration { - for _, cfg := range itg { - if cfg.Name == "github" && cfg.Enabled { - return cfg - } +func (itg Integrations) GetClairConfig() *ClairIntegration { + cfg := ClairIntegration{ + Enabled: false, + } + clairCfg, ok := itg["clair"] + if !ok { + return &cfg + } + + bz, err := yaml.Marshal(clairCfg) + if err != nil { + color.Red("error reading clair integration config as json: %s", err) + return nil + } + + if err = yaml.Unmarshal(bz, &cfg); err != nil { + color.Red("error parsing Clair integration config: %s", err) + return nil + } + + if cfg.Host == "" { + cfg.Host = "localhost" + } + + if cfg.Port == 0 { + cfg.Port = 5004 } - return &Integration{} + return &cfg } -func (itg Integrations) SetGithubConfig(config *Integration) { - for i, cfg := range itg { - if cfg.Name == "github" { - itg[i] = config - break - } +func (itg Integrations) GetGithubConfig() *GithubIntegration { + cfg := GithubIntegration{ + Enabled: false, + } + ghCfg, ok := itg["github"] + if !ok { + return &cfg + } + + bz, err := yaml.Marshal(ghCfg) + if err != nil { + color.Red("error reading github integration config as json: %s", err) + return nil + } + + if err = yaml.Unmarshal(bz, &cfg); err != nil { + color.Red("error parsing GitHub integration config: %s", err) + return nil } + + if cfg.Host == "" { + cfg.Host = "localhost" + } + + if cfg.Port == 0 { + cfg.Port = 5001 + } + + return &cfg +} + +func (itg Integrations) SetGithubConfig(config map[string]any) { + itg["github"] = config } type Environment int @@ -375,7 +433,11 @@ func (cfg *WebAppConfig) GetAllowedURLFromEchoContext(ctx echo.Context, env Envi return cfg.AllowedEndpoints[0] } -func (itg *Integration) GetAllowedURLFromEchoContext(ctx echo.Context, env Environment, allowedURLs []string) string { +func (itg *GithubIntegration) GetAllowedURLFromEchoContext( + ctx echo.Context, + env Environment, + allowedURLs []string, +) string { origin := ctx.Request().Header.Get("Origin") if env == Staging { return origin diff --git a/config/yaml.go b/config/yaml.go index b5056b15..ff5d5bb5 100644 --- a/config/yaml.go +++ b/config/yaml.go @@ -11,7 +11,7 @@ import ( "github.com/fatih/color" "github.com/golang-jwt/jwt/v5" "github.com/spf13/viper" - "gopkg.in/yaml.v2" + "gopkg.in/yaml.v3" ) func ReadYamlConfig(configPath string) (*OpenRegistryConfig, error) { @@ -77,7 +77,7 @@ func ReadYamlConfig(configPath string) (*OpenRegistryConfig, error) { githubConfig.Port = 5001 } - cfg.Integrations.SetGithubConfig(githubConfig) + // cfg.Integrations.SetGithubConfig(githubConfig) if err := cfg.Validate(); err != nil { return nil, err diff --git a/dfs/mock/memMappedSystem.go b/dfs/mock/memMappedSystem.go index 5fb61239..efe66a60 100644 --- a/dfs/mock/memMappedSystem.go +++ b/dfs/mock/memMappedSystem.go @@ -230,16 +230,22 @@ func (ms *memMappedMockStorage) FileServer() { fileID := ctx.Param("uuid") fd, err := ms.memFs.Open(fileID) if err != nil { - return ctx.JSON(http.StatusBadRequest, echo.Map{ + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), }) + + ms.logger.Log(ctx, err).Send() + return echoErr } bz, _ := io.ReadAll(fd) fd.Close() - return ctx.Blob(http.StatusOK, "", bz) + echoErr := ctx.Blob(http.StatusOK, "", bz) + ms.logger.Log(ctx, err).Send() + return echoErr }) + color.Yellow("Started Mock MemMapped DFS on %s", ms.serviceEndpoint) if err := e.Start(ms.serviceEndpoint); err != nil { color.Red("MockStorage service failed: %s", err) os.Exit(1) diff --git a/go.mod b/go.mod index eba68c8d..90a61082 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( golang.org/x/net v0.19.0 golang.org/x/oauth2 v0.15.0 google.golang.org/protobuf v1.32.0 - gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.1 storj.io/uplink v1.12.2 ) @@ -233,7 +233,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect google.golang.org/grpc v1.59.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect lukechampine.com/uint128 v1.3.0 // indirect mellium.im/sasl v0.3.1 // indirect diff --git a/orgmode/admin.go b/orgmode/admin.go index 13039372..47cfb4fa 100644 --- a/orgmode/admin.go +++ b/orgmode/admin.go @@ -26,8 +26,8 @@ func (o *orgMode) AllowOrgAdmin() echo.MiddlewareFunc { p := ctx.Request().URL.Path switch { - case p == "/org/migrate": - var body MigrateToOrgRequest + case p == "/api/org/migrate": + var body types.MigrateToOrgRequest if err := json.NewDecoder(ctx.Request().Body).Decode(&body); err != nil { echoErr := ctx.JSON(http.StatusUnauthorized, echo.Map{ "error": err.Error(), @@ -49,7 +49,7 @@ func (o *orgMode) AllowOrgAdmin() echo.MiddlewareFunc { ctx.Set(string(types.OrgModeRequestBodyContextKey), &body) return handler(ctx) - case p == "/org/users" || strings.HasPrefix(p, "/org/permissions/users"): + case p == "/api/org/users" || strings.HasPrefix(p, "/api/org/permissions/users"): orgOwner, err := o.userStore.GetOrgAdmin(ctx.Request().Context(), user.ID) if err != nil { echoErr := ctx.JSON(http.StatusUnauthorized, echo.Map{ @@ -61,9 +61,17 @@ func (o *orgMode) AllowOrgAdmin() echo.MiddlewareFunc { } switch ctx.Request().Method { - case http.MethodPost, http.MethodPatch: + case http.MethodPost: + if err = o.parseAddUsersToOrgRequest(ctx, user, orgOwner); err != nil { + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ + "error": err.Error(), + }) + o.logger.Log(ctx, err).Send() + return echoErr + } + case http.MethodPatch: if err = o.handleOrgModePermissionRequests(ctx, user, orgOwner); err != nil { - echoErr := ctx.JSON(http.StatusUnauthorized, echo.Map{ + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), }) o.logger.Log(ctx, err).Send() @@ -85,6 +93,22 @@ func (o *orgMode) AllowOrgAdmin() echo.MiddlewareFunc { } } +func (o *orgMode) parseAddUsersToOrgRequest(ctx echo.Context, user *types.User, orgOwner *types.User) error { + var body types.AddUsersToOrgRequest + if err := ctx.Bind(&body); err != nil { + return err + } + defer ctx.Request().Body.Close() + + // @TODO(jay-dee7) - Use a better comparison method + if !strings.EqualFold(orgOwner.ID.String(), body.OrganizationID.String()) { + return fmt.Errorf("organization id mismatch, invalid organization id") + } + + ctx.Set(string(types.OrgModeRequestBodyContextKey), &body) + return nil +} + func (o *orgMode) handleOrgModePermissionRequests(ctx echo.Context, user *types.User, orgOwner *types.User) error { var perms types.Permissions if err := json.NewDecoder(ctx.Request().Body).Decode(&perms); err != nil { @@ -106,7 +130,7 @@ func (o *orgMode) handleOrgModePermissionRequests(ctx echo.Context, user *types. } func (o *orgMode) handleOrgModeRemoveUser(ctx echo.Context, p string, orgOwner *types.User) error { - if strings.HasPrefix(p, fmt.Sprintf("/org/permissions/users/%s/", orgOwner.ID.String())) { + if strings.HasPrefix(p, fmt.Sprintf("/api/org/permissions/users/%s/", orgOwner.ID.String())) { orgID, err := uuid.Parse(ctx.Param("orgId")) if err != nil { return err @@ -120,7 +144,7 @@ func (o *orgMode) handleOrgModeRemoveUser(ctx echo.Context, p string, orgOwner * return echoErr } - body := &RemoveUserFromOrgRequest{ + body := &types.RemoveUserFromOrgRequest{ UserID: userID, OrganizationID: orgID, } diff --git a/orgmode/orgmode.go b/orgmode/orgmode.go index 59af2b93..a27ea2fb 100644 --- a/orgmode/orgmode.go +++ b/orgmode/orgmode.go @@ -1,6 +1,7 @@ package orgmode import ( + "fmt" "net/http" "time" @@ -18,18 +19,10 @@ type ( AddUserToOrg(ctx echo.Context) error RemoveUserFromOrg(ctx echo.Context) error UpdateUserPermissions(ctx echo.Context) error + GetOrgUsers(ctx echo.Context) error AllowOrgAdmin() echo.MiddlewareFunc } - MigrateToOrgRequest struct { - UserID uuid.UUID `json:"user_id"` - } - - RemoveUserFromOrgRequest struct { - UserID uuid.UUID `json:"user_id"` - OrganizationID uuid.UUID `json:"organization_id"` - } - orgMode struct { logger telemetry.Logger permissionsStore permissions.PermissionsStore @@ -49,7 +42,7 @@ func New(permStore permissions.PermissionsStore, usersStore users.UserStore, log func (o *orgMode) MigrateToOrg(ctx echo.Context) error { ctx.Set(types.HandlerStartTime, time.Now()) - body := ctx.Get(string(types.OrgModeRequestBodyContextKey)).(*MigrateToOrgRequest) + body := ctx.Get(string(types.OrgModeRequestBodyContextKey)).(*types.MigrateToOrgRequest) if err := o.userStore.ConvertUserToOrg(ctx.Request().Context(), body.UserID); err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), @@ -67,25 +60,22 @@ func (o *orgMode) MigrateToOrg(ctx echo.Context) error { // AddUserToOrg implements OrgMode. func (o *orgMode) AddUserToOrg(ctx echo.Context) error { - body := ctx.Get(string(types.OrgModeRequestBodyContextKey)).(*types.Permissions) + body := ctx.Get(string(types.OrgModeRequestBodyContextKey)).(*types.AddUsersToOrgRequest) - user, err := o.userStore.GetUserByID(ctx.Request().Context(), body.UserID) - if err != nil { - echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ - "error": err.Error(), - }) - o.logger.Log(ctx, err).Send() - return echoErr + userIdsToCheck := make([]uuid.UUID, len(body.Users)) + for i, u := range body.Users { + userIdsToCheck[i] = u.ID } - if user.UserType != types.UserTypeRegular.String() { + ok := o.userStore.MatchUserType(ctx.Request().Context(), types.UserTypeRegular, userIdsToCheck...) + if !ok { + err := fmt.Errorf("invalid user ids in the request") echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ - "error": "only regular users can be added to an organization", + "error": err.Error(), }) o.logger.Log(ctx, err).Send() return echoErr } - if err := o.permissionsStore.AddPermissions(ctx.Request().Context(), body); err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), @@ -103,7 +93,7 @@ func (o *orgMode) AddUserToOrg(ctx echo.Context) error { // RemoveUserFromOrg implements OrgMode. func (o *orgMode) RemoveUserFromOrg(ctx echo.Context) error { - body := ctx.Get(string(types.OrgModeRequestBodyContextKey)).(*RemoveUserFromOrgRequest) + body := ctx.Get(string(types.OrgModeRequestBodyContextKey)).(*types.RemoveUserFromOrgRequest) if err := o.permissionsStore.RemoveUserFromOrg(ctx.Request().Context(), body.OrganizationID, body.UserID); err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ @@ -138,3 +128,31 @@ func (o *orgMode) UpdateUserPermissions(ctx echo.Context) error { return echoErr } + +func (o *orgMode) GetOrgUsers(ctx echo.Context) error { + orgID, err := uuid.Parse(ctx.QueryParam("org_id")) + if err != nil { + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ + "error": err.Error(), + }) + o.logger.Log(ctx, err).Send() + return echoErr + } + + orgMembers, err := o.userStore.GetOrgUsersByOrgID(ctx.Request().Context(), orgID) + if err != nil { + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ + "error": err.Error(), + }) + o.logger.Log(ctx, err).Send() + return echoErr + } + + if len(orgMembers) == 0 { + orgMembers = make([]*types.Permissions, 0) + } + + echoErr := ctx.JSON(http.StatusOK, orgMembers) + o.logger.Log(ctx, nil).Send() + return echoErr +} diff --git a/protos/services/yor/clair/v1/clair.proto b/protos/services/yor/clair/v1/clair.proto new file mode 100644 index 00000000..4de74470 --- /dev/null +++ b/protos/services/yor/clair/v1/clair.proto @@ -0,0 +1,121 @@ +syntax = "proto3"; + +package services.yor.clair.v1; +option go_package = "github.com/containerish/OpenRegistry/services/yor/clair/v1;clair"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; + +service ClairService { + rpc SubmitManifestToScan(SubmitManifestToScanRequest) returns (SubmitManifestToScanResponse) {} + rpc GetVulnerabilityReport(GetVulnerabilityReportRequest) returns (GetVulnerabilityReportResponse) {} +} + +message ClairReportPackage { + string id = 1; + string name = 2; + string version = 3; + string kind = 4; + string arch = 5; +} + +message SubmitManifestToScanResponse { + bool success = 1; + string manifest_hash = 2; + string state = 3; + string err = 4; + map packages = 5; + map distributions = 6; + map repository = 7; + map environments = 8; +} + +message ClairDescriptor { + string hash = 1; + string uri = 2; + map headers = 3; +} + +message SubmitManifestToScanRequest { + string hash = 1; + repeated ClairDescriptor layers = 2; +} + +message GetVulnerabilityReportRequest { + string manifest_id = 1; +} + +message ClairPackageSource { + string id = 1; + string name = 2; + string version = 3; + string kind = 4; +} + +message ClairPackage { + string id = 1; + string name = 2; + string version = 3; + string kind = 4; + ClairPackageSource source = 5; + string arch = 6; +} + +message ClairDistribution { + string id = 1; + string did = 2; + string name = 3; + string version = 4; + string version_code_name = 5; + string version_id = 6; + string arch = 7; + string cpe = 8; + string pretty_name = 9; +} + +message ClairEnvironmentItem { + string package_db = 1; + string introduced_in = 2; + string distribution_id = 3; + repeated string repository_ids = 4; +} + +message ClairRepository { + string id = 1; +} + +message ClairVulnerability { + string id = 1; + string updater = 2; + string name = 3; + string description = 4; + google.protobuf.Timestamp issued = 5; + string links = 6; + string severity = 7; + string normalized_severity = 8; + ClairPackage package = 9; + ClairDistribution distribution = 10; + ClairRepository repository = 11; + string fixed_in_version = 12; +} + +message ClairEnrichment { + string id = 1; +} + +message ClairVulnerabilityIdList { + repeated string ids = 1; +} + +message GetVulnerabilityReportResponse { + string manifest_hash = 1; + string state = 2; + string err = 3; + bool success = 4; + map packages = 5; + map distributions = 6; + map environments = 7; + map package_vulnerabilities = 8; + ClairEnrichment enrichments = 9; + map repository = 10; + map vulnerabilities = 11; +} diff --git a/router/github.go b/router/github.go index 438b2164..9963d22f 100644 --- a/router/github.go +++ b/router/github.go @@ -2,6 +2,7 @@ package router import ( "fmt" + "net" "net/http" "github.com/containerish/OpenRegistry/config" @@ -18,7 +19,7 @@ import ( func RegisterGitHubRoutes( router *echo.Group, - cfg *config.Integration, + cfg *config.GithubIntegration, env config.Environment, authConfig *config.Auth, logger telemetry.Logger, @@ -44,10 +45,10 @@ func RegisterGitHubRoutes( usersStore, ) go func() { - hostPort := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port) - color.Green("connect-go gRPC running on: %s", hostPort) - if err := http.ListenAndServe(hostPort, h2c.NewHandler(githubMux, &http2.Server{})); err != nil { - color.Red("gRPC listen error: %s", err) + addr := net.JoinHostPort(cfg.Host, fmt.Sprintf("%d", cfg.Port)) + color.Green("connect-go GitHub Automation gRPC service running on: %s", addr) + if err := http.ListenAndServe(addr, h2c.NewHandler(githubMux, &http2.Server{})); err != nil { + color.Red("connect-go GitHub Automation service listen error: %s", err) } }() } diff --git a/router/orgmode.go b/router/orgmode.go index bd6d50a8..f254dbc7 100644 --- a/router/orgmode.go +++ b/router/orgmode.go @@ -8,6 +8,7 @@ import ( func RegisterOrgModeRoutes(router *echo.Group, svc orgmode.OrgMode) { router.POST("/migrate", svc.MigrateToOrg) router.POST("/users", svc.AddUserToOrg) + router.GET("/users", svc.GetOrgUsers) router.PATCH("/permissions/users", svc.UpdateUserPermissions) router.DELETE("/permissions/users/:orgId/:userId", svc.RemoveUserFromOrg) } diff --git a/router/router.go b/router/router.go index abb5ba4f..6d90c8b0 100644 --- a/router/router.go +++ b/router/router.go @@ -44,7 +44,7 @@ func Register( githubRouter := e.Group("/github") authRouter := e.Group(Auth) webauthnRouter := e.Group(Webauthn) - orgModeRouter := e.Group("/org", authApi.JWTRest(), orgModeApi.AllowOrgAdmin()) + orgModeRouter := baseAPIRouter.Group("/org", authApi.JWTRest(), orgModeApi.AllowOrgAdmin()) ociRouter := e.Group(V2, registryNamespaceValidator(logger), authApi.BasicAuth(), authApi.JWT()) userApiRouter := baseAPIRouter.Group("/users", authApi.JWTRest()) nsRouter := ociRouter.Group(Namespace, authApi.RepositoryPermissionsMiddleware()) @@ -61,6 +61,7 @@ func Register( RegisterExtensionsRoutes(ociRouter, registryApi, extensionsApi) RegisterWebauthnRoutes(webauthnRouter, webauthnApi) RegisterOrgModeRoutes(orgModeRouter, orgModeApi) + RegisterVulnScaningRoutes(cfg.Integrations.GetClairConfig(), logger) if cfg.Integrations.GetGithubConfig() != nil && cfg.Integrations.GetGithubConfig().Enabled { RegisterGitHubRoutes( diff --git a/router/vuln_scanning_routes.go b/router/vuln_scanning_routes.go new file mode 100644 index 00000000..a051e142 --- /dev/null +++ b/router/vuln_scanning_routes.go @@ -0,0 +1,30 @@ +package router + +import ( + "fmt" + "net" + "net/http" + + "github.com/containerish/OpenRegistry/config" + "github.com/containerish/OpenRegistry/services/yor/clair/v1/server" + "github.com/containerish/OpenRegistry/telemetry" + "github.com/fatih/color" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" +) + +func RegisterVulnScaningRoutes( + config *config.ClairIntegration, + logger telemetry.Logger, +) { + if config != nil && config.Enabled { + clairApi := server.NewClairClient(config, logger) + go func() { + addr := net.JoinHostPort(config.Host, fmt.Sprintf("%d", config.Port)) + color.Green("connect-go Clair gRPC service running on: %s", addr) + if err := http.ListenAndServe(addr, h2c.NewHandler(clairApi, &http2.Server{})); err != nil { + color.Red("connect-go listen error: %s", err) + } + }() + } +} diff --git a/services/kon/github_actions/v1/server/server.go b/services/kon/github_actions/v1/server/server.go index 82e49197..ded25bf2 100644 --- a/services/kon/github_actions/v1/server/server.go +++ b/services/kon/github_actions/v1/server/server.go @@ -19,7 +19,7 @@ import ( type GitHubActionsServer struct { logger telemetry.Logger - config *config.Integration + config *config.GithubIntegration github *github.Client transport *ghinstallation.AppsTransport store automation.BuildAutomationStore @@ -33,7 +33,7 @@ type streamLogsJob struct { } func NewGithubActionsServer( - config *config.Integration, + config *config.GithubIntegration, authConfig *config.Auth, logger telemetry.Logger, store automation.BuildAutomationStore, diff --git a/services/yor/clair/v1/clair.pb.go b/services/yor/clair/v1/clair.pb.go new file mode 100644 index 00000000..28145af2 --- /dev/null +++ b/services/yor/clair/v1/clair.pb.go @@ -0,0 +1,1708 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: services/yor/clair/v1/clair.proto + +package clair + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + structpb "google.golang.org/protobuf/types/known/structpb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" +) + +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 ClairReportPackage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Kind string `protobuf:"bytes,4,opt,name=kind,proto3" json:"kind,omitempty"` + Arch string `protobuf:"bytes,5,opt,name=arch,proto3" json:"arch,omitempty"` +} + +func (x *ClairReportPackage) Reset() { + *x = ClairReportPackage{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairReportPackage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairReportPackage) ProtoMessage() {} + +func (x *ClairReportPackage) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairReportPackage.ProtoReflect.Descriptor instead. +func (*ClairReportPackage) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{0} +} + +func (x *ClairReportPackage) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ClairReportPackage) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ClairReportPackage) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *ClairReportPackage) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *ClairReportPackage) GetArch() string { + if x != nil { + return x.Arch + } + return "" +} + +type SubmitManifestToScanResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` + ManifestHash string `protobuf:"bytes,2,opt,name=manifest_hash,json=manifestHash,proto3" json:"manifest_hash,omitempty"` + State string `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` + Err string `protobuf:"bytes,4,opt,name=err,proto3" json:"err,omitempty"` + Packages map[string]*ClairReportPackage `protobuf:"bytes,5,rep,name=packages,proto3" json:"packages,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Distributions map[string]*ClairDistribution `protobuf:"bytes,6,rep,name=distributions,proto3" json:"distributions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Repository map[string]*ClairRepository `protobuf:"bytes,7,rep,name=repository,proto3" json:"repository,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Environments map[string]*structpb.ListValue `protobuf:"bytes,8,rep,name=environments,proto3" json:"environments,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *SubmitManifestToScanResponse) Reset() { + *x = SubmitManifestToScanResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SubmitManifestToScanResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubmitManifestToScanResponse) ProtoMessage() {} + +func (x *SubmitManifestToScanResponse) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubmitManifestToScanResponse.ProtoReflect.Descriptor instead. +func (*SubmitManifestToScanResponse) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{1} +} + +func (x *SubmitManifestToScanResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *SubmitManifestToScanResponse) GetManifestHash() string { + if x != nil { + return x.ManifestHash + } + return "" +} + +func (x *SubmitManifestToScanResponse) GetState() string { + if x != nil { + return x.State + } + return "" +} + +func (x *SubmitManifestToScanResponse) GetErr() string { + if x != nil { + return x.Err + } + return "" +} + +func (x *SubmitManifestToScanResponse) GetPackages() map[string]*ClairReportPackage { + if x != nil { + return x.Packages + } + return nil +} + +func (x *SubmitManifestToScanResponse) GetDistributions() map[string]*ClairDistribution { + if x != nil { + return x.Distributions + } + return nil +} + +func (x *SubmitManifestToScanResponse) GetRepository() map[string]*ClairRepository { + if x != nil { + return x.Repository + } + return nil +} + +func (x *SubmitManifestToScanResponse) GetEnvironments() map[string]*structpb.ListValue { + if x != nil { + return x.Environments + } + return nil +} + +type ClairDescriptor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Uri string `protobuf:"bytes,2,opt,name=uri,proto3" json:"uri,omitempty"` + Headers map[string]*structpb.ListValue `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *ClairDescriptor) Reset() { + *x = ClairDescriptor{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairDescriptor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairDescriptor) ProtoMessage() {} + +func (x *ClairDescriptor) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairDescriptor.ProtoReflect.Descriptor instead. +func (*ClairDescriptor) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{2} +} + +func (x *ClairDescriptor) GetHash() string { + if x != nil { + return x.Hash + } + return "" +} + +func (x *ClairDescriptor) GetUri() string { + if x != nil { + return x.Uri + } + return "" +} + +func (x *ClairDescriptor) GetHeaders() map[string]*structpb.ListValue { + if x != nil { + return x.Headers + } + return nil +} + +type SubmitManifestToScanRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Layers []*ClairDescriptor `protobuf:"bytes,2,rep,name=layers,proto3" json:"layers,omitempty"` +} + +func (x *SubmitManifestToScanRequest) Reset() { + *x = SubmitManifestToScanRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SubmitManifestToScanRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubmitManifestToScanRequest) ProtoMessage() {} + +func (x *SubmitManifestToScanRequest) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubmitManifestToScanRequest.ProtoReflect.Descriptor instead. +func (*SubmitManifestToScanRequest) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{3} +} + +func (x *SubmitManifestToScanRequest) GetHash() string { + if x != nil { + return x.Hash + } + return "" +} + +func (x *SubmitManifestToScanRequest) GetLayers() []*ClairDescriptor { + if x != nil { + return x.Layers + } + return nil +} + +type GetVulnerabilityReportRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ManifestId string `protobuf:"bytes,1,opt,name=manifest_id,json=manifestId,proto3" json:"manifest_id,omitempty"` +} + +func (x *GetVulnerabilityReportRequest) Reset() { + *x = GetVulnerabilityReportRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetVulnerabilityReportRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVulnerabilityReportRequest) ProtoMessage() {} + +func (x *GetVulnerabilityReportRequest) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetVulnerabilityReportRequest.ProtoReflect.Descriptor instead. +func (*GetVulnerabilityReportRequest) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{4} +} + +func (x *GetVulnerabilityReportRequest) GetManifestId() string { + if x != nil { + return x.ManifestId + } + return "" +} + +type ClairPackageSource struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Kind string `protobuf:"bytes,4,opt,name=kind,proto3" json:"kind,omitempty"` +} + +func (x *ClairPackageSource) Reset() { + *x = ClairPackageSource{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairPackageSource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairPackageSource) ProtoMessage() {} + +func (x *ClairPackageSource) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairPackageSource.ProtoReflect.Descriptor instead. +func (*ClairPackageSource) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{5} +} + +func (x *ClairPackageSource) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ClairPackageSource) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ClairPackageSource) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *ClairPackageSource) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +type ClairPackage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Kind string `protobuf:"bytes,4,opt,name=kind,proto3" json:"kind,omitempty"` + Source *ClairPackageSource `protobuf:"bytes,5,opt,name=source,proto3" json:"source,omitempty"` + Arch string `protobuf:"bytes,6,opt,name=arch,proto3" json:"arch,omitempty"` +} + +func (x *ClairPackage) Reset() { + *x = ClairPackage{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairPackage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairPackage) ProtoMessage() {} + +func (x *ClairPackage) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairPackage.ProtoReflect.Descriptor instead. +func (*ClairPackage) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{6} +} + +func (x *ClairPackage) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ClairPackage) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ClairPackage) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *ClairPackage) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *ClairPackage) GetSource() *ClairPackageSource { + if x != nil { + return x.Source + } + return nil +} + +func (x *ClairPackage) GetArch() string { + if x != nil { + return x.Arch + } + return "" +} + +type ClairDistribution struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Did string `protobuf:"bytes,2,opt,name=did,proto3" json:"did,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + VersionCodeName string `protobuf:"bytes,5,opt,name=version_code_name,json=versionCodeName,proto3" json:"version_code_name,omitempty"` + VersionId string `protobuf:"bytes,6,opt,name=version_id,json=versionId,proto3" json:"version_id,omitempty"` + Arch string `protobuf:"bytes,7,opt,name=arch,proto3" json:"arch,omitempty"` + Cpe string `protobuf:"bytes,8,opt,name=cpe,proto3" json:"cpe,omitempty"` + PrettyName string `protobuf:"bytes,9,opt,name=pretty_name,json=prettyName,proto3" json:"pretty_name,omitempty"` +} + +func (x *ClairDistribution) Reset() { + *x = ClairDistribution{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairDistribution) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairDistribution) ProtoMessage() {} + +func (x *ClairDistribution) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairDistribution.ProtoReflect.Descriptor instead. +func (*ClairDistribution) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{7} +} + +func (x *ClairDistribution) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ClairDistribution) GetDid() string { + if x != nil { + return x.Did + } + return "" +} + +func (x *ClairDistribution) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ClairDistribution) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *ClairDistribution) GetVersionCodeName() string { + if x != nil { + return x.VersionCodeName + } + return "" +} + +func (x *ClairDistribution) GetVersionId() string { + if x != nil { + return x.VersionId + } + return "" +} + +func (x *ClairDistribution) GetArch() string { + if x != nil { + return x.Arch + } + return "" +} + +func (x *ClairDistribution) GetCpe() string { + if x != nil { + return x.Cpe + } + return "" +} + +func (x *ClairDistribution) GetPrettyName() string { + if x != nil { + return x.PrettyName + } + return "" +} + +type ClairEnvironmentItem struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PackageDb string `protobuf:"bytes,1,opt,name=package_db,json=packageDb,proto3" json:"package_db,omitempty"` + IntroducedIn string `protobuf:"bytes,2,opt,name=introduced_in,json=introducedIn,proto3" json:"introduced_in,omitempty"` + DistributionId string `protobuf:"bytes,3,opt,name=distribution_id,json=distributionId,proto3" json:"distribution_id,omitempty"` + RepositoryIds []string `protobuf:"bytes,4,rep,name=repository_ids,json=repositoryIds,proto3" json:"repository_ids,omitempty"` +} + +func (x *ClairEnvironmentItem) Reset() { + *x = ClairEnvironmentItem{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairEnvironmentItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairEnvironmentItem) ProtoMessage() {} + +func (x *ClairEnvironmentItem) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairEnvironmentItem.ProtoReflect.Descriptor instead. +func (*ClairEnvironmentItem) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{8} +} + +func (x *ClairEnvironmentItem) GetPackageDb() string { + if x != nil { + return x.PackageDb + } + return "" +} + +func (x *ClairEnvironmentItem) GetIntroducedIn() string { + if x != nil { + return x.IntroducedIn + } + return "" +} + +func (x *ClairEnvironmentItem) GetDistributionId() string { + if x != nil { + return x.DistributionId + } + return "" +} + +func (x *ClairEnvironmentItem) GetRepositoryIds() []string { + if x != nil { + return x.RepositoryIds + } + return nil +} + +type ClairRepository struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *ClairRepository) Reset() { + *x = ClairRepository{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairRepository) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairRepository) ProtoMessage() {} + +func (x *ClairRepository) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairRepository.ProtoReflect.Descriptor instead. +func (*ClairRepository) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{9} +} + +func (x *ClairRepository) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type ClairVulnerability struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Updater string `protobuf:"bytes,2,opt,name=updater,proto3" json:"updater,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` + Issued *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=issued,proto3" json:"issued,omitempty"` + Links string `protobuf:"bytes,6,opt,name=links,proto3" json:"links,omitempty"` + Severity string `protobuf:"bytes,7,opt,name=severity,proto3" json:"severity,omitempty"` + NormalizedSeverity string `protobuf:"bytes,8,opt,name=normalized_severity,json=normalizedSeverity,proto3" json:"normalized_severity,omitempty"` + Package *ClairPackage `protobuf:"bytes,9,opt,name=package,proto3" json:"package,omitempty"` + Distribution *ClairDistribution `protobuf:"bytes,10,opt,name=distribution,proto3" json:"distribution,omitempty"` + Repository *ClairRepository `protobuf:"bytes,11,opt,name=repository,proto3" json:"repository,omitempty"` + FixedInVersion string `protobuf:"bytes,12,opt,name=fixed_in_version,json=fixedInVersion,proto3" json:"fixed_in_version,omitempty"` +} + +func (x *ClairVulnerability) Reset() { + *x = ClairVulnerability{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairVulnerability) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairVulnerability) ProtoMessage() {} + +func (x *ClairVulnerability) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairVulnerability.ProtoReflect.Descriptor instead. +func (*ClairVulnerability) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{10} +} + +func (x *ClairVulnerability) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *ClairVulnerability) GetUpdater() string { + if x != nil { + return x.Updater + } + return "" +} + +func (x *ClairVulnerability) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ClairVulnerability) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *ClairVulnerability) GetIssued() *timestamppb.Timestamp { + if x != nil { + return x.Issued + } + return nil +} + +func (x *ClairVulnerability) GetLinks() string { + if x != nil { + return x.Links + } + return "" +} + +func (x *ClairVulnerability) GetSeverity() string { + if x != nil { + return x.Severity + } + return "" +} + +func (x *ClairVulnerability) GetNormalizedSeverity() string { + if x != nil { + return x.NormalizedSeverity + } + return "" +} + +func (x *ClairVulnerability) GetPackage() *ClairPackage { + if x != nil { + return x.Package + } + return nil +} + +func (x *ClairVulnerability) GetDistribution() *ClairDistribution { + if x != nil { + return x.Distribution + } + return nil +} + +func (x *ClairVulnerability) GetRepository() *ClairRepository { + if x != nil { + return x.Repository + } + return nil +} + +func (x *ClairVulnerability) GetFixedInVersion() string { + if x != nil { + return x.FixedInVersion + } + return "" +} + +type ClairEnrichment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *ClairEnrichment) Reset() { + *x = ClairEnrichment{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairEnrichment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairEnrichment) ProtoMessage() {} + +func (x *ClairEnrichment) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairEnrichment.ProtoReflect.Descriptor instead. +func (*ClairEnrichment) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{11} +} + +func (x *ClairEnrichment) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type ClairVulnerabilityIdList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` +} + +func (x *ClairVulnerabilityIdList) Reset() { + *x = ClairVulnerabilityIdList{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairVulnerabilityIdList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairVulnerabilityIdList) ProtoMessage() {} + +func (x *ClairVulnerabilityIdList) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairVulnerabilityIdList.ProtoReflect.Descriptor instead. +func (*ClairVulnerabilityIdList) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{12} +} + +func (x *ClairVulnerabilityIdList) GetIds() []string { + if x != nil { + return x.Ids + } + return nil +} + +type GetVulnerabilityReportResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ManifestHash string `protobuf:"bytes,1,opt,name=manifest_hash,json=manifestHash,proto3" json:"manifest_hash,omitempty"` + State string `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"` + Err string `protobuf:"bytes,3,opt,name=err,proto3" json:"err,omitempty"` + Success bool `protobuf:"varint,4,opt,name=success,proto3" json:"success,omitempty"` + Packages map[string]*ClairPackage `protobuf:"bytes,5,rep,name=packages,proto3" json:"packages,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Distributions map[string]*ClairDistribution `protobuf:"bytes,6,rep,name=distributions,proto3" json:"distributions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Environments map[string]*structpb.ListValue `protobuf:"bytes,7,rep,name=environments,proto3" json:"environments,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + PackageVulnerabilities map[string]*structpb.ListValue `protobuf:"bytes,8,rep,name=package_vulnerabilities,json=packageVulnerabilities,proto3" json:"package_vulnerabilities,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Enrichments *ClairEnrichment `protobuf:"bytes,9,opt,name=enrichments,proto3" json:"enrichments,omitempty"` + Repository map[string]*ClairRepository `protobuf:"bytes,10,rep,name=repository,proto3" json:"repository,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Vulnerabilities map[string]*ClairVulnerability `protobuf:"bytes,11,rep,name=vulnerabilities,proto3" json:"vulnerabilities,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *GetVulnerabilityReportResponse) Reset() { + *x = GetVulnerabilityReportResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetVulnerabilityReportResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVulnerabilityReportResponse) ProtoMessage() {} + +func (x *GetVulnerabilityReportResponse) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetVulnerabilityReportResponse.ProtoReflect.Descriptor instead. +func (*GetVulnerabilityReportResponse) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{13} +} + +func (x *GetVulnerabilityReportResponse) GetManifestHash() string { + if x != nil { + return x.ManifestHash + } + return "" +} + +func (x *GetVulnerabilityReportResponse) GetState() string { + if x != nil { + return x.State + } + return "" +} + +func (x *GetVulnerabilityReportResponse) GetErr() string { + if x != nil { + return x.Err + } + return "" +} + +func (x *GetVulnerabilityReportResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *GetVulnerabilityReportResponse) GetPackages() map[string]*ClairPackage { + if x != nil { + return x.Packages + } + return nil +} + +func (x *GetVulnerabilityReportResponse) GetDistributions() map[string]*ClairDistribution { + if x != nil { + return x.Distributions + } + return nil +} + +func (x *GetVulnerabilityReportResponse) GetEnvironments() map[string]*structpb.ListValue { + if x != nil { + return x.Environments + } + return nil +} + +func (x *GetVulnerabilityReportResponse) GetPackageVulnerabilities() map[string]*structpb.ListValue { + if x != nil { + return x.PackageVulnerabilities + } + return nil +} + +func (x *GetVulnerabilityReportResponse) GetEnrichments() *ClairEnrichment { + if x != nil { + return x.Enrichments + } + return nil +} + +func (x *GetVulnerabilityReportResponse) GetRepository() map[string]*ClairRepository { + if x != nil { + return x.Repository + } + return nil +} + +func (x *GetVulnerabilityReportResponse) GetVulnerabilities() map[string]*ClairVulnerability { + if x != nil { + return x.Vulnerabilities + } + return nil +} + +var File_services_yor_clair_v1_clair_proto protoreflect.FileDescriptor + +var file_services_yor_clair_v1_clair_proto_rawDesc = []byte{ + 0x0a, 0x21, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x79, 0x6f, 0x72, 0x2f, 0x63, + 0x6c, 0x61, 0x69, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, + 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x7a, 0x0a, 0x12, 0x43, 0x6c, 0x61, + 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0xba, 0x07, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, + 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, + 0x72, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x72, 0x72, 0x12, 0x5d, 0x0a, + 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x41, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, + 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, + 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x6c, 0x0a, 0x0d, + 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, + 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x64, 0x69, 0x73, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x63, 0x0a, 0x0a, 0x72, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, + 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, + 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, + 0x69, 0x0a, 0x0c, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, + 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, + 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x65, 0x6e, + 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x66, 0x0a, 0x0d, 0x50, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3f, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x1a, 0x6a, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65, + 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, + 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5b, 0x0a, 0x11, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0xde, 0x01, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, + 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x4d, 0x0a, 0x07, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, + 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x56, 0x0a, 0x0c, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0x71, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, + 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3e, 0x0a, 0x06, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6c, 0x61, 0x69, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x06, + 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x22, 0x40, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, + 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x6e, 0x69, 0x66, + 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, + 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x66, 0x0a, 0x12, 0x43, 0x6c, 0x61, 0x69, + 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, + 0x22, 0xb7, 0x01, 0x0a, 0x0c, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, + 0x69, 0x6e, 0x64, 0x12, 0x41, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, + 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, + 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0xf5, 0x01, 0x0a, 0x11, 0x43, + 0x6c, 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, + 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, + 0x72, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x12, + 0x10, 0x0a, 0x03, 0x63, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x70, + 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x4e, 0x61, + 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, 0x14, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x45, 0x6e, 0x76, 0x69, + 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x44, 0x62, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, + 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x49, 0x6e, 0x12, + 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x73, 0x22, + 0x21, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x8a, 0x04, 0x0a, 0x12, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x56, 0x75, 0x6c, 0x6e, + 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x06, 0x69, 0x73, 0x73, + 0x75, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x69, + 0x6e, 0x6b, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, + 0x2f, 0x0a, 0x13, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x73, 0x65, + 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6e, 0x6f, + 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, + 0x12, 0x3d, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, + 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, + 0x4c, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, + 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0c, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, + 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, + 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x69, + 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x66, 0x69, 0x78, 0x65, 0x64, 0x49, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, + 0x21, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x45, 0x6e, 0x72, 0x69, 0x63, 0x68, 0x6d, 0x65, + 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x2c, 0x0a, 0x18, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x56, 0x75, 0x6c, 0x6e, 0x65, + 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, + 0x22, 0xe1, 0x0b, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, + 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x6e, 0x69, + 0x66, 0x65, 0x73, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x72, 0x72, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x5f, 0x0a, 0x08, 0x70, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x6e, 0x0a, 0x0d, 0x64, + 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, + 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, + 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x64, 0x69, + 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x6b, 0x0a, 0x0c, 0x65, + 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x47, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, + 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, + 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x65, 0x6e, 0x76, 0x69, + 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x8a, 0x01, 0x0a, 0x17, 0x70, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x51, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x16, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x0b, 0x65, 0x6e, 0x72, 0x69, 0x63, 0x68, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x45, 0x6e, 0x72, 0x69, 0x63, 0x68, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x72, 0x69, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, + 0x65, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x0a, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, + 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, + 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x74, 0x0a, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, + 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x4a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, + 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, + 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x76, 0x75, 0x6c, + 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x60, 0x0a, 0x0d, + 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, + 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x61, 0x63, 0x6b, + 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6a, + 0x0a, 0x12, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, + 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5b, 0x0a, 0x11, 0x45, 0x6e, + 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65, 0x0a, 0x1b, 0x50, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65, + 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, + 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6d, 0x0a, 0x14, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, + 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x56, 0x75, 0x6c, 0x6e, + 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x32, 0x9c, 0x02, 0x0a, 0x0c, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x32, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, + 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, + 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, + 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x87, 0x01, 0x0a, 0x16, 0x47, 0x65, + 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x12, 0x34, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x42, 0xe0, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, + 0x31, 0x42, 0x0a, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x69, 0x73, 0x68, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x79, + 0x6f, 0x72, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6c, 0x61, 0x69, + 0x72, 0xa2, 0x02, 0x03, 0x53, 0x59, 0x43, 0xaa, 0x02, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x59, 0x6f, 0x72, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x56, 0x31, 0xca, + 0x02, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x59, 0x6f, 0x72, 0x5c, 0x43, + 0x6c, 0x61, 0x69, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x21, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x5c, 0x59, 0x6f, 0x72, 0x5c, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x5c, 0x56, 0x31, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x18, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x3a, 0x59, 0x6f, 0x72, 0x3a, 0x3a, 0x43, 0x6c, 0x61, + 0x69, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_services_yor_clair_v1_clair_proto_rawDescOnce sync.Once + file_services_yor_clair_v1_clair_proto_rawDescData = file_services_yor_clair_v1_clair_proto_rawDesc +) + +func file_services_yor_clair_v1_clair_proto_rawDescGZIP() []byte { + file_services_yor_clair_v1_clair_proto_rawDescOnce.Do(func() { + file_services_yor_clair_v1_clair_proto_rawDescData = protoimpl.X.CompressGZIP(file_services_yor_clair_v1_clair_proto_rawDescData) + }) + return file_services_yor_clair_v1_clair_proto_rawDescData +} + +var file_services_yor_clair_v1_clair_proto_msgTypes = make([]protoimpl.MessageInfo, 25) +var file_services_yor_clair_v1_clair_proto_goTypes = []interface{}{ + (*ClairReportPackage)(nil), // 0: services.yor.clair.v1.ClairReportPackage + (*SubmitManifestToScanResponse)(nil), // 1: services.yor.clair.v1.SubmitManifestToScanResponse + (*ClairDescriptor)(nil), // 2: services.yor.clair.v1.ClairDescriptor + (*SubmitManifestToScanRequest)(nil), // 3: services.yor.clair.v1.SubmitManifestToScanRequest + (*GetVulnerabilityReportRequest)(nil), // 4: services.yor.clair.v1.GetVulnerabilityReportRequest + (*ClairPackageSource)(nil), // 5: services.yor.clair.v1.ClairPackageSource + (*ClairPackage)(nil), // 6: services.yor.clair.v1.ClairPackage + (*ClairDistribution)(nil), // 7: services.yor.clair.v1.ClairDistribution + (*ClairEnvironmentItem)(nil), // 8: services.yor.clair.v1.ClairEnvironmentItem + (*ClairRepository)(nil), // 9: services.yor.clair.v1.ClairRepository + (*ClairVulnerability)(nil), // 10: services.yor.clair.v1.ClairVulnerability + (*ClairEnrichment)(nil), // 11: services.yor.clair.v1.ClairEnrichment + (*ClairVulnerabilityIdList)(nil), // 12: services.yor.clair.v1.ClairVulnerabilityIdList + (*GetVulnerabilityReportResponse)(nil), // 13: services.yor.clair.v1.GetVulnerabilityReportResponse + nil, // 14: services.yor.clair.v1.SubmitManifestToScanResponse.PackagesEntry + nil, // 15: services.yor.clair.v1.SubmitManifestToScanResponse.DistributionsEntry + nil, // 16: services.yor.clair.v1.SubmitManifestToScanResponse.RepositoryEntry + nil, // 17: services.yor.clair.v1.SubmitManifestToScanResponse.EnvironmentsEntry + nil, // 18: services.yor.clair.v1.ClairDescriptor.HeadersEntry + nil, // 19: services.yor.clair.v1.GetVulnerabilityReportResponse.PackagesEntry + nil, // 20: services.yor.clair.v1.GetVulnerabilityReportResponse.DistributionsEntry + nil, // 21: services.yor.clair.v1.GetVulnerabilityReportResponse.EnvironmentsEntry + nil, // 22: services.yor.clair.v1.GetVulnerabilityReportResponse.PackageVulnerabilitiesEntry + nil, // 23: services.yor.clair.v1.GetVulnerabilityReportResponse.RepositoryEntry + nil, // 24: services.yor.clair.v1.GetVulnerabilityReportResponse.VulnerabilitiesEntry + (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp + (*structpb.ListValue)(nil), // 26: google.protobuf.ListValue +} +var file_services_yor_clair_v1_clair_proto_depIdxs = []int32{ + 14, // 0: services.yor.clair.v1.SubmitManifestToScanResponse.packages:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.PackagesEntry + 15, // 1: services.yor.clair.v1.SubmitManifestToScanResponse.distributions:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.DistributionsEntry + 16, // 2: services.yor.clair.v1.SubmitManifestToScanResponse.repository:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.RepositoryEntry + 17, // 3: services.yor.clair.v1.SubmitManifestToScanResponse.environments:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.EnvironmentsEntry + 18, // 4: services.yor.clair.v1.ClairDescriptor.headers:type_name -> services.yor.clair.v1.ClairDescriptor.HeadersEntry + 2, // 5: services.yor.clair.v1.SubmitManifestToScanRequest.layers:type_name -> services.yor.clair.v1.ClairDescriptor + 5, // 6: services.yor.clair.v1.ClairPackage.source:type_name -> services.yor.clair.v1.ClairPackageSource + 25, // 7: services.yor.clair.v1.ClairVulnerability.issued:type_name -> google.protobuf.Timestamp + 6, // 8: services.yor.clair.v1.ClairVulnerability.package:type_name -> services.yor.clair.v1.ClairPackage + 7, // 9: services.yor.clair.v1.ClairVulnerability.distribution:type_name -> services.yor.clair.v1.ClairDistribution + 9, // 10: services.yor.clair.v1.ClairVulnerability.repository:type_name -> services.yor.clair.v1.ClairRepository + 19, // 11: services.yor.clair.v1.GetVulnerabilityReportResponse.packages:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.PackagesEntry + 20, // 12: services.yor.clair.v1.GetVulnerabilityReportResponse.distributions:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.DistributionsEntry + 21, // 13: services.yor.clair.v1.GetVulnerabilityReportResponse.environments:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.EnvironmentsEntry + 22, // 14: services.yor.clair.v1.GetVulnerabilityReportResponse.package_vulnerabilities:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.PackageVulnerabilitiesEntry + 11, // 15: services.yor.clair.v1.GetVulnerabilityReportResponse.enrichments:type_name -> services.yor.clair.v1.ClairEnrichment + 23, // 16: services.yor.clair.v1.GetVulnerabilityReportResponse.repository:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.RepositoryEntry + 24, // 17: services.yor.clair.v1.GetVulnerabilityReportResponse.vulnerabilities:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.VulnerabilitiesEntry + 0, // 18: services.yor.clair.v1.SubmitManifestToScanResponse.PackagesEntry.value:type_name -> services.yor.clair.v1.ClairReportPackage + 7, // 19: services.yor.clair.v1.SubmitManifestToScanResponse.DistributionsEntry.value:type_name -> services.yor.clair.v1.ClairDistribution + 9, // 20: services.yor.clair.v1.SubmitManifestToScanResponse.RepositoryEntry.value:type_name -> services.yor.clair.v1.ClairRepository + 26, // 21: services.yor.clair.v1.SubmitManifestToScanResponse.EnvironmentsEntry.value:type_name -> google.protobuf.ListValue + 26, // 22: services.yor.clair.v1.ClairDescriptor.HeadersEntry.value:type_name -> google.protobuf.ListValue + 6, // 23: services.yor.clair.v1.GetVulnerabilityReportResponse.PackagesEntry.value:type_name -> services.yor.clair.v1.ClairPackage + 7, // 24: services.yor.clair.v1.GetVulnerabilityReportResponse.DistributionsEntry.value:type_name -> services.yor.clair.v1.ClairDistribution + 26, // 25: services.yor.clair.v1.GetVulnerabilityReportResponse.EnvironmentsEntry.value:type_name -> google.protobuf.ListValue + 26, // 26: services.yor.clair.v1.GetVulnerabilityReportResponse.PackageVulnerabilitiesEntry.value:type_name -> google.protobuf.ListValue + 9, // 27: services.yor.clair.v1.GetVulnerabilityReportResponse.RepositoryEntry.value:type_name -> services.yor.clair.v1.ClairRepository + 10, // 28: services.yor.clair.v1.GetVulnerabilityReportResponse.VulnerabilitiesEntry.value:type_name -> services.yor.clair.v1.ClairVulnerability + 3, // 29: services.yor.clair.v1.ClairService.SubmitManifestToScan:input_type -> services.yor.clair.v1.SubmitManifestToScanRequest + 4, // 30: services.yor.clair.v1.ClairService.GetVulnerabilityReport:input_type -> services.yor.clair.v1.GetVulnerabilityReportRequest + 1, // 31: services.yor.clair.v1.ClairService.SubmitManifestToScan:output_type -> services.yor.clair.v1.SubmitManifestToScanResponse + 13, // 32: services.yor.clair.v1.ClairService.GetVulnerabilityReport:output_type -> services.yor.clair.v1.GetVulnerabilityReportResponse + 31, // [31:33] is the sub-list for method output_type + 29, // [29:31] is the sub-list for method input_type + 29, // [29:29] is the sub-list for extension type_name + 29, // [29:29] is the sub-list for extension extendee + 0, // [0:29] is the sub-list for field type_name +} + +func init() { file_services_yor_clair_v1_clair_proto_init() } +func file_services_yor_clair_v1_clair_proto_init() { + if File_services_yor_clair_v1_clair_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_services_yor_clair_v1_clair_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairReportPackage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SubmitManifestToScanResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairDescriptor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SubmitManifestToScanRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetVulnerabilityReportRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairPackageSource); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairPackage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairDistribution); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairEnvironmentItem); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairRepository); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairVulnerability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairEnrichment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairVulnerabilityIdList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetVulnerabilityReportResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_services_yor_clair_v1_clair_proto_rawDesc, + NumEnums: 0, + NumMessages: 25, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_services_yor_clair_v1_clair_proto_goTypes, + DependencyIndexes: file_services_yor_clair_v1_clair_proto_depIdxs, + MessageInfos: file_services_yor_clair_v1_clair_proto_msgTypes, + }.Build() + File_services_yor_clair_v1_clair_proto = out.File + file_services_yor_clair_v1_clair_proto_rawDesc = nil + file_services_yor_clair_v1_clair_proto_goTypes = nil + file_services_yor_clair_v1_clair_proto_depIdxs = nil +} diff --git a/services/yor/clair/v1/clair.pb.validate.go b/services/yor/clair/v1/clair.pb.validate.go new file mode 100644 index 00000000..199e7e39 --- /dev/null +++ b/services/yor/clair/v1/clair.pb.validate.go @@ -0,0 +1,2269 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: services/yor/clair/v1/clair.proto + +package clair + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) + +// Validate checks the field values on ClairReportPackage with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ClairReportPackage) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairReportPackage with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairReportPackageMultiError, or nil if none found. +func (m *ClairReportPackage) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairReportPackage) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + // no validation rules for Name + + // no validation rules for Version + + // no validation rules for Kind + + // no validation rules for Arch + + if len(errors) > 0 { + return ClairReportPackageMultiError(errors) + } + + return nil +} + +// ClairReportPackageMultiError is an error wrapping multiple validation errors +// returned by ClairReportPackage.ValidateAll() if the designated constraints +// aren't met. +type ClairReportPackageMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairReportPackageMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairReportPackageMultiError) AllErrors() []error { return m } + +// ClairReportPackageValidationError is the validation error returned by +// ClairReportPackage.Validate if the designated constraints aren't met. +type ClairReportPackageValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairReportPackageValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairReportPackageValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairReportPackageValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairReportPackageValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairReportPackageValidationError) ErrorName() string { + return "ClairReportPackageValidationError" +} + +// Error satisfies the builtin error interface +func (e ClairReportPackageValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairReportPackage.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairReportPackageValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairReportPackageValidationError{} + +// Validate checks the field values on SubmitManifestToScanResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *SubmitManifestToScanResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on SubmitManifestToScanResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// SubmitManifestToScanResponseMultiError, or nil if none found. +func (m *SubmitManifestToScanResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *SubmitManifestToScanResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Success + + // no validation rules for ManifestHash + + // no validation rules for State + + // no validation rules for Err + + { + sorted_keys := make([]string, len(m.GetPackages())) + i := 0 + for key := range m.GetPackages() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetPackages()[key] + _ = val + + // no validation rules for Packages[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Packages[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Packages[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Packages[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + { + sorted_keys := make([]string, len(m.GetDistributions())) + i := 0 + for key := range m.GetDistributions() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetDistributions()[key] + _ = val + + // no validation rules for Distributions[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Distributions[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Distributions[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Distributions[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + { + sorted_keys := make([]string, len(m.GetRepository())) + i := 0 + for key := range m.GetRepository() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetRepository()[key] + _ = val + + // no validation rules for Repository[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Repository[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Repository[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Repository[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + { + sorted_keys := make([]string, len(m.GetEnvironments())) + i := 0 + for key := range m.GetEnvironments() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetEnvironments()[key] + _ = val + + // no validation rules for Environments[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Environments[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Environments[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SubmitManifestToScanResponseValidationError{ + field: fmt.Sprintf("Environments[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + if len(errors) > 0 { + return SubmitManifestToScanResponseMultiError(errors) + } + + return nil +} + +// SubmitManifestToScanResponseMultiError is an error wrapping multiple +// validation errors returned by SubmitManifestToScanResponse.ValidateAll() if +// the designated constraints aren't met. +type SubmitManifestToScanResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m SubmitManifestToScanResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m SubmitManifestToScanResponseMultiError) AllErrors() []error { return m } + +// SubmitManifestToScanResponseValidationError is the validation error returned +// by SubmitManifestToScanResponse.Validate if the designated constraints +// aren't met. +type SubmitManifestToScanResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e SubmitManifestToScanResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e SubmitManifestToScanResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e SubmitManifestToScanResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e SubmitManifestToScanResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e SubmitManifestToScanResponseValidationError) ErrorName() string { + return "SubmitManifestToScanResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e SubmitManifestToScanResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSubmitManifestToScanResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = SubmitManifestToScanResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = SubmitManifestToScanResponseValidationError{} + +// Validate checks the field values on ClairDescriptor with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *ClairDescriptor) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairDescriptor with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairDescriptorMultiError, or nil if none found. +func (m *ClairDescriptor) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairDescriptor) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Hash + + // no validation rules for Uri + + { + sorted_keys := make([]string, len(m.GetHeaders())) + i := 0 + for key := range m.GetHeaders() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetHeaders()[key] + _ = val + + // no validation rules for Headers[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ClairDescriptorValidationError{ + field: fmt.Sprintf("Headers[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ClairDescriptorValidationError{ + field: fmt.Sprintf("Headers[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClairDescriptorValidationError{ + field: fmt.Sprintf("Headers[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + if len(errors) > 0 { + return ClairDescriptorMultiError(errors) + } + + return nil +} + +// ClairDescriptorMultiError is an error wrapping multiple validation errors +// returned by ClairDescriptor.ValidateAll() if the designated constraints +// aren't met. +type ClairDescriptorMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairDescriptorMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairDescriptorMultiError) AllErrors() []error { return m } + +// ClairDescriptorValidationError is the validation error returned by +// ClairDescriptor.Validate if the designated constraints aren't met. +type ClairDescriptorValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairDescriptorValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairDescriptorValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairDescriptorValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairDescriptorValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairDescriptorValidationError) ErrorName() string { return "ClairDescriptorValidationError" } + +// Error satisfies the builtin error interface +func (e ClairDescriptorValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairDescriptor.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairDescriptorValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairDescriptorValidationError{} + +// Validate checks the field values on SubmitManifestToScanRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *SubmitManifestToScanRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on SubmitManifestToScanRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// SubmitManifestToScanRequestMultiError, or nil if none found. +func (m *SubmitManifestToScanRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *SubmitManifestToScanRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Hash + + for idx, item := range m.GetLayers() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, SubmitManifestToScanRequestValidationError{ + field: fmt.Sprintf("Layers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, SubmitManifestToScanRequestValidationError{ + field: fmt.Sprintf("Layers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return SubmitManifestToScanRequestValidationError{ + field: fmt.Sprintf("Layers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return SubmitManifestToScanRequestMultiError(errors) + } + + return nil +} + +// SubmitManifestToScanRequestMultiError is an error wrapping multiple +// validation errors returned by SubmitManifestToScanRequest.ValidateAll() if +// the designated constraints aren't met. +type SubmitManifestToScanRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m SubmitManifestToScanRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m SubmitManifestToScanRequestMultiError) AllErrors() []error { return m } + +// SubmitManifestToScanRequestValidationError is the validation error returned +// by SubmitManifestToScanRequest.Validate if the designated constraints +// aren't met. +type SubmitManifestToScanRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e SubmitManifestToScanRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e SubmitManifestToScanRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e SubmitManifestToScanRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e SubmitManifestToScanRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e SubmitManifestToScanRequestValidationError) ErrorName() string { + return "SubmitManifestToScanRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e SubmitManifestToScanRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sSubmitManifestToScanRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = SubmitManifestToScanRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = SubmitManifestToScanRequestValidationError{} + +// Validate checks the field values on GetVulnerabilityReportRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetVulnerabilityReportRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetVulnerabilityReportRequest with +// the rules defined in the proto definition for this message. If any rules +// are violated, the result is a list of violation errors wrapped in +// GetVulnerabilityReportRequestMultiError, or nil if none found. +func (m *GetVulnerabilityReportRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GetVulnerabilityReportRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for ManifestId + + if len(errors) > 0 { + return GetVulnerabilityReportRequestMultiError(errors) + } + + return nil +} + +// GetVulnerabilityReportRequestMultiError is an error wrapping multiple +// validation errors returned by GetVulnerabilityReportRequest.ValidateAll() +// if the designated constraints aren't met. +type GetVulnerabilityReportRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetVulnerabilityReportRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetVulnerabilityReportRequestMultiError) AllErrors() []error { return m } + +// GetVulnerabilityReportRequestValidationError is the validation error +// returned by GetVulnerabilityReportRequest.Validate if the designated +// constraints aren't met. +type GetVulnerabilityReportRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetVulnerabilityReportRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetVulnerabilityReportRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetVulnerabilityReportRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetVulnerabilityReportRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetVulnerabilityReportRequestValidationError) ErrorName() string { + return "GetVulnerabilityReportRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GetVulnerabilityReportRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetVulnerabilityReportRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetVulnerabilityReportRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetVulnerabilityReportRequestValidationError{} + +// Validate checks the field values on ClairPackageSource with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ClairPackageSource) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairPackageSource with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairPackageSourceMultiError, or nil if none found. +func (m *ClairPackageSource) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairPackageSource) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + // no validation rules for Name + + // no validation rules for Version + + // no validation rules for Kind + + if len(errors) > 0 { + return ClairPackageSourceMultiError(errors) + } + + return nil +} + +// ClairPackageSourceMultiError is an error wrapping multiple validation errors +// returned by ClairPackageSource.ValidateAll() if the designated constraints +// aren't met. +type ClairPackageSourceMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairPackageSourceMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairPackageSourceMultiError) AllErrors() []error { return m } + +// ClairPackageSourceValidationError is the validation error returned by +// ClairPackageSource.Validate if the designated constraints aren't met. +type ClairPackageSourceValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairPackageSourceValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairPackageSourceValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairPackageSourceValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairPackageSourceValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairPackageSourceValidationError) ErrorName() string { + return "ClairPackageSourceValidationError" +} + +// Error satisfies the builtin error interface +func (e ClairPackageSourceValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairPackageSource.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairPackageSourceValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairPackageSourceValidationError{} + +// Validate checks the field values on ClairPackage with the rules defined in +// the proto definition for this message. If any rules are violated, the first +// error encountered is returned, or nil if there are no violations. +func (m *ClairPackage) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairPackage with the rules defined +// in the proto definition for this message. If any rules are violated, the +// result is a list of violation errors wrapped in ClairPackageMultiError, or +// nil if none found. +func (m *ClairPackage) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairPackage) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + // no validation rules for Name + + // no validation rules for Version + + // no validation rules for Kind + + if all { + switch v := interface{}(m.GetSource()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ClairPackageValidationError{ + field: "Source", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ClairPackageValidationError{ + field: "Source", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetSource()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClairPackageValidationError{ + field: "Source", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Arch + + if len(errors) > 0 { + return ClairPackageMultiError(errors) + } + + return nil +} + +// ClairPackageMultiError is an error wrapping multiple validation errors +// returned by ClairPackage.ValidateAll() if the designated constraints aren't met. +type ClairPackageMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairPackageMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairPackageMultiError) AllErrors() []error { return m } + +// ClairPackageValidationError is the validation error returned by +// ClairPackage.Validate if the designated constraints aren't met. +type ClairPackageValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairPackageValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairPackageValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairPackageValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairPackageValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairPackageValidationError) ErrorName() string { return "ClairPackageValidationError" } + +// Error satisfies the builtin error interface +func (e ClairPackageValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairPackage.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairPackageValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairPackageValidationError{} + +// Validate checks the field values on ClairDistribution with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *ClairDistribution) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairDistribution with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairDistributionMultiError, or nil if none found. +func (m *ClairDistribution) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairDistribution) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + // no validation rules for Did + + // no validation rules for Name + + // no validation rules for Version + + // no validation rules for VersionCodeName + + // no validation rules for VersionId + + // no validation rules for Arch + + // no validation rules for Cpe + + // no validation rules for PrettyName + + if len(errors) > 0 { + return ClairDistributionMultiError(errors) + } + + return nil +} + +// ClairDistributionMultiError is an error wrapping multiple validation errors +// returned by ClairDistribution.ValidateAll() if the designated constraints +// aren't met. +type ClairDistributionMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairDistributionMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairDistributionMultiError) AllErrors() []error { return m } + +// ClairDistributionValidationError is the validation error returned by +// ClairDistribution.Validate if the designated constraints aren't met. +type ClairDistributionValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairDistributionValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairDistributionValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairDistributionValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairDistributionValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairDistributionValidationError) ErrorName() string { + return "ClairDistributionValidationError" +} + +// Error satisfies the builtin error interface +func (e ClairDistributionValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairDistribution.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairDistributionValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairDistributionValidationError{} + +// Validate checks the field values on ClairEnvironmentItem with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ClairEnvironmentItem) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairEnvironmentItem with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairEnvironmentItemMultiError, or nil if none found. +func (m *ClairEnvironmentItem) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairEnvironmentItem) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for PackageDb + + // no validation rules for IntroducedIn + + // no validation rules for DistributionId + + if len(errors) > 0 { + return ClairEnvironmentItemMultiError(errors) + } + + return nil +} + +// ClairEnvironmentItemMultiError is an error wrapping multiple validation +// errors returned by ClairEnvironmentItem.ValidateAll() if the designated +// constraints aren't met. +type ClairEnvironmentItemMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairEnvironmentItemMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairEnvironmentItemMultiError) AllErrors() []error { return m } + +// ClairEnvironmentItemValidationError is the validation error returned by +// ClairEnvironmentItem.Validate if the designated constraints aren't met. +type ClairEnvironmentItemValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairEnvironmentItemValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairEnvironmentItemValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairEnvironmentItemValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairEnvironmentItemValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairEnvironmentItemValidationError) ErrorName() string { + return "ClairEnvironmentItemValidationError" +} + +// Error satisfies the builtin error interface +func (e ClairEnvironmentItemValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairEnvironmentItem.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairEnvironmentItemValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairEnvironmentItemValidationError{} + +// Validate checks the field values on ClairRepository with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *ClairRepository) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairRepository with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairRepositoryMultiError, or nil if none found. +func (m *ClairRepository) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairRepository) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + if len(errors) > 0 { + return ClairRepositoryMultiError(errors) + } + + return nil +} + +// ClairRepositoryMultiError is an error wrapping multiple validation errors +// returned by ClairRepository.ValidateAll() if the designated constraints +// aren't met. +type ClairRepositoryMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairRepositoryMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairRepositoryMultiError) AllErrors() []error { return m } + +// ClairRepositoryValidationError is the validation error returned by +// ClairRepository.Validate if the designated constraints aren't met. +type ClairRepositoryValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairRepositoryValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairRepositoryValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairRepositoryValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairRepositoryValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairRepositoryValidationError) ErrorName() string { return "ClairRepositoryValidationError" } + +// Error satisfies the builtin error interface +func (e ClairRepositoryValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairRepository.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairRepositoryValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairRepositoryValidationError{} + +// Validate checks the field values on ClairVulnerability with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ClairVulnerability) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairVulnerability with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairVulnerabilityMultiError, or nil if none found. +func (m *ClairVulnerability) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairVulnerability) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + // no validation rules for Updater + + // no validation rules for Name + + // no validation rules for Description + + if all { + switch v := interface{}(m.GetIssued()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ClairVulnerabilityValidationError{ + field: "Issued", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ClairVulnerabilityValidationError{ + field: "Issued", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetIssued()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClairVulnerabilityValidationError{ + field: "Issued", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for Links + + // no validation rules for Severity + + // no validation rules for NormalizedSeverity + + if all { + switch v := interface{}(m.GetPackage()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ClairVulnerabilityValidationError{ + field: "Package", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ClairVulnerabilityValidationError{ + field: "Package", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetPackage()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClairVulnerabilityValidationError{ + field: "Package", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if all { + switch v := interface{}(m.GetDistribution()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ClairVulnerabilityValidationError{ + field: "Distribution", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ClairVulnerabilityValidationError{ + field: "Distribution", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetDistribution()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClairVulnerabilityValidationError{ + field: "Distribution", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if all { + switch v := interface{}(m.GetRepository()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ClairVulnerabilityValidationError{ + field: "Repository", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ClairVulnerabilityValidationError{ + field: "Repository", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRepository()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClairVulnerabilityValidationError{ + field: "Repository", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for FixedInVersion + + if len(errors) > 0 { + return ClairVulnerabilityMultiError(errors) + } + + return nil +} + +// ClairVulnerabilityMultiError is an error wrapping multiple validation errors +// returned by ClairVulnerability.ValidateAll() if the designated constraints +// aren't met. +type ClairVulnerabilityMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairVulnerabilityMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairVulnerabilityMultiError) AllErrors() []error { return m } + +// ClairVulnerabilityValidationError is the validation error returned by +// ClairVulnerability.Validate if the designated constraints aren't met. +type ClairVulnerabilityValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairVulnerabilityValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairVulnerabilityValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairVulnerabilityValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairVulnerabilityValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairVulnerabilityValidationError) ErrorName() string { + return "ClairVulnerabilityValidationError" +} + +// Error satisfies the builtin error interface +func (e ClairVulnerabilityValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairVulnerability.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairVulnerabilityValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairVulnerabilityValidationError{} + +// Validate checks the field values on ClairEnrichment with the rules defined +// in the proto definition for this message. If any rules are violated, the +// first error encountered is returned, or nil if there are no violations. +func (m *ClairEnrichment) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairEnrichment with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairEnrichmentMultiError, or nil if none found. +func (m *ClairEnrichment) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairEnrichment) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Id + + if len(errors) > 0 { + return ClairEnrichmentMultiError(errors) + } + + return nil +} + +// ClairEnrichmentMultiError is an error wrapping multiple validation errors +// returned by ClairEnrichment.ValidateAll() if the designated constraints +// aren't met. +type ClairEnrichmentMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairEnrichmentMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairEnrichmentMultiError) AllErrors() []error { return m } + +// ClairEnrichmentValidationError is the validation error returned by +// ClairEnrichment.Validate if the designated constraints aren't met. +type ClairEnrichmentValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairEnrichmentValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairEnrichmentValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairEnrichmentValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairEnrichmentValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairEnrichmentValidationError) ErrorName() string { return "ClairEnrichmentValidationError" } + +// Error satisfies the builtin error interface +func (e ClairEnrichmentValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairEnrichment.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairEnrichmentValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairEnrichmentValidationError{} + +// Validate checks the field values on ClairVulnerabilityIdList with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ClairVulnerabilityIdList) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairVulnerabilityIdList with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairVulnerabilityIdListMultiError, or nil if none found. +func (m *ClairVulnerabilityIdList) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairVulnerabilityIdList) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return ClairVulnerabilityIdListMultiError(errors) + } + + return nil +} + +// ClairVulnerabilityIdListMultiError is an error wrapping multiple validation +// errors returned by ClairVulnerabilityIdList.ValidateAll() if the designated +// constraints aren't met. +type ClairVulnerabilityIdListMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairVulnerabilityIdListMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairVulnerabilityIdListMultiError) AllErrors() []error { return m } + +// ClairVulnerabilityIdListValidationError is the validation error returned by +// ClairVulnerabilityIdList.Validate if the designated constraints aren't met. +type ClairVulnerabilityIdListValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairVulnerabilityIdListValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairVulnerabilityIdListValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairVulnerabilityIdListValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairVulnerabilityIdListValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairVulnerabilityIdListValidationError) ErrorName() string { + return "ClairVulnerabilityIdListValidationError" +} + +// Error satisfies the builtin error interface +func (e ClairVulnerabilityIdListValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairVulnerabilityIdList.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairVulnerabilityIdListValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairVulnerabilityIdListValidationError{} + +// Validate checks the field values on GetVulnerabilityReportResponse with the +// rules defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *GetVulnerabilityReportResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetVulnerabilityReportResponse with +// the rules defined in the proto definition for this message. If any rules +// are violated, the result is a list of violation errors wrapped in +// GetVulnerabilityReportResponseMultiError, or nil if none found. +func (m *GetVulnerabilityReportResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GetVulnerabilityReportResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for ManifestHash + + // no validation rules for State + + // no validation rules for Err + + // no validation rules for Success + + { + sorted_keys := make([]string, len(m.GetPackages())) + i := 0 + for key := range m.GetPackages() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetPackages()[key] + _ = val + + // no validation rules for Packages[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Packages[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Packages[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Packages[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + { + sorted_keys := make([]string, len(m.GetDistributions())) + i := 0 + for key := range m.GetDistributions() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetDistributions()[key] + _ = val + + // no validation rules for Distributions[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Distributions[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Distributions[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Distributions[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + { + sorted_keys := make([]string, len(m.GetEnvironments())) + i := 0 + for key := range m.GetEnvironments() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetEnvironments()[key] + _ = val + + // no validation rules for Environments[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Environments[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Environments[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Environments[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + { + sorted_keys := make([]string, len(m.GetPackageVulnerabilities())) + i := 0 + for key := range m.GetPackageVulnerabilities() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetPackageVulnerabilities()[key] + _ = val + + // no validation rules for PackageVulnerabilities[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("PackageVulnerabilities[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("PackageVulnerabilities[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("PackageVulnerabilities[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + if all { + switch v := interface{}(m.GetEnrichments()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: "Enrichments", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: "Enrichments", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetEnrichments()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetVulnerabilityReportResponseValidationError{ + field: "Enrichments", + reason: "embedded message failed validation", + cause: err, + } + } + } + + { + sorted_keys := make([]string, len(m.GetRepository())) + i := 0 + for key := range m.GetRepository() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetRepository()[key] + _ = val + + // no validation rules for Repository[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Repository[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Repository[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Repository[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + { + sorted_keys := make([]string, len(m.GetVulnerabilities())) + i := 0 + for key := range m.GetVulnerabilities() { + sorted_keys[i] = key + i++ + } + sort.Slice(sorted_keys, func(i, j int) bool { return sorted_keys[i] < sorted_keys[j] }) + for _, key := range sorted_keys { + val := m.GetVulnerabilities()[key] + _ = val + + // no validation rules for Vulnerabilities[key] + + if all { + switch v := interface{}(val).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Vulnerabilities[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Vulnerabilities[%v]", key), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(val).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetVulnerabilityReportResponseValidationError{ + field: fmt.Sprintf("Vulnerabilities[%v]", key), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + } + + if len(errors) > 0 { + return GetVulnerabilityReportResponseMultiError(errors) + } + + return nil +} + +// GetVulnerabilityReportResponseMultiError is an error wrapping multiple +// validation errors returned by GetVulnerabilityReportResponse.ValidateAll() +// if the designated constraints aren't met. +type GetVulnerabilityReportResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetVulnerabilityReportResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetVulnerabilityReportResponseMultiError) AllErrors() []error { return m } + +// GetVulnerabilityReportResponseValidationError is the validation error +// returned by GetVulnerabilityReportResponse.Validate if the designated +// constraints aren't met. +type GetVulnerabilityReportResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetVulnerabilityReportResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetVulnerabilityReportResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetVulnerabilityReportResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetVulnerabilityReportResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetVulnerabilityReportResponseValidationError) ErrorName() string { + return "GetVulnerabilityReportResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GetVulnerabilityReportResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sGetVulnerabilityReportResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetVulnerabilityReportResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetVulnerabilityReportResponseValidationError{} diff --git a/services/yor/clair/v1/clairconnect/clair.connect.go b/services/yor/clair/v1/clairconnect/clair.connect.go new file mode 100644 index 00000000..b364fb77 --- /dev/null +++ b/services/yor/clair/v1/clairconnect/clair.connect.go @@ -0,0 +1,132 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: services/yor/clair/v1/clair.proto + +package clairconnect + +import ( + context "context" + errors "errors" + connect_go "github.com/bufbuild/connect-go" + v1 "github.com/containerish/OpenRegistry/services/yor/clair/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect_go.IsAtLeastVersion0_1_0 + +const ( + // ClairServiceName is the fully-qualified name of the ClairService service. + ClairServiceName = "services.yor.clair.v1.ClairService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // ClairServiceSubmitManifestToScanProcedure is the fully-qualified name of the ClairService's + // SubmitManifestToScan RPC. + ClairServiceSubmitManifestToScanProcedure = "/services.yor.clair.v1.ClairService/SubmitManifestToScan" + // ClairServiceGetVulnerabilityReportProcedure is the fully-qualified name of the ClairService's + // GetVulnerabilityReport RPC. + ClairServiceGetVulnerabilityReportProcedure = "/services.yor.clair.v1.ClairService/GetVulnerabilityReport" +) + +// ClairServiceClient is a client for the services.yor.clair.v1.ClairService service. +type ClairServiceClient interface { + SubmitManifestToScan(context.Context, *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) + GetVulnerabilityReport(context.Context, *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) +} + +// NewClairServiceClient constructs a client for the services.yor.clair.v1.ClairService service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewClairServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) ClairServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &clairServiceClient{ + submitManifestToScan: connect_go.NewClient[v1.SubmitManifestToScanRequest, v1.SubmitManifestToScanResponse]( + httpClient, + baseURL+ClairServiceSubmitManifestToScanProcedure, + opts..., + ), + getVulnerabilityReport: connect_go.NewClient[v1.GetVulnerabilityReportRequest, v1.GetVulnerabilityReportResponse]( + httpClient, + baseURL+ClairServiceGetVulnerabilityReportProcedure, + opts..., + ), + } +} + +// clairServiceClient implements ClairServiceClient. +type clairServiceClient struct { + submitManifestToScan *connect_go.Client[v1.SubmitManifestToScanRequest, v1.SubmitManifestToScanResponse] + getVulnerabilityReport *connect_go.Client[v1.GetVulnerabilityReportRequest, v1.GetVulnerabilityReportResponse] +} + +// SubmitManifestToScan calls services.yor.clair.v1.ClairService.SubmitManifestToScan. +func (c *clairServiceClient) SubmitManifestToScan(ctx context.Context, req *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) { + return c.submitManifestToScan.CallUnary(ctx, req) +} + +// GetVulnerabilityReport calls services.yor.clair.v1.ClairService.GetVulnerabilityReport. +func (c *clairServiceClient) GetVulnerabilityReport(ctx context.Context, req *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) { + return c.getVulnerabilityReport.CallUnary(ctx, req) +} + +// ClairServiceHandler is an implementation of the services.yor.clair.v1.ClairService service. +type ClairServiceHandler interface { + SubmitManifestToScan(context.Context, *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) + GetVulnerabilityReport(context.Context, *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) +} + +// NewClairServiceHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewClairServiceHandler(svc ClairServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { + clairServiceSubmitManifestToScanHandler := connect_go.NewUnaryHandler( + ClairServiceSubmitManifestToScanProcedure, + svc.SubmitManifestToScan, + opts..., + ) + clairServiceGetVulnerabilityReportHandler := connect_go.NewUnaryHandler( + ClairServiceGetVulnerabilityReportProcedure, + svc.GetVulnerabilityReport, + opts..., + ) + return "/services.yor.clair.v1.ClairService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case ClairServiceSubmitManifestToScanProcedure: + clairServiceSubmitManifestToScanHandler.ServeHTTP(w, r) + case ClairServiceGetVulnerabilityReportProcedure: + clairServiceGetVulnerabilityReportHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedClairServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedClairServiceHandler struct{} + +func (UnimplementedClairServiceHandler) SubmitManifestToScan(context.Context, *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.SubmitManifestToScan is not implemented")) +} + +func (UnimplementedClairServiceHandler) GetVulnerabilityReport(context.Context, *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.GetVulnerabilityReport is not implemented")) +} diff --git a/services/yor/clair/v1/server/clair.go b/services/yor/clair/v1/server/clair.go new file mode 100644 index 00000000..97b58004 --- /dev/null +++ b/services/yor/clair/v1/server/clair.go @@ -0,0 +1,155 @@ +package server + +import ( + "bytes" + "context" + "fmt" + "io" + "net/http" + + "github.com/bufbuild/connect-go" + clair_v1 "github.com/containerish/OpenRegistry/services/yor/clair/v1" + "github.com/golang-jwt/jwt/v5" + "google.golang.org/protobuf/encoding/protojson" +) + +func (c *clair) GetVulnerabilityReport( + ctx context.Context, + req *connect.Request[clair_v1.GetVulnerabilityReportRequest], +) ( + *connect.Response[clair_v1.GetVulnerabilityReportResponse], + error, +) { + logEvent := c.logger.Debug().Str("method", "GetVulnerabilityReport") + + err := req.Msg.Validate() + if err != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + manifestID := req.Msg.GetManifestId() + logEvent.Str("manifest", manifestID) + report, err := c.getVulnReport(ctx, manifestID) + if err != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + reportBz, err := io.ReadAll(report) + if err != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInternal, err) + } + defer report.Close() + + resp := &clair_v1.GetVulnerabilityReportResponse{} + if err = protojson.Unmarshal(reportBz, resp); err != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInternal, err) + } + + logEvent.Bool("success", true).Send() + return connect.NewResponse(resp), nil +} + +// SubmitManifestToScan implements clairconnect.ClairServiceHandler. +func (c *clair) SubmitManifestToScan( + ctx context.Context, + req *connect.Request[clair_v1.SubmitManifestToScanRequest], +) ( + *connect.Response[clair_v1.SubmitManifestToScanResponse], + error, +) { + logEvent := c.logger.Debug().Str("method", "SubmitManifestToScan") + + err := req.Msg.Validate() + if err != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + logEvent.Str("manifest", req.Msg.GetHash()) + + result, err := c.submitManifest(ctx, req.Msg) + if err != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + resultBz, err := io.ReadAll(result) + if err != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInternal, err) + } + defer result.Close() + + msg := &clair_v1.SubmitManifestToScanResponse{} + if err = protojson.Unmarshal(resultBz, msg); err != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInternal, err) + } + + logEvent.Bool("success", true).Send() + + return connect.NewResponse(msg), nil +} + +func (c *clair) getVulnReport(ctx context.Context, manifestID string) (io.ReadCloser, error) { + uri := fmt.Sprintf("%s/matcher/api/v1/vulnerability_report/%s", c.config.ClairEndpoint, manifestID) + + req, err := c.newClairRequest(ctx, http.MethodGet, uri, nil) + if err != nil { + return nil, err + } + + resp, err := c.http.Do(req) + if err != nil { + return nil, err + } + + return resp.Body, nil +} + +func (c *clair) submitManifest( + ctx context.Context, + manifest *clair_v1.SubmitManifestToScanRequest, +) (io.ReadCloser, error) { + uri := fmt.Sprintf("%s/indexer/api/v1/index_report", c.config.ClairEndpoint) + + bz, err := protojson.Marshal(manifest) + if err != nil { + return nil, err + } + req, err := c.newClairRequest(ctx, http.MethodPost, uri, bytes.NewBuffer(bz)) + if err != nil { + return nil, err + } + + res, err := c.http.Do(req) + if err != nil { + return nil, err + } + + return res.Body, nil +} + +func (c *clair) newClairRequest(ctx context.Context, method string, url string, body io.Reader) (*http.Request, error) { + req, err := http.NewRequestWithContext(ctx, method, url, body) + if err != nil { + return nil, fmt.Errorf("ERR_NEW_CLAIR_REQ: %w", err) + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{ + Issuer: "quay", + }) + + authToken, err := token.SignedString([]byte(c.config.AuthToken)) + if err != nil { + return nil, fmt.Errorf("ERR_NEW_CLAIR_REQ: SignAuthToken: %w - AuthToken: %s", err, c.config.AuthToken) + } + + req.Header.Set("Authorization", "Bearer "+authToken) + + return req, nil +} diff --git a/services/yor/clair/v1/server/server.go b/services/yor/clair/v1/server/server.go new file mode 100644 index 00000000..10af3844 --- /dev/null +++ b/services/yor/clair/v1/server/server.go @@ -0,0 +1,46 @@ +package server + +import ( + "net/http" + "sync" + "time" + + "github.com/containerish/OpenRegistry/config" + connect_v1 "github.com/containerish/OpenRegistry/services/yor/clair/v1/clairconnect" + "github.com/containerish/OpenRegistry/telemetry" +) + +type ( + clair struct { + http *http.Client + logger telemetry.Logger + config *config.ClairIntegration + mu *sync.RWMutex + } +) + +func NewClairClient( + config *config.ClairIntegration, + logger telemetry.Logger, +) *http.ServeMux { + if !config.Enabled { + return nil + } + + httpClient := &http.Client{ + Timeout: time.Minute * 3, + Transport: http.DefaultTransport, + } + + server := &clair{ + logger: logger, + config: config, + mu: &sync.RWMutex{}, + http: httpClient, + } + + // interceptors := connect.WithInterceptors(NewGithubAppInterceptor(logger, ghStore, nil, authConfig)) + mux := http.NewServeMux() + mux.Handle(connect_v1.NewClairServiceHandler(server)) + return mux +} diff --git a/store/v1/permissions/permissions.go b/store/v1/permissions/permissions.go index e7df1290..a1fa2a6f 100644 --- a/store/v1/permissions/permissions.go +++ b/store/v1/permissions/permissions.go @@ -17,7 +17,7 @@ type ( // It doesn't return any errors. If the user has permissions, they're be reflect in the returned // *types.Permissions struct, otherwise, the returned type will be an empty, non-nil struct GetUserPermissionsForNamespace(ctx context.Context, ns string, userID uuid.UUID) *types.Permissions - AddPermissions(ctx context.Context, perm *types.Permissions) error + AddPermissions(ctx context.Context, perm *types.AddUsersToOrgRequest) error UpdatePermissions(ctx context.Context, perm *types.Permissions) error RemoveUserFromOrg(ctx context.Context, orgID, userID uuid.UUID) error } diff --git a/store/v1/permissions/permissions_impl.go b/store/v1/permissions/permissions_impl.go index 682714c9..d9911e67 100644 --- a/store/v1/permissions/permissions_impl.go +++ b/store/v1/permissions/permissions_impl.go @@ -14,14 +14,31 @@ import ( // AddPermission implements PermissionsStore. func (p *permissionStore) AddPermissions( ctx context.Context, - perm *types.Permissions, + input *types.AddUsersToOrgRequest, ) error { - err := p.validatePermissionInput(perm) + err := p.validateAddOrgMembersInput(input) if err != nil { return v1.WrapDatabaseError(err, v1.DatabaseOperationWrite) } + perms := make([]*types.Permissions, len(input.Users)) + + for i, p := range input.Users { + perm := &types.Permissions{ + UserID: p.ID, + OrganizationID: input.OrganizationID, + Push: p.Push, + Pull: p.Pull, + IsAdmin: p.IsAdmin, + } + if p.IsAdmin { + perm.Pull = true + perm.Push = true + } + + perms[i] = perm + } - if _, err = p.db.NewInsert().Model(perm).Exec(ctx); err != nil { + if _, err = p.db.NewInsert().Model(&perms).Exec(ctx); err != nil { return err } @@ -101,6 +118,24 @@ func (p *permissionStore) validatePermissionInput(perm *types.Permissions) error return nil } +func (p *permissionStore) validateAddOrgMembersInput(input *types.AddUsersToOrgRequest) error { + if input == nil { + return fmt.Errorf("permission set is nil") + } + + if input.OrganizationID.String() == "" { + return fmt.Errorf("invalid organization id") + } + + for _, u := range input.Users { + if u.ID.String() == "" { + return fmt.Errorf("invalid user id") + } + } + + return nil +} + func (p *permissionStore) RemoveUserFromOrg(ctx context.Context, orgID, userID uuid.UUID) error { var perm types.Permissions _, err := p. diff --git a/store/v1/types/permissions.go b/store/v1/types/permissions.go index 9cdfb5ce..f4a118eb 100644 --- a/store/v1/types/permissions.go +++ b/store/v1/types/permissions.go @@ -13,9 +13,9 @@ type ( Permissions struct { bun.BaseModel `bun:"table:permissions,alias:p" json:"-"` - UpdatedAt time.Time `bun:"updated_at" json:"updated_at,omitempty" validate:"-"` - CreatedAt time.Time `bun:"created_at" json:"created_at,omitempty" validate:"-"` - User *User `bun:"rel:belongs-to,join:user_id=id" json:"-"` + UpdatedAt time.Time `bun:"updated_at" json:"updated_at,omitempty"` + CreatedAt time.Time `bun:"created_at" json:"created_at,omitempty"` + User *User `bun:"rel:belongs-to,join:user_id=id" json:"user"` Organization *User `bun:"rel:belongs-to,join:organization_id=id" json:"-"` UserID uuid.UUID `bun:"user_id,type:uuid" json:"user_id"` OrganizationID uuid.UUID `bun:"organization_id,type:uuid" json:"organization_id"` @@ -23,6 +23,25 @@ type ( Pull bool `bun:"pull" json:"pull"` IsAdmin bool `bun:"is_admin" json:"is_admin"` } + + MigrateToOrgRequest struct { + UserID uuid.UUID `json:"user_id"` + } + + RemoveUserFromOrgRequest struct { + UserID uuid.UUID `json:"user_id"` + OrganizationID uuid.UUID `json:"organization_id"` + } + + AddUsersToOrgRequest struct { + Users []struct { + ID uuid.UUID `json:"id"` + Pull bool `json:"pull"` + Push bool `json:"push"` + IsAdmin bool `json:"is_admin"` + } `json:"users"` + OrganizationID uuid.UUID `json:"organization_id"` + } ) var _ bun.AfterCreateTableHook = (*Permissions)(nil) diff --git a/store/v1/types/users.go b/store/v1/types/users.go index 9443fdcb..20d96d70 100644 --- a/store/v1/types/users.go +++ b/store/v1/types/users.go @@ -50,13 +50,14 @@ type ( Username string `bun:"username,notnull,unique" json:"username,omitempty" validate:"-"` Password string `bun:"password" json:"password,omitempty"` // nolint:lll - Email string `bun:"email,notnull,unique" json:"email,omitempty" validate:"email"` - UserType string `bun:"user_type" json:"user_type"` - Sessions []*Session `bun:"rel:has-many,join:id=owner_id" json:"-"` - WebauthnSessions []*WebauthnSession `bun:"rel:has-many,join:id=user_id" json:"-"` - WebauthnCredentials []*WebauthnCredential `bun:"rel:has-many,join:id=credential_owner_id" json:"-"` - Permissions []*Permissions `bun:"rel:has-many,join:id=user_id" json:"-"` - Repositories []*ContainerImageRepository `bun:"rel:has-many,join:id=owner_id" json:"-"` + Email string `bun:"email,notnull,unique" json:"email,omitempty" validate:"email"` + UserType string `bun:"user_type" json:"user_type"` + Sessions []*Session `bun:"rel:has-many,join:id=owner_id" json:"-"` + WebauthnSessions []*WebauthnSession `bun:"rel:has-many,join:id=user_id" json:"-"` + WebauthnCredentials []*WebauthnCredential `bun:"rel:has-many,join:id=credential_owner_id" json:"-"` + Permissions []*Permissions `bun:"rel:has-many,join:id=user_id" json:"permissions"` + // Permissions []*Permissions `bun:"m2m:permissions,join:" json:"permissions"` + Repositories []*ContainerImageRepository `bun:"rel:has-many,join:id=owner_id" json:"-"` // nolint:lll FavoriteRepositories []uuid.UUID `bun:"favorite_repositories,type:uuid[],default:'{}'" json:"favorite_repositories"` ID uuid.UUID `bun:"id,type:uuid,pk" json:"id,omitempty" validate:"-"` diff --git a/store/v1/users/store.go b/store/v1/users/store.go index daca0e04..348d0797 100644 --- a/store/v1/users/store.go +++ b/store/v1/users/store.go @@ -45,6 +45,8 @@ type UserReader interface { UserExists(ctx context.Context, username, email string) (bool, bool) GetOrgAdmin(ctx context.Context, orgID uuid.UUID) (*types.User, error) Search(ctx context.Context, query string) ([]*types.User, error) + GetOrgUsersByOrgID(ctx context.Context, orgID uuid.UUID) ([]*types.Permissions, error) + MatchUserType(ctx context.Context, userType types.UserType, userIds ...uuid.UUID) bool } type UserWriter interface { diff --git a/store/v1/users/users_impl.go b/store/v1/users/users_impl.go index c8574ff3..9c9ac4db 100644 --- a/store/v1/users/users_impl.go +++ b/store/v1/users/users_impl.go @@ -255,7 +255,7 @@ func (us *userStore) GetOrgAdmin(ctx context.Context, orgID uuid.UUID) (*types.U } func (us *userStore) Search(ctx context.Context, query string) ([]*types.User, error) { - var users []*types.User + users := []*types.User{} b := strings.Builder{} b.WriteString("%") @@ -286,3 +286,36 @@ func (us *userStore) Search(ctx context.Context, query string) ([]*types.User, e return users, nil } + +// GetOrgUsersByOrgID returns a list of Permission structs, which also has the user to which the permissions belongs to +func (us *userStore) GetOrgUsersByOrgID(ctx context.Context, orgID uuid.UUID) ([]*types.Permissions, error) { + var perms []*types.Permissions + + q := us.db.NewSelect().Model(&perms).Relation("User", func(sq *bun.SelectQuery) *bun.SelectQuery { + return sq.ExcludeColumn("password") + }).Where("organization_id = ?", orgID) + + if err := q.Scan(ctx); err != nil { + return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) + } + + return perms, nil +} + +func (us *userStore) MatchUserType(ctx context.Context, userType types.UserType, userIds ...uuid.UUID) bool { + var users []*types.User + + q := us. + db. + NewSelect(). + Model(&users). + Where("user_type = ?", types.UserTypeRegular.String()). + Where("id in (?)", bun.In(userIds)) + + count, err := q.Count(ctx) + if err != nil { + return false + } + + return len(userIds) == count +} diff --git a/vcs/github/github.go b/vcs/github/github.go index e8abd6f1..fd79086f 100644 --- a/vcs/github/github.go +++ b/vcs/github/github.go @@ -22,7 +22,7 @@ import ( type ghAppService struct { store vcs.VCSStore logger telemetry.Logger - config *config.Integration + config *config.GithubIntegration ghClient *github.Client ghAppTransport *ghinstallation.AppsTransport automationBranchName string @@ -32,7 +32,7 @@ type ghAppService struct { } func NewGithubApp( - cfg *config.Integration, + cfg *config.GithubIntegration, store vcs.VCSStore, logger telemetry.Logger, webInterfaceURLs []string, @@ -168,7 +168,7 @@ func (gh *ghAppService) getGitubInstallationID(skipRoutes ...string) echo.Middle func newGHClient(appID int64, privKeyPem string) (*ghinstallation.AppsTransport, *github.Client, error) { transport, err := ghinstallation.NewAppsTransportKeyFromFile(http.DefaultTransport, appID, privKeyPem) if err != nil { - return nil, nil, fmt.Errorf("ERR_CREATE_NEW_TRANSPORT: %w", err) + return nil, nil, fmt.Errorf("ERR_CREATE_NEW_TRANSPORT: %w - file: %s", err, privKeyPem) } client := github.NewClient(&http.Client{Transport: transport, Timeout: time.Second * 30}) diff --git a/vcs/github/handlers.go b/vcs/github/handlers.go index 6ccc6902..76b4fb51 100644 --- a/vcs/github/handlers.go +++ b/vcs/github/handlers.go @@ -51,6 +51,10 @@ func (gh *ghAppService) HandleAppFinish(ctx echo.Context) error { } if user.Identities.GetGitHubIdentity() == nil { + if user.Identities == nil { + user.Identities = make(types.Identities) + } + user.Identities[types.IdentityProviderGitHub] = &types.UserIdentity{ ID: fmt.Sprintf("%d", ghUser.GetID()), Name: ghUser.GetName(), From 06a1296780e787d029df1f25617865d2853a7f22 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Thu, 21 Dec 2023 14:40:54 +0530 Subject: [PATCH 02/23] refactor: JWT signing key operations Signed-off-by: jay-dee7 --- auth/jwt.go | 57 +++----------------------------------- auth/jwt_oci_middleware.go | 5 ++++ config/config.go | 36 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 53 deletions(-) diff --git a/auth/jwt.go b/auth/jwt.go index 0f806b9d..018a87c8 100644 --- a/auth/jwt.go +++ b/auth/jwt.go @@ -1,12 +1,7 @@ package auth import ( - "bytes" - "crypto/sha256" - "crypto/x509" - "encoding/base32" "fmt" - "strings" "time" "github.com/containerish/OpenRegistry/store/v1/types" @@ -43,19 +38,6 @@ type ServiceClaims struct { Access AccessList } -func (a *auth) keyIDEncode(b []byte) string { - s := strings.TrimRight(base32.StdEncoding.EncodeToString(b), "=") - var buf bytes.Buffer - var i int - for i = 0; i < len(s)/4-1; i++ { - start := i * 4 - end := start + 4 - buf.WriteString(s[start:end] + ":") - } - buf.WriteString(s[i*4:]) - return buf.String() -} - func (a *auth) SignOAuthToken(userId uuid.UUID, payload *oauth2.Token) (string, string, error) { return a.newOAuthToken(userId, payload) } @@ -64,23 +46,12 @@ func (a *auth) newOAuthToken(userId uuid.UUID, payload *oauth2.Token) (string, s accessClaims := a.createOAuthClaims(userId, payload) refreshClaims := a.createRefreshClaims(userId) - pubKeyDerBz, err := x509.MarshalPKIXPublicKey(a.c.Registry.Auth.JWTSigningPubKey) - if err != nil { - return "", "", err - } - - hasher := sha256.New() - hasher.Write(pubKeyDerBz) - accessToken := jwt.NewWithClaims(jwt.SigningMethodRS256, &accessClaims) - accessToken.Header["kid"] = a.keyIDEncode(hasher.Sum(nil)[:30]) - accessSign, err := accessToken.SignedString(a.c.Registry.Auth.JWTSigningPrivateKey) + accessSign, err := a.c.Registry.Auth.SignWithPubKey(&accessClaims) if err != nil { return "", "", fmt.Errorf("ERR_ACCESS_TOKEN_SIGN: %w", err) } - refreshToken := jwt.NewWithClaims(jwt.SigningMethodRS256, &refreshClaims) - refreshToken.Header["kid"] = a.keyIDEncode(hasher.Sum(nil)[:30]) - refreshSign, err := refreshToken.SignedString(a.c.Registry.Auth.JWTSigningPrivateKey) + refreshSign, err := a.c.Registry.Auth.SignWithPubKey(&refreshClaims) if err != nil { return "", "", fmt.Errorf("ERR_REFRESH_TOKEN_SIGN: %w", err) } @@ -105,17 +76,7 @@ func (a *auth) newServiceToken(u types.User) (string, error) { Acl: acl, } claims := CreateClaims(opts) - - pubKeyDerBz, err := x509.MarshalPKIXPublicKey(a.c.Registry.Auth.JWTSigningPubKey) - if err != nil { - return "", err - } - - hasher := sha256.New() - hasher.Write(pubKeyDerBz) - token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) - token.Header["kid"] = a.keyIDEncode(hasher.Sum(nil)[:30]) - sign, err := token.SignedString(a.c.Registry.Auth.JWTSigningPrivateKey) + sign, err := a.c.Registry.Auth.SignWithPubKey(&claims) if err != nil { return "", fmt.Errorf("error signing secret %w", err) } @@ -132,17 +93,7 @@ func (a *auth) newOCIToken(userID uuid.UUID, scopes types.OCITokenPermissonClaim Acl: scopes, } claims := CreateOCIClaims(opts) - - pubKeyDerBz, err := x509.MarshalPKIXPublicKey(a.c.Registry.Auth.JWTSigningPubKey) - if err != nil { - return "", err - } - - hasher := sha256.New() - hasher.Write(pubKeyDerBz) - token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) - token.Header["kid"] = a.keyIDEncode(hasher.Sum(nil)[:30]) - sign, err := token.SignedString(a.c.Registry.Auth.JWTSigningPrivateKey) + sign, err := a.c.Registry.Auth.SignWithPubKey(&claims) if err != nil { return "", fmt.Errorf("error signing secret %w", err) } diff --git a/auth/jwt_oci_middleware.go b/auth/jwt_oci_middleware.go index 15bc54c2..de340b5d 100644 --- a/auth/jwt_oci_middleware.go +++ b/auth/jwt_oci_middleware.go @@ -3,6 +3,7 @@ package auth import ( "fmt" "net/http" + "strings" "time" "github.com/containerish/OpenRegistry/common" @@ -23,6 +24,10 @@ func (a *auth) JWT() echo.MiddlewareFunc { ctx.Set(types.HandlerStartTime, time.Now()) } + if strings.HasPrefix(ctx.Request().URL.Path, "/v2/ext/") { + return true + } + // public read is allowed readOp := ctx.Request().Method == http.MethodGet || ctx.Request().Method == http.MethodHead // repository should be present at this step since the BasicAuth Middleware sets it diff --git a/config/config.go b/config/config.go index 4cb90030..b0e61199 100644 --- a/config/config.go +++ b/config/config.go @@ -1,7 +1,11 @@ package config import ( + "bytes" "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/base32" "fmt" "strings" "time" @@ -11,6 +15,7 @@ import ( ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" enTranslations "github.com/go-playground/validator/v10/translations/en" + "github.com/golang-jwt/jwt/v5" "github.com/hashicorp/go-multierror" "github.com/labstack/echo/v4" "github.com/spf13/viper" @@ -478,3 +483,34 @@ func (wan *WebAuthnConfig) GetAllowedURLFromEchoContext(ctx echo.Context, env En return wan.RPOrigins[0] } + +func (a *Auth) keyIDEncode(b []byte) string { + s := strings.TrimRight(base32.StdEncoding.EncodeToString(b), "=") + var buf bytes.Buffer + var i int + for i = 0; i < len(s)/4-1; i++ { + start := i * 4 + end := start + 4 + buf.WriteString(s[start:end] + ":") + } + buf.WriteString(s[i*4:]) + return buf.String() +} + +func (a *Auth) SignWithPubKey(claims jwt.Claims) (string, error) { + pubKeyDerBz, err := x509.MarshalPKIXPublicKey(a.JWTSigningPubKey) + if err != nil { + return "", err + } + + hasher := sha256.New() + hasher.Write(pubKeyDerBz) + token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) + token.Header["kid"] = a.keyIDEncode(hasher.Sum(nil)[:30]) + signed, err := token.SignedString(a.JWTSigningPrivateKey) + if err != nil { + return "", fmt.Errorf("error signing secret %w", err) + } + + return signed, nil +} From 660c56e618e491d43739336560fa09e965d4d851 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Thu, 21 Dec 2023 14:44:35 +0530 Subject: [PATCH 03/23] fix: Create build project options Signed-off-by: jay-dee7 --- .../kon/github_actions/v1/build_project.proto | 13 +- .../kon/github_actions/v1/build_project.pb.go | 377 ++++++++++-------- .../v1/build_project.pb.validate.go | 60 +++ .../github_actions/v1/server/build_logs.go | 2 +- .../github_actions/v1/server/build_project.go | 6 +- .../v1/server/github_action_logs.go | 2 +- .../v1/server/github_event_listener.go | 6 +- .../github_actions/v1/server/interceptor.go | 1 + store/v1/automation/projects.go | 52 ++- store/v1/registry/registry_impl.go | 37 +- store/v1/registry/store.go | 3 +- store/v1/types/auth.go | 5 + store/v1/types/automation.go | 2 + store/v1/types/registry.go | 12 +- store/v1/types/users.go | 17 +- store/v1/users/store.go | 16 +- store/v1/users/users_impl.go | 8 +- types/types.go | 5 - vcs/github/github.go | 10 + vcs/github/handlers.go | 50 ++- 20 files changed, 442 insertions(+), 242 deletions(-) diff --git a/protos/services/kon/github_actions/v1/build_project.proto b/protos/services/kon/github_actions/v1/build_project.proto index 77230790..da904c29 100644 --- a/protos/services/kon/github_actions/v1/build_project.proto +++ b/protos/services/kon/github_actions/v1/build_project.proto @@ -23,11 +23,12 @@ message ListProjectsResponse { message CreateProjectRequest { common.v1.UUID id = 1; common.v1.UUID owner_id = 2; - string project_name = 3; - string production_branch = 4; - ProjectBuildSettingsMessage build_settings = 5; - ProjectEnvironmentVariableListMessage environment_variables = 6; - google.protobuf.Timestamp created_at = 7; + common.v1.UUID repository_id = 3; + string project_name = 4; + string production_branch = 5; + ProjectBuildSettingsMessage build_settings = 6; + ProjectEnvironmentVariableListMessage environment_variables = 7; + google.protobuf.Timestamp created_at = 8; } message GetProjectRequest { @@ -50,6 +51,8 @@ message GetProjectResponse { ProjectEnvironmentVariableListMessage environment_variables = 5; google.protobuf.Timestamp created_at = 6; common.v1.UUID owner_id = 7; + common.v1.UUID repository_id = 8; + string repository_name = 9; } message ProjectEnvironmentVariableListMessage { diff --git a/services/kon/github_actions/v1/build_project.pb.go b/services/kon/github_actions/v1/build_project.pb.go index 09fe0802..77ce9085 100644 --- a/services/kon/github_actions/v1/build_project.pb.go +++ b/services/kon/github_actions/v1/build_project.pb.go @@ -123,11 +123,12 @@ type CreateProjectRequest struct { Id *v1.UUID `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` OwnerId *v1.UUID `protobuf:"bytes,2,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` - ProjectName string `protobuf:"bytes,3,opt,name=project_name,json=projectName,proto3" json:"project_name,omitempty"` - ProductionBranch string `protobuf:"bytes,4,opt,name=production_branch,json=productionBranch,proto3" json:"production_branch,omitempty"` - BuildSettings *ProjectBuildSettingsMessage `protobuf:"bytes,5,opt,name=build_settings,json=buildSettings,proto3" json:"build_settings,omitempty"` - EnvironmentVariables *ProjectEnvironmentVariableListMessage `protobuf:"bytes,6,opt,name=environment_variables,json=environmentVariables,proto3" json:"environment_variables,omitempty"` - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + RepositoryId *v1.UUID `protobuf:"bytes,3,opt,name=repository_id,json=repositoryId,proto3" json:"repository_id,omitempty"` + ProjectName string `protobuf:"bytes,4,opt,name=project_name,json=projectName,proto3" json:"project_name,omitempty"` + ProductionBranch string `protobuf:"bytes,5,opt,name=production_branch,json=productionBranch,proto3" json:"production_branch,omitempty"` + BuildSettings *ProjectBuildSettingsMessage `protobuf:"bytes,6,opt,name=build_settings,json=buildSettings,proto3" json:"build_settings,omitempty"` + EnvironmentVariables *ProjectEnvironmentVariableListMessage `protobuf:"bytes,7,opt,name=environment_variables,json=environmentVariables,proto3" json:"environment_variables,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` } func (x *CreateProjectRequest) Reset() { @@ -176,6 +177,13 @@ func (x *CreateProjectRequest) GetOwnerId() *v1.UUID { return nil } +func (x *CreateProjectRequest) GetRepositoryId() *v1.UUID { + if x != nil { + return x.RepositoryId + } + return nil +} + func (x *CreateProjectRequest) GetProjectName() string { if x != nil { return x.ProjectName @@ -364,6 +372,8 @@ type GetProjectResponse struct { EnvironmentVariables *ProjectEnvironmentVariableListMessage `protobuf:"bytes,5,opt,name=environment_variables,json=environmentVariables,proto3" json:"environment_variables,omitempty"` CreatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` OwnerId *v1.UUID `protobuf:"bytes,7,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` + RepositoryId *v1.UUID `protobuf:"bytes,8,opt,name=repository_id,json=repositoryId,proto3" json:"repository_id,omitempty"` + RepositoryName string `protobuf:"bytes,9,opt,name=repository_name,json=repositoryName,proto3" json:"repository_name,omitempty"` } func (x *GetProjectResponse) Reset() { @@ -447,6 +457,20 @@ func (x *GetProjectResponse) GetOwnerId() *v1.UUID { return nil } +func (x *GetProjectResponse) GetRepositoryId() *v1.UUID { + if x != nil { + return x.RepositoryId + } + return nil +} + +func (x *GetProjectResponse) GetRepositoryName() string { + if x != nil { + return x.RepositoryName + } + return "" +} + type ProjectEnvironmentVariableListMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -697,157 +721,166 @@ var file_services_kon_github_actions_v1_build_project_proto_rawDesc = []byte{ 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x73, 0x22, 0xce, 0x03, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, + 0x65, 0x63, 0x74, 0x73, 0x22, 0x84, 0x04, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, - 0x44, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, - 0x11, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x72, 0x61, 0x6e, - 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x62, 0x0a, 0x0e, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, - 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x7a, - 0x0a, 0x15, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, - 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, + 0x44, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x0d, 0x72, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, + 0x49, 0x44, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, + 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x12, 0x62, 0x0a, 0x0e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x7a, 0x0a, 0x15, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, + 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, + 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x45, 0x6e, 0x76, 0x69, + 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4c, + 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x14, 0x65, 0x6e, 0x76, 0x69, + 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, + 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x34, 0x0a, 0x11, 0x47, + 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1f, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, 0x44, 0x52, 0x02, 0x69, + 0x64, 0x22, 0x37, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x55, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x22, 0x31, 0x0a, 0x15, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xab, 0x04, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, + 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x62, 0x0a, 0x0e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x14, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x34, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x22, 0x37, 0x0a, 0x14, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, 0x44, - 0x52, 0x02, 0x69, 0x64, 0x22, 0x31, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xcc, 0x03, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, - 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, - 0x62, 0x0a, 0x0e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x12, 0x7a, 0x0a, 0x15, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, - 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x45, 0x6e, 0x76, 0x69, 0x72, - 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x14, 0x65, 0x6e, 0x76, 0x69, 0x72, - 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, - 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2a, 0x0a, 0x08, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, 0x44, 0x52, 0x07, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0x98, 0x01, 0x0a, 0x25, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, - 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x6f, 0x0a, 0x15, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, - 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, - 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x14, 0x65, 0x6e, 0x76, - 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, - 0x73, 0x22, 0x62, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x45, 0x6e, 0x76, 0x69, - 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 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, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x65, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x65, 0x64, 0x22, 0x84, 0x01, 0x0a, 0x1b, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, - 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x54, 0x6f, 0x6f, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x65, 0x63, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, - 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x77, 0x6f, 0x72, 0x66, 0x6b, - 0x6c, 0x6f, 0x77, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x77, 0x6f, 0x72, 0x66, 0x6b, 0x6c, 0x6f, 0x77, 0x46, 0x69, 0x6c, 0x65, 0x22, 0x52, 0x0a, 0x15, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x1f, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, - 0x32, 0x91, 0x04, 0x0a, 0x1b, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x41, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x7e, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x12, 0x34, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, - 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x75, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x31, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x32, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, - 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x7e, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x34, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x7a, 0x0a, 0x15, 0x65, 0x6e, 0x76, + 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, + 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x7b, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x33, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x73, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, + 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x14, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, + 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x2a, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x55, 0x49, 0x44, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x0d, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x55, 0x49, 0x44, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x25, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x6f, 0x0a, 0x15, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x45, 0x6e, 0x76, + 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, + 0x52, 0x14, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, + 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, 0x62, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, + 0x61, 0x62, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 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, 0x12, 0x1c, 0x0a, 0x09, + 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x22, 0x84, 0x01, 0x0a, 0x1b, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x75, + 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x65, + 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x65, 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x0d, + 0x77, 0x6f, 0x72, 0x66, 0x6b, 0x6c, 0x6f, 0x77, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, 0x6f, 0x72, 0x66, 0x6b, 0x6c, 0x6f, 0x77, 0x46, 0x69, 0x6c, + 0x65, 0x22, 0x52, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, + 0x44, 0x52, 0x02, 0x69, 0x64, 0x32, 0x91, 0x04, 0x0a, 0x1b, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7e, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x34, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x75, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x12, 0x31, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, + 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x7e, 0x0a, 0x0d, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x34, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, + 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x7b, 0x0a, 0x0c, + 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x33, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0xa5, 0x02, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x11, 0x42, 0x75, 0x69, - 0x6c, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x69, 0x73, 0x68, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, - 0x6b, 0x6f, 0x6e, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x53, 0x4b, 0x47, 0xaa, 0x02, 0x1d, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x4b, 0x6f, 0x6e, 0x2e, 0x47, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x1d, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x4b, 0x6f, 0x6e, 0x5c, 0x47, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x29, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x4b, 0x6f, 0x6e, 0x5c, 0x47, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x3a, 0x3a, 0x4b, 0x6f, 0x6e, 0x3a, 0x3a, 0x47, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x34, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, + 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xa5, 0x02, 0x0a, 0x22, 0x63, 0x6f, + 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6b, 0x6f, 0x6e, 0x2e, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, + 0x42, 0x11, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x69, 0x73, 0x68, 0x2f, 0x4f, + 0x70, 0x65, 0x6e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2f, 0x6b, 0x6f, 0x6e, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x53, + 0x4b, 0x47, 0xaa, 0x02, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x4b, 0x6f, + 0x6e, 0x2e, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x56, 0x31, 0xca, 0x02, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x4b, 0x6f, + 0x6e, 0x5c, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5c, + 0x56, 0x31, 0xe2, 0x02, 0x29, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x4b, 0x6f, + 0x6e, 0x5c, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5c, + 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x3a, 0x4b, 0x6f, 0x6e, 0x3a, 0x3a, + 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x3a, 0x56, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -883,31 +916,33 @@ var file_services_kon_github_actions_v1_build_project_proto_depIdxs = []int32{ 6, // 1: services.kon.github_actions.v1.ListProjectsResponse.projects:type_name -> services.kon.github_actions.v1.GetProjectResponse 11, // 2: services.kon.github_actions.v1.CreateProjectRequest.id:type_name -> common.v1.UUID 11, // 3: services.kon.github_actions.v1.CreateProjectRequest.owner_id:type_name -> common.v1.UUID - 9, // 4: services.kon.github_actions.v1.CreateProjectRequest.build_settings:type_name -> services.kon.github_actions.v1.ProjectBuildSettingsMessage - 7, // 5: services.kon.github_actions.v1.CreateProjectRequest.environment_variables:type_name -> services.kon.github_actions.v1.ProjectEnvironmentVariableListMessage - 12, // 6: services.kon.github_actions.v1.CreateProjectRequest.created_at:type_name -> google.protobuf.Timestamp - 11, // 7: services.kon.github_actions.v1.GetProjectRequest.id:type_name -> common.v1.UUID - 11, // 8: services.kon.github_actions.v1.DeleteProjectRequest.id:type_name -> common.v1.UUID - 11, // 9: services.kon.github_actions.v1.GetProjectResponse.id:type_name -> common.v1.UUID - 9, // 10: services.kon.github_actions.v1.GetProjectResponse.build_settings:type_name -> services.kon.github_actions.v1.ProjectBuildSettingsMessage - 7, // 11: services.kon.github_actions.v1.GetProjectResponse.environment_variables:type_name -> services.kon.github_actions.v1.ProjectEnvironmentVariableListMessage - 12, // 12: services.kon.github_actions.v1.GetProjectResponse.created_at:type_name -> google.protobuf.Timestamp - 11, // 13: services.kon.github_actions.v1.GetProjectResponse.owner_id:type_name -> common.v1.UUID - 8, // 14: services.kon.github_actions.v1.ProjectEnvironmentVariableListMessage.environment_variables:type_name -> services.kon.github_actions.v1.ProjectEnvironmentVariable - 11, // 15: services.kon.github_actions.v1.CreateProjectResponse.id:type_name -> common.v1.UUID - 2, // 16: services.kon.github_actions.v1.GitHubActionsProjectService.CreateProject:input_type -> services.kon.github_actions.v1.CreateProjectRequest - 3, // 17: services.kon.github_actions.v1.GitHubActionsProjectService.GetProject:input_type -> services.kon.github_actions.v1.GetProjectRequest - 4, // 18: services.kon.github_actions.v1.GitHubActionsProjectService.DeleteProject:input_type -> services.kon.github_actions.v1.DeleteProjectRequest - 0, // 19: services.kon.github_actions.v1.GitHubActionsProjectService.ListProjects:input_type -> services.kon.github_actions.v1.ListProjectsRequest - 10, // 20: services.kon.github_actions.v1.GitHubActionsProjectService.CreateProject:output_type -> services.kon.github_actions.v1.CreateProjectResponse - 6, // 21: services.kon.github_actions.v1.GitHubActionsProjectService.GetProject:output_type -> services.kon.github_actions.v1.GetProjectResponse - 5, // 22: services.kon.github_actions.v1.GitHubActionsProjectService.DeleteProject:output_type -> services.kon.github_actions.v1.DeleteProjectResponse - 1, // 23: services.kon.github_actions.v1.GitHubActionsProjectService.ListProjects:output_type -> services.kon.github_actions.v1.ListProjectsResponse - 20, // [20:24] is the sub-list for method output_type - 16, // [16:20] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name + 11, // 4: services.kon.github_actions.v1.CreateProjectRequest.repository_id:type_name -> common.v1.UUID + 9, // 5: services.kon.github_actions.v1.CreateProjectRequest.build_settings:type_name -> services.kon.github_actions.v1.ProjectBuildSettingsMessage + 7, // 6: services.kon.github_actions.v1.CreateProjectRequest.environment_variables:type_name -> services.kon.github_actions.v1.ProjectEnvironmentVariableListMessage + 12, // 7: services.kon.github_actions.v1.CreateProjectRequest.created_at:type_name -> google.protobuf.Timestamp + 11, // 8: services.kon.github_actions.v1.GetProjectRequest.id:type_name -> common.v1.UUID + 11, // 9: services.kon.github_actions.v1.DeleteProjectRequest.id:type_name -> common.v1.UUID + 11, // 10: services.kon.github_actions.v1.GetProjectResponse.id:type_name -> common.v1.UUID + 9, // 11: services.kon.github_actions.v1.GetProjectResponse.build_settings:type_name -> services.kon.github_actions.v1.ProjectBuildSettingsMessage + 7, // 12: services.kon.github_actions.v1.GetProjectResponse.environment_variables:type_name -> services.kon.github_actions.v1.ProjectEnvironmentVariableListMessage + 12, // 13: services.kon.github_actions.v1.GetProjectResponse.created_at:type_name -> google.protobuf.Timestamp + 11, // 14: services.kon.github_actions.v1.GetProjectResponse.owner_id:type_name -> common.v1.UUID + 11, // 15: services.kon.github_actions.v1.GetProjectResponse.repository_id:type_name -> common.v1.UUID + 8, // 16: services.kon.github_actions.v1.ProjectEnvironmentVariableListMessage.environment_variables:type_name -> services.kon.github_actions.v1.ProjectEnvironmentVariable + 11, // 17: services.kon.github_actions.v1.CreateProjectResponse.id:type_name -> common.v1.UUID + 2, // 18: services.kon.github_actions.v1.GitHubActionsProjectService.CreateProject:input_type -> services.kon.github_actions.v1.CreateProjectRequest + 3, // 19: services.kon.github_actions.v1.GitHubActionsProjectService.GetProject:input_type -> services.kon.github_actions.v1.GetProjectRequest + 4, // 20: services.kon.github_actions.v1.GitHubActionsProjectService.DeleteProject:input_type -> services.kon.github_actions.v1.DeleteProjectRequest + 0, // 21: services.kon.github_actions.v1.GitHubActionsProjectService.ListProjects:input_type -> services.kon.github_actions.v1.ListProjectsRequest + 10, // 22: services.kon.github_actions.v1.GitHubActionsProjectService.CreateProject:output_type -> services.kon.github_actions.v1.CreateProjectResponse + 6, // 23: services.kon.github_actions.v1.GitHubActionsProjectService.GetProject:output_type -> services.kon.github_actions.v1.GetProjectResponse + 5, // 24: services.kon.github_actions.v1.GitHubActionsProjectService.DeleteProject:output_type -> services.kon.github_actions.v1.DeleteProjectResponse + 1, // 25: services.kon.github_actions.v1.GitHubActionsProjectService.ListProjects:output_type -> services.kon.github_actions.v1.ListProjectsResponse + 22, // [22:26] is the sub-list for method output_type + 18, // [18:22] is the sub-list for method input_type + 18, // [18:18] is the sub-list for extension type_name + 18, // [18:18] is the sub-list for extension extendee + 0, // [0:18] is the sub-list for field type_name } func init() { file_services_kon_github_actions_v1_build_project_proto_init() } diff --git a/services/kon/github_actions/v1/build_project.pb.validate.go b/services/kon/github_actions/v1/build_project.pb.validate.go index 9c70837d..a1f2344b 100644 --- a/services/kon/github_actions/v1/build_project.pb.validate.go +++ b/services/kon/github_actions/v1/build_project.pb.validate.go @@ -382,6 +382,35 @@ func (m *CreateProjectRequest) validate(all bool) error { } } + if all { + switch v := interface{}(m.GetRepositoryId()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, CreateProjectRequestValidationError{ + field: "RepositoryId", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, CreateProjectRequestValidationError{ + field: "RepositoryId", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRepositoryId()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return CreateProjectRequestValidationError{ + field: "RepositoryId", + reason: "embedded message failed validation", + cause: err, + } + } + } + // no validation rules for ProjectName // no validation rules for ProductionBranch @@ -1090,6 +1119,37 @@ func (m *GetProjectResponse) validate(all bool) error { } } + if all { + switch v := interface{}(m.GetRepositoryId()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetProjectResponseValidationError{ + field: "RepositoryId", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetProjectResponseValidationError{ + field: "RepositoryId", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRepositoryId()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetProjectResponseValidationError{ + field: "RepositoryId", + reason: "embedded message failed validation", + cause: err, + } + } + } + + // no validation rules for RepositoryName + if len(errors) > 0 { return GetProjectResponseMultiError(errors) } diff --git a/services/kon/github_actions/v1/server/build_logs.go b/services/kon/github_actions/v1/server/build_logs.go index a6b507e3..a9e09a19 100644 --- a/services/kon/github_actions/v1/server/build_logs.go +++ b/services/kon/github_actions/v1/server/build_logs.go @@ -316,7 +316,7 @@ func (ghs *GitHubActionsServer) waitForJobToFinish( stream *connect_go.ServerStream[github_actions_v1.StreamWorkflowRunLogsResponse], ) error { now := time.Now() - logEvent := ghs.logger.Debug().Str("method", "waitForJobToFinish") + logEvent := ghs.logger.Debug().Str("method", "waitForJobToFinish").Int64("run_id", req.Msg.GetRunId()).Str("repo_name", req.Msg.GetRepoName()).Str("repo_owner", req.Msg.GetRepoOwner()) workflowRun, _, err := githubClient.Actions.GetWorkflowRunByID( ctx, diff --git a/services/kon/github_actions/v1/server/build_project.go b/services/kon/github_actions/v1/server/build_project.go index a72b69f7..b81b1269 100644 --- a/services/kon/github_actions/v1/server/build_project.go +++ b/services/kon/github_actions/v1/server/build_project.go @@ -2,7 +2,6 @@ package server import ( "context" - "time" connect_go "github.com/bufbuild/connect-go" common_v1 "github.com/containerish/OpenRegistry/common/v1" @@ -28,13 +27,10 @@ func (ghs *GitHubActionsServer) CreateProject( return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) } - if err = req.Msg.GetCreatedAt().CheckValid(); err != nil { - req.Msg.CreatedAt = timestamppb.New(time.Now()) - } - req.Msg.Id = &common_v1.UUID{ Value: uuid.New().String(), } + req.Msg.CreatedAt = timestamppb.Now() if err = ghs.store.StoreProject(ctx, req.Msg); err != nil { logEvent.Err(err).Send() return nil, connect_go.NewError(connect_go.CodeInternal, err) diff --git a/services/kon/github_actions/v1/server/github_action_logs.go b/services/kon/github_actions/v1/server/github_action_logs.go index 86e6239e..9a6463ec 100644 --- a/services/kon/github_actions/v1/server/github_action_logs.go +++ b/services/kon/github_actions/v1/server/github_action_logs.go @@ -80,7 +80,7 @@ func (ghs *GitHubActionsServer) getLogsToStream( sort.SliceStable(workflowSteps, func(i, j int) bool { return workflowSteps[i].StepPosition < workflowSteps[j].StepPosition }) - ghs.logger.Log(nil, nil).Str("done_slice_sort", "true").Send() + ghs.logger.Debug().Str("done_slice_sort", "true").Send() if len(errList) > 0 { return nil, fmt.Errorf("%v", errList) } diff --git a/services/kon/github_actions/v1/server/github_event_listener.go b/services/kon/github_actions/v1/server/github_event_listener.go index 8edf31e3..7f12b0fd 100644 --- a/services/kon/github_actions/v1/server/github_event_listener.go +++ b/services/kon/github_actions/v1/server/github_event_listener.go @@ -21,7 +21,7 @@ func (ghs *GitHubActionsServer) Listen(resp http.ResponseWriter, req *http.Reque ) if err != nil { - ghs.logger.Log(nil, nil). + ghs.logger.Debug(). Str("method", "Listen"). Str("error", err.Error()). Send() @@ -31,7 +31,7 @@ func (ghs *GitHubActionsServer) Listen(resp http.ResponseWriter, req *http.Reque event, err := github.ParseWebHook(github.WebHookType(req), payload) if err != nil { - ghs.logger.Log(nil, nil). + ghs.logger.Debug(). Str("method", "Listen"). Str("error", err.Error()). Send() @@ -51,7 +51,7 @@ func (ghs *GitHubActionsServer) Listen(resp http.ResponseWriter, req *http.Reque action: event.GetAction(), } eventKey := ghs.getLogsEventKey(val.req) - ghs.logger.Log(nil, nil). + ghs.logger.Debug(). Str("method", "Listen"). Str("github_event", "WorkflowRunEvent"). Int64("workflow_id", event.GetWorkflowRun().GetID()). diff --git a/services/kon/github_actions/v1/server/interceptor.go b/services/kon/github_actions/v1/server/interceptor.go index 78015897..2bd59d6e 100644 --- a/services/kon/github_actions/v1/server/interceptor.go +++ b/services/kon/github_actions/v1/server/interceptor.go @@ -119,6 +119,7 @@ func (i *githubAppStreamingInterceptor) WrapUnary(next connect.UnaryFunc) connec logEvent.Bool("skip_check", true).Str("Procedure", req.Spec().Procedure).Send() return next(ctx, req) } + githubIdentity := user.Identities.GetGitHubIdentity() if githubIdentity == nil { errMsg := fmt.Errorf("github identity is not available") diff --git a/store/v1/automation/projects.go b/store/v1/automation/projects.go index bd108a14..1551dd64 100644 --- a/store/v1/automation/projects.go +++ b/store/v1/automation/projects.go @@ -7,6 +7,7 @@ import ( common_v1 "github.com/containerish/OpenRegistry/common/v1" github_actions_v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" + v1 "github.com/containerish/OpenRegistry/store/v1" "github.com/containerish/OpenRegistry/store/v1/types" "github.com/google/uuid" "google.golang.org/protobuf/types/known/timestamppb" @@ -64,16 +65,25 @@ func (s *store) GetProject( // ListProjects implements BuildAutomationStore func (s *store) ListProjects( ctx context.Context, - project *github_actions_v1.ListProjectsRequest, + req *github_actions_v1.ListProjectsRequest, ) (*github_actions_v1.ListProjectsResponse, error) { projects := make([]*types.RepositoryBuildProject, 0) - if err := s.db.NewSelect().Model(&projects).Scan(ctx); err != nil { + + err := s. + db. + NewSelect(). + Model(&projects). + Relation("Repository"). + Where("owner_id = ?", req.GetOwnerId().GetValue()). + Scan(ctx) + if err != nil { return nil, fmt.Errorf("ERR_LIST_PROJECTS: %w", err) } protoProjects := &github_actions_v1.ListProjectsResponse{ Projects: make([]*github_actions_v1.GetProjectResponse, len(projects)), } + for i, p := range projects { proj := &github_actions_v1.GetProjectResponse{ Id: &common_v1.UUID{ @@ -87,6 +97,13 @@ func (s *store) ListProjects( WorfklowFile: p.WorkflowFile, }, CreatedAt: timestamppb.New(p.CreatedAt), + OwnerId: &common_v1.UUID{ + Value: p.RepositoryOwnerID.String(), + }, + RepositoryId: &common_v1.UUID{ + Value: p.RepositoryID.String(), + }, + RepositoryName: p.Repository.Name, } for key, value := range p.EnvironmentVariables { @@ -108,15 +125,30 @@ func (s *store) ListProjects( // StoreProject implements BuildAutomationStore func (s *store) StoreProject(ctx context.Context, project *github_actions_v1.CreateProjectRequest) error { + projectID, err := uuid.Parse(project.GetId().GetValue()) + if err != nil { + return v1.WrapDatabaseError(err, v1.DatabaseOperationWrite) + } + ownerID, err := uuid.Parse(project.GetOwnerId().GetValue()) + if err != nil { + return v1.WrapDatabaseError(err, v1.DatabaseOperationWrite) + } + + repositoryID, err := uuid.Parse(project.GetRepositoryId().GetValue()) + if err != nil { + return v1.WrapDatabaseError(err, v1.DatabaseOperationWrite) + } + proj := &types.RepositoryBuildProject{ - CreatedAt: time.Now(), - Name: project.GetProjectName(), - ProductionBranch: project.GetProductionBranch(), - BuildTool: project.GetBuildSettings().GetBuildTool(), - ExecCommand: project.GetBuildSettings().GetExecCommand(), - WorkflowFile: project.GetBuildSettings().GetWorfklowFile(), - ID: uuid.MustParse(project.GetId().GetValue()), - RepositoryID: uuid.MustParse(project.GetOwnerId().GetValue()), + CreatedAt: time.Now(), + Name: project.GetProjectName(), + ProductionBranch: project.GetProductionBranch(), + BuildTool: project.GetBuildSettings().GetBuildTool(), + ExecCommand: project.GetBuildSettings().GetExecCommand(), + WorkflowFile: project.GetBuildSettings().GetWorfklowFile(), + ID: projectID, + RepositoryOwnerID: ownerID, + RepositoryID: repositoryID, } for _, envVar := range project.GetEnvironmentVariables().GetEnvironmentVariables() { diff --git a/store/v1/registry/registry_impl.go b/store/v1/registry/registry_impl.go index 5d3a9c31..75d745d9 100644 --- a/store/v1/registry/registry_impl.go +++ b/store/v1/registry/registry_impl.go @@ -510,7 +510,7 @@ func (s *registryStore) GetRepoDetail( // SetContainerImageVisibility implements registry.RegistryStore. func (s *registryStore) SetContainerImageVisibility( ctx context.Context, - imageId string, + imageId uuid.UUID, visibility types.RepositoryVisibility, ) error { logEvent := s.logger.Debug().Str("method", "SetContainerImageVisibility") @@ -518,9 +518,9 @@ func (s *registryStore) SetContainerImageVisibility( _, err := s. db. NewUpdate(). - Model(&types.ContainerImageRepository{}). - Set("visibility = ?", visibility). - WherePK(imageId). + Model(&types.ContainerImageRepository{ID: imageId}). + Set("visibility = ?", visibility.String()). + WherePK(). Where("name != ?", types.SystemUsernameIPFS). // IPFS repositories cannot be set to private since they are P2P Exec(ctx) @@ -789,3 +789,32 @@ func (s *registryStore) RemoveRepositoryFromFavorites(ctx context.Context, repoI v1.DatabaseOperationUpdate, ) } + +func (s *registryStore) GetLayersLinksForManifest(ctx context.Context, manifestDigest string) ([]*types.ContainerImageLayer, error) { + logEvent := s.logger.Debug().Str("method", "GetLayersLinksForManifest").Str("digest", manifestDigest) + + manifest := &types.ImageManifest{} + err := s.db.NewSelect().Model(manifest).Where("digest = ?", manifestDigest).Scan(ctx) + if err != nil { + return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) + } + + layerDigests := make([]string, len(manifest.Layers)) + for i, l := range manifest.Layers { + layerDigests[i] = l.Digest.String() + } + + var layers []*types.ContainerImageLayer + if err = s. + db. + NewSelect(). + Model(&layers). + Where("digest in (?)", bun.In(layerDigests)). + Scan(ctx); err != nil { + logEvent.Err(err).Send() + return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) + } + + logEvent.Bool("success", true).Send() + return layers, nil +} diff --git a/store/v1/registry/store.go b/store/v1/registry/store.go index 4550643c..c8b427ce 100644 --- a/store/v1/registry/store.go +++ b/store/v1/registry/store.go @@ -76,7 +76,7 @@ type RegistryStore interface { DeleteLayerByDigestWithTxn(ctx context.Context, txn *bun.Tx, digest string) error DeleteManifestOrTag(ctx context.Context, reference string) error DeleteManifestOrTagWithTxn(ctx context.Context, txn *bun.Tx, reference string) error - SetContainerImageVisibility(ctx context.Context, imageId string, visibility types.RepositoryVisibility) error + SetContainerImageVisibility(ctx context.Context, imageId uuid.UUID, visibility types.RepositoryVisibility) error CreateRepository(ctx context.Context, repository *types.ContainerImageRepository) error GetRepositoryByID(ctx context.Context, ID uuid.UUID) (*types.ContainerImageRepository, error) @@ -86,4 +86,5 @@ type RegistryStore interface { IncrementRepositoryPullCounter(ctx context.Context, repoID uuid.UUID) error AddRepositoryToFavorites(ctx context.Context, repoID uuid.UUID, userID uuid.UUID) error RemoveRepositoryFromFavorites(ctx context.Context, repoID uuid.UUID, userID uuid.UUID) error + GetLayersLinksForManifest(ctx context.Context, manifestDigest string) ([]*types.ContainerImageLayer, error) } diff --git a/store/v1/types/auth.go b/store/v1/types/auth.go index be611b29..539a6b50 100644 --- a/store/v1/types/auth.go +++ b/store/v1/types/auth.go @@ -19,6 +19,11 @@ type ( Type string Name string } + + ResetPasswordRequest struct { + OldPassword string `json:"old_password"` + NewPassword string `json:"new_password"` + } ) func (c *OCITokenPermissonClaim) HasPushAccess() bool { diff --git a/store/v1/types/automation.go b/store/v1/types/automation.go index 05484ed7..35218f6f 100644 --- a/store/v1/types/automation.go +++ b/store/v1/types/automation.go @@ -32,6 +32,7 @@ type ( CreatedAt time.Time `bun:"created_at" json:"created_at,omitempty" validate:"-"` EnvironmentVariables map[string]string `bun:"environment_variables,type:jsonb" json:"environment_variables"` Repository *ContainerImageRepository `bun:"rel:belongs-to,join:repository_id=id" json:"-"` + User *User `bun:"rel:belongs-to,join:repository_owner_id=id" json:"-"` Name string `bun:"name" json:"name"` ProductionBranch string `bun:"production_branch" json:"production_branch"` BuildTool string `bun:"build_tool" json:"build_tool"` @@ -39,5 +40,6 @@ type ( WorkflowFile string `bun:"workflow_file" json:"workflow_file"` ID uuid.UUID `bun:"id,type:uuid,pk" json:"id,omitempty" validate:"-"` RepositoryID uuid.UUID `bun:"repository_id,type:uuid" json:"repository_id"` + RepositoryOwnerID uuid.UUID `bun:"repository_owner_id,type:uuid" json:"repository_owner_id"` } ) diff --git a/store/v1/types/registry.go b/store/v1/types/registry.go index c14da12f..68290869 100644 --- a/store/v1/types/registry.go +++ b/store/v1/types/registry.go @@ -33,8 +33,8 @@ func (v RepositoryVisibility) String() string { type ( ContainerImageVisibilityChangeRequest struct { - ImageManifestUUID string `json:"image_manifest_uuid"` - Visibility RepositoryVisibility `json:"visibility_mode"` + Visibility RepositoryVisibility `json:"visibility_mode"` + RepositoryID uuid.UUID `json:"repository_id"` } ImageManifest struct { @@ -95,15 +95,15 @@ type ( MetaTags map[string]any `bun:"meta_tags" json:"meta_tags"` User *User `bun:"rel:belongs-to,join:owner_id=id" json:"-"` Project *RepositoryBuild `bun:"rel:has-one,join:id=repository_id" json:"-"` - Description string `bun:"description" json:"description"` - Visibility RepositoryVisibility `bun:"visibility,notnull" json:"visibility"` Name string `bun:"name,notnull" json:"name"` + Visibility RepositoryVisibility `bun:"visibility,notnull" json:"visibility"` + Description string `bun:"description" json:"description"` ImageManifests []*ImageManifest `bun:"rel:has-many,join:id=repository_id" json:"image_manifests,omitempty"` Builds []*RepositoryBuild `bun:"rel:has-many,join:id=repository_id" json:"-"` - ID uuid.UUID `bun:"id,pk,type:uuid,default:gen_random_uuid()" json:"id"` - OwnerID uuid.UUID `bun:"owner_id,type:uuid" json:"owner_id"` PullCount uint64 `bun:"pull_count" json:"pull_count"` FavoriteCount uint64 `bun:"favorite_count" json:"favorite_count"` + ID uuid.UUID `bun:"id,pk,type:uuid,default:gen_random_uuid()" json:"id"` + OwnerID uuid.UUID `bun:"owner_id,type:uuid" json:"owner_id"` } RepositoryVisibility string diff --git a/store/v1/types/users.go b/store/v1/types/users.go index 20d96d70..a19e99f4 100644 --- a/store/v1/types/users.go +++ b/store/v1/types/users.go @@ -50,14 +50,14 @@ type ( Username string `bun:"username,notnull,unique" json:"username,omitempty" validate:"-"` Password string `bun:"password" json:"password,omitempty"` // nolint:lll - Email string `bun:"email,notnull,unique" json:"email,omitempty" validate:"email"` - UserType string `bun:"user_type" json:"user_type"` - Sessions []*Session `bun:"rel:has-many,join:id=owner_id" json:"-"` - WebauthnSessions []*WebauthnSession `bun:"rel:has-many,join:id=user_id" json:"-"` - WebauthnCredentials []*WebauthnCredential `bun:"rel:has-many,join:id=credential_owner_id" json:"-"` - Permissions []*Permissions `bun:"rel:has-many,join:id=user_id" json:"permissions"` - // Permissions []*Permissions `bun:"m2m:permissions,join:" json:"permissions"` - Repositories []*ContainerImageRepository `bun:"rel:has-many,join:id=owner_id" json:"-"` + Email string `bun:"email,notnull,unique" json:"email,omitempty" validate:"email"` + UserType string `bun:"user_type" json:"user_type"` + Sessions []*Session `bun:"rel:has-many,join:id=owner_id" json:"-"` + WebauthnSessions []*WebauthnSession `bun:"rel:has-many,join:id=user_id" json:"-"` + WebauthnCredentials []*WebauthnCredential `bun:"rel:has-many,join:id=credential_owner_id" json:"-"` + Permissions []*Permissions `bun:"rel:has-many,join:id=user_id" json:"permissions"` + Repositories []*ContainerImageRepository `bun:"rel:has-many,join:id=owner_id" json:"-"` + Projects []*RepositoryBuildProject `bun:"rel:has-many,join:id=repository_owner_id" json:"-"` // nolint:lll FavoriteRepositories []uuid.UUID `bun:"favorite_repositories,type:uuid[],default:'{}'" json:"favorite_repositories"` ID uuid.UUID `bun:"id,type:uuid,pk" json:"id,omitempty" validate:"-"` @@ -120,6 +120,7 @@ func (*User) NewUserFromGitHubUser(ghUser github.User) *User { Email: ghUser.GetEmail(), IsActive: true, GithubConnected: true, + UserType: UserTypeRegular.String(), Identities: map[string]*UserIdentity{ IdentityProviderGitHub: { ID: fmt.Sprintf("%d", ghUser.GetID()), diff --git a/store/v1/users/store.go b/store/v1/users/store.go index 348d0797..d1ff9270 100644 --- a/store/v1/users/store.go +++ b/store/v1/users/store.go @@ -32,23 +32,27 @@ type UserStore interface { } type UserReader interface { + UserGetter + GetIPFSUser(ctx context.Context) (*types.User, error) - GetUserByID(ctx context.Context, userID uuid.UUID) (*types.User, error) GetUserByIDWithTxn(ctx context.Context, id uuid.UUID, txn *bun.Tx) (*types.User, error) - GetUserByUsername(ctx context.Context, username string) (*types.User, error) GetUserByUsernameWithTxn(ctx context.Context, username string, txn *bun.Tx) (*types.User, error) - GetUserByEmail(ctx context.Context, email string) (*types.User, error) - GetUserWithSession(ctx context.Context, sessionId string) (*types.User, error) GetGitHubUser(ctx context.Context, identifier string, txn *bun.Tx) (*types.User, error) IsActive(ctx context.Context, identifier uuid.UUID) bool - // ID can be either a username, oauth login (GitHub username) or the user id (uuid) - UserExists(ctx context.Context, username, email string) (bool, bool) GetOrgAdmin(ctx context.Context, orgID uuid.UUID) (*types.User, error) Search(ctx context.Context, query string) ([]*types.User, error) GetOrgUsersByOrgID(ctx context.Context, orgID uuid.UUID) ([]*types.Permissions, error) MatchUserType(ctx context.Context, userType types.UserType, userIds ...uuid.UUID) bool } +type UserGetter interface { + GetUserByID(ctx context.Context, userID uuid.UUID) (*types.User, error) + GetUserByUsername(ctx context.Context, username string) (*types.User, error) + GetUserByEmail(ctx context.Context, email string) (*types.User, error) + GetUserWithSession(ctx context.Context, sessionId string) (*types.User, error) + UserExists(ctx context.Context, username, email string) (bool, bool) +} + type UserWriter interface { AddUser(ctx context.Context, u *types.User, txn *bun.Tx) error UpdateUser(ctx context.Context, u *types.User) (*types.User, error) diff --git a/store/v1/users/users_impl.go b/store/v1/users/users_impl.go index 9c9ac4db..f6a8ba27 100644 --- a/store/v1/users/users_impl.go +++ b/store/v1/users/users_impl.go @@ -62,12 +62,14 @@ func (us *userStore) DeleteUser(ctx context.Context, identifier uuid.UUID) error // GetGitHubUser implements UserStore. func (us *userStore) GetGitHubUser(ctx context.Context, githubEmail string, txn *bun.Tx) (*types.User, error) { user := &types.User{} - selectFn := us.db.NewSelect().Model(user) + q := us.db.NewSelect().Model(user) if txn != nil { - selectFn = txn.NewSelect().Model(user) + q = txn.NewSelect().Model(user) } - if err := selectFn.Where("coalesce(identities->'github'->>'email', '') = ?", githubEmail).Scan(ctx); err != nil { + q.Where("coalesce(identities->'github'->>'email', '') = ?", githubEmail) + + if err := q.Scan(ctx); err != nil { return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) } diff --git a/types/types.go b/types/types.go index 1686d805..589b5b12 100644 --- a/types/types.go +++ b/types/types.go @@ -137,11 +137,6 @@ type ( Namespace string `json:"namespace"` Tags []*ConfigV2 `json:"tags"` } - - Password struct { - OldPassword string `json:"old_password"` - NewPassword string `json:"new_password"` - } ) func (md Metadata) GetManifestByRef(ref string) (*Config, error) { diff --git a/vcs/github/github.go b/vcs/github/github.go index fd79086f..e30694ba 100644 --- a/vcs/github/github.go +++ b/vcs/github/github.go @@ -85,9 +85,11 @@ func (gh *ghAppService) RegisterRoutes(r *echo.Group) { func (gh *ghAppService) getUsernameMiddleware() echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { + // skip if it's a webhook call if c.Path() == "/github"+vcs.HandleWebhookEventsEndpoint { return next(c) } + sessionCookie, err := c.Cookie("session_id") if err != nil { echoErr := c.JSON(http.StatusNotAcceptable, echo.Map{ @@ -159,6 +161,14 @@ func (gh *ghAppService) getGitubInstallationID(skipRoutes ...string) echo.Middle return next(c) } + if user.Identities == nil || user.Identities.GetGitHubIdentity() == nil { + echoErr := c.JSON(http.StatusBadRequest, echo.Map{ + "error": "GH_MDW_ERR: GitHub identity not found", + }) + gh.logger.Log(c, echoErr).Send() + return echoErr + } + c.Set(string(GithubInstallationIDContextKey), user.Identities.GetGitHubIdentity().InstallationID) return next(c) } diff --git a/vcs/github/handlers.go b/vcs/github/handlers.go index 76b4fb51..ccd76841 100644 --- a/vcs/github/handlers.go +++ b/vcs/github/handlers.go @@ -50,11 +50,11 @@ func (gh *ghAppService) HandleAppFinish(ctx echo.Context) error { return echoErr } - if user.Identities.GetGitHubIdentity() == nil { - if user.Identities == nil { - user.Identities = make(types.Identities) - } + if user.Identities == nil { + user.Identities = types.Identities{} + } + if user.Identities.GetGitHubIdentity() == nil { user.Identities[types.IdentityProviderGitHub] = &types.UserIdentity{ ID: fmt.Sprintf("%d", ghUser.GetID()), Name: ghUser.GetName(), @@ -63,6 +63,9 @@ func (gh *ghAppService) HandleAppFinish(ctx echo.Context) error { Avatar: ghUser.GetAvatarURL(), InstallationID: installationID, } + } else { + user.Identities[types.IdentityProviderGitHub].Username = ghUser.GetEmail() + user.Identities[types.IdentityProviderGitHub].Email = ghUser.GetLogin() } if _, err = gh.store.UpdateUser(ctx.Request().Context(), user); err != nil { @@ -91,23 +94,42 @@ func (gh *ghAppService) HandleSetupCallback(ctx echo.Context) error { return echoErr } + if user.Identities == nil { + user.Identities = types.Identities{} + } + if user.Identities.GetGitHubIdentity() == nil { user.Identities[types.IdentityProviderGitHub] = &types.UserIdentity{} } + installation, _, err := gh.ghClient.Apps.GetInstallation(ctx.Request().Context(), installationID) if err != nil { - return ctx.JSON(http.StatusInternalServerError, echo.Map{ + echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), "message": "could not find the GitHub App installation", }) + + gh.logger.Log(ctx, err).Send() + return echoErr + } + + ghClient := gh.refreshGHClient(installationID) + ghUser, _, err := ghClient.Users.Get(ctx.Request().Context(), installation.GetAccount().GetLogin()) + if err != nil { + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ + "error": err.Error(), + }) + + gh.logger.Log(ctx, err).Send() + return echoErr } user.Identities[types.IdentityProviderGitHub] = &types.UserIdentity{ ID: fmt.Sprintf("%d", installation.GetID()), - Name: installation.GetAccount().GetName(), - Username: installation.GetAccount().GetLogin(), - Email: installation.GetAccount().GetEmail(), - Avatar: installation.GetAccount().GetAvatarURL(), + Name: ghUser.GetName(), + Username: ghUser.GetLogin(), + Email: ghUser.GetEmail(), + Avatar: ghUser.GetAvatarURL(), InstallationID: installationID, } @@ -164,7 +186,9 @@ func (gh *ghAppService) HandleWebhookEvents(ctx echo.Context) error { case *github.InstallationEvent: } - return ctx.NoContent(http.StatusNoContent) + echoErr := ctx.NoContent(http.StatusNoContent) + gh.logger.Log(ctx, nil).Send() + return echoErr } // @TODO pending implementation (@jay-dee7) @@ -235,9 +259,9 @@ func (gh *ghAppService) ListAuthorisedRepositories(ctx echo.Context) error { }) } - err = ctx.JSON(http.StatusOK, repoList) - gh.logger.Log(ctx, err).Send() - return err + echoErr := ctx.JSON(http.StatusOK, repoList) + gh.logger.Log(ctx, nil).Send() + return echoErr } func (gh *ghAppService) CreateInitialPR(ctx echo.Context) error { From 92d07a0575668c2549aa19aeb69df1a18a224dc7 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Thu, 21 Dec 2023 14:45:43 +0530 Subject: [PATCH 04/23] feat: Add multiple users to org in a single request Signed-off-by: jay-dee7 --- auth/basic_auth.go | 16 +++ auth/github.go | 20 ++-- auth/oci_token.go | 190 ++++++++++++++++----------------- auth/permissions.go | 76 ++++++------- auth/reset_password.go | 51 ++------- auth/server/webauthn_server.go | 10 +- cmd/registry/registry.go | 1 + orgmode/admin.go | 28 ++++- orgmode/orgmode.go | 1 + 9 files changed, 203 insertions(+), 190 deletions(-) diff --git a/auth/basic_auth.go b/auth/basic_auth.go index 3134f1e4..a4986522 100644 --- a/auth/basic_auth.go +++ b/auth/basic_auth.go @@ -1,6 +1,7 @@ package auth import ( + "context" "encoding/base64" "fmt" "net/http" @@ -72,6 +73,10 @@ func (a *auth) BasicAuth() echo.MiddlewareFunc { func (a *auth) SkipBasicAuth(ctx echo.Context) bool { authHeader := ctx.Request().Header.Get(echo.HeaderAuthorization) + if strings.HasPrefix(ctx.Request().URL.Path, "/v2/ext/") { + return true + } + hasJWT := a.checkJWT(authHeader, ctx.Request().Cookies()) if hasJWT { return true @@ -157,6 +162,17 @@ func (a *auth) validateBasicAuthCredentials(auth string) (*types.User, error) { basicAuthCredentials := strings.Split(string(decodedCredentials), ":") username, password := basicAuthCredentials[0], basicAuthCredentials[1] + // try login with GitHub PAT + // 1. "github_pat_" prefix is for the new fine-grained, repo scoped tokens + // 2. "ghp_" prefix is for the old (classic) github tokens + if strings.HasPrefix(password, "github_pat_") || strings.HasPrefix(password, "ghp_") { + user, ghErr := a.getUserWithGithubOauthToken(context.Background(), password) + if ghErr != nil { + return nil, fmt.Errorf("ERR_READ_USER_WITH_GITHUB_TOKEN: %w", ghErr) + } + + return user, nil + } user, err := a.validateUser(username, password) if err != nil { return nil, err diff --git a/auth/github.go b/auth/github.go index e1f40b26..ab7b59f7 100644 --- a/auth/github.go +++ b/auth/github.go @@ -9,8 +9,7 @@ import ( "time" "github.com/containerish/OpenRegistry/config" - v2_types "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/containerish/OpenRegistry/types" + "github.com/containerish/OpenRegistry/store/v1/types" "github.com/google/go-github/v56/github" "github.com/google/uuid" "github.com/labstack/echo/v4" @@ -116,6 +115,11 @@ func (a *auth) GithubLoginCallbackHandler(ctx echo.Context) error { } if user.GithubConnected { + ghIdentity := user.Identities.GetGitHubIdentity() + ghIdentity.Email = ghUser.GetEmail() + ghIdentity.Username = ghUser.GetLogin() + user.Identities[types.IdentityProviderGitHub] = ghIdentity + _, err = a.userStore.UpdateUser(ctx.Request().Context(), user) if err != nil { uri := a.getGitHubErrorURI(ctx, http.StatusConflict, err.Error()) @@ -136,7 +140,7 @@ func (a *auth) GithubLoginCallbackHandler(ctx echo.Context) error { return err } - user.Identities[v2_types.IdentityProviderGitHub] = &v2_types.UserIdentity{ + user.Identities[types.IdentityProviderGitHub] = &types.UserIdentity{ ID: fmt.Sprint(ghUser.GetID()), Name: ghUser.GetName(), Username: ghUser.GetLogin(), @@ -211,14 +215,14 @@ func (a *auth) createCookie( } // makes an http request to get user info from token, if it's valid, it's all good :) -func (a *auth) getUserWithGithubOauthToken(ctx context.Context, token string) (*v2_types.User, error) { +func (a *auth) getUserWithGithubOauthToken(ctx context.Context, token string) (*types.User, error) { req, err := a.ghClient.NewRequest(http.MethodGet, "/user", nil) if err != nil { return nil, fmt.Errorf("GH_AUTH_REQUEST_ERROR: %w", err) } req.Header.Set(AuthorizationHeaderKey, "token "+token) - var oauthUser v2_types.User + var oauthUser github.User resp, err := a.ghClient.Do(ctx, req, &oauthUser) if err != nil { return nil, fmt.Errorf("GH_AUTH_ERROR: %w", err) @@ -228,7 +232,7 @@ func (a *auth) getUserWithGithubOauthToken(ctx context.Context, token string) (* return nil, fmt.Errorf("GHO_UNAUTHORIZED") } - user, err := a.userStore.GetUserByEmail(ctx, oauthUser.Email) + user, err := a.userStore.GetUserByEmail(ctx, oauthUser.GetEmail()) if err != nil { return nil, fmt.Errorf("PG_GET_USER_ERR: %w", err) } @@ -245,7 +249,7 @@ func (a *auth) getGitHubErrorURI(ctx echo.Context, status int, err string) strin return fmt.Sprintf("%s%s?%s", webAppEndoint, a.c.WebAppConfig.ErrorRedirectPath, queryParams.Encode()) } -func (a *auth) finishGitHubCallback(ctx echo.Context, user *v2_types.User, oauthToken *oauth2.Token) error { +func (a *auth) finishGitHubCallback(ctx echo.Context, user *types.User, oauthToken *oauth2.Token) error { sessionId, err := uuid.NewRandom() if err != nil { return err @@ -279,7 +283,7 @@ func (a *auth) finishGitHubCallback(ctx echo.Context, user *v2_types.User, oauth return nil } -func (a *auth) storeGitHubUserIfDoesntExist(ctx context.Context, pgErr error, user *v2_types.User) error { +func (a *auth) storeGitHubUserIfDoesntExist(ctx context.Context, pgErr error, user *types.User) error { if strings.HasSuffix(pgErr.Error(), "no rows in result set") { id, err := uuid.NewRandom() if err != nil { diff --git a/auth/oci_token.go b/auth/oci_token.go index 07c59f0c..3d8e22e1 100644 --- a/auth/oci_token.go +++ b/auth/oci_token.go @@ -25,6 +25,100 @@ const ( DefaultOCITokenLifetime = time.Minute * 10 ) +// Request format: https://openregistry.dev/token?service=registry.docker.io&scope=repository:samalba/my-app:pull,push +func (a *auth) Token(ctx echo.Context) error { + // TODO (jay-dee7) - check for all valid query params here like serive, client_id, offline_token, etc + // more at this link - https://docs.docker.com/registry/spec/auth/token/ + ctx.Set(types.HandlerStartTime, time.Now()) + + scopes, err := ParseOCITokenPermissionRequest(ctx.Request().URL) + if err != nil { + registryErr := common.RegistryErrorResponse(registry.RegistryErrorCodeUnknown, "invalid scope provided", echo.Map{ + "error": err.Error(), + }) + echoErr := ctx.JSONBlob(http.StatusBadRequest, registryErr.Bytes()) + a.logger.Log(ctx, registryErr).Send() + return echoErr + } + + // when scopes only have one action, and that action is pull + isPullRequest := len(scopes) == 1 && len(scopes[0].Actions) == 1 && scopes[0].HasPullAccess() + if isPullRequest { + repo, repoErr := a.registryStore.GetRepositoryByNamespace(ctx.Request().Context(), scopes[0].Name) + if repoErr != nil { + registryErr := common.RegistryErrorResponse( + registry.RegistryErrorCodeNameInvalid, + "requested resource does not exist on the registry", + echo.Map{ + "error": repoErr.Error(), + }, + ) + echoErr := ctx.JSONBlob(http.StatusBadRequest, registryErr.Bytes()) + a.logger.Log(ctx, registryErr).Send() + return echoErr + } + user := ctx.Get(string(types.UserContextKey)).(*types.User) + + if repo.Visibility == types.RepositoryVisibilityPublic { + token, tokenErr := a.newOCIToken(user.ID, scopes) + if tokenErr != nil { + registryErr := common.RegistryErrorResponse( + registry.RegistryErrorCodeNameInvalid, + "error creating oci token", + echo.Map{ + "error": tokenErr.Error(), + }, + ) + echoErr := ctx.JSONBlob(http.StatusBadRequest, registryErr.Bytes()) + a.logger.Log(ctx, registryErr).Send() + return echoErr + } + now := time.Now() + echoErr := ctx.JSON(http.StatusOK, echo.Map{ + "token": token, + "expires_in": now.Add(DefaultOCITokenLifetime).Unix(), + "issued_at": now, + }) + a.logger.Log(ctx, nil).Send() + return echoErr + } + } + + authHeader := ctx.Request().Header.Get(AuthorizationHeaderKey) + if authHeader != "" && len(scopes) != 0 { + token, authErr := a.tryBasicAuthFlow(ctx, scopes) + if authErr != nil { + registryErr := common.RegistryErrorResponse( + registry.RegistryErrorCodeUnauthorized, + "authentication failed", + echo.Map{ + "error": authErr.Error(), + }, + ) + echoErr := ctx.JSONBlob(http.StatusUnauthorized, registryErr.Bytes()) + a.logger.Log(ctx, authErr).Send() + return echoErr + } + now := time.Now() + echoErr := ctx.JSON(http.StatusOK, echo.Map{ + "token": token, + "expires_in": now.Add(DefaultOCITokenLifetime).Unix(), + "issued_at": now, + }) + a.logger.Log(ctx, nil).Send() + return echoErr + } + + registryErr := common.RegistryErrorResponse( + registry.RegistryErrorCodeUnauthorized, + "authentication failed", + nil, + ) + err = ctx.JSONBlob(http.StatusUnauthorized, registryErr.Bytes()) + a.logger.Log(ctx, registryErr).Send() + return err +} + func isOCILoginRequest(url *url.URL) types.OCITokenPermissonClaimList { account := url.Query().Get(OCITokenQueryParamAccount) if account != "" { @@ -157,102 +251,6 @@ func (a *auth) tryBasicAuthFlow(ctx echo.Context, scopes types.OCITokenPermisson return "", nil } -// Token -// request basically comes for -// https://openregistry.dev/token?service=registry.docker.io&scope=repository:samalba/my-app:pull,push -func (a *auth) Token(ctx echo.Context) error { - // TODO (jay-dee7) - check for all valid query params here like serive, client_id, offline_token, etc - // more at this link - https://docs.docker.com/registry/spec/auth/token/ - ctx.Set(types.HandlerStartTime, time.Now()) - - scopes, err := ParseOCITokenPermissionRequest(ctx.Request().URL) - if err != nil { - registryErr := common.RegistryErrorResponse(registry.RegistryErrorCodeUnknown, "invalid scope provided", echo.Map{ - "error": err.Error(), - }) - echoErr := ctx.JSONBlob(http.StatusBadRequest, registryErr.Bytes()) - a.logger.Log(ctx, registryErr).Send() - return echoErr - } - - // when scopes only have one action, and that action is pull - isPullRequest := len(scopes) == 1 && len(scopes[0].Actions) == 1 && scopes[0].HasPullAccess() - if isPullRequest { - repo, repoErr := a.registryStore.GetRepositoryByNamespace(ctx.Request().Context(), scopes[0].Name) - if repoErr != nil { - registryErr := common.RegistryErrorResponse( - registry.RegistryErrorCodeNameInvalid, - "requested resource does not exist on the registry", - echo.Map{ - "error": repoErr.Error(), - }, - ) - echoErr := ctx.JSONBlob(http.StatusBadRequest, registryErr.Bytes()) - a.logger.Log(ctx, registryErr).Send() - return echoErr - } - user := ctx.Get(string(types.UserContextKey)).(*types.User) - - if repo.Visibility == types.RepositoryVisibilityPublic { - token, tokenErr := a.newOCIToken(user.ID, scopes) - if tokenErr != nil { - registryErr := common.RegistryErrorResponse( - registry.RegistryErrorCodeNameInvalid, - "error creating oci token", - echo.Map{ - "error": tokenErr.Error(), - }, - ) - echoErr := ctx.JSONBlob(http.StatusBadRequest, registryErr.Bytes()) - a.logger.Log(ctx, registryErr).Send() - return echoErr - } - now := time.Now() - echoErr := ctx.JSON(http.StatusOK, echo.Map{ - "token": token, - "expires_in": now.Add(DefaultOCITokenLifetime).Unix(), - "issued_at": now, - }) - a.logger.Log(ctx, nil).Send() - return echoErr - } - } - - authHeader := ctx.Request().Header.Get(AuthorizationHeaderKey) - if authHeader != "" && len(scopes) != 0 { - token, authErr := a.tryBasicAuthFlow(ctx, scopes) - if authErr != nil { - registryErr := common.RegistryErrorResponse( - registry.RegistryErrorCodeUnauthorized, - "authentication failed", - echo.Map{ - "error": authErr.Error(), - }, - ) - echoErr := ctx.JSONBlob(http.StatusUnauthorized, registryErr.Bytes()) - a.logger.Log(ctx, authErr).Send() - return echoErr - } - now := time.Now() - echoErr := ctx.JSON(http.StatusOK, echo.Map{ - "token": token, - "expires_in": now.Add(DefaultOCITokenLifetime).Unix(), - "issued_at": now, - }) - a.logger.Log(ctx, nil).Send() - return echoErr - } - - registryErr := common.RegistryErrorResponse( - registry.RegistryErrorCodeUnauthorized, - "authentication failed", - nil, - ) - err = ctx.JSONBlob(http.StatusUnauthorized, registryErr.Bytes()) - a.logger.Log(ctx, registryErr).Send() - return err -} - func (a *auth) getCredsFromHeader(r *http.Request) (string, string, error) { authHeader := r.Header.Get(AuthorizationHeaderKey) if authHeader == "" { diff --git a/auth/permissions.go b/auth/permissions.go index 256677ea..378d666d 100644 --- a/auth/permissions.go +++ b/auth/permissions.go @@ -11,44 +11,6 @@ import ( "github.com/labstack/echo/v4" ) -func (a *auth) getImageNamespace(ctx echo.Context) (string, error) { - if ctx.Request().URL.Path == "/token" { - scope, err := a.getScopeFromQueryParams(ctx.QueryParam("scope")) - if err != nil { - return "", err - } - - return scope.Name, nil - } - username := ctx.Param("username") - imageName := ctx.Param("imagename") - return username + "/" + imageName, nil -} - -func (a *auth) populateUserFromPermissionsCheck(ctx echo.Context) error { - auth := ctx.Request().Header.Get(echo.HeaderAuthorization) - isTokenRequest := ctx.Request().URL.Path == "/token" - - if len(auth) > len(authSchemeBasic)+1 && strings.EqualFold(auth[:len(authSchemeBasic)], authSchemeBasic) { - user, err := a.validateBasicAuthCredentials(auth) - if err != nil { - return err - } - - ctx.Set(string(types.UserContextKey), user) - return nil - } - - // Check if it's an OCI request - if !isTokenRequest { - if _, ok := ctx.Get(string(types.UserContextKey)).(*types.User); ok { - return nil - } - } - - return fmt.Errorf("invalid user credentials: %s", auth) -} - func (a *auth) RepositoryPermissionsMiddleware() echo.MiddlewareFunc { return func(handler echo.HandlerFunc) echo.HandlerFunc { return func(ctx echo.Context) error { @@ -125,6 +87,44 @@ func (a *auth) RepositoryPermissionsMiddleware() echo.MiddlewareFunc { } } +func (a *auth) getImageNamespace(ctx echo.Context) (string, error) { + if ctx.Request().URL.Path == "/token" { + scope, err := a.getScopeFromQueryParams(ctx.QueryParam("scope")) + if err != nil { + return "", err + } + + return scope.Name, nil + } + username := ctx.Param("username") + imageName := ctx.Param("imagename") + return username + "/" + imageName, nil +} + +func (a *auth) populateUserFromPermissionsCheck(ctx echo.Context) error { + auth := ctx.Request().Header.Get(echo.HeaderAuthorization) + isTokenRequest := ctx.Request().URL.Path == "/token" + + if len(auth) > len(authSchemeBasic)+1 && strings.EqualFold(auth[:len(authSchemeBasic)], authSchemeBasic) { + user, err := a.validateBasicAuthCredentials(auth) + if err != nil { + return fmt.Errorf("ERR_USER_PERM_CHECK: %w", err) + } + + ctx.Set(string(types.UserContextKey), user) + return nil + } + + // Check if it's an OCI request + if !isTokenRequest { + if _, ok := ctx.Get(string(types.UserContextKey)).(*types.User); ok { + return nil + } + } + + return fmt.Errorf("invalid user credentials: %s", auth) +} + func (a *auth) handleTokenRequest(ctx echo.Context, handler echo.HandlerFunc) (error, bool) { if err := a.populateUserFromPermissionsCheck(ctx); err != nil { registryErr := common.RegistryErrorResponse( diff --git a/auth/reset_password.go b/auth/reset_password.go index b79931e2..c194269a 100644 --- a/auth/reset_password.go +++ b/auth/reset_password.go @@ -8,8 +8,7 @@ import ( "time" "github.com/containerish/OpenRegistry/services/email" - v2_types "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/containerish/OpenRegistry/types" + "github.com/containerish/OpenRegistry/store/v1/types" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" "github.com/jackc/pgx/v4" @@ -41,7 +40,7 @@ func (a *auth) ResetForgottenPassword(ctx echo.Context) error { return echoErr } - var pwd *types.Password + var pwd *types.ResetPasswordRequest if err := json.NewDecoder(ctx.Request().Body).Decode(&pwd); err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), @@ -72,7 +71,7 @@ func (a *auth) ResetForgottenPassword(ctx echo.Context) error { return echoErr } - if err = v2_types.ValidatePassword(pwd.NewPassword); err != nil { + if err = types.ValidatePassword(pwd.NewPassword); err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), "message": `password must be alphanumeric, at least 8 chars long, must have at least one special character @@ -122,29 +121,17 @@ and an uppercase letter`, func (a *auth) ResetPassword(ctx echo.Context) error { ctx.Set(types.HandlerStartTime, time.Now()) - token, ok := ctx.Get("user").(*jwt.Token) + user, ok := ctx.Get(string(types.UserContextKey)).(*types.User) if !ok { - err := fmt.Errorf("ERR_EMPTY_TOKEN") + err := fmt.Errorf("Unauthorized: missing user auth credentials") echoErr := ctx.JSON(http.StatusUnauthorized, echo.Map{ - "error": err.Error(), - "message": "JWT token can not be empty", - }) - a.logger.Log(ctx, err).Send() - return echoErr - } - - c, ok := token.Claims.(*Claims) - if !ok { - err := fmt.Errorf("ERR_INVALID_CLAIMS") - echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ - "error": err.Error(), - "message": "invalid claims in JWT", + "error": err.Error(), }) a.logger.Log(ctx, err).Send() return echoErr } - var pwd *types.Password + var pwd types.ResetPasswordRequest err := json.NewDecoder(ctx.Request().Body).Decode(&pwd) if err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ @@ -156,26 +143,6 @@ func (a *auth) ResetPassword(ctx echo.Context) error { } defer ctx.Request().Body.Close() - userId, err := uuid.Parse(c.ID) - if err != nil { - echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ - "error": err.Error(), - "message": "invalid user id format", - }) - a.logger.Log(ctx, err).Send() - return echoErr - } - - user, err := a.userStore.GetUserByID(ctx.Request().Context(), userId) - if err != nil { - echoErr := ctx.JSON(http.StatusNotFound, echo.Map{ - "error": err.Error(), - "message": "error getting user by ID from DB", - }) - a.logger.Log(ctx, err).Send() - return echoErr - } - // compare the current password with password hash from DB if !a.verifyPassword(user.Password, pwd.OldPassword) { err = fmt.Errorf("ERR_WRONG_PASSWORD") @@ -208,7 +175,7 @@ func (a *auth) ResetPassword(ctx echo.Context) error { return echoErr } - if err = v2_types.ValidatePassword(pwd.NewPassword); err != nil { + if err = types.ValidatePassword(pwd.NewPassword); err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), "message": `password must be alphanumeric, at least 8 chars long, must have at least one special character @@ -218,7 +185,7 @@ and an uppercase letter`, return echoErr } - if err = a.userStore.UpdateUserPWD(ctx.Request().Context(), userId, hashPassword); err != nil { + if err = a.userStore.UpdateUserPWD(ctx.Request().Context(), user.ID, hashPassword); err != nil { echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), "message": "error updating new password", diff --git a/auth/server/webauthn_server.go b/auth/server/webauthn_server.go index a8fc789a..7108654c 100644 --- a/auth/server/webauthn_server.go +++ b/auth/server/webauthn_server.go @@ -12,11 +12,10 @@ import ( "github.com/containerish/OpenRegistry/auth" "github.com/containerish/OpenRegistry/auth/webauthn" "github.com/containerish/OpenRegistry/config" - v2_types "github.com/containerish/OpenRegistry/store/v1/types" + "github.com/containerish/OpenRegistry/store/v1/types" "github.com/containerish/OpenRegistry/store/v1/users" webauthn_store "github.com/containerish/OpenRegistry/store/v1/webauthn" "github.com/containerish/OpenRegistry/telemetry" - "github.com/containerish/OpenRegistry/types" "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/uptrace/bun" @@ -86,7 +85,7 @@ func (wa *webauthn_server) webAuthNTxnCleanup() { func (wa *webauthn_server) BeginRegistration(ctx echo.Context) error { ctx.Set(types.HandlerStartTime, time.Now()) - user := v2_types.User{} + user := types.User{} if err := json.NewDecoder(ctx.Request().Body).Decode(&user); err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ @@ -97,7 +96,7 @@ func (wa *webauthn_server) BeginRegistration(ctx echo.Context) error { return echoErr } defer ctx.Request().Body.Close() - user.Identities = make(v2_types.Identities) + user.Identities = make(types.Identities) err := user.Validate(false) if err != nil { @@ -131,7 +130,8 @@ func (wa *webauthn_server) BeginRegistration(ctx echo.Context) error { user.ID = uuid.New() user.IsActive = true user.WebauthnConnected = true - user.Identities[v2_types.IdentityProviderWebauthn] = &v2_types.UserIdentity{ + user.UserType = types.UserTypeRegular.String() + user.Identities[types.IdentityProviderWebauthn] = &types.UserIdentity{ ID: user.ID.String(), Username: user.Username, Email: user.Email, diff --git a/cmd/registry/registry.go b/cmd/registry/registry.go index 6f457367..ad3ab2c4 100644 --- a/cmd/registry/registry.go +++ b/cmd/registry/registry.go @@ -99,6 +99,7 @@ func RunRegistryServer(ctx *cli.Context) error { registryStore, usersStore, automationStore, + dfs, ) otelShutdownFunc := otel.ConfigureOtel(cfg.Telemetry, "openregistry-api", baseRouter) diff --git a/orgmode/admin.go b/orgmode/admin.go index 47cfb4fa..3b88fa27 100644 --- a/orgmode/admin.go +++ b/orgmode/admin.go @@ -105,7 +105,23 @@ func (o *orgMode) parseAddUsersToOrgRequest(ctx echo.Context, user *types.User, return fmt.Errorf("organization id mismatch, invalid organization id") } - ctx.Set(string(types.OrgModeRequestBodyContextKey), &body) + parsedBody := types.AddUsersToOrgRequest{ + OrganizationID: body.OrganizationID, + } + for _, perm := range body.Users { + if perm.Pull && perm.Push && !perm.IsAdmin { + perm.IsAdmin = true + } + + if perm.IsAdmin { + perm.Pull = true + perm.Push = true + } + + parsedBody.Users = append(parsedBody.Users, perm) + } + + ctx.Set(string(types.OrgModeRequestBodyContextKey), parsedBody) return nil } @@ -125,6 +141,16 @@ func (o *orgMode) handleOrgModePermissionRequests(ctx echo.Context, user *types. if strings.EqualFold(perms.UserID.String(), perms.OrganizationID.String()) { return fmt.Errorf("user id and organization id can not be the same") } + + if perms.Pull && perms.Push && !perms.IsAdmin { + perms.IsAdmin = true + } + + if perms.IsAdmin { + perms.Pull = true + perms.Push = true + } + ctx.Set(string(types.OrgModeRequestBodyContextKey), &perms) return nil } diff --git a/orgmode/orgmode.go b/orgmode/orgmode.go index a27ea2fb..d271b083 100644 --- a/orgmode/orgmode.go +++ b/orgmode/orgmode.go @@ -76,6 +76,7 @@ func (o *orgMode) AddUserToOrg(ctx echo.Context) error { o.logger.Log(ctx, err).Send() return echoErr } + if err := o.permissionsStore.AddPermissions(ctx.Request().Context(), body); err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), From f14a3c580fc8dd7b379e3a6ff5f78fcde9f15970 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Thu, 21 Dec 2023 14:47:02 +0530 Subject: [PATCH 05/23] feat: Vulnerability Scanning via Clair Signed-off-by: jay-dee7 --- protos/services/yor/clair/v1/clair.proto | 17 +- registry/v2/extensions/private_images.go | 18 +- router/helpers.go | 2 +- router/middlewares.go | 5 +- router/router.go | 13 +- router/vuln_scanning_routes.go | 20 +- .../github_actions/v1/server/build_logs.go | 6 +- services/yor/clair/v1/clair.pb.go | 1064 ++++++++++------- services/yor/clair/v1/clair.pb.validate.go | 442 ++++++- .../clair/v1/clairconnect/clair.connect.go | 31 +- services/yor/clair/v1/server/clair.go | 38 +- services/yor/clair/v1/server/interceptors.go | 124 ++ services/yor/clair/v1/server/server.go | 39 +- store/v1/registry/registry_impl.go | 5 +- 14 files changed, 1337 insertions(+), 487 deletions(-) create mode 100644 services/yor/clair/v1/server/interceptors.go diff --git a/protos/services/yor/clair/v1/clair.proto b/protos/services/yor/clair/v1/clair.proto index 4de74470..df920f87 100644 --- a/protos/services/yor/clair/v1/clair.proto +++ b/protos/services/yor/clair/v1/clair.proto @@ -4,10 +4,20 @@ package services.yor.clair.v1; option go_package = "github.com/containerish/OpenRegistry/services/yor/clair/v1;clair"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; +import "common/v1/id.proto"; service ClairService { rpc SubmitManifestToScan(SubmitManifestToScanRequest) returns (SubmitManifestToScanResponse) {} rpc GetVulnerabilityReport(GetVulnerabilityReportRequest) returns (GetVulnerabilityReportResponse) {} + rpc EnableVulnerabilityScanning(EnableVulnerabilityScanningRequest) returns (EnableVulnerabilityScanningResponse) {} +} + +message EnableVulnerabilityScanningRequest { + common.v1.UUID repository_id = 1; +} + +message EnableVulnerabilityScanningResponse { + string message = 1; } message ClairReportPackage { @@ -16,6 +26,7 @@ message ClairReportPackage { string version = 3; string kind = 4; string arch = 5; + ClairPackageSource source = 6; } message SubmitManifestToScanResponse { @@ -37,13 +48,17 @@ message ClairDescriptor { message SubmitManifestToScanRequest { string hash = 1; - repeated ClairDescriptor layers = 2; } message GetVulnerabilityReportRequest { string manifest_id = 1; } +message ClairIndexManifestRequest { + string hash = 1; + repeated ClairDescriptor layers = 2; +} + message ClairPackageSource { string id = 1; string name = 2; diff --git a/registry/v2/extensions/private_images.go b/registry/v2/extensions/private_images.go index 189a0548..38a56fb6 100644 --- a/registry/v2/extensions/private_images.go +++ b/registry/v2/extensions/private_images.go @@ -1,7 +1,6 @@ package extensions import ( - "encoding/json" "net/http" "time" @@ -14,21 +13,28 @@ func (ext *extension) ChangeContainerImageVisibility(ctx echo.Context) error { var body types.ContainerImageVisibilityChangeRequest - if err := json.NewDecoder(ctx.Request().Body).Decode(&body); err != nil { - return ctx.JSON(http.StatusBadRequest, echo.Map{ + if err := ctx.Bind(&body); err != nil { + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": "invalid request body", }) + + ext.logger.Log(ctx, err).Send() + return echoErr } defer ctx.Request().Body.Close() - err := ext.store.SetContainerImageVisibility(ctx.Request().Context(), body.ImageManifestUUID, body.Visibility) + err := ext.store.SetContainerImageVisibility(ctx.Request().Context(), body.RepositoryID, body.Visibility) if err != nil { - return ctx.JSON(http.StatusBadRequest, echo.Map{ + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), }) + ext.logger.Log(ctx, err).Send() + return echoErr } - return ctx.JSON(http.StatusOK, echo.Map{ + echoErr := ctx.JSON(http.StatusOK, echo.Map{ "message": "container image visibility mode changed successfully", }) + ext.logger.Log(ctx, nil).Send() + return echoErr } diff --git a/router/helpers.go b/router/helpers.go index 0c6351ae..49fef37c 100644 --- a/router/helpers.go +++ b/router/helpers.go @@ -19,7 +19,7 @@ func RegisterAuthRoutes(authRouter *echo.Group, authSvc auth.Authentication) { authRouter.Add(http.MethodGet, "/sessions/me", authSvc.ReadUserWithSession) authRouter.Add(http.MethodDelete, "/sessions", authSvc.ExpireSessions) authRouter.Add(http.MethodGet, "/renew", authSvc.RenewAccessToken) - authRouter.Add(http.MethodPost, "/reset-password", authSvc.ResetPassword, authSvc.JWT()) + authRouter.Add(http.MethodPost, "/reset-password", authSvc.ResetPassword, authSvc.JWTRest()) authRouter.Add(http.MethodPost, "/reset-forgotten-password", authSvc.ResetForgottenPassword, authSvc.JWT()) authRouter.Add(http.MethodGet, "/forgot-password", authSvc.ForgotPassword) } diff --git a/router/middlewares.go b/router/middlewares.go index 55fd2ec7..114a7c08 100644 --- a/router/middlewares.go +++ b/router/middlewares.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "regexp" + "strings" "github.com/containerish/OpenRegistry/common" "github.com/containerish/OpenRegistry/registry/v2" @@ -20,12 +21,12 @@ func registryNamespaceValidator(logger telemetry.Logger) echo.MiddlewareFunc { return func(handler echo.HandlerFunc) echo.HandlerFunc { return func(ctx echo.Context) error { // we skip the /v2/ path since it isn't a namespaced path - if ctx.Request().URL.Path == "/v2/" { + if ctx.Request().URL.Path == "/v2/" || strings.HasPrefix(ctx.Request().URL.Path, "/v2/ext/") { return handler(ctx) } namespace := ctx.Param("username") + "/" + ctx.Param("imagename") - if namespace != "/" && !nsRegex.MatchString(namespace) { + if !nsRegex.MatchString(namespace) { registryErr := common.RegistryErrorResponse( registry.RegistryErrorCodeNameInvalid, "invalid user namespace", diff --git a/router/router.go b/router/router.go index 6d90c8b0..792b505f 100644 --- a/router/router.go +++ b/router/router.go @@ -9,6 +9,7 @@ import ( "github.com/containerish/OpenRegistry/auth" auth_server "github.com/containerish/OpenRegistry/auth/server" "github.com/containerish/OpenRegistry/config" + "github.com/containerish/OpenRegistry/dfs" "github.com/containerish/OpenRegistry/orgmode" "github.com/containerish/OpenRegistry/registry/v2" "github.com/containerish/OpenRegistry/registry/v2/extensions" @@ -37,6 +38,7 @@ func Register( registryStore registry_store.RegistryStore, usersStore users_store.UserStore, automationStore automation.BuildAutomationStore, + dfs dfs.DFS, ) *echo.Echo { e := setDefaultEchoOptions(cfg.WebAppConfig, healthCheckApi) @@ -58,10 +60,17 @@ func Register( RegisterUserRoutes(userApiRouter, usersApi) RegisterNSRoutes(nsRouter, registryApi, registryStore, logger) RegisterAuthRoutes(authRouter, authApi) - RegisterExtensionsRoutes(ociRouter, registryApi, extensionsApi) + RegisterExtensionsRoutes(ociRouter, registryApi, extensionsApi, authApi.JWTRest()) RegisterWebauthnRoutes(webauthnRouter, webauthnApi) RegisterOrgModeRoutes(orgModeRouter, orgModeApi) - RegisterVulnScaningRoutes(cfg.Integrations.GetClairConfig(), logger) + RegisterVulnScaningRoutes( + usersStore, + cfg.Integrations.GetClairConfig(), + &cfg.Registry.Auth, + logger, + registryStore.GetLayersLinksForManifest, + dfs.GeneratePresignedURL, + ) if cfg.Integrations.GetGithubConfig() != nil && cfg.Integrations.GetGithubConfig().Enabled { RegisterGitHubRoutes( diff --git a/router/vuln_scanning_routes.go b/router/vuln_scanning_routes.go index a051e142..4f98f0b1 100644 --- a/router/vuln_scanning_routes.go +++ b/router/vuln_scanning_routes.go @@ -7,6 +7,7 @@ import ( "github.com/containerish/OpenRegistry/config" "github.com/containerish/OpenRegistry/services/yor/clair/v1/server" + "github.com/containerish/OpenRegistry/store/v1/users" "github.com/containerish/OpenRegistry/telemetry" "github.com/fatih/color" "golang.org/x/net/http2" @@ -14,13 +15,24 @@ import ( ) func RegisterVulnScaningRoutes( - config *config.ClairIntegration, + userStore users.UserStore, + clairConfig *config.ClairIntegration, + authConfig *config.Auth, logger telemetry.Logger, + layerLinkReader server.LayerLinkReader, + prePresignedURLGenerator server.PresignedURLGenerator, ) { - if config != nil && config.Enabled { - clairApi := server.NewClairClient(config, logger) + if clairConfig != nil && clairConfig.Enabled { + clairApi := server.NewClairClient( + userStore, + clairConfig, + authConfig, + logger, + layerLinkReader, + prePresignedURLGenerator, + ) go func() { - addr := net.JoinHostPort(config.Host, fmt.Sprintf("%d", config.Port)) + addr := net.JoinHostPort(clairConfig.Host, fmt.Sprintf("%d", clairConfig.Port)) color.Green("connect-go Clair gRPC service running on: %s", addr) if err := http.ListenAndServe(addr, h2c.NewHandler(clairApi, &http2.Server{})); err != nil { color.Red("connect-go listen error: %s", err) diff --git a/services/kon/github_actions/v1/server/build_logs.go b/services/kon/github_actions/v1/server/build_logs.go index a9e09a19..dcaafebe 100644 --- a/services/kon/github_actions/v1/server/build_logs.go +++ b/services/kon/github_actions/v1/server/build_logs.go @@ -316,7 +316,11 @@ func (ghs *GitHubActionsServer) waitForJobToFinish( stream *connect_go.ServerStream[github_actions_v1.StreamWorkflowRunLogsResponse], ) error { now := time.Now() - logEvent := ghs.logger.Debug().Str("method", "waitForJobToFinish").Int64("run_id", req.Msg.GetRunId()).Str("repo_name", req.Msg.GetRepoName()).Str("repo_owner", req.Msg.GetRepoOwner()) + logEvent := ghs.logger.Debug(). + Str("method", "waitForJobToFinish"). + Int64("run_id", req.Msg.GetRunId()). + Str("repo_name", req.Msg.GetRepoName()). + Str("repo_owner", req.Msg.GetRepoOwner()) workflowRun, _, err := githubClient.Actions.GetWorkflowRunByID( ctx, diff --git a/services/yor/clair/v1/clair.pb.go b/services/yor/clair/v1/clair.pb.go index 28145af2..c8e704bb 100644 --- a/services/yor/clair/v1/clair.pb.go +++ b/services/yor/clair/v1/clair.pb.go @@ -7,6 +7,7 @@ package clair import ( + v1 "github.com/containerish/OpenRegistry/common/v1" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" structpb "google.golang.org/protobuf/types/known/structpb" @@ -22,22 +23,117 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type EnableVulnerabilityScanningRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RepositoryId *v1.UUID `protobuf:"bytes,1,opt,name=repository_id,json=repositoryId,proto3" json:"repository_id,omitempty"` +} + +func (x *EnableVulnerabilityScanningRequest) Reset() { + *x = EnableVulnerabilityScanningRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnableVulnerabilityScanningRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnableVulnerabilityScanningRequest) ProtoMessage() {} + +func (x *EnableVulnerabilityScanningRequest) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EnableVulnerabilityScanningRequest.ProtoReflect.Descriptor instead. +func (*EnableVulnerabilityScanningRequest) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{0} +} + +func (x *EnableVulnerabilityScanningRequest) GetRepositoryId() *v1.UUID { + if x != nil { + return x.RepositoryId + } + return nil +} + +type EnableVulnerabilityScanningResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *EnableVulnerabilityScanningResponse) Reset() { + *x = EnableVulnerabilityScanningResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnableVulnerabilityScanningResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnableVulnerabilityScanningResponse) ProtoMessage() {} + +func (x *EnableVulnerabilityScanningResponse) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EnableVulnerabilityScanningResponse.ProtoReflect.Descriptor instead. +func (*EnableVulnerabilityScanningResponse) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{1} +} + +func (x *EnableVulnerabilityScanningResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + type ClairReportPackage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` - Kind string `protobuf:"bytes,4,opt,name=kind,proto3" json:"kind,omitempty"` - Arch string `protobuf:"bytes,5,opt,name=arch,proto3" json:"arch,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + Kind string `protobuf:"bytes,4,opt,name=kind,proto3" json:"kind,omitempty"` + Arch string `protobuf:"bytes,5,opt,name=arch,proto3" json:"arch,omitempty"` + Source *ClairPackageSource `protobuf:"bytes,6,opt,name=source,proto3" json:"source,omitempty"` } func (x *ClairReportPackage) Reset() { *x = ClairReportPackage{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[0] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -50,7 +146,7 @@ func (x *ClairReportPackage) String() string { func (*ClairReportPackage) ProtoMessage() {} func (x *ClairReportPackage) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[0] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -63,7 +159,7 @@ func (x *ClairReportPackage) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairReportPackage.ProtoReflect.Descriptor instead. func (*ClairReportPackage) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{0} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{2} } func (x *ClairReportPackage) GetId() string { @@ -101,6 +197,13 @@ func (x *ClairReportPackage) GetArch() string { return "" } +func (x *ClairReportPackage) GetSource() *ClairPackageSource { + if x != nil { + return x.Source + } + return nil +} + type SubmitManifestToScanResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -119,7 +222,7 @@ type SubmitManifestToScanResponse struct { func (x *SubmitManifestToScanResponse) Reset() { *x = SubmitManifestToScanResponse{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[1] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -132,7 +235,7 @@ func (x *SubmitManifestToScanResponse) String() string { func (*SubmitManifestToScanResponse) ProtoMessage() {} func (x *SubmitManifestToScanResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[1] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -145,7 +248,7 @@ func (x *SubmitManifestToScanResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitManifestToScanResponse.ProtoReflect.Descriptor instead. func (*SubmitManifestToScanResponse) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{1} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{3} } func (x *SubmitManifestToScanResponse) GetSuccess() bool { @@ -217,7 +320,7 @@ type ClairDescriptor struct { func (x *ClairDescriptor) Reset() { *x = ClairDescriptor{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[2] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -230,7 +333,7 @@ func (x *ClairDescriptor) String() string { func (*ClairDescriptor) ProtoMessage() {} func (x *ClairDescriptor) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[2] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -243,7 +346,7 @@ func (x *ClairDescriptor) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairDescriptor.ProtoReflect.Descriptor instead. func (*ClairDescriptor) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{2} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{4} } func (x *ClairDescriptor) GetHash() string { @@ -272,14 +375,13 @@ type SubmitManifestToScanRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` - Layers []*ClairDescriptor `protobuf:"bytes,2,rep,name=layers,proto3" json:"layers,omitempty"` + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` } func (x *SubmitManifestToScanRequest) Reset() { *x = SubmitManifestToScanRequest{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[3] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -292,7 +394,7 @@ func (x *SubmitManifestToScanRequest) String() string { func (*SubmitManifestToScanRequest) ProtoMessage() {} func (x *SubmitManifestToScanRequest) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[3] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -305,7 +407,7 @@ func (x *SubmitManifestToScanRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitManifestToScanRequest.ProtoReflect.Descriptor instead. func (*SubmitManifestToScanRequest) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{3} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{5} } func (x *SubmitManifestToScanRequest) GetHash() string { @@ -315,13 +417,6 @@ func (x *SubmitManifestToScanRequest) GetHash() string { return "" } -func (x *SubmitManifestToScanRequest) GetLayers() []*ClairDescriptor { - if x != nil { - return x.Layers - } - return nil -} - type GetVulnerabilityReportRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -333,7 +428,7 @@ type GetVulnerabilityReportRequest struct { func (x *GetVulnerabilityReportRequest) Reset() { *x = GetVulnerabilityReportRequest{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[4] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -346,7 +441,7 @@ func (x *GetVulnerabilityReportRequest) String() string { func (*GetVulnerabilityReportRequest) ProtoMessage() {} func (x *GetVulnerabilityReportRequest) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[4] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -359,7 +454,7 @@ func (x *GetVulnerabilityReportRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetVulnerabilityReportRequest.ProtoReflect.Descriptor instead. func (*GetVulnerabilityReportRequest) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{4} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{6} } func (x *GetVulnerabilityReportRequest) GetManifestId() string { @@ -369,6 +464,61 @@ func (x *GetVulnerabilityReportRequest) GetManifestId() string { return "" } +type ClairIndexManifestRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` + Layers []*ClairDescriptor `protobuf:"bytes,2,rep,name=layers,proto3" json:"layers,omitempty"` +} + +func (x *ClairIndexManifestRequest) Reset() { + *x = ClairIndexManifestRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClairIndexManifestRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClairIndexManifestRequest) ProtoMessage() {} + +func (x *ClairIndexManifestRequest) ProtoReflect() protoreflect.Message { + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClairIndexManifestRequest.ProtoReflect.Descriptor instead. +func (*ClairIndexManifestRequest) Descriptor() ([]byte, []int) { + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{7} +} + +func (x *ClairIndexManifestRequest) GetHash() string { + if x != nil { + return x.Hash + } + return "" +} + +func (x *ClairIndexManifestRequest) GetLayers() []*ClairDescriptor { + if x != nil { + return x.Layers + } + return nil +} + type ClairPackageSource struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -383,7 +533,7 @@ type ClairPackageSource struct { func (x *ClairPackageSource) Reset() { *x = ClairPackageSource{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[5] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -396,7 +546,7 @@ func (x *ClairPackageSource) String() string { func (*ClairPackageSource) ProtoMessage() {} func (x *ClairPackageSource) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[5] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -409,7 +559,7 @@ func (x *ClairPackageSource) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairPackageSource.ProtoReflect.Descriptor instead. func (*ClairPackageSource) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{5} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{8} } func (x *ClairPackageSource) GetId() string { @@ -456,7 +606,7 @@ type ClairPackage struct { func (x *ClairPackage) Reset() { *x = ClairPackage{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[6] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -469,7 +619,7 @@ func (x *ClairPackage) String() string { func (*ClairPackage) ProtoMessage() {} func (x *ClairPackage) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[6] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -482,7 +632,7 @@ func (x *ClairPackage) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairPackage.ProtoReflect.Descriptor instead. func (*ClairPackage) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{6} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{9} } func (x *ClairPackage) GetId() string { @@ -546,7 +696,7 @@ type ClairDistribution struct { func (x *ClairDistribution) Reset() { *x = ClairDistribution{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[7] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -559,7 +709,7 @@ func (x *ClairDistribution) String() string { func (*ClairDistribution) ProtoMessage() {} func (x *ClairDistribution) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[7] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -572,7 +722,7 @@ func (x *ClairDistribution) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairDistribution.ProtoReflect.Descriptor instead. func (*ClairDistribution) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{7} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{10} } func (x *ClairDistribution) GetId() string { @@ -652,7 +802,7 @@ type ClairEnvironmentItem struct { func (x *ClairEnvironmentItem) Reset() { *x = ClairEnvironmentItem{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[8] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -665,7 +815,7 @@ func (x *ClairEnvironmentItem) String() string { func (*ClairEnvironmentItem) ProtoMessage() {} func (x *ClairEnvironmentItem) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[8] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -678,7 +828,7 @@ func (x *ClairEnvironmentItem) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairEnvironmentItem.ProtoReflect.Descriptor instead. func (*ClairEnvironmentItem) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{8} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{11} } func (x *ClairEnvironmentItem) GetPackageDb() string { @@ -720,7 +870,7 @@ type ClairRepository struct { func (x *ClairRepository) Reset() { *x = ClairRepository{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[9] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -733,7 +883,7 @@ func (x *ClairRepository) String() string { func (*ClairRepository) ProtoMessage() {} func (x *ClairRepository) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[9] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -746,7 +896,7 @@ func (x *ClairRepository) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairRepository.ProtoReflect.Descriptor instead. func (*ClairRepository) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{9} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{12} } func (x *ClairRepository) GetId() string { @@ -778,7 +928,7 @@ type ClairVulnerability struct { func (x *ClairVulnerability) Reset() { *x = ClairVulnerability{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[10] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -791,7 +941,7 @@ func (x *ClairVulnerability) String() string { func (*ClairVulnerability) ProtoMessage() {} func (x *ClairVulnerability) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[10] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -804,7 +954,7 @@ func (x *ClairVulnerability) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairVulnerability.ProtoReflect.Descriptor instead. func (*ClairVulnerability) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{10} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{13} } func (x *ClairVulnerability) GetId() string { @@ -902,7 +1052,7 @@ type ClairEnrichment struct { func (x *ClairEnrichment) Reset() { *x = ClairEnrichment{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[11] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -915,7 +1065,7 @@ func (x *ClairEnrichment) String() string { func (*ClairEnrichment) ProtoMessage() {} func (x *ClairEnrichment) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[11] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -928,7 +1078,7 @@ func (x *ClairEnrichment) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairEnrichment.ProtoReflect.Descriptor instead. func (*ClairEnrichment) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{11} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{14} } func (x *ClairEnrichment) GetId() string { @@ -949,7 +1099,7 @@ type ClairVulnerabilityIdList struct { func (x *ClairVulnerabilityIdList) Reset() { *x = ClairVulnerabilityIdList{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[12] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -962,7 +1112,7 @@ func (x *ClairVulnerabilityIdList) String() string { func (*ClairVulnerabilityIdList) ProtoMessage() {} func (x *ClairVulnerabilityIdList) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[12] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -975,7 +1125,7 @@ func (x *ClairVulnerabilityIdList) ProtoReflect() protoreflect.Message { // Deprecated: Use ClairVulnerabilityIdList.ProtoReflect.Descriptor instead. func (*ClairVulnerabilityIdList) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{12} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{15} } func (x *ClairVulnerabilityIdList) GetIds() []string { @@ -1006,7 +1156,7 @@ type GetVulnerabilityReportResponse struct { func (x *GetVulnerabilityReportResponse) Reset() { *x = GetVulnerabilityReportResponse{} if protoimpl.UnsafeEnabled { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[13] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1019,7 +1169,7 @@ func (x *GetVulnerabilityReportResponse) String() string { func (*GetVulnerabilityReportResponse) ProtoMessage() {} func (x *GetVulnerabilityReportResponse) ProtoReflect() protoreflect.Message { - mi := &file_services_yor_clair_v1_clair_proto_msgTypes[13] + mi := &file_services_yor_clair_v1_clair_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1032,7 +1182,7 @@ func (x *GetVulnerabilityReportResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetVulnerabilityReportResponse.ProtoReflect.Descriptor instead. func (*GetVulnerabilityReportResponse) Descriptor() ([]byte, []int) { - return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{13} + return file_services_yor_clair_v1_clair_proto_rawDescGZIP(), []int{16} } func (x *GetVulnerabilityReportResponse) GetManifestHash() string { @@ -1122,311 +1272,339 @@ var file_services_yor_clair_v1_clair_proto_rawDesc = []byte{ 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x7a, 0x0a, 0x12, 0x43, 0x6c, 0x61, - 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, - 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0xba, 0x07, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, - 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, - 0x72, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x72, 0x72, 0x12, 0x5d, 0x0a, - 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x41, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, - 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, - 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x6c, 0x0a, 0x0d, - 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, - 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x64, 0x69, 0x73, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x63, 0x0a, 0x0a, 0x72, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, - 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, - 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, - 0x69, 0x0a, 0x0c, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, - 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, - 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x65, 0x6e, - 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x66, 0x0a, 0x0d, 0x50, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3f, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x1a, 0x6a, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65, - 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, - 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5b, 0x0a, 0x11, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0xde, 0x01, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, - 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x4d, 0x0a, 0x07, - 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, - 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x1a, 0x56, 0x0a, 0x0c, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x71, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, - 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3e, 0x0a, 0x06, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6c, 0x61, 0x69, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x06, - 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x22, 0x40, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, - 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x6e, 0x69, 0x66, - 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, - 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x66, 0x0a, 0x12, 0x43, 0x6c, 0x61, 0x69, - 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, - 0x22, 0xb7, 0x01, 0x0a, 0x0c, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x12, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5a, 0x0a, + 0x22, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x55, 0x49, 0x44, 0x52, 0x0c, 0x72, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3f, 0x0a, 0x23, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xbd, 0x01, 0x0a, 0x12, 0x43, + 0x6c, 0x61, 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, - 0x69, 0x6e, 0x64, 0x12, 0x41, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, - 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, - 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x22, 0xf5, 0x01, 0x0a, 0x11, 0x43, - 0x6c, 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, - 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, - 0x72, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x12, - 0x10, 0x0a, 0x03, 0x63, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x70, - 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x4e, 0x61, - 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, 0x14, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x45, 0x6e, 0x76, 0x69, - 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x44, 0x62, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, - 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x49, 0x6e, 0x12, - 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x73, 0x22, - 0x21, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x22, 0x8a, 0x04, 0x0a, 0x12, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x56, 0x75, 0x6c, 0x6e, - 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x06, 0x69, 0x73, 0x73, - 0x75, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x12, 0x14, 0x0a, - 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x69, - 0x6e, 0x6b, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, - 0x2f, 0x0a, 0x13, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x73, 0x65, - 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6e, 0x6f, - 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, - 0x12, 0x3d, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, - 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, - 0x4c, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, - 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0c, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, - 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, - 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x69, - 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x66, 0x69, 0x78, 0x65, 0x64, 0x49, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0x21, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x45, 0x6e, 0x72, 0x69, 0x63, 0x68, 0x6d, 0x65, - 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, - 0x69, 0x64, 0x22, 0x2c, 0x0a, 0x18, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x56, 0x75, 0x6c, 0x6e, 0x65, - 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, - 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, - 0x22, 0xe1, 0x0b, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, - 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x6e, 0x69, - 0x66, 0x65, 0x73, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, - 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x72, 0x72, - 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x5f, 0x0a, 0x08, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x6e, 0x0a, 0x0d, 0x64, - 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, - 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, - 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x64, 0x69, - 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x6b, 0x0a, 0x0c, 0x65, - 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x47, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, - 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, - 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x65, 0x6e, 0x76, 0x69, - 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x8a, 0x01, 0x0a, 0x17, 0x70, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x51, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, - 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x16, 0x70, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x0b, 0x65, 0x6e, 0x72, 0x69, 0x63, 0x68, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, + 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, 0x12, 0x41, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xba, 0x07, 0x0a, 0x1c, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, + 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, + 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, + 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, + 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, + 0x72, 0x72, 0x12, 0x5d, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x73, 0x12, 0x6c, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, + 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x69, + 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0d, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x63, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x07, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, + 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x12, 0x69, 0x0a, 0x0c, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x45, 0x6e, 0x72, 0x69, 0x63, 0x68, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x72, 0x69, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, - 0x65, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x0a, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, - 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, - 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x74, 0x0a, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, - 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x4a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, - 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, - 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x76, 0x75, 0x6c, - 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x60, 0x0a, 0x0d, - 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, + 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0c, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x1a, + 0x66, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, + 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6a, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, + 0x3e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, - 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x61, 0x63, 0x6b, - 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6a, - 0x0a, 0x12, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, - 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x1a, 0x65, 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5b, 0x0a, 0x11, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65, 0x0a, 0x1b, 0x50, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65, - 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xde, 0x01, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, + 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, + 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, + 0x69, 0x12, 0x4d, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, - 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6d, 0x0a, 0x14, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, - 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, - 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x56, 0x75, 0x6c, 0x6e, - 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x32, 0x9c, 0x02, 0x0a, 0x0c, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x32, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, + 0x1a, 0x56, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x31, 0x0a, 0x1b, 0x53, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x40, 0x0a, 0x1d, 0x47, + 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, + 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x6f, 0x0a, + 0x19, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d, 0x61, 0x6e, 0x69, 0x66, + 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3e, + 0x0a, 0x06, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, - 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, - 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, - 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x87, 0x01, 0x0a, 0x16, 0x47, 0x65, + 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x06, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x22, 0x66, + 0x0a, 0x12, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0xb7, 0x01, 0x0a, 0x0c, 0x43, 0x6c, 0x61, 0x69, 0x72, + 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x41, 0x0a, 0x06, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x61, 0x72, 0x63, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x72, 0x63, 0x68, + 0x22, 0xf5, 0x01, 0x0a, 0x11, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x61, 0x72, 0x63, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x63, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x74, 0x74, + 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, + 0x65, 0x74, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xaa, 0x01, 0x0a, 0x14, 0x43, 0x6c, 0x61, + 0x69, 0x72, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x74, 0x65, + 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x62, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x44, 0x62, + 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x5f, 0x69, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x65, 0x64, 0x49, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x25, + 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x49, 0x64, 0x73, 0x22, 0x21, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x8a, 0x04, 0x0a, 0x12, 0x43, 0x6c, 0x61, + 0x69, 0x72, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x18, 0x0a, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x32, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x69, 0x73, 0x73, + 0x75, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, + 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, + 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2f, 0x0a, 0x13, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x12, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x53, 0x65, + 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x07, 0x70, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x4c, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, + 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, + 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x66, + 0x69, 0x78, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x69, 0x78, 0x65, 0x64, 0x49, 0x6e, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x21, 0x0a, 0x0f, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x45, 0x6e, + 0x72, 0x69, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2c, 0x0a, 0x18, 0x43, 0x6c, 0x61, 0x69, + 0x72, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x49, 0x64, + 0x4c, 0x69, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0xe1, 0x0b, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x56, 0x75, + 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x6e, + 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, + 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x65, 0x72, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x12, 0x5f, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, + 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, + 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x73, 0x12, 0x6e, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x6b, 0x0a, 0x0c, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x47, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, + 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0c, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x8a, + 0x01, 0x0a, 0x17, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x75, 0x6c, 0x6e, 0x65, + 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x51, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, + 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, + 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, + 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x16, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x75, 0x6c, 0x6e, + 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x0b, 0x65, + 0x6e, 0x72, 0x69, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, + 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x45, 0x6e, + 0x72, 0x69, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x6e, 0x72, 0x69, 0x63, 0x68, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x65, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x79, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x74, 0x0a, 0x0f, + 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, + 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x12, 0x34, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, - 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x73, 0x65, 0x72, + 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x75, 0x6c, + 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0f, 0x76, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x1a, 0x60, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, + 0x69, 0x72, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6a, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x1a, 0x5b, 0x0a, 0x11, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65, 0x0a, + 0x1b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x65, 0x0a, 0x0f, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3c, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6d, 0x0a, 0x14, 0x56, + 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, + 0x69, 0x72, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xb5, 0x03, 0x0a, 0x0c, 0x43, + 0x6c, 0x61, 0x69, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x14, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, + 0x53, 0x63, 0x61, 0x6e, 0x12, 0x32, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, 0x6f, 0x53, 0x63, 0x61, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x54, + 0x6f, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x87, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x34, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x42, 0xe0, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x35, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, + 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x75, 0x6c, 0x6e, + 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x96, 0x01, 0x0a, 0x1b, 0x45, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x39, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, - 0x31, 0x42, 0x0a, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x69, 0x73, 0x68, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x79, - 0x6f, 0x72, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6c, 0x61, 0x69, - 0x72, 0xa2, 0x02, 0x03, 0x53, 0x59, 0x43, 0xaa, 0x02, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x59, 0x6f, 0x72, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x56, 0x31, 0xca, - 0x02, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x59, 0x6f, 0x72, 0x5c, 0x43, - 0x6c, 0x61, 0x69, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x21, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x5c, 0x59, 0x6f, 0x72, 0x5c, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x5c, 0x56, 0x31, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x18, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x3a, 0x59, 0x6f, 0x72, 0x3a, 0x3a, 0x43, 0x6c, 0x61, - 0x69, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x56, 0x75, 0x6c, 0x6e, 0x65, 0x72, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x42, 0xe0, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x2e, 0x79, 0x6f, 0x72, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x31, + 0x42, 0x0a, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x40, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x69, 0x73, 0x68, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x52, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x72, 0x79, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x79, 0x6f, + 0x72, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6c, 0x61, 0x69, 0x72, + 0xa2, 0x02, 0x03, 0x53, 0x59, 0x43, 0xaa, 0x02, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2e, 0x59, 0x6f, 0x72, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, + 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5c, 0x59, 0x6f, 0x72, 0x5c, 0x43, 0x6c, + 0x61, 0x69, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x21, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x5c, 0x59, 0x6f, 0x72, 0x5c, 0x43, 0x6c, 0x61, 0x69, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x18, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x3a, 0x59, 0x6f, 0x72, 0x3a, 0x3a, 0x43, 0x6c, 0x61, 0x69, + 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1441,75 +1619,83 @@ func file_services_yor_clair_v1_clair_proto_rawDescGZIP() []byte { return file_services_yor_clair_v1_clair_proto_rawDescData } -var file_services_yor_clair_v1_clair_proto_msgTypes = make([]protoimpl.MessageInfo, 25) +var file_services_yor_clair_v1_clair_proto_msgTypes = make([]protoimpl.MessageInfo, 28) var file_services_yor_clair_v1_clair_proto_goTypes = []interface{}{ - (*ClairReportPackage)(nil), // 0: services.yor.clair.v1.ClairReportPackage - (*SubmitManifestToScanResponse)(nil), // 1: services.yor.clair.v1.SubmitManifestToScanResponse - (*ClairDescriptor)(nil), // 2: services.yor.clair.v1.ClairDescriptor - (*SubmitManifestToScanRequest)(nil), // 3: services.yor.clair.v1.SubmitManifestToScanRequest - (*GetVulnerabilityReportRequest)(nil), // 4: services.yor.clair.v1.GetVulnerabilityReportRequest - (*ClairPackageSource)(nil), // 5: services.yor.clair.v1.ClairPackageSource - (*ClairPackage)(nil), // 6: services.yor.clair.v1.ClairPackage - (*ClairDistribution)(nil), // 7: services.yor.clair.v1.ClairDistribution - (*ClairEnvironmentItem)(nil), // 8: services.yor.clair.v1.ClairEnvironmentItem - (*ClairRepository)(nil), // 9: services.yor.clair.v1.ClairRepository - (*ClairVulnerability)(nil), // 10: services.yor.clair.v1.ClairVulnerability - (*ClairEnrichment)(nil), // 11: services.yor.clair.v1.ClairEnrichment - (*ClairVulnerabilityIdList)(nil), // 12: services.yor.clair.v1.ClairVulnerabilityIdList - (*GetVulnerabilityReportResponse)(nil), // 13: services.yor.clair.v1.GetVulnerabilityReportResponse - nil, // 14: services.yor.clair.v1.SubmitManifestToScanResponse.PackagesEntry - nil, // 15: services.yor.clair.v1.SubmitManifestToScanResponse.DistributionsEntry - nil, // 16: services.yor.clair.v1.SubmitManifestToScanResponse.RepositoryEntry - nil, // 17: services.yor.clair.v1.SubmitManifestToScanResponse.EnvironmentsEntry - nil, // 18: services.yor.clair.v1.ClairDescriptor.HeadersEntry - nil, // 19: services.yor.clair.v1.GetVulnerabilityReportResponse.PackagesEntry - nil, // 20: services.yor.clair.v1.GetVulnerabilityReportResponse.DistributionsEntry - nil, // 21: services.yor.clair.v1.GetVulnerabilityReportResponse.EnvironmentsEntry - nil, // 22: services.yor.clair.v1.GetVulnerabilityReportResponse.PackageVulnerabilitiesEntry - nil, // 23: services.yor.clair.v1.GetVulnerabilityReportResponse.RepositoryEntry - nil, // 24: services.yor.clair.v1.GetVulnerabilityReportResponse.VulnerabilitiesEntry - (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp - (*structpb.ListValue)(nil), // 26: google.protobuf.ListValue + (*EnableVulnerabilityScanningRequest)(nil), // 0: services.yor.clair.v1.EnableVulnerabilityScanningRequest + (*EnableVulnerabilityScanningResponse)(nil), // 1: services.yor.clair.v1.EnableVulnerabilityScanningResponse + (*ClairReportPackage)(nil), // 2: services.yor.clair.v1.ClairReportPackage + (*SubmitManifestToScanResponse)(nil), // 3: services.yor.clair.v1.SubmitManifestToScanResponse + (*ClairDescriptor)(nil), // 4: services.yor.clair.v1.ClairDescriptor + (*SubmitManifestToScanRequest)(nil), // 5: services.yor.clair.v1.SubmitManifestToScanRequest + (*GetVulnerabilityReportRequest)(nil), // 6: services.yor.clair.v1.GetVulnerabilityReportRequest + (*ClairIndexManifestRequest)(nil), // 7: services.yor.clair.v1.ClairIndexManifestRequest + (*ClairPackageSource)(nil), // 8: services.yor.clair.v1.ClairPackageSource + (*ClairPackage)(nil), // 9: services.yor.clair.v1.ClairPackage + (*ClairDistribution)(nil), // 10: services.yor.clair.v1.ClairDistribution + (*ClairEnvironmentItem)(nil), // 11: services.yor.clair.v1.ClairEnvironmentItem + (*ClairRepository)(nil), // 12: services.yor.clair.v1.ClairRepository + (*ClairVulnerability)(nil), // 13: services.yor.clair.v1.ClairVulnerability + (*ClairEnrichment)(nil), // 14: services.yor.clair.v1.ClairEnrichment + (*ClairVulnerabilityIdList)(nil), // 15: services.yor.clair.v1.ClairVulnerabilityIdList + (*GetVulnerabilityReportResponse)(nil), // 16: services.yor.clair.v1.GetVulnerabilityReportResponse + nil, // 17: services.yor.clair.v1.SubmitManifestToScanResponse.PackagesEntry + nil, // 18: services.yor.clair.v1.SubmitManifestToScanResponse.DistributionsEntry + nil, // 19: services.yor.clair.v1.SubmitManifestToScanResponse.RepositoryEntry + nil, // 20: services.yor.clair.v1.SubmitManifestToScanResponse.EnvironmentsEntry + nil, // 21: services.yor.clair.v1.ClairDescriptor.HeadersEntry + nil, // 22: services.yor.clair.v1.GetVulnerabilityReportResponse.PackagesEntry + nil, // 23: services.yor.clair.v1.GetVulnerabilityReportResponse.DistributionsEntry + nil, // 24: services.yor.clair.v1.GetVulnerabilityReportResponse.EnvironmentsEntry + nil, // 25: services.yor.clair.v1.GetVulnerabilityReportResponse.PackageVulnerabilitiesEntry + nil, // 26: services.yor.clair.v1.GetVulnerabilityReportResponse.RepositoryEntry + nil, // 27: services.yor.clair.v1.GetVulnerabilityReportResponse.VulnerabilitiesEntry + (*v1.UUID)(nil), // 28: common.v1.UUID + (*timestamppb.Timestamp)(nil), // 29: google.protobuf.Timestamp + (*structpb.ListValue)(nil), // 30: google.protobuf.ListValue } var file_services_yor_clair_v1_clair_proto_depIdxs = []int32{ - 14, // 0: services.yor.clair.v1.SubmitManifestToScanResponse.packages:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.PackagesEntry - 15, // 1: services.yor.clair.v1.SubmitManifestToScanResponse.distributions:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.DistributionsEntry - 16, // 2: services.yor.clair.v1.SubmitManifestToScanResponse.repository:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.RepositoryEntry - 17, // 3: services.yor.clair.v1.SubmitManifestToScanResponse.environments:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.EnvironmentsEntry - 18, // 4: services.yor.clair.v1.ClairDescriptor.headers:type_name -> services.yor.clair.v1.ClairDescriptor.HeadersEntry - 2, // 5: services.yor.clair.v1.SubmitManifestToScanRequest.layers:type_name -> services.yor.clair.v1.ClairDescriptor - 5, // 6: services.yor.clair.v1.ClairPackage.source:type_name -> services.yor.clair.v1.ClairPackageSource - 25, // 7: services.yor.clair.v1.ClairVulnerability.issued:type_name -> google.protobuf.Timestamp - 6, // 8: services.yor.clair.v1.ClairVulnerability.package:type_name -> services.yor.clair.v1.ClairPackage - 7, // 9: services.yor.clair.v1.ClairVulnerability.distribution:type_name -> services.yor.clair.v1.ClairDistribution - 9, // 10: services.yor.clair.v1.ClairVulnerability.repository:type_name -> services.yor.clair.v1.ClairRepository - 19, // 11: services.yor.clair.v1.GetVulnerabilityReportResponse.packages:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.PackagesEntry - 20, // 12: services.yor.clair.v1.GetVulnerabilityReportResponse.distributions:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.DistributionsEntry - 21, // 13: services.yor.clair.v1.GetVulnerabilityReportResponse.environments:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.EnvironmentsEntry - 22, // 14: services.yor.clair.v1.GetVulnerabilityReportResponse.package_vulnerabilities:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.PackageVulnerabilitiesEntry - 11, // 15: services.yor.clair.v1.GetVulnerabilityReportResponse.enrichments:type_name -> services.yor.clair.v1.ClairEnrichment - 23, // 16: services.yor.clair.v1.GetVulnerabilityReportResponse.repository:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.RepositoryEntry - 24, // 17: services.yor.clair.v1.GetVulnerabilityReportResponse.vulnerabilities:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.VulnerabilitiesEntry - 0, // 18: services.yor.clair.v1.SubmitManifestToScanResponse.PackagesEntry.value:type_name -> services.yor.clair.v1.ClairReportPackage - 7, // 19: services.yor.clair.v1.SubmitManifestToScanResponse.DistributionsEntry.value:type_name -> services.yor.clair.v1.ClairDistribution - 9, // 20: services.yor.clair.v1.SubmitManifestToScanResponse.RepositoryEntry.value:type_name -> services.yor.clair.v1.ClairRepository - 26, // 21: services.yor.clair.v1.SubmitManifestToScanResponse.EnvironmentsEntry.value:type_name -> google.protobuf.ListValue - 26, // 22: services.yor.clair.v1.ClairDescriptor.HeadersEntry.value:type_name -> google.protobuf.ListValue - 6, // 23: services.yor.clair.v1.GetVulnerabilityReportResponse.PackagesEntry.value:type_name -> services.yor.clair.v1.ClairPackage - 7, // 24: services.yor.clair.v1.GetVulnerabilityReportResponse.DistributionsEntry.value:type_name -> services.yor.clair.v1.ClairDistribution - 26, // 25: services.yor.clair.v1.GetVulnerabilityReportResponse.EnvironmentsEntry.value:type_name -> google.protobuf.ListValue - 26, // 26: services.yor.clair.v1.GetVulnerabilityReportResponse.PackageVulnerabilitiesEntry.value:type_name -> google.protobuf.ListValue - 9, // 27: services.yor.clair.v1.GetVulnerabilityReportResponse.RepositoryEntry.value:type_name -> services.yor.clair.v1.ClairRepository - 10, // 28: services.yor.clair.v1.GetVulnerabilityReportResponse.VulnerabilitiesEntry.value:type_name -> services.yor.clair.v1.ClairVulnerability - 3, // 29: services.yor.clair.v1.ClairService.SubmitManifestToScan:input_type -> services.yor.clair.v1.SubmitManifestToScanRequest - 4, // 30: services.yor.clair.v1.ClairService.GetVulnerabilityReport:input_type -> services.yor.clair.v1.GetVulnerabilityReportRequest - 1, // 31: services.yor.clair.v1.ClairService.SubmitManifestToScan:output_type -> services.yor.clair.v1.SubmitManifestToScanResponse - 13, // 32: services.yor.clair.v1.ClairService.GetVulnerabilityReport:output_type -> services.yor.clair.v1.GetVulnerabilityReportResponse - 31, // [31:33] is the sub-list for method output_type - 29, // [29:31] is the sub-list for method input_type - 29, // [29:29] is the sub-list for extension type_name - 29, // [29:29] is the sub-list for extension extendee - 0, // [0:29] is the sub-list for field type_name + 28, // 0: services.yor.clair.v1.EnableVulnerabilityScanningRequest.repository_id:type_name -> common.v1.UUID + 8, // 1: services.yor.clair.v1.ClairReportPackage.source:type_name -> services.yor.clair.v1.ClairPackageSource + 17, // 2: services.yor.clair.v1.SubmitManifestToScanResponse.packages:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.PackagesEntry + 18, // 3: services.yor.clair.v1.SubmitManifestToScanResponse.distributions:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.DistributionsEntry + 19, // 4: services.yor.clair.v1.SubmitManifestToScanResponse.repository:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.RepositoryEntry + 20, // 5: services.yor.clair.v1.SubmitManifestToScanResponse.environments:type_name -> services.yor.clair.v1.SubmitManifestToScanResponse.EnvironmentsEntry + 21, // 6: services.yor.clair.v1.ClairDescriptor.headers:type_name -> services.yor.clair.v1.ClairDescriptor.HeadersEntry + 4, // 7: services.yor.clair.v1.ClairIndexManifestRequest.layers:type_name -> services.yor.clair.v1.ClairDescriptor + 8, // 8: services.yor.clair.v1.ClairPackage.source:type_name -> services.yor.clair.v1.ClairPackageSource + 29, // 9: services.yor.clair.v1.ClairVulnerability.issued:type_name -> google.protobuf.Timestamp + 9, // 10: services.yor.clair.v1.ClairVulnerability.package:type_name -> services.yor.clair.v1.ClairPackage + 10, // 11: services.yor.clair.v1.ClairVulnerability.distribution:type_name -> services.yor.clair.v1.ClairDistribution + 12, // 12: services.yor.clair.v1.ClairVulnerability.repository:type_name -> services.yor.clair.v1.ClairRepository + 22, // 13: services.yor.clair.v1.GetVulnerabilityReportResponse.packages:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.PackagesEntry + 23, // 14: services.yor.clair.v1.GetVulnerabilityReportResponse.distributions:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.DistributionsEntry + 24, // 15: services.yor.clair.v1.GetVulnerabilityReportResponse.environments:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.EnvironmentsEntry + 25, // 16: services.yor.clair.v1.GetVulnerabilityReportResponse.package_vulnerabilities:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.PackageVulnerabilitiesEntry + 14, // 17: services.yor.clair.v1.GetVulnerabilityReportResponse.enrichments:type_name -> services.yor.clair.v1.ClairEnrichment + 26, // 18: services.yor.clair.v1.GetVulnerabilityReportResponse.repository:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.RepositoryEntry + 27, // 19: services.yor.clair.v1.GetVulnerabilityReportResponse.vulnerabilities:type_name -> services.yor.clair.v1.GetVulnerabilityReportResponse.VulnerabilitiesEntry + 2, // 20: services.yor.clair.v1.SubmitManifestToScanResponse.PackagesEntry.value:type_name -> services.yor.clair.v1.ClairReportPackage + 10, // 21: services.yor.clair.v1.SubmitManifestToScanResponse.DistributionsEntry.value:type_name -> services.yor.clair.v1.ClairDistribution + 12, // 22: services.yor.clair.v1.SubmitManifestToScanResponse.RepositoryEntry.value:type_name -> services.yor.clair.v1.ClairRepository + 30, // 23: services.yor.clair.v1.SubmitManifestToScanResponse.EnvironmentsEntry.value:type_name -> google.protobuf.ListValue + 30, // 24: services.yor.clair.v1.ClairDescriptor.HeadersEntry.value:type_name -> google.protobuf.ListValue + 9, // 25: services.yor.clair.v1.GetVulnerabilityReportResponse.PackagesEntry.value:type_name -> services.yor.clair.v1.ClairPackage + 10, // 26: services.yor.clair.v1.GetVulnerabilityReportResponse.DistributionsEntry.value:type_name -> services.yor.clair.v1.ClairDistribution + 30, // 27: services.yor.clair.v1.GetVulnerabilityReportResponse.EnvironmentsEntry.value:type_name -> google.protobuf.ListValue + 30, // 28: services.yor.clair.v1.GetVulnerabilityReportResponse.PackageVulnerabilitiesEntry.value:type_name -> google.protobuf.ListValue + 12, // 29: services.yor.clair.v1.GetVulnerabilityReportResponse.RepositoryEntry.value:type_name -> services.yor.clair.v1.ClairRepository + 13, // 30: services.yor.clair.v1.GetVulnerabilityReportResponse.VulnerabilitiesEntry.value:type_name -> services.yor.clair.v1.ClairVulnerability + 5, // 31: services.yor.clair.v1.ClairService.SubmitManifestToScan:input_type -> services.yor.clair.v1.SubmitManifestToScanRequest + 6, // 32: services.yor.clair.v1.ClairService.GetVulnerabilityReport:input_type -> services.yor.clair.v1.GetVulnerabilityReportRequest + 0, // 33: services.yor.clair.v1.ClairService.EnableVulnerabilityScanning:input_type -> services.yor.clair.v1.EnableVulnerabilityScanningRequest + 3, // 34: services.yor.clair.v1.ClairService.SubmitManifestToScan:output_type -> services.yor.clair.v1.SubmitManifestToScanResponse + 16, // 35: services.yor.clair.v1.ClairService.GetVulnerabilityReport:output_type -> services.yor.clair.v1.GetVulnerabilityReportResponse + 1, // 36: services.yor.clair.v1.ClairService.EnableVulnerabilityScanning:output_type -> services.yor.clair.v1.EnableVulnerabilityScanningResponse + 34, // [34:37] is the sub-list for method output_type + 31, // [31:34] is the sub-list for method input_type + 31, // [31:31] is the sub-list for extension type_name + 31, // [31:31] is the sub-list for extension extendee + 0, // [0:31] is the sub-list for field type_name } func init() { file_services_yor_clair_v1_clair_proto_init() } @@ -1519,7 +1705,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } if !protoimpl.UnsafeEnabled { file_services_yor_clair_v1_clair_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairReportPackage); i { + switch v := v.(*EnableVulnerabilityScanningRequest); i { case 0: return &v.state case 1: @@ -1531,7 +1717,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitManifestToScanResponse); i { + switch v := v.(*EnableVulnerabilityScanningResponse); i { case 0: return &v.state case 1: @@ -1543,7 +1729,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairDescriptor); i { + switch v := v.(*ClairReportPackage); i { case 0: return &v.state case 1: @@ -1555,7 +1741,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitManifestToScanRequest); i { + switch v := v.(*SubmitManifestToScanResponse); i { case 0: return &v.state case 1: @@ -1567,7 +1753,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetVulnerabilityReportRequest); i { + switch v := v.(*ClairDescriptor); i { case 0: return &v.state case 1: @@ -1579,7 +1765,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairPackageSource); i { + switch v := v.(*SubmitManifestToScanRequest); i { case 0: return &v.state case 1: @@ -1591,7 +1777,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairPackage); i { + switch v := v.(*GetVulnerabilityReportRequest); i { case 0: return &v.state case 1: @@ -1603,7 +1789,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairDistribution); i { + switch v := v.(*ClairIndexManifestRequest); i { case 0: return &v.state case 1: @@ -1615,7 +1801,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairEnvironmentItem); i { + switch v := v.(*ClairPackageSource); i { case 0: return &v.state case 1: @@ -1627,7 +1813,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairRepository); i { + switch v := v.(*ClairPackage); i { case 0: return &v.state case 1: @@ -1639,7 +1825,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairVulnerability); i { + switch v := v.(*ClairDistribution); i { case 0: return &v.state case 1: @@ -1651,7 +1837,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairEnrichment); i { + switch v := v.(*ClairEnvironmentItem); i { case 0: return &v.state case 1: @@ -1663,7 +1849,7 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ClairVulnerabilityIdList); i { + switch v := v.(*ClairRepository); i { case 0: return &v.state case 1: @@ -1675,6 +1861,42 @@ func file_services_yor_clair_v1_clair_proto_init() { } } file_services_yor_clair_v1_clair_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairVulnerability); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairEnrichment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClairVulnerabilityIdList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_services_yor_clair_v1_clair_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetVulnerabilityReportResponse); i { case 0: return &v.state @@ -1693,7 +1915,7 @@ func file_services_yor_clair_v1_clair_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_services_yor_clair_v1_clair_proto_rawDesc, NumEnums: 0, - NumMessages: 25, + NumMessages: 28, NumExtensions: 0, NumServices: 1, }, diff --git a/services/yor/clair/v1/clair.pb.validate.go b/services/yor/clair/v1/clair.pb.validate.go index 199e7e39..c98cb754 100644 --- a/services/yor/clair/v1/clair.pb.validate.go +++ b/services/yor/clair/v1/clair.pb.validate.go @@ -35,6 +35,247 @@ var ( _ = sort.Sort ) +// Validate checks the field values on EnableVulnerabilityScanningRequest with +// the rules defined in the proto definition for this message. If any rules +// are violated, the first error encountered is returned, or nil if there are +// no violations. +func (m *EnableVulnerabilityScanningRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on EnableVulnerabilityScanningRequest +// with the rules defined in the proto definition for this message. If any +// rules are violated, the result is a list of violation errors wrapped in +// EnableVulnerabilityScanningRequestMultiError, or nil if none found. +func (m *EnableVulnerabilityScanningRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *EnableVulnerabilityScanningRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetRepositoryId()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, EnableVulnerabilityScanningRequestValidationError{ + field: "RepositoryId", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, EnableVulnerabilityScanningRequestValidationError{ + field: "RepositoryId", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetRepositoryId()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return EnableVulnerabilityScanningRequestValidationError{ + field: "RepositoryId", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return EnableVulnerabilityScanningRequestMultiError(errors) + } + + return nil +} + +// EnableVulnerabilityScanningRequestMultiError is an error wrapping multiple +// validation errors returned by +// EnableVulnerabilityScanningRequest.ValidateAll() if the designated +// constraints aren't met. +type EnableVulnerabilityScanningRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m EnableVulnerabilityScanningRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m EnableVulnerabilityScanningRequestMultiError) AllErrors() []error { return m } + +// EnableVulnerabilityScanningRequestValidationError is the validation error +// returned by EnableVulnerabilityScanningRequest.Validate if the designated +// constraints aren't met. +type EnableVulnerabilityScanningRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e EnableVulnerabilityScanningRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e EnableVulnerabilityScanningRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e EnableVulnerabilityScanningRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e EnableVulnerabilityScanningRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e EnableVulnerabilityScanningRequestValidationError) ErrorName() string { + return "EnableVulnerabilityScanningRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e EnableVulnerabilityScanningRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEnableVulnerabilityScanningRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = EnableVulnerabilityScanningRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = EnableVulnerabilityScanningRequestValidationError{} + +// Validate checks the field values on EnableVulnerabilityScanningResponse with +// the rules defined in the proto definition for this message. If any rules +// are violated, the first error encountered is returned, or nil if there are +// no violations. +func (m *EnableVulnerabilityScanningResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on EnableVulnerabilityScanningResponse +// with the rules defined in the proto definition for this message. If any +// rules are violated, the result is a list of violation errors wrapped in +// EnableVulnerabilityScanningResponseMultiError, or nil if none found. +func (m *EnableVulnerabilityScanningResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *EnableVulnerabilityScanningResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Message + + if len(errors) > 0 { + return EnableVulnerabilityScanningResponseMultiError(errors) + } + + return nil +} + +// EnableVulnerabilityScanningResponseMultiError is an error wrapping multiple +// validation errors returned by +// EnableVulnerabilityScanningResponse.ValidateAll() if the designated +// constraints aren't met. +type EnableVulnerabilityScanningResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m EnableVulnerabilityScanningResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m EnableVulnerabilityScanningResponseMultiError) AllErrors() []error { return m } + +// EnableVulnerabilityScanningResponseValidationError is the validation error +// returned by EnableVulnerabilityScanningResponse.Validate if the designated +// constraints aren't met. +type EnableVulnerabilityScanningResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e EnableVulnerabilityScanningResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e EnableVulnerabilityScanningResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e EnableVulnerabilityScanningResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e EnableVulnerabilityScanningResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e EnableVulnerabilityScanningResponseValidationError) ErrorName() string { + return "EnableVulnerabilityScanningResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e EnableVulnerabilityScanningResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEnableVulnerabilityScanningResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = EnableVulnerabilityScanningResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = EnableVulnerabilityScanningResponseValidationError{} + // Validate checks the field values on ClairReportPackage with the rules // defined in the proto definition for this message. If any rules are // violated, the first error encountered is returned, or nil if there are no violations. @@ -67,6 +308,35 @@ func (m *ClairReportPackage) validate(all bool) error { // no validation rules for Arch + if all { + switch v := interface{}(m.GetSource()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ClairReportPackageValidationError{ + field: "Source", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ClairReportPackageValidationError{ + field: "Source", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetSource()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClairReportPackageValidationError{ + field: "Source", + reason: "embedded message failed validation", + cause: err, + } + } + } + if len(errors) > 0 { return ClairReportPackageMultiError(errors) } @@ -616,40 +886,6 @@ func (m *SubmitManifestToScanRequest) validate(all bool) error { // no validation rules for Hash - for idx, item := range m.GetLayers() { - _, _ = idx, item - - if all { - switch v := interface{}(item).(type) { - case interface{ ValidateAll() error }: - if err := v.ValidateAll(); err != nil { - errors = append(errors, SubmitManifestToScanRequestValidationError{ - field: fmt.Sprintf("Layers[%v]", idx), - reason: "embedded message failed validation", - cause: err, - }) - } - case interface{ Validate() error }: - if err := v.Validate(); err != nil { - errors = append(errors, SubmitManifestToScanRequestValidationError{ - field: fmt.Sprintf("Layers[%v]", idx), - reason: "embedded message failed validation", - cause: err, - }) - } - } - } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { - if err := v.Validate(); err != nil { - return SubmitManifestToScanRequestValidationError{ - field: fmt.Sprintf("Layers[%v]", idx), - reason: "embedded message failed validation", - cause: err, - } - } - } - - } - if len(errors) > 0 { return SubmitManifestToScanRequestMultiError(errors) } @@ -836,6 +1072,144 @@ var _ interface { ErrorName() string } = GetVulnerabilityReportRequestValidationError{} +// Validate checks the field values on ClairIndexManifestRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ClairIndexManifestRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ClairIndexManifestRequest with the +// rules defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ClairIndexManifestRequestMultiError, or nil if none found. +func (m *ClairIndexManifestRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *ClairIndexManifestRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Hash + + for idx, item := range m.GetLayers() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ClairIndexManifestRequestValidationError{ + field: fmt.Sprintf("Layers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ClairIndexManifestRequestValidationError{ + field: fmt.Sprintf("Layers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ClairIndexManifestRequestValidationError{ + field: fmt.Sprintf("Layers[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return ClairIndexManifestRequestMultiError(errors) + } + + return nil +} + +// ClairIndexManifestRequestMultiError is an error wrapping multiple validation +// errors returned by ClairIndexManifestRequest.ValidateAll() if the +// designated constraints aren't met. +type ClairIndexManifestRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ClairIndexManifestRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ClairIndexManifestRequestMultiError) AllErrors() []error { return m } + +// ClairIndexManifestRequestValidationError is the validation error returned by +// ClairIndexManifestRequest.Validate if the designated constraints aren't met. +type ClairIndexManifestRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ClairIndexManifestRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ClairIndexManifestRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ClairIndexManifestRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ClairIndexManifestRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ClairIndexManifestRequestValidationError) ErrorName() string { + return "ClairIndexManifestRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e ClairIndexManifestRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sClairIndexManifestRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ClairIndexManifestRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ClairIndexManifestRequestValidationError{} + // Validate checks the field values on ClairPackageSource with the rules // defined in the proto definition for this message. If any rules are // violated, the first error encountered is returned, or nil if there are no violations. diff --git a/services/yor/clair/v1/clairconnect/clair.connect.go b/services/yor/clair/v1/clairconnect/clair.connect.go index b364fb77..db62506a 100644 --- a/services/yor/clair/v1/clairconnect/clair.connect.go +++ b/services/yor/clair/v1/clairconnect/clair.connect.go @@ -39,12 +39,16 @@ const ( // ClairServiceGetVulnerabilityReportProcedure is the fully-qualified name of the ClairService's // GetVulnerabilityReport RPC. ClairServiceGetVulnerabilityReportProcedure = "/services.yor.clair.v1.ClairService/GetVulnerabilityReport" + // ClairServiceEnableVulnerabilityScanningProcedure is the fully-qualified name of the + // ClairService's EnableVulnerabilityScanning RPC. + ClairServiceEnableVulnerabilityScanningProcedure = "/services.yor.clair.v1.ClairService/EnableVulnerabilityScanning" ) // ClairServiceClient is a client for the services.yor.clair.v1.ClairService service. type ClairServiceClient interface { SubmitManifestToScan(context.Context, *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) GetVulnerabilityReport(context.Context, *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) + EnableVulnerabilityScanning(context.Context, *connect_go.Request[v1.EnableVulnerabilityScanningRequest]) (*connect_go.Response[v1.EnableVulnerabilityScanningResponse], error) } // NewClairServiceClient constructs a client for the services.yor.clair.v1.ClairService service. By @@ -67,13 +71,19 @@ func NewClairServiceClient(httpClient connect_go.HTTPClient, baseURL string, opt baseURL+ClairServiceGetVulnerabilityReportProcedure, opts..., ), + enableVulnerabilityScanning: connect_go.NewClient[v1.EnableVulnerabilityScanningRequest, v1.EnableVulnerabilityScanningResponse]( + httpClient, + baseURL+ClairServiceEnableVulnerabilityScanningProcedure, + opts..., + ), } } // clairServiceClient implements ClairServiceClient. type clairServiceClient struct { - submitManifestToScan *connect_go.Client[v1.SubmitManifestToScanRequest, v1.SubmitManifestToScanResponse] - getVulnerabilityReport *connect_go.Client[v1.GetVulnerabilityReportRequest, v1.GetVulnerabilityReportResponse] + submitManifestToScan *connect_go.Client[v1.SubmitManifestToScanRequest, v1.SubmitManifestToScanResponse] + getVulnerabilityReport *connect_go.Client[v1.GetVulnerabilityReportRequest, v1.GetVulnerabilityReportResponse] + enableVulnerabilityScanning *connect_go.Client[v1.EnableVulnerabilityScanningRequest, v1.EnableVulnerabilityScanningResponse] } // SubmitManifestToScan calls services.yor.clair.v1.ClairService.SubmitManifestToScan. @@ -86,10 +96,16 @@ func (c *clairServiceClient) GetVulnerabilityReport(ctx context.Context, req *co return c.getVulnerabilityReport.CallUnary(ctx, req) } +// EnableVulnerabilityScanning calls services.yor.clair.v1.ClairService.EnableVulnerabilityScanning. +func (c *clairServiceClient) EnableVulnerabilityScanning(ctx context.Context, req *connect_go.Request[v1.EnableVulnerabilityScanningRequest]) (*connect_go.Response[v1.EnableVulnerabilityScanningResponse], error) { + return c.enableVulnerabilityScanning.CallUnary(ctx, req) +} + // ClairServiceHandler is an implementation of the services.yor.clair.v1.ClairService service. type ClairServiceHandler interface { SubmitManifestToScan(context.Context, *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) GetVulnerabilityReport(context.Context, *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) + EnableVulnerabilityScanning(context.Context, *connect_go.Request[v1.EnableVulnerabilityScanningRequest]) (*connect_go.Response[v1.EnableVulnerabilityScanningResponse], error) } // NewClairServiceHandler builds an HTTP handler from the service implementation. It returns the @@ -108,12 +124,19 @@ func NewClairServiceHandler(svc ClairServiceHandler, opts ...connect_go.HandlerO svc.GetVulnerabilityReport, opts..., ) + clairServiceEnableVulnerabilityScanningHandler := connect_go.NewUnaryHandler( + ClairServiceEnableVulnerabilityScanningProcedure, + svc.EnableVulnerabilityScanning, + opts..., + ) return "/services.yor.clair.v1.ClairService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case ClairServiceSubmitManifestToScanProcedure: clairServiceSubmitManifestToScanHandler.ServeHTTP(w, r) case ClairServiceGetVulnerabilityReportProcedure: clairServiceGetVulnerabilityReportHandler.ServeHTTP(w, r) + case ClairServiceEnableVulnerabilityScanningProcedure: + clairServiceEnableVulnerabilityScanningHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -130,3 +153,7 @@ func (UnimplementedClairServiceHandler) SubmitManifestToScan(context.Context, *c func (UnimplementedClairServiceHandler) GetVulnerabilityReport(context.Context, *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) { return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.GetVulnerabilityReport is not implemented")) } + +func (UnimplementedClairServiceHandler) EnableVulnerabilityScanning(context.Context, *connect_go.Request[v1.EnableVulnerabilityScanningRequest]) (*connect_go.Response[v1.EnableVulnerabilityScanningResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.EnableVulnerabilityScanning is not implemented")) +} diff --git a/services/yor/clair/v1/server/clair.go b/services/yor/clair/v1/server/clair.go index 97b58004..21309aaf 100644 --- a/services/yor/clair/v1/server/clair.go +++ b/services/yor/clair/v1/server/clair.go @@ -13,6 +13,16 @@ import ( "google.golang.org/protobuf/encoding/protojson" ) +func (c *clair) EnableVulnerabilityScanning( + ctx context.Context, + req *connect.Request[clair_v1.EnableVulnerabilityScanningRequest], +) ( + *connect.Response[clair_v1.EnableVulnerabilityScanningResponse], + error, +) { + return nil, connect.NewError(connect.CodeUnimplemented, fmt.Errorf("UNIMPLEMENTED")) +} + func (c *clair) GetVulnerabilityReport( ctx context.Context, req *connect.Request[clair_v1.GetVulnerabilityReportRequest], @@ -71,7 +81,31 @@ func (c *clair) SubmitManifestToScan( logEvent.Str("manifest", req.Msg.GetHash()) - result, err := c.submitManifest(ctx, req.Msg) + dfsLinks, err := c.layerLinkReader(ctx, req.Msg.GetHash()) + if err != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + + layers := make([]*clair_v1.ClairDescriptor, len(dfsLinks)) + for i, link := range dfsLinks { + presignedURL, signErr := c.prePresignedURLGenerator(ctx, link.DFSLink) + if signErr != nil { + logEvent.Err(err).Send() + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + layers[i] = &clair_v1.ClairDescriptor{ + Hash: link.Digest, + Uri: presignedURL, + } + } + + body := &clair_v1.ClairIndexManifestRequest{ + Hash: req.Msg.GetHash(), + Layers: layers, + } + + result, err := c.submitManifest(ctx, body) if err != nil { logEvent.Err(err).Send() return nil, connect.NewError(connect.CodeInvalidArgument, err) @@ -113,7 +147,7 @@ func (c *clair) getVulnReport(ctx context.Context, manifestID string) (io.ReadCl func (c *clair) submitManifest( ctx context.Context, - manifest *clair_v1.SubmitManifestToScanRequest, + manifest *clair_v1.ClairIndexManifestRequest, ) (io.ReadCloser, error) { uri := fmt.Sprintf("%s/indexer/api/v1/index_report", c.config.ClairEndpoint) diff --git a/services/yor/clair/v1/server/interceptors.go b/services/yor/clair/v1/server/interceptors.go new file mode 100644 index 00000000..3e08bbdb --- /dev/null +++ b/services/yor/clair/v1/server/interceptors.go @@ -0,0 +1,124 @@ +package server + +import ( + "context" + "crypto/rsa" + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/bufbuild/connect-go" + "github.com/containerish/OpenRegistry/auth" + "github.com/containerish/OpenRegistry/store/v1/types" + "github.com/golang-jwt/jwt/v5" + "github.com/google/uuid" +) + +// NewJWTInterceptor is a UnaryInterceptorFunc that inspects and tries to parse a JWT from the request. +// If the JWT is invalid, an Unauthorized error is returned +func (c *clair) NewJWTInterceptor() connect.UnaryInterceptorFunc { + return connect.UnaryInterceptorFunc(func(next connect.UnaryFunc) connect.UnaryFunc { + return connect.UnaryFunc(func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { + logEvent := c.logger.Debug().Str("procedure", req.Spec().Procedure) + + userID, err := c.getTokenFromReq(req, c.authConfig.JWTSigningPubKey) + if err != nil { + return nil, err + } + + user, err := c.userGetter.GetUserByID(ctx, userID) + if err != nil { + logEvent.Str("error", err.Error()).Send() + return nil, connect.NewError(connect.CodeFailedPrecondition, err) + } + + logEvent.Bool("success", true).Send() + ctx = context.WithValue(ctx, types.UserContextKey, user) + return next(ctx, req) + }) + }) +} + +func (c *clair) getTokenFromReq(req connect.AnyRequest, jwtSigningPubKey *rsa.PublicKey) (uuid.UUID, error) { + token, err := c.tryTokenFromReqHeaders(req, jwtSigningPubKey) + if err != nil { + token, err = c.tryTokenFromReqCookies(req, jwtSigningPubKey) + if err != nil { + return uuid.Nil, fmt.Errorf("getTokenFromReq: tryTokenFromReqCookies: %w", err) + } + } + + return token, nil +} + +func (c *clair) tryTokenFromReqCookies(req connect.AnyRequest, jwtSigningPubKey *rsa.PublicKey) (uuid.UUID, error) { + tmpReq := http.Request{Header: req.Header()} + sessionCookie, err := tmpReq.Cookie("access") + if err != nil { + return uuid.Nil, fmt.Errorf("tryTokenFromReqCookies: ERR_NO_COOKIE: %w", err) + } + + authToken, err := url.QueryUnescape(sessionCookie.Value) + if err != nil { + return uuid.Nil, fmt.Errorf("tryTokenFromReqCookies: ERR_WRONG_ENCODING: %w", err) + } + + if authToken != "" { + claims := &auth.Claims{} + token, err := jwt.ParseWithClaims(authToken, claims, func(t *jwt.Token) (interface{}, error) { + return jwtSigningPubKey, nil + }) + if err != nil { + return uuid.Nil, fmt.Errorf("tryTokenFromReqHeaders: ERR_JWT_CLAIM_PARSE: %w", err) + } + + claims, ok := token.Claims.(*auth.Claims) + if !ok { + return uuid.Nil, fmt.Errorf("tryTokenFromReqHeaders: error parsing claims from token") + } + + parsedID, err := uuid.Parse(claims.Subject) + if err != nil { + return uuid.Nil, fmt.Errorf("tryTokenFromReqHeaders: ERR_UUID_PARSE: %w", err) + } + + return parsedID, nil + } + + errMsg := fmt.Errorf("auth token contains invalid parts") + return uuid.Nil, errMsg +} + +func (c *clair) tryTokenFromReqHeaders(req connect.AnyRequest, jwtSigningPubKey *rsa.PublicKey) (uuid.UUID, error) { + authToken := req.Header().Get("Authorization") + tokenParts := strings.Split(authToken, " ") + if len(tokenParts) == 2 { + if !strings.EqualFold(tokenParts[0], "Bearer") { + errMsg := fmt.Errorf("tryTokenFromReqHeaders: invalid authorization scheme") + return uuid.Nil, errMsg + } + + claims := &auth.Claims{} + token, err := jwt.ParseWithClaims(tokenParts[1], claims, func(t *jwt.Token) (interface{}, error) { + return jwtSigningPubKey, nil + }) + if err != nil { + return uuid.Nil, fmt.Errorf("tryTokenFromReqHeaders: ERR_JWT_CLAIM_PARSE: %w", err) + } + + claims, ok := token.Claims.(*auth.Claims) + if !ok { + return uuid.Nil, fmt.Errorf("tryTokenFromReqHeaders: error parsing claims from token") + } + + parsedID, err := uuid.Parse(claims.Subject) + if err != nil { + return uuid.Nil, fmt.Errorf("tryTokenFromReqHeaders: ERR_UUID_PARSE: %w", err) + } + return parsedID, nil + } + + errMsg := fmt.Errorf("auth token contains invalid parts") + return uuid.Nil, errMsg +} diff --git a/services/yor/clair/v1/server/server.go b/services/yor/clair/v1/server/server.go index 10af3844..28ab1bf8 100644 --- a/services/yor/clair/v1/server/server.go +++ b/services/yor/clair/v1/server/server.go @@ -1,27 +1,42 @@ package server import ( + "context" "net/http" "sync" "time" + "github.com/bufbuild/connect-go" "github.com/containerish/OpenRegistry/config" connect_v1 "github.com/containerish/OpenRegistry/services/yor/clair/v1/clairconnect" + "github.com/containerish/OpenRegistry/store/v1/types" + "github.com/containerish/OpenRegistry/store/v1/users" "github.com/containerish/OpenRegistry/telemetry" ) type ( clair struct { - http *http.Client - logger telemetry.Logger - config *config.ClairIntegration - mu *sync.RWMutex + http *http.Client + logger telemetry.Logger + config *config.ClairIntegration + userGetter users.UserStore + authConfig *config.Auth + mu *sync.RWMutex + layerLinkReader LayerLinkReader + prePresignedURLGenerator PresignedURLGenerator } + + LayerLinkReader func(ctx context.Context, manifestDigest string) ([]*types.ContainerImageLayer, error) + PresignedURLGenerator func(ctx context.Context, path string) (string, error) ) func NewClairClient( + userStore users.UserStore, config *config.ClairIntegration, + authConfig *config.Auth, logger telemetry.Logger, + layerLinkReader LayerLinkReader, + prePresignedURLGenerator PresignedURLGenerator, ) *http.ServeMux { if !config.Enabled { return nil @@ -33,14 +48,18 @@ func NewClairClient( } server := &clair{ - logger: logger, - config: config, - mu: &sync.RWMutex{}, - http: httpClient, + logger: logger, + config: config, + mu: &sync.RWMutex{}, + http: httpClient, + userGetter: userStore, + authConfig: authConfig, + layerLinkReader: layerLinkReader, + prePresignedURLGenerator: prePresignedURLGenerator, } - // interceptors := connect.WithInterceptors(NewGithubAppInterceptor(logger, ghStore, nil, authConfig)) + interceptors := connect.WithInterceptors(server.NewJWTInterceptor()) mux := http.NewServeMux() - mux.Handle(connect_v1.NewClairServiceHandler(server)) + mux.Handle(connect_v1.NewClairServiceHandler(server, interceptors)) return mux } diff --git a/store/v1/registry/registry_impl.go b/store/v1/registry/registry_impl.go index 75d745d9..5b9d896a 100644 --- a/store/v1/registry/registry_impl.go +++ b/store/v1/registry/registry_impl.go @@ -790,7 +790,10 @@ func (s *registryStore) RemoveRepositoryFromFavorites(ctx context.Context, repoI ) } -func (s *registryStore) GetLayersLinksForManifest(ctx context.Context, manifestDigest string) ([]*types.ContainerImageLayer, error) { +func (s *registryStore) GetLayersLinksForManifest( + ctx context.Context, + manifestDigest string, +) ([]*types.ContainerImageLayer, error) { logEvent := s.logger.Debug().Str("method", "GetLayersLinksForManifest").Str("digest", manifestDigest) manifest := &types.ImageManifest{} From d5964b5a630449a9b96f191ef3e00a33be94f2aa Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Thu, 21 Dec 2023 15:38:39 +0530 Subject: [PATCH 06/23] fix: Skip Mock DFS config parsing if not set Signed-off-by: jay-dee7 --- cmd/migrations/migrations.go | 2 +- config/yaml.go | 10 ++++++++++ store/v1/emails/emails_impl.go | 7 ++++--- store/v1/users/users_impl.go | 4 ++-- store/v1/webauthn/webauthn_impl.go | 2 +- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/cmd/migrations/migrations.go b/cmd/migrations/migrations.go index 7bd03bb1..7e20a2ac 100644 --- a/cmd/migrations/migrations.go +++ b/cmd/migrations/migrations.go @@ -223,7 +223,7 @@ func createOpenRegistryDatabase(ctx *cli.Context, opts *databaseOptions) (*bun.D _, err = adminDB. ExecContext( ctx.Context, - "GRANT ALL PRIVILEGES ON DATABASE ?0 to ?1", + "GRANT ALL PRIVILEGES ON DATABASE ? to ?", bun.Ident(opts.database), bun.Ident(opts.username), ) diff --git a/config/yaml.go b/config/yaml.go index ff5d5bb5..6fafc46c 100644 --- a/config/yaml.go +++ b/config/yaml.go @@ -150,6 +150,16 @@ func setDefaultsForDatabaseStore(cfg *OpenRegistryConfig) { } func parseAndSetMockStorageDriverOptions(cfg *OpenRegistryConfig) { + mockConfig := viper.GetStringMap("dfs.mock") + keys := make([]string, 0, len(mockConfig)) + for k := range mockConfig { + keys = append(keys, k) + } + + // skip is mock config is absent + if len(keys) == 0 { + return + } mockDFSType := viper.GetString("dfs.mock.type") if mockDFSType == "MemMapped" { viper.Set("dfs.mock.type", MockStorageBackendMemMapped) diff --git a/store/v1/emails/emails_impl.go b/store/v1/emails/emails_impl.go index 03dfd0fb..825ca660 100644 --- a/store/v1/emails/emails_impl.go +++ b/store/v1/emails/emails_impl.go @@ -34,7 +34,7 @@ func (es *emailStore) AddVerifyEmail(ctx context.Context, userID uuid.UUID, toke } func (es *emailStore) DeleteVerifyEmail(ctx context.Context, userID uuid.UUID) error { - if _, err := es.db.NewDelete().Model(&types.Email{}).Where("user_id = ?1", userID).Exec(ctx); err != nil { + if _, err := es.db.NewDelete().Model(&types.Email{}).Where("user_id = ?", userID).Exec(ctx); err != nil { return v2.WrapDatabaseError(err, v2.DatabaseOperationDelete) } @@ -42,8 +42,9 @@ func (es *emailStore) DeleteVerifyEmail(ctx context.Context, userID uuid.UUID) e } func (es *emailStore) GetVerifyEmail(ctx context.Context, userID uuid.UUID) (uuid.UUID, error) { - email := &types.Email{} - if err := es.db.NewSelect().Model(email).Where("user_id = ?1", userID).Scan(ctx); err != nil { + var email types.Email + + if err := es.db.NewSelect().Model(&email).Where("user_id = ?", userID).Scan(ctx); err != nil { return uuid.UUID{}, v2.WrapDatabaseError(err, v2.DatabaseOperationRead) } diff --git a/store/v1/users/users_impl.go b/store/v1/users/users_impl.go index f6a8ba27..615031cb 100644 --- a/store/v1/users/users_impl.go +++ b/store/v1/users/users_impl.go @@ -191,7 +191,7 @@ func (us *userStore) githubUserExists(ctx context.Context, username, email strin NewSelect(). Model(&types.User{}). Where( - "identities->'github'->>'email' = ?1 or identities->'github'->>'username' = ?", + "identities->'github'->>'email' = ? or identities->'github'->>'username' = ?", bun.Ident(email), bun.Ident(username), ). @@ -210,7 +210,7 @@ func (us *userStore) webAuthnUserExists(ctx context.Context, username, email str NewSelect(). Model(&types.User{}). Where( - "identities->'webauthn'->>'email' = ?1 or identities->'webauthn'->>'username' = ?", + "identities->'webauthn'->>'email' = ? or identities->'webauthn'->>'username' = ?", bun.Ident(email), bun.Ident(username), ). diff --git a/store/v1/webauthn/webauthn_impl.go b/store/v1/webauthn/webauthn_impl.go index e1674070..b5ae8765 100644 --- a/store/v1/webauthn/webauthn_impl.go +++ b/store/v1/webauthn/webauthn_impl.go @@ -158,7 +158,7 @@ func (ws *webauthnStore) WebauthnUserExists(ctx context.Context, email, username NewSelect(). Model(&types.User{}). Where( - "identities->'webauthn'->>'email' = ?1 or identities->'webauthn'->>'username' = ?", + "identities->'webauthn'->>'email' = ? or identities->'webauthn'->>'username' = ?", bun.Ident(email), bun.Ident(username), ). From ba9721d694eb905d14e695f626e094e351cd6626 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Fri, 22 Dec 2023 00:00:20 +0530 Subject: [PATCH 07/23] fix: User catalog list and search queries Signed-off-by: jay-dee7 --- auth/basic_auth.go | 1 - auth/jwt_middleware.go | 5 +++++ registry/v2/registry.go | 21 ++++++++++++++++----- store/v1/registry/registry_impl.go | 27 +++++++++++++++++++-------- store/v1/types/registry.go | 2 +- 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/auth/basic_auth.go b/auth/basic_auth.go index a4986522..2e1d7369 100644 --- a/auth/basic_auth.go +++ b/auth/basic_auth.go @@ -29,7 +29,6 @@ func (a *auth) BasicAuth() echo.MiddlewareFunc { return func(ctx echo.Context) error { if a.SkipBasicAuth(ctx) { - a.logger.DebugWithContext(ctx).Bool("skip_basic_auth", true).Send() // Note: there might be other middlewares attached to this handler return handler(ctx) } diff --git a/auth/jwt_middleware.go b/auth/jwt_middleware.go index f84c2aa3..cd0cdb73 100644 --- a/auth/jwt_middleware.go +++ b/auth/jwt_middleware.go @@ -22,6 +22,11 @@ const ( // JWT basically uses the default JWT middleware by echo, but has a slightly different skipper func func (a *auth) JWTRest() echo.MiddlewareFunc { return echo_jwt.WithConfig(echo_jwt.Config{ + Skipper: func(ctx echo.Context) bool { + p := ctx.Request().URL.Path + isPublicRepoDetailApi := p == "/v2/ext/catalog/repository" && ctx.QueryParam("public") == "true" + return p == "/v2/ext/catalog/detail" || p == "/v2/_catalog/public" || isPublicRepoDetailApi + }, ErrorHandler: func(ctx echo.Context, err error) error { ctx.Set(types.HandlerStartTime, time.Now()) diff --git a/registry/v2/registry.go b/registry/v2/registry.go index 23fabb76..aca77c2e 100644 --- a/registry/v2/registry.go +++ b/registry/v2/registry.go @@ -1004,31 +1004,42 @@ func (r *registry) GetImageNamespace(ctx echo.Context) error { searchQuery := ctx.QueryParam("search_query") if searchQuery == "" { - return ctx.JSON(http.StatusBadRequest, echo.Map{ - "error": "search query must not be empty", + errMsg := fmt.Errorf("search query must not be empty") + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ + "error": errMsg.Error(), }) + + r.logger.Log(ctx, errMsg).Send() + return echoErr } result, err := r.store.GetImageNamespace(ctx.Request().Context(), searchQuery) if err != nil { - return ctx.JSON(http.StatusInternalServerError, echo.Map{ + echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), "message": "error getting image namespace", }) + + r.logger.Log(ctx, err).Send() + return echoErr } // empty namespace to pull full catalog list total, err := r.store.GetCatalogCount(ctx.Request().Context(), "") if err != nil { - return ctx.JSON(http.StatusInternalServerError, echo.Map{ + echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), "message": "ERR_GET_CATALOG_COUNT", }) + r.logger.Log(ctx, err).Send() + return echoErr } - return ctx.JSON(http.StatusOK, echo.Map{ + echoErr := ctx.JSON(http.StatusOK, echo.Map{ "repositories": result, "total": total, }) + r.logger.Log(ctx, nil).Send() + return echoErr } func (r *registry) GetUserFromCtx(ctx echo.Context) (*types_v2.User, error) { diff --git a/store/v1/registry/registry_impl.go b/store/v1/registry/registry_impl.go index 5b9d896a..164f7153 100644 --- a/store/v1/registry/registry_impl.go +++ b/store/v1/registry/registry_impl.go @@ -291,7 +291,7 @@ func (s *registryStore) GetCatalogCount(ctx context.Context, namespace string) ( repositoryName = parts[1] } - stmnt := s. + q := s. db. NewSelect(). Model(&types.ImageManifest{}). @@ -299,10 +299,10 @@ func (s *registryStore) GetCatalogCount(ctx context.Context, namespace string) ( Where("visibility = ?", types.RepositoryVisibilityPublic) if repositoryName != "" { - stmnt.Where("name = ?", repositoryName) + q.Where("name = ?", repositoryName) } - count, err := stmnt.Count(ctx) + count, err := q.Count(ctx) if err != nil { logEvent.Err(err).Send() return 0, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) @@ -328,20 +328,23 @@ func (s *registryStore) GetCatalogDetail( repositoryName = parts[1] } - stmnt := s. + q := s. db. NewSelect(). Model(&repositoryList). + Relation("User", func(sq *bun.SelectQuery) *bun.SelectQuery { + return sq.Column("username") + }). Relation("ImageManifests"). Limit(pageSize). Offset(offset). Where("visibility = ?", types.RepositoryVisibilityPublic) if repositoryName != "" { - stmnt.Where("name = ?", repositoryName) + q.Where("name = ?", repositoryName) } - err := stmnt.Scan(ctx) + err := q.Scan(ctx) if err != nil { logEvent.Err(err).Send() return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) @@ -370,8 +373,16 @@ func (s *registryStore) GetImageNamespace(ctx context.Context, search string) ([ logEvent := s.logger.Debug().Str("method", "GetImageNamespace").Str("search_query", search) var manifests []*types.ImageManifest - err := s.db.NewSelect().Model(&manifests).Where("substr(namespace, 1, 50) LIKE ?", bun.Ident(search)).Scan(ctx) - if err != nil { + q := s. + db. + NewSelect(). + Model(&manifests). + Relation("User"). + Relation("Repository"). + WhereOr("substr(username, 1, 50) ILIKE ?", search). + WhereOr("substr(name, 1, 50) ILIKE ?", search) + + if err := q.Scan(ctx); err != nil { logEvent.Err(err).Send() return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) } diff --git a/store/v1/types/registry.go b/store/v1/types/registry.go index 68290869..c85a8ccc 100644 --- a/store/v1/types/registry.go +++ b/store/v1/types/registry.go @@ -93,7 +93,7 @@ type ( CreatedAt time.Time `bun:"created_at" json:"created_at"` UpdatedAt time.Time `bun:"updated_at" json:"updated_at"` MetaTags map[string]any `bun:"meta_tags" json:"meta_tags"` - User *User `bun:"rel:belongs-to,join:owner_id=id" json:"-"` + User *User `bun:"rel:belongs-to,join:owner_id=id" json:"user"` Project *RepositoryBuild `bun:"rel:has-one,join:id=repository_id" json:"-"` Name string `bun:"name,notnull" json:"name"` Visibility RepositoryVisibility `bun:"visibility,notnull" json:"visibility"` From 6a83b7d494c218d31085dcdbf1856e2305ace6d8 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Fri, 22 Dec 2023 00:34:36 +0530 Subject: [PATCH 08/23] refactor: Internal UUID package references Signed-off-by: jay-dee7 --- dfs/filebase/filebase.go | 3 +- dfs/mock/memMappedSystem.go | 3 +- dfs/mock/mockFileSystem.go | 3 +- dfs/storj/storj.go | 3 +- dfs/storj/uplink/uplink.go | 3 +- registry/v2/blobs.go | 2 +- registry/v2/extensions/catalog_detail.go | 16 +++++----- registry/v2/registry.go | 37 ++++++++++++++---------- store/v1/registry/registry_impl.go | 24 ++++++++++----- store/v1/registry/store.go | 6 +++- store/v1/types/registry.go | 2 +- {types => store/v1/types}/uuid.go | 0 12 files changed, 56 insertions(+), 46 deletions(-) rename {types => store/v1/types}/uuid.go (100%) diff --git a/dfs/filebase/filebase.go b/dfs/filebase/filebase.go index 6c17299a..d9be7456 100644 --- a/dfs/filebase/filebase.go +++ b/dfs/filebase/filebase.go @@ -13,7 +13,6 @@ import ( "github.com/containerish/OpenRegistry/config" "github.com/containerish/OpenRegistry/dfs" "github.com/containerish/OpenRegistry/store/v1/types" - core_types "github.com/containerish/OpenRegistry/types" oci_digest "github.com/opencontainers/go-digest" ) @@ -225,7 +224,7 @@ func (fb *filebase) Metadata(layer *types.ContainerImageLayer) (*types.ObjectMet var resp *s3.HeadObjectOutput var err error - identifier := core_types.GetLayerIdentifier(layer.ID) + identifier := types.GetLayerIdentifier(layer.ID) for i := 3; i > 0; i-- { resp, err = fb.client.HeadObject(context.Background(), &s3.HeadObjectInput{ Bucket: &fb.bucket, diff --git a/dfs/mock/memMappedSystem.go b/dfs/mock/memMappedSystem.go index efe66a60..dace1fbb 100644 --- a/dfs/mock/memMappedSystem.go +++ b/dfs/mock/memMappedSystem.go @@ -16,7 +16,6 @@ import ( "github.com/containerish/OpenRegistry/dfs" types "github.com/containerish/OpenRegistry/store/v1/types" "github.com/containerish/OpenRegistry/telemetry" - core_types "github.com/containerish/OpenRegistry/types" "github.com/fatih/color" "github.com/google/uuid" "github.com/labstack/echo/v4" @@ -151,7 +150,7 @@ func (ms *memMappedMockStorage) Metadata(layer *types.ContainerImageLayer) (*typ err error ) - identifier := core_types.GetLayerIdentifier(layer.ID) + identifier := types.GetLayerIdentifier(layer.ID) parts := strings.Split(identifier, "/") if len(parts) > 1 { fd, err = ms.memFs.Open(parts[1]) diff --git a/dfs/mock/mockFileSystem.go b/dfs/mock/mockFileSystem.go index b5caed0e..9dae810d 100644 --- a/dfs/mock/mockFileSystem.go +++ b/dfs/mock/mockFileSystem.go @@ -16,7 +16,6 @@ import ( "github.com/containerish/OpenRegistry/dfs" types "github.com/containerish/OpenRegistry/store/v1/types" "github.com/containerish/OpenRegistry/telemetry" - core_types "github.com/containerish/OpenRegistry/types" "github.com/fatih/color" "github.com/google/uuid" "github.com/labstack/echo/v4" @@ -168,7 +167,7 @@ func (ms *fileBasedMockStorage) Metadata(layer *types.ContainerImageLayer) (*typ err error ) - identifier := core_types.GetLayerIdentifier(layer.ID) + identifier := types.GetLayerIdentifier(layer.ID) parts := strings.Split(identifier, "/") if len(parts) > 1 { fd, err = ms.fs.Open(parts[1]) diff --git a/dfs/storj/storj.go b/dfs/storj/storj.go index 04518086..b8a06b22 100644 --- a/dfs/storj/storj.go +++ b/dfs/storj/storj.go @@ -13,7 +13,6 @@ import ( "github.com/containerish/OpenRegistry/config" "github.com/containerish/OpenRegistry/dfs" "github.com/containerish/OpenRegistry/store/v1/types" - core_types "github.com/containerish/OpenRegistry/types" oci_digest "github.com/opencontainers/go-digest" ) @@ -203,7 +202,7 @@ func (sj *storj) AddImage(ns string, mf, l map[string][]byte) (string, error) { func (sj *storj) Metadata(layer *types.ContainerImageLayer) (*types.ObjectMetadata, error) { var resp *s3.HeadObjectOutput var err error - id := core_types.GetLayerIdentifier(layer.ID) + id := types.GetLayerIdentifier(layer.ID) for i := 3; i > 0; i-- { resp, err = sj.client.HeadObject(context.Background(), &s3.HeadObjectInput{ Bucket: &sj.bucket, diff --git a/dfs/storj/uplink/uplink.go b/dfs/storj/uplink/uplink.go index 284824f0..7ee864ef 100644 --- a/dfs/storj/uplink/uplink.go +++ b/dfs/storj/uplink/uplink.go @@ -12,7 +12,6 @@ import ( "github.com/containerish/OpenRegistry/config" "github.com/containerish/OpenRegistry/dfs" "github.com/containerish/OpenRegistry/store/v1/types" - core_types "github.com/containerish/OpenRegistry/types" "github.com/fatih/color" "storj.io/uplink" "storj.io/uplink/edge" @@ -172,7 +171,7 @@ func (u *storjUplink) GetUploadProgress(identifier string, uploadID string) (*ty // Metadata implements dfs.DFS func (u *storjUplink) Metadata(layer *types.ContainerImageLayer) (*types.ObjectMetadata, error) { - identifier := core_types.GetLayerIdentifier(layer.ID) + identifier := types.GetLayerIdentifier(layer.ID) metadata, err := u.client.StatObject(context.Background(), u.bucket, identifier) if err != nil { diff --git a/registry/v2/blobs.go b/registry/v2/blobs.go index a231290e..9ff1c394 100644 --- a/registry/v2/blobs.go +++ b/registry/v2/blobs.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/containerish/OpenRegistry/types" + "github.com/containerish/OpenRegistry/store/v1/types" "github.com/fatih/color" "github.com/labstack/echo/v4" oci_digest "github.com/opencontainers/go-digest" diff --git a/registry/v2/extensions/catalog_detail.go b/registry/v2/extensions/catalog_detail.go index 0b884f97..b2f4d985 100644 --- a/registry/v2/extensions/catalog_detail.go +++ b/registry/v2/extensions/catalog_detail.go @@ -259,15 +259,13 @@ func (ext *extension) GetUserCatalog(ctx echo.Context) error { visibility = types.RepositoryVisibilityPrivate } - repositories, total, err := ext. - store. - GetUserRepositories( - ctx.Request().Context(), - user.ID, - visibility, - pageSize, - offset, - ) + repositories, total, err := ext.store.GetUserRepositories( + ctx.Request().Context(), + user.ID, + visibility, + pageSize, + offset, + ) if err != nil { return ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), diff --git a/registry/v2/registry.go b/registry/v2/registry.go index aca77c2e..717f9624 100644 --- a/registry/v2/registry.go +++ b/registry/v2/registry.go @@ -19,9 +19,8 @@ import ( "github.com/containerish/OpenRegistry/config" dfsImpl "github.com/containerish/OpenRegistry/dfs" store_v2 "github.com/containerish/OpenRegistry/store/v1/registry" - types_v2 "github.com/containerish/OpenRegistry/store/v1/types" + "github.com/containerish/OpenRegistry/store/v1/types" "github.com/containerish/OpenRegistry/telemetry" - "github.com/containerish/OpenRegistry/types" "github.com/labstack/echo/v4" oci_digest "github.com/opencontainers/go-digest" img_spec_v1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -359,7 +358,7 @@ func (r *registry) MonolithicUpload(ctx echo.Context) error { return echoErr } - layerV2 := &types_v2.ContainerImageLayer{ + layerV2 := &types.ContainerImageLayer{ MediaType: ctx.Request().Header.Get("content-type"), Digest: imageDigest, DFSLink: dfsLink, @@ -551,7 +550,7 @@ func (r *registry) MonolithicPut(ctx echo.Context) error { return echoErr } - layer := &types_v2.ContainerImageLayer{ + layer := &types.ContainerImageLayer{ CreatedAt: time.Now(), ID: layerKey, Digest: digest, @@ -682,7 +681,7 @@ func (r *registry) CompleteUpload(ctx echo.Context) error { return echoErr } - layer := &types_v2.ContainerImageLayer{ + layer := &types.ContainerImageLayer{ MediaType: ctx.Request().Header.Get("content-type"), Digest: digest, DFSLink: dfsLink, @@ -765,17 +764,17 @@ func (r *registry) PushManifest(ctx echo.Context) error { } - repository = &types_v2.ContainerImageRepository{ + repository = &types.ContainerImageRepository{ CreatedAt: time.Now(), OwnerID: user.ID, ID: repositoryID, Name: strings.Split(namespace, "/")[1], - Visibility: types_v2.RepositoryVisibilityPrivate, + Visibility: types.RepositoryVisibilityPrivate, } // IPFS P2P repositories are public - if user.Username == types_v2.SystemUsernameIPFS { - repository.Visibility = types_v2.RepositoryVisibilityPublic + if user.Username == types.SystemUsernameIPFS { + repository.Visibility = types.RepositoryVisibilityPublic } idErr = r.store.CreateRepository(ctx.Request().Context(), repository) @@ -811,7 +810,7 @@ func (r *registry) PushManifest(ctx echo.Context) error { return echoErr } - manifest := types_v2.ImageManifest{ + manifest := types.ImageManifest{ CreatedAt: time.Now(), ID: uuid, RepositoryID: repository.ID, @@ -883,7 +882,7 @@ func (r *registry) PushManifest(ctx echo.Context) error { func (r *registry) setPushManifestHaeders( ctx echo.Context, namespace, ref, digest string, - manifest *types_v2.ImageManifest, + manifest *types.ImageManifest, ) { locationHeader := fmt.Sprintf("%s/v2/%s/manifests/%s", r.config.Endpoint(), namespace, ref) ctx.Response().Header().Set("Location", locationHeader) @@ -1012,7 +1011,13 @@ func (r *registry) GetImageNamespace(ctx echo.Context) error { r.logger.Log(ctx, errMsg).Send() return echoErr } - result, err := r.store.GetImageNamespace(ctx.Request().Context(), searchQuery) + + var visibility types.RepositoryVisibility + if ctx.QueryParam("public") == "true" { + visibility = types.RepositoryVisibilityPublic + } + + result, err := r.store.GetImageNamespace(ctx.Request().Context(), searchQuery, visibility) if err != nil { echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), @@ -1042,8 +1047,8 @@ func (r *registry) GetImageNamespace(ctx echo.Context) error { return echoErr } -func (r *registry) GetUserFromCtx(ctx echo.Context) (*types_v2.User, error) { - user, ok := ctx.Get(string(types_v2.UserContextKey)).(*types_v2.User) +func (r *registry) GetUserFromCtx(ctx echo.Context) (*types.User, error) { + user, ok := ctx.Get(string(types.UserContextKey)).(*types.User) if !ok { return nil, fmt.Errorf("ERR_USER_NOT_PRESENT_IN_REQUEST_CTX") } @@ -1051,8 +1056,8 @@ func (r *registry) GetUserFromCtx(ctx echo.Context) (*types_v2.User, error) { return user, nil } -func (r *registry) GetRepositoryFromCtx(ctx echo.Context) *types_v2.ContainerImageRepository { - if repository, ok := ctx.Get(string(types_v2.UserRepositoryContextKey)).(*types_v2.ContainerImageRepository); ok { +func (r *registry) GetRepositoryFromCtx(ctx echo.Context) *types.ContainerImageRepository { + if repository, ok := ctx.Get(string(types.UserRepositoryContextKey)).(*types.ContainerImageRepository); ok { return repository } return nil diff --git a/store/v1/registry/registry_impl.go b/store/v1/registry/registry_impl.go index 164f7153..c905e273 100644 --- a/store/v1/registry/registry_impl.go +++ b/store/v1/registry/registry_impl.go @@ -262,6 +262,9 @@ func (s *registryStore) GetUserRepositories( db. NewSelect(). Model(&repositories). + Relation("User", func(sq *bun.SelectQuery) *bun.SelectQuery { + return sq.ExcludeColumn("password").ExcludeColumn("github_connected").ExcludeColumn("webauthn_connected") + }). WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery { if visibility != "" { return q.Where("visibility = ?", visibility) @@ -332,9 +335,7 @@ func (s *registryStore) GetCatalogDetail( db. NewSelect(). Model(&repositoryList). - Relation("User", func(sq *bun.SelectQuery) *bun.SelectQuery { - return sq.Column("username") - }). + Relation("User"). Relation("ImageManifests"). Limit(pageSize). Offset(offset). @@ -369,26 +370,33 @@ func (s *registryStore) GetContentHashById(ctx context.Context, uuid string) (st } // GetImageNamespace implements registry.RegistryStore. -func (s *registryStore) GetImageNamespace(ctx context.Context, search string) ([]*types.ImageManifest, error) { +func (s *registryStore) GetImageNamespace( + ctx context.Context, + search string, + visibility types.RepositoryVisibility, +) ([]*types.ContainerImageRepository, error) { logEvent := s.logger.Debug().Str("method", "GetImageNamespace").Str("search_query", search) - var manifests []*types.ImageManifest + var repos []*types.ContainerImageRepository q := s. db. NewSelect(). - Model(&manifests). + Model(&repos). Relation("User"). - Relation("Repository"). WhereOr("substr(username, 1, 50) ILIKE ?", search). WhereOr("substr(name, 1, 50) ILIKE ?", search) + if visibility == types.RepositoryVisibilityPublic { + q.Where("visibility = ? ", visibility.String()) + } + if err := q.Scan(ctx); err != nil { logEvent.Err(err).Send() return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) } logEvent.Bool("success", true).Send() - return manifests, nil + return repos, nil } // GetImageTags implements registry.RegistryStore. diff --git a/store/v1/registry/store.go b/store/v1/registry/store.go index c8b427ce..9f68302a 100644 --- a/store/v1/registry/store.go +++ b/store/v1/registry/store.go @@ -63,7 +63,11 @@ type RegistryStore interface { offset int, ) (*types.ContainerImageRepository, error) GetCatalogCount(ctx context.Context, ns string) (int64, error) - GetImageNamespace(ctx context.Context, search string) ([]*types.ImageManifest, error) + GetImageNamespace( + ctx context.Context, + search string, + visibility types.RepositoryVisibility, + ) ([]*types.ContainerImageRepository, error) DeleteLayerByDigest(ctx context.Context, digest string) error GetPublicRepositories(ctx context.Context, pageSize int, offset int) ([]*types.ContainerImageRepository, int, error) GetUserRepositories( diff --git a/store/v1/types/registry.go b/store/v1/types/registry.go index c85a8ccc..32285188 100644 --- a/store/v1/types/registry.go +++ b/store/v1/types/registry.go @@ -42,7 +42,7 @@ type ( CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp" json:"createdAt"` UpdatedAt time.Time `bun:"updated_at,nullzero" json:"updatedAt"` - Repository *ContainerImageRepository `bun:"rel:belongs-to,join:repository_id=id" json:"-"` + Repository *ContainerImageRepository `bun:"rel:belongs-to,join:repository_id=id" json:"repository"` User *User `bun:"rel:belongs-to,join:owner_id=id" json:"-"` Subject *img_spec_v1.Descriptor `bun:"embed:subject_" json:"subject,omitempty"` Config *img_spec_v1.Descriptor `bun:"embed:config_" json:"config"` diff --git a/types/uuid.go b/store/v1/types/uuid.go similarity index 100% rename from types/uuid.go rename to store/v1/types/uuid.go From 2bb28ee70107b927a77baf5acb3c81527db061a2 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Sat, 23 Dec 2023 21:22:42 +0530 Subject: [PATCH 09/23] fix: Search repositories query Signed-off-by: jay-dee7 --- registry/v2/registry.go | 9 ++++++++- store/v1/registry/registry_impl.go | 20 +++++++++++++++++--- store/v1/registry/store.go | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/registry/v2/registry.go b/registry/v2/registry.go index 717f9624..98c6a505 100644 --- a/registry/v2/registry.go +++ b/registry/v2/registry.go @@ -21,6 +21,7 @@ import ( store_v2 "github.com/containerish/OpenRegistry/store/v1/registry" "github.com/containerish/OpenRegistry/store/v1/types" "github.com/containerish/OpenRegistry/telemetry" + "github.com/google/uuid" "github.com/labstack/echo/v4" oci_digest "github.com/opencontainers/go-digest" img_spec_v1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -1001,6 +1002,12 @@ func (r *registry) ApiVersion(ctx echo.Context) error { func (r *registry) GetImageNamespace(ctx echo.Context) error { ctx.Set(types.HandlerStartTime, time.Now()) + userId := uuid.NullUUID{}.UUID + user, ok := ctx.Get(string(types.UserContextKey)).(*types.User) + if ok { + userId = user.ID + } + searchQuery := ctx.QueryParam("search_query") if searchQuery == "" { errMsg := fmt.Errorf("search query must not be empty") @@ -1017,7 +1024,7 @@ func (r *registry) GetImageNamespace(ctx echo.Context) error { visibility = types.RepositoryVisibilityPublic } - result, err := r.store.GetImageNamespace(ctx.Request().Context(), searchQuery, visibility) + result, err := r.store.GetImageNamespace(ctx.Request().Context(), searchQuery, visibility, userId) if err != nil { echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), diff --git a/store/v1/registry/registry_impl.go b/store/v1/registry/registry_impl.go index c905e273..1cb1d1dc 100644 --- a/store/v1/registry/registry_impl.go +++ b/store/v1/registry/registry_impl.go @@ -369,11 +369,16 @@ func (s *registryStore) GetContentHashById(ctx context.Context, uuid string) (st return dfsLink, nil } +func (s *registryStore) excludeUserSensitiveFieldsOnJoin(sq *bun.SelectQuery) *bun.SelectQuery { + return sq.ExcludeColumn("password").ExcludeColumn("created_at").ExcludeColumn("updated_at") +} + // GetImageNamespace implements registry.RegistryStore. func (s *registryStore) GetImageNamespace( ctx context.Context, search string, visibility types.RepositoryVisibility, + userID uuid.UUID, ) ([]*types.ContainerImageRepository, error) { logEvent := s.logger.Debug().Str("method", "GetImageNamespace").Str("search_query", search) var repos []*types.ContainerImageRepository @@ -382,9 +387,18 @@ func (s *registryStore) GetImageNamespace( db. NewSelect(). Model(&repos). - Relation("User"). - WhereOr("substr(username, 1, 50) ILIKE ?", search). - WhereOr("substr(name, 1, 50) ILIKE ?", search) + Relation("User", func(sq *bun.SelectQuery) *bun.SelectQuery { + return s.excludeUserSensitiveFieldsOnJoin(sq) + }). + WhereGroup(" AND ", func(sq *bun.SelectQuery) *bun.SelectQuery { + return sq. + WhereOr("visibility = ?", types.RepositoryVisibilityPublic.String()). + WhereOr("owner_id = ?", userID) + }). + WhereGroup(" AND ", func(sq *bun.SelectQuery) *bun.SelectQuery { + return sq.WhereOr("substr(username, 1, 50) ILIKE ?", search). + WhereOr("substr(name, 1, 50) ILIKE ?", search) + }) if visibility == types.RepositoryVisibilityPublic { q.Where("visibility = ? ", visibility.String()) diff --git a/store/v1/registry/store.go b/store/v1/registry/store.go index 9f68302a..61b40674 100644 --- a/store/v1/registry/store.go +++ b/store/v1/registry/store.go @@ -67,6 +67,7 @@ type RegistryStore interface { ctx context.Context, search string, visibility types.RepositoryVisibility, + userId uuid.UUID, ) ([]*types.ContainerImageRepository, error) DeleteLayerByDigest(ctx context.Context, digest string) error GetPublicRepositories(ctx context.Context, pageSize int, offset int) ([]*types.ContainerImageRepository, int, error) From 2734cc400595666125f96466714d7d1742c5f277 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Sat, 23 Dec 2023 21:23:02 +0530 Subject: [PATCH 10/23] fix: Storing parsed value in ctx for AddUsersToOrgRequest Signed-off-by: jay-dee7 --- orgmode/admin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orgmode/admin.go b/orgmode/admin.go index 3b88fa27..761a02d1 100644 --- a/orgmode/admin.go +++ b/orgmode/admin.go @@ -121,7 +121,7 @@ func (o *orgMode) parseAddUsersToOrgRequest(ctx echo.Context, user *types.User, parsedBody.Users = append(parsedBody.Users, perm) } - ctx.Set(string(types.OrgModeRequestBodyContextKey), parsedBody) + ctx.Set(string(types.OrgModeRequestBodyContextKey), &parsedBody) return nil } From 7db8f96f0b99f94cc0c5fea99b835bb7a0f3ce7e Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Sat, 23 Dec 2023 21:24:05 +0530 Subject: [PATCH 11/23] fix: Remove repositories from fav list API Signed-off-by: jay-dee7 --- registry/v2/extensions/analytics.go | 23 +++++++++++++++++++---- router/registry.go | 2 +- router/route_names.go | 1 + 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/registry/v2/extensions/analytics.go b/registry/v2/extensions/analytics.go index 828077e8..52ddf5dc 100644 --- a/registry/v2/extensions/analytics.go +++ b/registry/v2/extensions/analytics.go @@ -1,6 +1,7 @@ package extensions import ( + "fmt" "net/http" "time" @@ -46,17 +47,31 @@ func (ext *extension) AddRepositoryToFavorites(ctx echo.Context) error { func (ext *extension) RemoveRepositoryFromFavorites(ctx echo.Context) error { ctx.Set(types.HandlerStartTime, time.Now()) - var body FavoriteRepositoryRequest - if err := ctx.Bind(&body); err != nil { + user, ok := ctx.Get(string(types.UserContextKey)).(*types.User) + if !ok { + err := fmt.Errorf("missing authentication credentials") + echoErr := ctx.JSON(http.StatusForbidden, echo.Map{ + "error": err.Error(), + }) + ext.logger.Log(ctx, err).Send() + return echoErr + } + + repositoryID, err := uuid.Parse(ctx.Param("repository_id")) + if err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), }) ext.logger.Log(ctx, err).Send() return echoErr } - defer ctx.Request().Body.Close() - err := ext.store.RemoveRepositoryFromFavorites(ctx.Request().Context(), body.RepositoryID, body.UserID) + body := FavoriteRepositoryRequest{ + RepositoryID: repositoryID, + UserID: user.ID, + } + + err = ext.store.RemoveRepositoryFromFavorites(ctx.Request().Context(), body.RepositoryID, body.UserID) if err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), diff --git a/router/registry.go b/router/registry.go index 8352baea..b599632a 100644 --- a/router/registry.go +++ b/router/registry.go @@ -105,5 +105,5 @@ func RegisterExtensionsRoutes( group.Add(http.MethodPost, ChangeRepositoryVisibility, ext.ChangeContainerImageVisibility, middlewares...) group.Add(http.MethodPost, CreateRepository, reg.CreateRepository, middlewares...) group.Add(http.MethodPost, RepositoryFavorites, ext.AddRepositoryToFavorites, middlewares...) - group.Add(http.MethodDelete, RepositoryFavorites, ext.RemoveRepositoryFromFavorites, middlewares...) + group.Add(http.MethodDelete, RemoveRepositoryFavorites, ext.RemoveRepositoryFromFavorites, middlewares...) } diff --git a/router/route_names.go b/router/route_names.go index bdba115a..ba10fa50 100644 --- a/router/route_names.go +++ b/router/route_names.go @@ -75,4 +75,5 @@ const ( ChangeRepositoryVisibility = Ext + "/repository/visibility" CreateRepository = Ext + "/repository/create" RepositoryFavorites = Ext + "/repository/favorites" + RemoveRepositoryFavorites = Ext + "/repository/favorites/:repository_id" ) From 7c5536b8e59de097484e2af4f25819bfbae1d9c0 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Sat, 23 Dec 2023 21:39:35 +0530 Subject: [PATCH 12/23] feat: Honeycomb configuration via yaml Signed-off-by: jay-dee7 --- cmd/registry/registry.go | 2 +- config/config.go | 13 ++++++++++--- telemetry/otel/otel.go | 20 ++++++++++++++++++-- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/cmd/registry/registry.go b/cmd/registry/registry.go index ad3ab2c4..43a90edd 100644 --- a/cmd/registry/registry.go +++ b/cmd/registry/registry.go @@ -102,7 +102,7 @@ func RunRegistryServer(ctx *cli.Context) error { dfs, ) - otelShutdownFunc := otel.ConfigureOtel(cfg.Telemetry, "openregistry-api", baseRouter) + otelShutdownFunc := otel.ConfigureOtel(cfg.Telemetry.Honeycomb, "openregistry-api", baseRouter) if otelShutdownFunc != nil { defer otelShutdownFunc() } diff --git a/config/config.go b/config/config.go index b0e61199..b17e5a7e 100644 --- a/config/config.go +++ b/config/config.go @@ -198,9 +198,16 @@ type ( } Telemetry struct { - Logging Logging `yaml:"logging" mapstructure:"logging"` - Otel Otel `yaml:"otel" mapstructure:"otel"` - Enabled bool `yaml:"enabled" mapstructure:"enabled"` + Honeycomb Honeycomb `yaml:"honeycomb" mapstructure:"honeycomb"` + Logging Logging `yaml:"logging" mapstructure:"logging"` + Otel Otel `yaml:"otel" mapstructure:"otel"` + Enabled bool `yaml:"enabled" mapstructure:"enabled"` + } + + Honeycomb struct { + ServiceName string `yaml:"service_name" mapstructure:"service_name"` + ApiKey string `yaml:"api_key" mapstructure:"api_key"` + Enabled bool `yaml:"enabled" mapstructure:"enabled"` } IpfsDFS struct { diff --git a/telemetry/otel/otel.go b/telemetry/otel/otel.go index 7b662bd4..cf930838 100644 --- a/telemetry/otel/otel.go +++ b/telemetry/otel/otel.go @@ -2,6 +2,7 @@ package otel import ( "log" + "os" "github.com/containerish/OpenRegistry/config" "github.com/fatih/color" @@ -11,9 +12,11 @@ import ( "go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho" ) -func ConfigureOtel(config config.Telemetry, service string, e *echo.Echo) func() { +func ConfigureOtel(config config.Honeycomb, service string, e *echo.Echo) func() { if config.Enabled { - color.Green("OpenTelemetry: Enabled") + checkAndLoadHoneycombConfig(config) + + color.Green("OpenTelemetry with Honeycomb.io: Enabled") bsp := honeycomb.NewBaggageSpanProcessor() otelShutdown, err := otelconfig.ConfigureOpenTelemetry( @@ -31,3 +34,16 @@ func ConfigureOtel(config config.Telemetry, service string, e *echo.Echo) func() return nil } + +func checkAndLoadHoneycombConfig(config config.Honeycomb) { + if config.ApiKey == "" { + log.Fatalln(color.RedString("ERR_MISSING_HONEYCOMB_API_KEY")) + } + + if config.ServiceName == "" { + config.ServiceName = "openregistry-api" + } + + os.Setenv("OTEL_SERVICE_NAME", config.ServiceName) + os.Setenv("HONEYCOMB_API_KEY", config.ApiKey) +} From c2faba2fef3c4546f666a33593187491dbd4b608 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Mon, 25 Dec 2023 01:27:45 +0530 Subject: [PATCH 13/23] fix: Concurrent map-write bug in mock DFS Signed-off-by: jay-dee7 --- dfs/mock/memMappedSystem.go | 9 +++++++++ dfs/mock/mockFileSystem.go | 9 +++++++++ store/v1/webauthn/webauthn_impl.go | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/dfs/mock/memMappedSystem.go b/dfs/mock/memMappedSystem.go index dace1fbb..19955696 100644 --- a/dfs/mock/memMappedSystem.go +++ b/dfs/mock/memMappedSystem.go @@ -9,6 +9,7 @@ import ( "net/url" "os" "strings" + "sync" "github.com/aws/aws-sdk-go-v2/aws" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" @@ -27,6 +28,7 @@ type memMappedMockStorage struct { logger telemetry.Logger uploadSession map[string]string config *config.S3CompatibleDFS + mutex *sync.RWMutex serviceEndpoint string } @@ -52,6 +54,7 @@ func newMemMappedMockStorage( config: cfg, serviceEndpoint: net.JoinHostPort(parsedHost.Hostname(), "5002"), logger: logger, + mutex: &sync.RWMutex{}, } go mocker.FileServer() @@ -60,7 +63,9 @@ func newMemMappedMockStorage( func (ms *memMappedMockStorage) CreateMultipartUpload(layerKey string) (string, error) { sessionId := uuid.NewString() + ms.mutex.Lock() ms.uploadSession[sessionId] = sessionId + defer ms.mutex.Unlock() return sessionId, nil } @@ -101,7 +106,9 @@ func (ms *memMappedMockStorage) CompleteMultipartUpload( layerDigest string, completedParts []s3types.CompletedPart, ) (string, error) { + ms.mutex.Lock() delete(ms.uploadSession, layerKey) + defer ms.mutex.Unlock() return layerKey, nil } @@ -212,7 +219,9 @@ func (ms *memMappedMockStorage) AbortMultipartUpload(ctx context.Context, layerK return err } + ms.mutex.Lock() delete(ms.uploadSession, uploadId) + defer ms.mutex.Unlock() return nil } diff --git a/dfs/mock/mockFileSystem.go b/dfs/mock/mockFileSystem.go index 9dae810d..823ed8c0 100644 --- a/dfs/mock/mockFileSystem.go +++ b/dfs/mock/mockFileSystem.go @@ -9,6 +9,7 @@ import ( "net/url" "os" "strings" + "sync" "github.com/aws/aws-sdk-go-v2/aws" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" @@ -28,6 +29,7 @@ type fileBasedMockStorage struct { logger telemetry.Logger uploadSession map[string]string config *config.S3CompatibleDFS + mutex *sync.RWMutex serviceEndpoint string } @@ -55,6 +57,7 @@ func newFileBasedMockStorage( config: cfg, serviceEndpoint: net.JoinHostPort(parsedHost.Hostname(), "5002"), logger: logger, + mutex: &sync.RWMutex{}, } go mocker.FileServer() @@ -63,7 +66,9 @@ func newFileBasedMockStorage( func (ms *fileBasedMockStorage) CreateMultipartUpload(layerKey string) (string, error) { sessionId := uuid.NewString() + ms.mutex.Lock() ms.uploadSession[sessionId] = sessionId + defer ms.mutex.Unlock() return sessionId, nil } @@ -114,7 +119,9 @@ func (ms *fileBasedMockStorage) CompleteMultipartUpload( layerDigest string, completedParts []s3types.CompletedPart, ) (string, error) { + ms.mutex.Lock() delete(ms.uploadSession, layerKey) + defer ms.mutex.Unlock() return layerKey, nil } @@ -229,7 +236,9 @@ func (ms *fileBasedMockStorage) AbortMultipartUpload(ctx context.Context, layerK return err } + ms.mutex.Lock() delete(ms.uploadSession, uploadId) + defer ms.mutex.Unlock() return nil } diff --git a/store/v1/webauthn/webauthn_impl.go b/store/v1/webauthn/webauthn_impl.go index b5ae8765..e87d059e 100644 --- a/store/v1/webauthn/webauthn_impl.go +++ b/store/v1/webauthn/webauthn_impl.go @@ -39,7 +39,7 @@ func (ws *webauthnStore) GetWebAuthnSessionData( userId uuid.UUID, sessionType string, ) (*webauthn.SessionData, error) { - session := &types.WebauthnSession{} + var session types.WebauthnSession err := ws. db. From ea045844a6440e2d9de85b57b53bedbf5e37ca5c Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Mon, 25 Dec 2023 01:28:43 +0530 Subject: [PATCH 14/23] fix: Clear webauthn session data at EOL Signed-off-by: jay-dee7 --- auth/webauthn/webauthn.go | 8 ++++++++ services/yor/clair/v1/server/interceptors.go | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/auth/webauthn/webauthn.go b/auth/webauthn/webauthn.go index 19dc5e86..c27274e9 100644 --- a/auth/webauthn/webauthn.go +++ b/auth/webauthn/webauthn.go @@ -236,6 +236,10 @@ func (wa *webAuthnService) FinishRegistration(ctx context.Context, opts *FinishR return fmt.Errorf("ERR_WEBAUTHN_ADD_CREDENTIAL: %w", err) } + if err = wa.store.RemoveWebAuthSessionData(ctx, opts.User.ID); err != nil { + return fmt.Errorf("ERR_WEBAUTHN_ADD_CREDENTIAL: RemoveWebAuthSessionData: %w", err) + } + return nil } @@ -306,5 +310,9 @@ func (wa *webAuthnService) FinishLogin(ctx context.Context, opts *FinishLoginOpt return fmt.Errorf("ERR_VALIDATE_WEBAUTHN_LOGIN: %w", err) } + if err = wa.store.RemoveWebAuthSessionData(ctx, opts.User.ID); err != nil { + return fmt.Errorf("ERR_WEBAUTHN_ADD_CREDENTIAL: RemoveWebAuthSessionData: %w", err) + } + return nil } diff --git a/services/yor/clair/v1/server/interceptors.go b/services/yor/clair/v1/server/interceptors.go index 3e08bbdb..64da34bb 100644 --- a/services/yor/clair/v1/server/interceptors.go +++ b/services/yor/clair/v1/server/interceptors.go @@ -24,12 +24,13 @@ func (c *clair) NewJWTInterceptor() connect.UnaryInterceptorFunc { userID, err := c.getTokenFromReq(req, c.authConfig.JWTSigningPubKey) if err != nil { + logEvent.Err(err).Send() return nil, err } user, err := c.userGetter.GetUserByID(ctx, userID) if err != nil { - logEvent.Str("error", err.Error()).Send() + logEvent.Err(err).Send() return nil, connect.NewError(connect.CodeFailedPrecondition, err) } From c7eadb7bf2854f9458f2a99b2b7fc64c44a30bb8 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Mon, 25 Dec 2023 19:52:56 +0530 Subject: [PATCH 15/23] feat: CORS for ConnectRPC APIs Signed-off-by: jay-dee7 --- auth/helpers.go | 2 +- go.mod | 2 +- go.sum | 2 ++ router/github.go | 20 ++++++++++++- router/router.go | 2 ++ router/vuln_scanning_routes.go | 31 +++++++++++++++++++- services/yor/clair/v1/server/clair.go | 7 ++++- services/yor/clair/v1/server/interceptors.go | 15 ++++++---- 8 files changed, 70 insertions(+), 11 deletions(-) diff --git a/auth/helpers.go b/auth/helpers.go index a2a3c6ec..7d7c29bb 100644 --- a/auth/helpers.go +++ b/auth/helpers.go @@ -118,7 +118,7 @@ func NewWebLoginToken(opts *WebLoginJWTOptions) (string, error) { hasher := sha256.New() hasher.Write(pubkeyDER) - raw := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) + raw := jwt.NewWithClaims(jwt.SigningMethodRS256, &claims) raw.Header["kid"] = KeyIDEncode(hasher.Sum(nil)[:30]) token, err := raw.SignedString(opts.Privkey) if err != nil { diff --git a/go.mod b/go.mod index 90a61082..6b6ab139 100644 --- a/go.mod +++ b/go.mod @@ -169,7 +169,7 @@ require ( github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/rs/cors v1.7.0 // indirect + github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect diff --git a/go.sum b/go.sum index daad63d1..9fc15dc7 100644 --- a/go.sum +++ b/go.sum @@ -662,6 +662,8 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= diff --git a/router/github.go b/router/github.go index 9963d22f..02f426d1 100644 --- a/router/github.go +++ b/router/github.go @@ -4,6 +4,7 @@ import ( "fmt" "net" "net/http" + "strings" "github.com/containerish/OpenRegistry/config" github_actions_server "github.com/containerish/OpenRegistry/services/kon/github_actions/v1/server" @@ -13,6 +14,7 @@ import ( "github.com/containerish/OpenRegistry/vcs/github" "github.com/fatih/color" "github.com/labstack/echo/v4" + "github.com/rs/cors" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) @@ -26,6 +28,7 @@ func RegisterGitHubRoutes( allowedEndpoints []string, usersStore vcs.VCSStore, automationStore automation.BuildAutomationStore, + allowedOrigins []string, ) { if cfg != nil && cfg.Enabled { ghAppApi := github.NewGithubApp( @@ -47,7 +50,22 @@ func RegisterGitHubRoutes( go func() { addr := net.JoinHostPort(cfg.Host, fmt.Sprintf("%d", cfg.Port)) color.Green("connect-go GitHub Automation gRPC service running on: %s", addr) - if err := http.ListenAndServe(addr, h2c.NewHandler(githubMux, &http2.Server{})); err != nil { + ghCors := cors.New(cors.Options{ + AllowedOrigins: allowedOrigins, + AllowOriginFunc: func(origin string) bool { + return strings.HasSuffix(origin, "openregistry.dev") || + strings.HasSuffix(origin, "cntr.sh") || + strings.HasSuffix(origin, "openregistry-web.pages.dev") + }, + AllowedMethods: []string{ + http.MethodOptions, http.MethodGet, http.MethodPost, + }, + AllowedHeaders: []string{"*"}, + AllowCredentials: true, + Debug: true, + }) + handler := ghCors.Handler(h2c.NewHandler(githubMux, &http2.Server{})) + if err := http.ListenAndServe(addr, handler); err != nil { color.Red("connect-go GitHub Automation service listen error: %s", err) } }() diff --git a/router/router.go b/router/router.go index 792b505f..eeb16367 100644 --- a/router/router.go +++ b/router/router.go @@ -70,6 +70,7 @@ func Register( logger, registryStore.GetLayersLinksForManifest, dfs.GeneratePresignedURL, + cfg.WebAppConfig.AllowedEndpoints, ) if cfg.Integrations.GetGithubConfig() != nil && cfg.Integrations.GetGithubConfig().Enabled { @@ -82,6 +83,7 @@ func Register( cfg.WebAppConfig.AllowedEndpoints, usersStore, automationStore, + cfg.WebAppConfig.AllowedEndpoints, ) } diff --git a/router/vuln_scanning_routes.go b/router/vuln_scanning_routes.go index 4f98f0b1..cc2d2079 100644 --- a/router/vuln_scanning_routes.go +++ b/router/vuln_scanning_routes.go @@ -4,12 +4,14 @@ import ( "fmt" "net" "net/http" + "strings" "github.com/containerish/OpenRegistry/config" "github.com/containerish/OpenRegistry/services/yor/clair/v1/server" "github.com/containerish/OpenRegistry/store/v1/users" "github.com/containerish/OpenRegistry/telemetry" "github.com/fatih/color" + "github.com/rs/cors" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) @@ -21,6 +23,7 @@ func RegisterVulnScaningRoutes( logger telemetry.Logger, layerLinkReader server.LayerLinkReader, prePresignedURLGenerator server.PresignedURLGenerator, + allowedOrigins []string, ) { if clairConfig != nil && clairConfig.Enabled { clairApi := server.NewClairClient( @@ -33,8 +36,34 @@ func RegisterVulnScaningRoutes( ) go func() { addr := net.JoinHostPort(clairConfig.Host, fmt.Sprintf("%d", clairConfig.Port)) + vulnScanningCors := cors.New(cors.Options{ + AllowedOrigins: allowedOrigins, + AllowOriginFunc: func(origin string) bool { + return strings.HasSuffix(origin, "openregistry.dev") || + strings.HasSuffix(origin, "cntr.sh") || + strings.HasSuffix(origin, "openregistry-web.pages.dev") || + strings.Contains(origin, "localhost") + }, + AllowedMethods: []string{ + http.MethodOptions, http.MethodGet, http.MethodPost, + }, + AllowedHeaders: []string{ + "Origin", + "Content-Type", + "Authorization", + "Connect-Protocol-Version", + "Connect-Timeout-Ms", + "Grpc-Timeout", + "X-Grpc-Web", + "X-User-Agent", + }, + AllowCredentials: true, + Debug: true, + }) + + handler := h2c.NewHandler(vulnScanningCors.Handler(clairApi), &http2.Server{}) color.Green("connect-go Clair gRPC service running on: %s", addr) - if err := http.ListenAndServe(addr, h2c.NewHandler(clairApi, &http2.Server{})); err != nil { + if err := http.ListenAndServe(addr, handler); err != nil { color.Red("connect-go listen error: %s", err) } }() diff --git a/services/yor/clair/v1/server/clair.go b/services/yor/clair/v1/server/clair.go index 21309aaf..8e339f35 100644 --- a/services/yor/clair/v1/server/clair.go +++ b/services/yor/clair/v1/server/clair.go @@ -165,7 +165,12 @@ func (c *clair) submitManifest( return nil, err } - return res.Body, nil + if res.StatusCode >= 200 && res.StatusCode <= 300 { + return res.Body, nil + } + + return nil, fmt.Errorf("ERR_SUBMIT_MANIFEST_TO_SCAN: CODE: %d", res.StatusCode) + } func (c *clair) newClairRequest(ctx context.Context, method string, url string, body io.Reader) (*http.Request, error) { diff --git a/services/yor/clair/v1/server/interceptors.go b/services/yor/clair/v1/server/interceptors.go index 64da34bb..899eced5 100644 --- a/services/yor/clair/v1/server/interceptors.go +++ b/services/yor/clair/v1/server/interceptors.go @@ -42,15 +42,18 @@ func (c *clair) NewJWTInterceptor() connect.UnaryInterceptorFunc { } func (c *clair) getTokenFromReq(req connect.AnyRequest, jwtSigningPubKey *rsa.PublicKey) (uuid.UUID, error) { - token, err := c.tryTokenFromReqHeaders(req, jwtSigningPubKey) - if err != nil { - token, err = c.tryTokenFromReqCookies(req, jwtSigningPubKey) - if err != nil { - return uuid.Nil, fmt.Errorf("getTokenFromReq: tryTokenFromReqCookies: %w", err) + tokenFromHeaders, headerErr := c.tryTokenFromReqHeaders(req, jwtSigningPubKey) + if headerErr != nil { + tokenFromCookies, cookieErr := c.tryTokenFromReqCookies(req, jwtSigningPubKey) + if cookieErr != nil { + return uuid.Nil, fmt.Errorf( + "getTokenFromReq: tryTokenFromReqCookies: %w - tryTokenFromReqHeaders: %w", cookieErr, headerErr, + ) } + return tokenFromCookies, nil } - return token, nil + return tokenFromHeaders, nil } func (c *clair) tryTokenFromReqCookies(req connect.AnyRequest, jwtSigningPubKey *rsa.PublicKey) (uuid.UUID, error) { From 8efb4114c4365b25cf0d6bdcba0dd0679ae2b2e3 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Wed, 27 Dec 2023 01:30:35 +0530 Subject: [PATCH 16/23] feat: Auth tokens for client-side usage Signed-off-by: jay-dee7 --- Makefile | 3 + api/users/users.go | 118 ++++++++++++++++++++++++++++++++++ auth/basic_auth.go | 10 +++ auth/bcrypt.go | 16 ++++- auth/permissions.go | 6 +- auth/user.go | 2 +- auth/validate_user.go | 25 +++++++ cmd/migrations/migrations.go | 8 +++ go.mod | 1 + go.sum | 3 + router/users.go | 6 +- scripts/load_dummy_users.sh | 14 ++++ store/v1/types/auth_tokens.go | 58 +++++++++++++++++ store/v1/types/users.go | 16 +++++ store/v1/users/store.go | 3 + store/v1/users/users_impl.go | 54 ++++++++++++++++ 16 files changed, 334 insertions(+), 9 deletions(-) create mode 100644 scripts/load_dummy_users.sh create mode 100644 store/v1/types/auth_tokens.go diff --git a/Makefile b/Makefile index 80732244..fead562a 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,9 @@ certs: openssl req -x509 -newkey rsa:4096 -keyout .certs/registry.local -out .certs/registry.local.crt -sha256 -days 365 \ -subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=registry.local" -nodes +load_dummy_users: + sh ./scripts/load_dummy_users.sh + reset: psql -c 'drop database open_registry' && \ psql -c 'drop role open_registry_user' && \ diff --git a/api/users/users.go b/api/users/users.go index 3887842f..157d4735 100644 --- a/api/users/users.go +++ b/api/users/users.go @@ -1,8 +1,11 @@ package users import ( + "fmt" "net/http" + "time" + "github.com/containerish/OpenRegistry/auth" "github.com/containerish/OpenRegistry/store/v1/types" "github.com/containerish/OpenRegistry/store/v1/users" "github.com/containerish/OpenRegistry/telemetry" @@ -12,6 +15,8 @@ import ( type ( UserApi interface { SearchUsers(echo.Context) error + CreateUserToken(ctx echo.Context) error + ListUserToken(ctx echo.Context) error } api struct { @@ -47,3 +52,116 @@ func (a *api) SearchUsers(ctx echo.Context) error { a.logger.Log(ctx, nil).Send() return echoErr } + +func (a *api) CreateUserToken(ctx echo.Context) error { + ctx.Set(types.HandlerStartTime, time.Now()) + + user, ok := ctx.Get(string(types.UserContextKey)).(*types.User) + if !ok { + err := fmt.Errorf("missing authentication credentials") + echoErr := ctx.JSON(http.StatusUnauthorized, echo.Map{ + "error": err.Error(), + }) + + a.logger.Log(ctx, err).Send() + return echoErr + } + + var body types.CreateAuthTokenRequest + if err := ctx.Bind(&body); err != nil { + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ + "error": err.Error(), + }) + + a.logger.Log(ctx, err).Send() + return echoErr + } + + if body.Name == "" { + err := fmt.Errorf("token name is a required field") + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ + "error": err.Error(), + }) + + a.logger.Log(ctx, err).Send() + return echoErr + } + + token, err := types.CreateNewAuthToken() + if err != nil { + echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ + "error": err.Error(), + }) + + a.logger.Log(ctx, err).Send() + return echoErr + } + + hashedToken, err := auth.GenerateSafeHash([]byte(token.RawString())) + if err != nil { + echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ + "error": err.Error(), + }) + + a.logger.Log(ctx, err).Send() + return echoErr + } + + authToken := &types.AuthTokens{ + CreatedAt: time.Now(), + ExpiresAt: body.ExpiresAt, + Name: body.Name, + AuthToken: hashedToken, + OwnerID: user.ID, + } + + if err = a.userStore.AddAuthToken(ctx.Request().Context(), authToken); err != nil { + echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ + "error": err.Error(), + }) + + a.logger.Log(ctx, err).Send() + return echoErr + } + + echoErr := ctx.JSON(http.StatusOK, echo.Map{ + "token": token.String(), + }) + + a.logger.Log(ctx, nil).Str("client_token", token.String()).Str("stored_token", hashedToken).Send() + return echoErr +} + +func (a *api) ListUserToken(ctx echo.Context) error { + ctx.Set(types.HandlerStartTime, time.Now()) + + user, ok := ctx.Get(string(types.UserContextKey)).(*types.User) + if !ok { + err := fmt.Errorf("missing authentication credentials") + echoErr := ctx.JSON(http.StatusUnauthorized, echo.Map{ + "error": err.Error(), + }) + + a.logger.Log(ctx, err).Send() + return echoErr + } + + tokens, err := a.userStore.ListAuthTokens(ctx.Request().Context(), user.ID) + if err != nil { + echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ + "error": err.Error(), + }) + + a.logger.Log(ctx, err).Send() + return echoErr + } + + if len(tokens) == 0 { + tokens = make([]*types.AuthTokens, 0) + } + + echoErr := ctx.JSON(http.StatusOK, tokens) + + a.logger.Log(ctx, nil).Send() + return echoErr +} diff --git a/auth/basic_auth.go b/auth/basic_auth.go index 2e1d7369..1921f1c1 100644 --- a/auth/basic_auth.go +++ b/auth/basic_auth.go @@ -172,6 +172,16 @@ func (a *auth) validateBasicAuthCredentials(auth string) (*types.User, error) { return user, nil } + + if strings.HasPrefix(password, types.OpenRegistryAuthTokenPrefix) { + user, err := a.validateUserWithPAT(context.Background(), username, password) + if err != nil { + return nil, err + } + + return user, nil + } + user, err := a.validateUser(username, password) if err != nil { return nil, err diff --git a/auth/bcrypt.go b/auth/bcrypt.go index c6e6b430..7dc2cd0c 100644 --- a/auth/bcrypt.go +++ b/auth/bcrypt.go @@ -1,17 +1,20 @@ package auth import ( + "crypto/sha256" + "fmt" + "golang.org/x/crypto/bcrypt" ) -const bcryptMinCost = 6 +const BcryptMinCost = 6 func (a *auth) hashPassword(password string) (string, error) { // Convert password string to byte slice var passwordBytes = []byte(password) // Hash password with Bcrypt's min cost - hashedPasswordBytes, err := bcrypt.GenerateFromPassword(passwordBytes, bcryptMinCost) + hashedPasswordBytes, err := bcrypt.GenerateFromPassword(passwordBytes, BcryptMinCost) return string(hashedPasswordBytes), err } @@ -20,3 +23,12 @@ func (a *auth) verifyPassword(hashedPassword, currPassword string) bool { err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(currPassword)) return err == nil } + +func GenerateSafeHash(input []byte) (string, error) { + hash := sha256.New() + if n, err := hash.Write(input); err != nil || n != len(input) { + return "", fmt.Errorf("error generating hash") + } + + return fmt.Sprintf("%x", hash.Sum(nil)), nil +} diff --git a/auth/permissions.go b/auth/permissions.go index 378d666d..ce1b6177 100644 --- a/auth/permissions.go +++ b/auth/permissions.go @@ -129,10 +129,8 @@ func (a *auth) handleTokenRequest(ctx echo.Context, handler echo.HandlerFunc) (e if err := a.populateUserFromPermissionsCheck(ctx); err != nil { registryErr := common.RegistryErrorResponse( registry.RegistryErrorCodeUnauthorized, - "missing user credentials in request", - echo.Map{ - "error": err.Error(), - }, + err.Error(), + nil, ) echoErr := ctx.JSONBlob(http.StatusUnauthorized, registryErr.Bytes()) diff --git a/auth/user.go b/auth/user.go index dddb555c..d7f6b97e 100644 --- a/auth/user.go +++ b/auth/user.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/containerish/OpenRegistry/types" + "github.com/containerish/OpenRegistry/store/v1/types" "github.com/labstack/echo/v4" ) diff --git a/auth/validate_user.go b/auth/validate_user.go index 0d4eceb1..26400f01 100644 --- a/auth/validate_user.go +++ b/auth/validate_user.go @@ -28,3 +28,28 @@ func (a *auth) validateUser(username, password string) (*types.User, error) { return user, nil } + +func (a *auth) validateUserWithPAT(ctx context.Context, username, authToken string) (*types.User, error) { + user, err := a.userStore.GetUserByUsername(ctx, username) + if err != nil { + return nil, err + } + + token, err := (&types.AuthToken{}).FromString(authToken) + if err != nil { + return nil, fmt.Errorf("ERR_PARSE_AUTH_TOKEN: %w", err) + } + + hashedToken, err := GenerateSafeHash([]byte(token.RawString())) + if err != nil { + return nil, err + } + + _, err = a.userStore.GetAuthToken(ctx, user.ID, hashedToken) + if err != nil { + return nil, err + } + + return user, nil + +} diff --git a/cmd/migrations/migrations.go b/cmd/migrations/migrations.go index 7e20a2ac..734b7a52 100644 --- a/cmd/migrations/migrations.go +++ b/cmd/migrations/migrations.go @@ -156,6 +156,14 @@ func createOpenRegistryTables(ctx *cli.Context, db *bun.DB) error { } color.Green(`Table "permissions" created ✔︎`) + _, err = db.NewCreateTable().Model(&types.AuthTokens{}).Table().IfNotExists().Exec(ctx.Context) + if err != nil { + return errors.New( + color.RedString("Table=auth_tokens Created=❌ Error=%s", err), + ) + } + color.Green(`Table "auth_tokens" created ✔︎`) + return nil } diff --git a/go.mod b/go.mod index 6b6ab139..22e674ed 100644 --- a/go.mod +++ b/go.mod @@ -158,6 +158,7 @@ require ( github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-multistream v0.5.0 // indirect github.com/multiformats/go-varint v0.0.7 // indirect + github.com/oklog/ulid/v2 v2.1.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 9fc15dc7..dbf95d9a 100644 --- a/go.sum +++ b/go.sum @@ -575,6 +575,8 @@ github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -589,6 +591,7 @@ github.com/openzipkin/zipkin-go v0.4.1 h1:kNd/ST2yLLWhaWrkgchya40TJabe8Hioj9udfP github.com/openzipkin/zipkin-go v0.4.1/go.mod h1:qY0VqDSN1pOBN94dBc6w2GJlWLiovAyg7Qt6/I9HecM= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= diff --git a/router/users.go b/router/users.go index e8595753..487252ad 100644 --- a/router/users.go +++ b/router/users.go @@ -7,6 +7,8 @@ import ( "github.com/labstack/echo/v4" ) -func RegisterUserRoutes(router *echo.Group, api users.UserApi) { - router.Add(http.MethodGet, "/search", api.SearchUsers) +func RegisterUserRoutes(router *echo.Group, api users.UserApi, middlewares ...echo.MiddlewareFunc) { + router.Add(http.MethodGet, "/search", api.SearchUsers, middlewares...) + router.Add(http.MethodPost, "/token", api.CreateUserToken, middlewares...) + router.Add(http.MethodGet, "/token", api.ListUserToken, middlewares...) } diff --git a/scripts/load_dummy_users.sh b/scripts/load_dummy_users.sh new file mode 100644 index 00000000..83325c8e --- /dev/null +++ b/scripts/load_dummy_users.sh @@ -0,0 +1,14 @@ +#!/bin/sh + + curl -sSL -XPOST -d '{"email": "me@example.com", "username": "johndoe", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "asta@example.com", "username": "asta", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "yuno@example.com", "username": "yuno", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "noelle@example.com", "username": "noelle", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "mimosa@example.com", "username": "mimosa", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "klaus@example.com", "username": "klaus", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "finral@example.com", "username": "finral", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "yami@example.com", "username": "yami", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "vangeance@example.com", "username": "vangeance", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "leopold@example.com", "username": "leopold", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "vanessa@example.com", "username": "vanessa", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq + curl -sSL -XPOST -d '{"email": "charmy@example.com", "username": "charmy", "password": "Qwerty@123"}' 'http://localhost:5000/auth/signup' | jq diff --git a/store/v1/types/auth_tokens.go b/store/v1/types/auth_tokens.go new file mode 100644 index 00000000..0dac1ad9 --- /dev/null +++ b/store/v1/types/auth_tokens.go @@ -0,0 +1,58 @@ +package types + +import ( + "crypto/rand" + "fmt" + "strings" + "time" + + "github.com/oklog/ulid/v2" +) + +type AuthToken struct { + id ulid.ULID +} + +const ( + OpenRegistryAuthTokenPrefix = "oreg_pat_" +) + +func (at *AuthToken) String() string { + return fmt.Sprintf("%s%s", OpenRegistryAuthTokenPrefix, at.id.String()) +} + +func (at *AuthToken) Bytes() []byte { + return at.id.Bytes() +} + +func (at *AuthToken) Compare(other ulid.ULID) int { + return at.id.Compare(other) +} + +func (at *AuthToken) FromString(token string) (*AuthToken, error) { + token = strings.TrimPrefix(token, OpenRegistryAuthTokenPrefix) + + id, err := ulid.Parse(token) + if err != nil { + return nil, err + } + + return &AuthToken{id: id}, nil +} + +func (at *AuthToken) RawString() string { + return at.id.String() +} + +func CreateNewAuthToken() (*AuthToken, error) { + now := time.Now() + ms := ulid.Timestamp(now) + id, err := ulid.New(ms, rand.Reader) + if err != nil { + return nil, err + } + + return &AuthToken{ + id: id, + }, nil +} diff --git a/store/v1/types/users.go b/store/v1/types/users.go index a19e99f4..ed345b2e 100644 --- a/store/v1/types/users.go +++ b/store/v1/types/users.go @@ -58,6 +58,7 @@ type ( Permissions []*Permissions `bun:"rel:has-many,join:id=user_id" json:"permissions"` Repositories []*ContainerImageRepository `bun:"rel:has-many,join:id=owner_id" json:"-"` Projects []*RepositoryBuildProject `bun:"rel:has-many,join:id=repository_owner_id" json:"-"` + AuthTokens []*AuthTokens `bun:"rel:has-many,join:id=owner_id" json:"-"` // nolint:lll FavoriteRepositories []uuid.UUID `bun:"favorite_repositories,type:uuid[],default:'{}'" json:"favorite_repositories"` ID uuid.UUID `bun:"id,type:uuid,pk" json:"id,omitempty" validate:"-"` @@ -67,6 +68,16 @@ type ( IsOrgOwner bool `bun:"is_org_owner" json:"is_org_owner,omitempty"` } + AuthTokens struct { + bun.BaseModel `bun:"table:auth_tokens,alias:s" json:"-"` + + Name string `bun:"name" json:"name"` + CreatedAt time.Time `bun:"created_at" json:"created_at,omitempty" validate:"-"` + ExpiresAt time.Time `bun:"expires_at" json:"expires_at,omitempty" validate:"-"` + OwnerID uuid.UUID `bun:"owner_id,type:uuid" json:"-"` + AuthToken string `bun:"auth_token,type:text,pk" json:"-"` + } + // type here is string so that we can use it with echo.Context & std context.Context ContextKey string @@ -95,6 +106,11 @@ type ( Token uuid.UUID `bun:"token,pk,type:uuid" json:"-"` UserId uuid.UUID `bun:"user_id,type:uuid" json:"-"` } + + CreateAuthTokenRequest struct { + ExpiresAt time.Time `json:"expires_at"` + Name string `json:"name"` + } ) const ( diff --git a/store/v1/users/store.go b/store/v1/users/store.go index d1ff9270..aa2d1055 100644 --- a/store/v1/users/store.go +++ b/store/v1/users/store.go @@ -43,6 +43,9 @@ type UserReader interface { Search(ctx context.Context, query string) ([]*types.User, error) GetOrgUsersByOrgID(ctx context.Context, orgID uuid.UUID) ([]*types.Permissions, error) MatchUserType(ctx context.Context, userType types.UserType, userIds ...uuid.UUID) bool + AddAuthToken(ctx context.Context, token *types.AuthTokens) error + ListAuthTokens(ctx context.Context, ownerID uuid.UUID) ([]*types.AuthTokens, error) + GetAuthToken(ctx context.Context, ownerID uuid.UUID, hashedToken string) (*types.AuthTokens, error) } type UserGetter interface { diff --git a/store/v1/users/users_impl.go b/store/v1/users/users_impl.go index 615031cb..064b2c10 100644 --- a/store/v1/users/users_impl.go +++ b/store/v1/users/users_impl.go @@ -3,7 +3,9 @@ package users import ( "context" "database/sql" + "fmt" "strings" + "time" v1 "github.com/containerish/OpenRegistry/store/v1" "github.com/containerish/OpenRegistry/store/v1/types" @@ -321,3 +323,55 @@ func (us *userStore) MatchUserType(ctx context.Context, userType types.UserType, return len(userIds) == count } + +func (us *userStore) AddAuthToken(ctx context.Context, token *types.AuthTokens) error { + if token.ExpiresAt.IsZero() { + token.ExpiresAt = time.Now().AddDate(1, 0, 0) + } + + _, err := us.db.NewInsert().Model(token).Exec(ctx) + return err +} + +func (us *userStore) ListAuthTokens(ctx context.Context, ownerID uuid.UUID) ([]*types.AuthTokens, error) { + var tokens []*types.AuthTokens + + err := us. + db. + NewSelect(). + Model(&tokens). + ExcludeColumn("auth_token"). + ExcludeColumn("owner_id"). + Where("owner_id = ?", ownerID). + Scan(ctx) + if err != nil { + return nil, err + } + + return tokens, nil +} + +func (us *userStore) GetAuthToken( + ctx context.Context, + ownerID uuid.UUID, + hashedToken string, +) (*types.AuthTokens, error) { + var token types.AuthTokens + + err := us. + db. + NewSelect(). + Model(&token). + Where("owner_id = ?", ownerID). + Where("auth_token = ?", hashedToken). + Scan(ctx) + if err != nil { + return nil, err + } + + if token.ExpiresAt.Unix() < time.Now().Unix() { + return nil, fmt.Errorf("Token has expired, please generate a new one") + } + + return &token, nil +} From a88203f0e60e427172597dee7e22a0eb6cd31caa Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Wed, 27 Dec 2023 13:22:28 +0530 Subject: [PATCH 17/23] fix: Database model definitions Signed-off-by: jay-dee7 --- store/v1/emails/emails_impl.go | 4 +- store/v1/permissions/permissions_impl.go | 20 ++++----- store/v1/registry/registry_impl.go | 52 ++++++++++++------------ store/v1/sessions/sessions_impl.og | 11 ----- store/v1/users/users_impl.go | 12 +++--- store/v1/webauthn/webauthn_impl.go | 2 +- 6 files changed, 45 insertions(+), 56 deletions(-) delete mode 100644 store/v1/sessions/sessions_impl.og diff --git a/store/v1/emails/emails_impl.go b/store/v1/emails/emails_impl.go index 825ca660..6acc3a19 100644 --- a/store/v1/emails/emails_impl.go +++ b/store/v1/emails/emails_impl.go @@ -42,9 +42,9 @@ func (es *emailStore) DeleteVerifyEmail(ctx context.Context, userID uuid.UUID) e } func (es *emailStore) GetVerifyEmail(ctx context.Context, userID uuid.UUID) (uuid.UUID, error) { - var email types.Email + var email *types.Email - if err := es.db.NewSelect().Model(&email).Where("user_id = ?", userID).Scan(ctx); err != nil { + if err := es.db.NewSelect().Model(email).Where("user_id = ?", userID).Scan(ctx); err != nil { return uuid.UUID{}, v2.WrapDatabaseError(err, v2.DatabaseOperationRead) } diff --git a/store/v1/permissions/permissions_impl.go b/store/v1/permissions/permissions_impl.go index d9911e67..156e0926 100644 --- a/store/v1/permissions/permissions_impl.go +++ b/store/v1/permissions/permissions_impl.go @@ -65,12 +65,12 @@ func (p *permissionStore) GetUserPermissionsForOrg( orgID uuid.UUID, userID uuid.UUID, ) (*types.Permissions, error) { - var perm types.Permissions + perm := &types.Permissions{} err := p. db. NewSelect(). - Model(&perm). + Model(perm). Where("user_id = ?", userID.String()). Where("organization_id = ?", orgID). Scan(ctx) @@ -79,7 +79,7 @@ func (p *permissionStore) GetUserPermissionsForOrg( return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) } - return &perm, nil + return perm, nil } func (p *permissionStore) UpdatePermissions(ctx context.Context, perm *types.Permissions) error { @@ -137,11 +137,11 @@ func (p *permissionStore) validateAddOrgMembersInput(input *types.AddUsersToOrgR } func (p *permissionStore) RemoveUserFromOrg(ctx context.Context, orgID, userID uuid.UUID) error { - var perm types.Permissions + perm := &types.Permissions{} _, err := p. db. NewDelete(). - Model(&perm). + Model(perm). Where("organization_id = ?", orgID.String()). Where("user_id = ?", userID.String()). Exec(ctx) @@ -157,18 +157,18 @@ func (p *permissionStore) GetUserPermissionsForNamespace( ns string, userID uuid.UUID, ) *types.Permissions { - perms := types.Permissions{} + perms := &types.Permissions{} nsParts := strings.Split(ns, "/") if len(nsParts) != 2 { - return &perms + return perms } orgName := nsParts[0] q := p. db. NewSelect(). - Model(&perms). + Model(perms). Relation("Organization", func(sq *bun.SelectQuery) *bun.SelectQuery { return sq. Where(`"organization"."username" = ?`, orgName). @@ -181,9 +181,9 @@ func (p *permissionStore) GetUserPermissionsForNamespace( }) if err := q.Scan(ctx); err != nil { - return &perms + return perms } - return &perms + return perms } diff --git a/store/v1/registry/registry_impl.go b/store/v1/registry/registry_impl.go index 1cb1d1dc..571dfeb4 100644 --- a/store/v1/registry/registry_impl.go +++ b/store/v1/registry/registry_impl.go @@ -114,11 +114,11 @@ func (s *registryStore) GetRepositoryByName( Str("name", name). Str("user_id", userId.String()) - var repository types.ContainerImageRepository + repository := &types.ContainerImageRepository{} err := s. db. NewSelect(). - Model(&repository). + Model(repository). WhereGroup(" AND ", func(sq *bun.SelectQuery) *bun.SelectQuery { return sq.Where("name = ?", name) }). @@ -132,7 +132,7 @@ func (s *registryStore) GetRepositoryByName( } logEvent.Bool("success", true).Send() - return &repository, nil + return repository, nil } func (s *registryStore) DeleteLayerByDigestWithTxn(ctx context.Context, txn *bun.Tx, digest string) error { @@ -207,7 +207,7 @@ func (s *registryStore) GetCatalog( pageSize int, offset int, ) ([]string, error) { - var catalog []types.ContainerImageRepository + var catalog []*types.ContainerImageRepository repositoryName := strings.Split(namespace, "/")[1] err := s. @@ -444,27 +444,27 @@ func (s *registryStore) GetImageTags(ctx context.Context, namespace string) ([]s // GetLayer implements registry.RegistryStore. func (s *registryStore) GetLayer(ctx context.Context, digest string) (*types.ContainerImageLayer, error) { logEvent := s.logger.Debug().Str("method", "GetLayer").Str("digest", digest) - var layer types.ContainerImageLayer - if err := s.db.NewSelect().Model(&layer).Where("digest = ?", digest).Scan(ctx); err != nil { + layer := &types.ContainerImageLayer{} + if err := s.db.NewSelect().Model(layer).Where("digest = ?", digest).Scan(ctx); err != nil { logEvent.Err(err).Send() return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) } logEvent.Bool("success", true).Send() - return &layer, nil + return layer, nil } // GetManifest implements registry.RegistryStore. func (s *registryStore) GetManifest(ctx context.Context, id string) (*types.ImageManifest, error) { logEvent := s.logger.Debug().Str("method", "GetManifest").Str("id", id) - var manifest types.ImageManifest - if err := s.db.NewSelect().Model(&manifest).Where("id = ?", id).Scan(ctx); err != nil { + manifest := &types.ImageManifest{} + if err := s.db.NewSelect().Model(manifest).Where("id = ?", id).Scan(ctx); err != nil { logEvent.Err(err).Send() return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) } logEvent.Bool("success", true).Send() - return &manifest, nil + return manifest, nil } // GetManifestByReference implements registry.RegistryStore. @@ -479,11 +479,11 @@ func (s *registryStore) GetManifestByReference( nsParts := strings.Split(namespace, "/") username, repoName := nsParts[0], nsParts[1] - var manifest types.ImageManifest + manifest := &types.ImageManifest{} q := s. db. NewSelect(). - Model(&manifest). + Model(manifest). Relation("Repository", func(sq *bun.SelectQuery) *bun.SelectQuery { return sq.Column("name") }). @@ -507,7 +507,7 @@ func (s *registryStore) GetManifestByReference( } logEvent.Bool("success", true).Send() - return &manifest, nil + return manifest, nil } // GetRepoDetail implements registry.RegistryStore. @@ -518,13 +518,13 @@ func (s *registryStore) GetRepoDetail( offset int, ) (*types.ContainerImageRepository, error) { logEvent := s.logger.Debug().Str("method", "GetRepoDetail") - var repoDetail types.ContainerImageRepository + repoDetail := &types.ContainerImageRepository{} repositoryName := strings.Split(namespace, "/")[1] err := s. db. NewSelect(). - Model(&repoDetail). + Model(repoDetail). Relation("ImageManifests"). Where("name = ?", repositoryName). Limit(pageSize). @@ -537,7 +537,7 @@ func (s *registryStore) GetRepoDetail( } logEvent.Bool("success", true).Send() - return &repoDetail, nil + return repoDetail, nil } // SetContainerImageVisibility implements registry.RegistryStore. @@ -740,11 +740,11 @@ func (s *registryStore) GetImageSizeByLayerIds(ctx context.Context, layerIDs []s } func (s *registryStore) IncrementRepositoryPullCounter(ctx context.Context, repoID uuid.UUID) error { - repo := types.ContainerImageRepository{ + repo := &types.ContainerImageRepository{ ID: repoID, } - _, err := s.db.NewUpdate().Model(&repo).WherePK().Set("pull_count = pull_count + 1").Exec(ctx) + _, err := s.db.NewUpdate().Model(repo).WherePK().Set("pull_count = pull_count + 1").Exec(ctx) if err != nil { return v1.WrapDatabaseError(err, v1.DatabaseOperationUpdate) } @@ -753,12 +753,12 @@ func (s *registryStore) IncrementRepositoryPullCounter(ctx context.Context, repo } func (s *registryStore) AddRepositoryToFavorites(ctx context.Context, repoID uuid.UUID, userID uuid.UUID) error { - user := types.User{} + user := &types.User{} q := s. db. NewUpdate(). - Model(&user). + Model(user). Set("favorite_repositories = array_append(favorite_repositories, ?)", repoID). Where("id = ?", userID). Where("NOT (? = ANY(favorite_repositories))", repoID) @@ -774,11 +774,11 @@ func (s *registryStore) AddRepositoryToFavorites(ctx context.Context, repoID uui } if rowsAffected == 1 { - repo := types.ContainerImageRepository{ + repo := &types.ContainerImageRepository{ ID: repoID, } - _, err = s.db.NewUpdate().Model(&repo).WherePK().Set("favorite_count = favorite_count + 1").Exec(ctx) + _, err = s.db.NewUpdate().Model(repo).WherePK().Set("favorite_count = favorite_count + 1").Exec(ctx) if err != nil { return v1.WrapDatabaseError(err, v1.DatabaseOperationUpdate) } @@ -790,11 +790,11 @@ func (s *registryStore) AddRepositoryToFavorites(ctx context.Context, repoID uui } func (s *registryStore) RemoveRepositoryFromFavorites(ctx context.Context, repoID uuid.UUID, userID uuid.UUID) error { - user := types.User{} + user := &types.User{} q := s. db. NewUpdate(). - Model(&user). + Model(user). Set("favorite_repositories = array_remove(favorite_repositories, ?)", repoID). Where("id = ?", userID). Where("? = ANY(favorite_repositories)", repoID) @@ -806,11 +806,11 @@ func (s *registryStore) RemoveRepositoryFromFavorites(ctx context.Context, repoI rowsAffected, err := result.RowsAffected() if err == nil && rowsAffected == 1 { - repo := types.ContainerImageRepository{ + repo := &types.ContainerImageRepository{ ID: repoID, } - _, err = s.db.NewUpdate().Model(&repo).WherePK().Set("favorite_count = favorite_count - 1").Exec(ctx) + _, err = s.db.NewUpdate().Model(repo).WherePK().Set("favorite_count = favorite_count - 1").Exec(ctx) if err != nil { return v1.WrapDatabaseError(err, v1.DatabaseOperationUpdate) } diff --git a/store/v1/sessions/sessions_impl.og b/store/v1/sessions/sessions_impl.og deleted file mode 100644 index 5dd3be9b..00000000 --- a/store/v1/sessions/sessions_impl.og +++ /dev/null @@ -1,11 +0,0 @@ - -// DeleteAllSessions implements UserStore. -func (u *userStore) DeleteAllSessions(ctx context.Context, userId string) error { - panic("unimplemented") -} - -// DeleteSession implements UserStore. -func (u *userStore) DeleteSession(ctx context.Context, sessionId string, userId string) error { - panic("unimplemented") -} - diff --git a/store/v1/users/users_impl.go b/store/v1/users/users_impl.go index 064b2c10..0daa3094 100644 --- a/store/v1/users/users_impl.go +++ b/store/v1/users/users_impl.go @@ -125,12 +125,12 @@ func (us *userStore) GetUserByUsernameWithTxn(ctx context.Context, username stri } func (us *userStore) GetIPFSUser(ctx context.Context) (*types.User, error) { - var user types.User - if err := us.db.NewSelect().Model(&user).Where("username = ?", types.SystemUsernameIPFS).Scan(ctx); err != nil { + user := &types.User{} + if err := us.db.NewSelect().Model(user).Where("username = ?", types.SystemUsernameIPFS).Scan(ctx); err != nil { return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) } - return &user, nil + return user, nil } // GetUserWithSession implements UserStore. @@ -225,12 +225,12 @@ func (us *userStore) webAuthnUserExists(ctx context.Context, username, email str } func (us *userStore) ConvertUserToOrg(ctx context.Context, userID uuid.UUID) error { - user := types.User{ID: userID} + user := &types.User{ID: userID} _, err := us. db. NewUpdate(). - Model(&user). + Model(user). WherePK(). Set("user_type = ?", types.UserTypeOrganization.String()). Set("is_org_owner = ?", true). @@ -370,7 +370,7 @@ func (us *userStore) GetAuthToken( } if token.ExpiresAt.Unix() < time.Now().Unix() { - return nil, fmt.Errorf("Token has expired, please generate a new one") + return nil, fmt.Errorf("token has expired, please generate a new one") } return &token, nil diff --git a/store/v1/webauthn/webauthn_impl.go b/store/v1/webauthn/webauthn_impl.go index e87d059e..b5ae8765 100644 --- a/store/v1/webauthn/webauthn_impl.go +++ b/store/v1/webauthn/webauthn_impl.go @@ -39,7 +39,7 @@ func (ws *webauthnStore) GetWebAuthnSessionData( userId uuid.UUID, sessionType string, ) (*webauthn.SessionData, error) { - var session types.WebauthnSession + session := &types.WebauthnSession{} err := ws. db. From 0a3a9057575e7cb4be19f5a3a6f9cb12bf2f3a50 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Sat, 30 Dec 2023 14:38:17 +0530 Subject: [PATCH 18/23] feat: List favorite repositories Signed-off-by: jay-dee7 --- Makefile | 2 +- auth/github.go | 15 ++++----- auth/reset_password.go | 8 +++-- go.mod | 4 +-- go.sum | 2 -- registry/v2/extensions/analytics.go | 24 +++++++++++++++ registry/v2/extensions/catalog_detail.go | 21 ++++++++++--- registry/v2/registry.go | 10 ++++-- registry/v2/repository.go | 20 +++++++++--- router/registry.go | 1 + router/router.go | 15 +++++++-- store/v1/registry/registry_impl.go | 39 ++++++++++++++++++++++++ store/v1/registry/store.go | 1 + store/v1/types/users.go | 6 ++-- 14 files changed, 136 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index fead562a..67811ca6 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ certs: openssl req -x509 -newkey rsa:4096 -keyout .certs/registry.local -out .certs/registry.local.crt -sha256 -days 365 \ -subj "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN=registry.local" -nodes -load_dummy_users: +dummy_users: sh ./scripts/load_dummy_users.sh reset: diff --git a/auth/github.go b/auth/github.go index ab7b59f7..0061a3aa 100644 --- a/auth/github.go +++ b/auth/github.go @@ -10,6 +10,7 @@ import ( "github.com/containerish/OpenRegistry/config" "github.com/containerish/OpenRegistry/store/v1/types" + "github.com/fatih/color" "github.com/google/go-github/v56/github" "github.com/google/uuid" "github.com/labstack/echo/v4" @@ -176,18 +177,12 @@ func (a *auth) createCookie( ) *http.Cookie { secure := true sameSite := http.SameSiteNoneMode - domain := "" - url, err := url.Parse(a.c.WebAppConfig.GetAllowedURLFromEchoContext(ctx, a.c.Environment)) - if err != nil { - domain = a.c.Registry.FQDN - } else { - domain = url.Hostname() - } + domain := a.c.Registry.FQDN - if a.c.Environment == config.Local { + if a.c.Environment == config.Local && domain == "" { secure = false sameSite = http.SameSiteLaxMode - url, err = url.Parse(a.c.WebAppConfig.GetAllowedURLFromEchoContext(ctx, a.c.Environment)) + url, err := url.Parse(a.c.WebAppConfig.GetAllowedURLFromEchoContext(ctx, a.c.Environment)) if err != nil { domain = "localhost" } else { @@ -206,6 +201,8 @@ func (a *auth) createCookie( HttpOnly: httpOnly, } + color.Red("cookie: %#v", cookie) + if expiresAt.Unix() < time.Now().Unix() { // set cookie deletion cookie.MaxAge = -1 diff --git a/auth/reset_password.go b/auth/reset_password.go index c194269a..2a717fa8 100644 --- a/auth/reset_password.go +++ b/auth/reset_password.go @@ -234,9 +234,13 @@ func (a *auth) ForgotPassword(ctx echo.Context) error { } if !user.IsActive { - return ctx.JSON(http.StatusUnauthorized, echo.Map{ - "message": "account is inactive, please check your email and verify your account", + err = fmt.Errorf("account is inactive, please check your email and verify your account") + echoErr := ctx.JSON(http.StatusUnauthorized, echo.Map{ + "message": err.Error(), }) + + a.logger.Log(ctx, err).Send() + return echoErr } opts := &WebLoginJWTOptions{ diff --git a/go.mod b/go.mod index 22e674ed..2ef42333 100644 --- a/go.mod +++ b/go.mod @@ -30,8 +30,10 @@ require ( github.com/labstack/echo-jwt/v4 v4.2.0 github.com/labstack/echo/v4 v4.11.4 github.com/multiformats/go-multiaddr v0.12.0 + github.com/oklog/ulid/v2 v2.1.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc5 + github.com/rs/cors v1.10.1 github.com/rs/zerolog v1.31.0 github.com/sendgrid/sendgrid-go v3.14.0+incompatible github.com/spf13/afero v1.11.0 @@ -158,7 +160,6 @@ require ( github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-multistream v0.5.0 // indirect github.com/multiformats/go-varint v0.0.7 // indirect - github.com/oklog/ulid/v2 v2.1.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect @@ -170,7 +171,6 @@ require ( github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect diff --git a/go.sum b/go.sum index dbf95d9a..e2919054 100644 --- a/go.sum +++ b/go.sum @@ -663,8 +663,6 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= -github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= diff --git a/registry/v2/extensions/analytics.go b/registry/v2/extensions/analytics.go index 52ddf5dc..93b76f7f 100644 --- a/registry/v2/extensions/analytics.go +++ b/registry/v2/extensions/analytics.go @@ -86,3 +86,27 @@ func (ext *extension) RemoveRepositoryFromFavorites(ctx echo.Context) error { ext.logger.Log(ctx, nil).Send() return echoErr } + +func (ext *extension) ListFavoriteRepositories(ctx echo.Context) error { + ctx.Set(types.HandlerStartTime, time.Now()) + + user, ok := ctx.Get(string(types.UserContextKey)).(*types.User) + if !ok { + err := fmt.Errorf("missing authentication credentials") + echoErr := ctx.JSON(http.StatusForbidden, echo.Map{ + "error": err.Error(), + }) + ext.logger.Log(ctx, err).Send() + return echoErr + } + + repos, err := ext.store.ListFavoriteRepositories(ctx.Request().Context(), user.ID) + if err != nil { + repos = make([]*types.ContainerImageRepository, 0) + } + + echoErr := ctx.JSON(http.StatusOK, repos) + + ext.logger.Log(ctx, nil).Send() + return echoErr +} diff --git a/registry/v2/extensions/catalog_detail.go b/registry/v2/extensions/catalog_detail.go index b2f4d985..8db429d3 100644 --- a/registry/v2/extensions/catalog_detail.go +++ b/registry/v2/extensions/catalog_detail.go @@ -20,6 +20,7 @@ type Extenion interface { GetUserCatalog(ctx echo.Context) error AddRepositoryToFavorites(ctx echo.Context) error RemoveRepositoryFromFavorites(ctx echo.Context) error + ListFavoriteRepositories(ctx echo.Context) error } type extension struct { @@ -198,15 +199,21 @@ func (ext *extension) PublicCatalog(ctx echo.Context) error { repositories, total, err := ext.store.GetPublicRepositories(ctx.Request().Context(), pageSize, offset) if err != nil { - return ctx.JSON(http.StatusInternalServerError, echo.Map{ + echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), }) + + ext.logger.Log(ctx, err).Send() + return echoErr } - return ctx.JSON(http.StatusOK, echo.Map{ + echoErr := ctx.JSON(http.StatusOK, echo.Map{ "repositories": repositories, "total": total, }) + + ext.logger.Log(ctx, nil).Send() + return echoErr } func (ext *extension) GetUserCatalog(ctx echo.Context) error { @@ -267,13 +274,19 @@ func (ext *extension) GetUserCatalog(ctx echo.Context) error { offset, ) if err != nil { - return ctx.JSON(http.StatusInternalServerError, echo.Map{ + echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), }) + + ext.logger.Log(ctx, err).Send() + return echoErr } - return ctx.JSON(http.StatusOK, echo.Map{ + echoErr := ctx.JSON(http.StatusOK, echo.Map{ "repositories": repositories, "total": total, }) + + ext.logger.Log(ctx, nil).Send() + return echoErr } diff --git a/registry/v2/registry.go b/registry/v2/registry.go index 98c6a505..0a8c15c8 100644 --- a/registry/v2/registry.go +++ b/registry/v2/registry.go @@ -86,8 +86,9 @@ func (r *registry) ManifestExists(ctx echo.Context) error { } errMsg := common.RegistryErrorResponse(RegistryErrorCodeManifestBlobUnknown, err.Error(), details) - r.logger.Log(ctx, fmt.Errorf("%s", errMsg)).Send() - return ctx.NoContent(http.StatusNotFound) + echoErr := ctx.JSONBlob(http.StatusNotFound, errMsg.Bytes()) + r.logger.Log(ctx, errMsg).Send() + return echoErr } ctx.Response().Header().Set("Content-Length", fmt.Sprintf("%d", manifest.Size)) @@ -792,10 +793,13 @@ func (r *registry) PushManifest(ctx echo.Context) error { buf := &bytes.Buffer{} _, err = io.Copy(buf, ctx.Request().Body) if err != nil { - return ctx.JSON(http.StatusBadRequest, echo.Map{ + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), "message": "failed in push manifest while io Copy", }) + + r.logger.Log(ctx, nil).Send() + return echoErr } defer ctx.Request().Body.Close() diff --git a/registry/v2/repository.go b/registry/v2/repository.go index b2bfcbd8..3c8ff7b1 100644 --- a/registry/v2/repository.go +++ b/registry/v2/repository.go @@ -31,18 +31,24 @@ func (r *registry) CreateRepository(ctx echo.Context) error { var body CreateRepositoryRequest err := json.NewDecoder(ctx.Request().Body).Decode(&body) if err != nil { - return ctx.JSON(http.StatusBadRequest, echo.Map{ + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), "message": "error parsing request input", }) + + r.logger.Log(ctx, err).Send() + return echoErr } defer ctx.Request().Body.Close() if err = body.Validate(); err != nil { - return ctx.JSON(http.StatusBadRequest, echo.Map{ + echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), "message": "invalid request body", }) + + r.logger.Log(ctx, err).Send() + return echoErr } user := ctx.Get(string(types.UserContextKey)).(*types.User) @@ -55,13 +61,19 @@ func (r *registry) CreateRepository(ctx echo.Context) error { OwnerID: user.ID, } if err := r.store.CreateRepository(ctx.Request().Context(), repository); err != nil { - return ctx.JSON(http.StatusBadGateway, echo.Map{ + echoErr := ctx.JSON(http.StatusBadGateway, echo.Map{ "error": err.Error(), "message": "error creating repository", }) + + r.logger.Log(ctx, err).Send() + return echoErr } - return ctx.JSON(http.StatusCreated, echo.Map{ + echoErr := ctx.JSON(http.StatusCreated, echo.Map{ "message": "repository created successfully", }) + + r.logger.Log(ctx, nil).Send() + return echoErr } diff --git a/router/registry.go b/router/registry.go index b599632a..41d84df5 100644 --- a/router/registry.go +++ b/router/registry.go @@ -105,5 +105,6 @@ func RegisterExtensionsRoutes( group.Add(http.MethodPost, ChangeRepositoryVisibility, ext.ChangeContainerImageVisibility, middlewares...) group.Add(http.MethodPost, CreateRepository, reg.CreateRepository, middlewares...) group.Add(http.MethodPost, RepositoryFavorites, ext.AddRepositoryToFavorites, middlewares...) + group.Add(http.MethodGet, RepositoryFavorites, ext.ListFavoriteRepositories, middlewares...) group.Add(http.MethodDelete, RemoveRepositoryFavorites, ext.RemoveRepositoryFromFavorites, middlewares...) } diff --git a/router/router.go b/router/router.go index eeb16367..1064e75b 100644 --- a/router/router.go +++ b/router/router.go @@ -88,7 +88,7 @@ func Register( } //catch-all will redirect user back to the web interface - e.Add(http.MethodGet, "/", func(ctx echo.Context) error { + e.Add(http.MethodGet, "", func(ctx echo.Context) error { webAppURL := "" for _, url := range cfg.WebAppConfig.AllowedEndpoints { if url == ctx.Request().Header.Get("Origin") { @@ -101,7 +101,18 @@ func Register( webAppURL = ctx.Request().Header.Get("Origin") } - return ctx.Redirect(http.StatusTemporaryRedirect, webAppURL) + if webAppURL != "" { + echoErr := ctx.Redirect(http.StatusTemporaryRedirect, webAppURL) + logger.Log(ctx, nil).Send() + return echoErr + } + + echoErr := ctx.JSON(http.StatusOK, echo.Map{ + "API": "running", + }) + + logger.Log(ctx, nil).Send() + return echoErr }) return e diff --git a/store/v1/registry/registry_impl.go b/store/v1/registry/registry_impl.go index 571dfeb4..8ac05bf8 100644 --- a/store/v1/registry/registry_impl.go +++ b/store/v1/registry/registry_impl.go @@ -854,3 +854,42 @@ func (s *registryStore) GetLayersLinksForManifest( logEvent.Bool("success", true).Send() return layers, nil } +func (s *registryStore) ListFavoriteRepositories( + ctx context.Context, + userID uuid.UUID, +) ([]*types.ContainerImageRepository, error) { + logEvent := s.logger.Debug().Str("method", "ListFavoriteRepositories") + + repositories := []*types.ContainerImageRepository{} + user := &types.User{ID: userID} + err := s. + db. + NewSelect(). + Model(user). + WherePK(). + Scan(ctx) + + if err != nil { + return nil, err + } + + if len(user.FavoriteRepositories) == 0 { + return repositories, nil + } + + q := s. + db. + NewSelect(). + Model(&repositories). + Where(`"r"."id" in (?)`, bun.In(user.FavoriteRepositories)). + Relation("User", func(sq *bun.SelectQuery) *bun.SelectQuery { + return sq.ExcludeColumn("password").ExcludeColumn("github_connected").ExcludeColumn("webauthn_connected") + }) + + if err := q.Scan(ctx); err != nil { + logEvent.Err(err).Send() + return nil, v1.WrapDatabaseError(err, v1.DatabaseOperationRead) + } + + return repositories, nil +} diff --git a/store/v1/registry/store.go b/store/v1/registry/store.go index 61b40674..0d16e44a 100644 --- a/store/v1/registry/store.go +++ b/store/v1/registry/store.go @@ -92,4 +92,5 @@ type RegistryStore interface { AddRepositoryToFavorites(ctx context.Context, repoID uuid.UUID, userID uuid.UUID) error RemoveRepositoryFromFavorites(ctx context.Context, repoID uuid.UUID, userID uuid.UUID) error GetLayersLinksForManifest(ctx context.Context, manifestDigest string) ([]*types.ContainerImageLayer, error) + ListFavoriteRepositories(ctx context.Context, userID uuid.UUID) ([]*types.ContainerImageRepository, error) } diff --git a/store/v1/types/users.go b/store/v1/types/users.go index ed345b2e..825ce5bd 100644 --- a/store/v1/types/users.go +++ b/store/v1/types/users.go @@ -60,7 +60,7 @@ type ( Projects []*RepositoryBuildProject `bun:"rel:has-many,join:id=repository_owner_id" json:"-"` AuthTokens []*AuthTokens `bun:"rel:has-many,join:id=owner_id" json:"-"` // nolint:lll - FavoriteRepositories []uuid.UUID `bun:"favorite_repositories,type:uuid[],default:'{}'" json:"favorite_repositories"` + FavoriteRepositories []uuid.UUID `bun:"favorite_repositories,nullzero,type:uuid[],default:'{}'" json:"favorite_repositories"` ID uuid.UUID `bun:"id,type:uuid,pk" json:"id,omitempty" validate:"-"` IsActive bool `bun:"is_active" json:"is_active,omitempty" validate:"-"` WebauthnConnected bool `bun:"webauthn_connected" json:"webauthn_connected"` @@ -71,11 +71,11 @@ type ( AuthTokens struct { bun.BaseModel `bun:"table:auth_tokens,alias:s" json:"-"` - Name string `bun:"name" json:"name"` CreatedAt time.Time `bun:"created_at" json:"created_at,omitempty" validate:"-"` ExpiresAt time.Time `bun:"expires_at" json:"expires_at,omitempty" validate:"-"` - OwnerID uuid.UUID `bun:"owner_id,type:uuid" json:"-"` + Name string `bun:"name" json:"name"` AuthToken string `bun:"auth_token,type:text,pk" json:"-"` + OwnerID uuid.UUID `bun:"owner_id,type:uuid" json:"-"` } // type here is string so that we can use it with echo.Context & std context.Context From 2b364bfc94d6448d664e198fd933adccc30aa617 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Mon, 8 Jan 2024 00:39:34 +0530 Subject: [PATCH 19/23] fix: Create project query Signed-off-by: jay-dee7 --- main.go | 3 +- orgmode/admin.go | 5 +- router/github.go | 2 + router/router.go | 1 + .../github_actions/v1/server/build_project.go | 4 +- .../github_actions/v1/server/interceptor.go | 11 +-- store/v1/automation/projects.go | 7 +- vcs/github/actions.go | 28 ++++++- vcs/github/github.go | 81 ++++++++++--------- vcs/github/handlers.go | 25 ++++-- vcs/github/workflow.go | 21 ++--- 11 files changed, 116 insertions(+), 72 deletions(-) diff --git a/main.go b/main.go index 0cc6dbb3..d32cf9b7 100644 --- a/main.go +++ b/main.go @@ -7,10 +7,11 @@ import ( "os" "strings" + "github.com/urfave/cli/v2" + "github.com/containerish/OpenRegistry/cmd/extras" "github.com/containerish/OpenRegistry/cmd/migrations" "github.com/containerish/OpenRegistry/cmd/registry" - "github.com/urfave/cli/v2" ) var ( diff --git a/orgmode/admin.go b/orgmode/admin.go index 761a02d1..daee9c9a 100644 --- a/orgmode/admin.go +++ b/orgmode/admin.go @@ -6,9 +6,10 @@ import ( "net/http" "strings" - "github.com/containerish/OpenRegistry/store/v1/types" "github.com/google/uuid" "github.com/labstack/echo/v4" + + "github.com/containerish/OpenRegistry/store/v1/types" ) func (o *orgMode) AllowOrgAdmin() echo.MiddlewareFunc { @@ -52,7 +53,7 @@ func (o *orgMode) AllowOrgAdmin() echo.MiddlewareFunc { case p == "/api/org/users" || strings.HasPrefix(p, "/api/org/permissions/users"): orgOwner, err := o.userStore.GetOrgAdmin(ctx.Request().Context(), user.ID) if err != nil { - echoErr := ctx.JSON(http.StatusUnauthorized, echo.Map{ + echoErr := ctx.JSON(http.StatusForbidden, echo.Map{ "error": err.Error(), "message": "user does not have permission to add users to organization", }) diff --git a/router/github.go b/router/github.go index 02f426d1..8937549b 100644 --- a/router/github.go +++ b/router/github.go @@ -29,6 +29,7 @@ func RegisterGitHubRoutes( usersStore vcs.VCSStore, automationStore automation.BuildAutomationStore, allowedOrigins []string, + registryEndpoint string, ) { if cfg != nil && cfg.Enabled { ghAppApi := github.NewGithubApp( @@ -37,6 +38,7 @@ func RegisterGitHubRoutes( logger, allowedEndpoints, env, + registryEndpoint, ) ghAppApi.RegisterRoutes(router) diff --git a/router/router.go b/router/router.go index 1064e75b..dfcda3db 100644 --- a/router/router.go +++ b/router/router.go @@ -84,6 +84,7 @@ func Register( usersStore, automationStore, cfg.WebAppConfig.AllowedEndpoints, + cfg.Endpoint(), ) } diff --git a/services/kon/github_actions/v1/server/build_project.go b/services/kon/github_actions/v1/server/build_project.go index b81b1269..b39f32af 100644 --- a/services/kon/github_actions/v1/server/build_project.go +++ b/services/kon/github_actions/v1/server/build_project.go @@ -7,7 +7,6 @@ import ( common_v1 "github.com/containerish/OpenRegistry/common/v1" github_actions_v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/containerish/OpenRegistry/vcs/github" "github.com/google/uuid" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -105,8 +104,7 @@ func (ghs *GitHubActionsServer) ListProjects( error, ) { logEvent := ghs.logger.Debug().Str("procedure", req.Spec().Procedure) - user := ctx.Value(github.UserContextKey).(*types.User) - ghs.logger.Debug().Any("user", user).Send() + user := ctx.Value(types.UserContextKey).(*types.User) err := req.Msg.Validate() if err != nil { logEvent.Err(err).Send() diff --git a/services/kon/github_actions/v1/server/interceptor.go b/services/kon/github_actions/v1/server/interceptor.go index 2bd59d6e..d76fc74f 100644 --- a/services/kon/github_actions/v1/server/interceptor.go +++ b/services/kon/github_actions/v1/server/interceptor.go @@ -5,7 +5,9 @@ import ( "fmt" "github.com/bufbuild/connect-go" + "github.com/containerish/OpenRegistry/config" + "github.com/containerish/OpenRegistry/store/v1/types" "github.com/containerish/OpenRegistry/telemetry" "github.com/containerish/OpenRegistry/vcs" "github.com/containerish/OpenRegistry/vcs/github" @@ -38,7 +40,7 @@ func NewGitHubAppUsernameInterceptor( } logEvent.Bool("success", true).Send() - ctx = context.WithValue(ctx, github.UsernameContextKey, user.Username) + ctx = context.WithValue(ctx, types.UserContextKey, user) return next(ctx, req) }) }) @@ -64,7 +66,7 @@ func PopulateContextWithUserInterceptor( } logEvent.Bool("success", true).Send() - ctx = context.WithValue(ctx, github.UsernameContextKey, user.Username) + ctx = context.WithValue(ctx, types.UserContextKey, user) return next(ctx, req) }) }) @@ -106,8 +108,7 @@ func (i *githubAppStreamingInterceptor) WrapUnary(next connect.UnaryFunc) connec ctx = context.WithValue(ctx, OpenRegistryUserContextKey, user) logEvent.Bool("success", true) - ctx = context.WithValue(ctx, github.UsernameContextKey, user.Username) - ctx = context.WithValue(ctx, github.UserContextKey, user) + ctx = context.WithValue(ctx, types.UserContextKey, user) skip := false for _, r := range i.routesToSkip { if req.Spec().Procedure == r { @@ -166,7 +167,7 @@ func (i *githubAppStreamingInterceptor) WrapStreamingHandler( } logEvent.Bool("success", true).Send() - ctx = context.WithValue(ctx, github.UsernameContextKey, user.Username) + ctx = context.WithValue(ctx, types.UserContextKey, user) skip := false for _, r := range i.routesToSkip { if conn.Spec().Procedure == r { diff --git a/store/v1/automation/projects.go b/store/v1/automation/projects.go index 1551dd64..d3020558 100644 --- a/store/v1/automation/projects.go +++ b/store/v1/automation/projects.go @@ -5,12 +5,13 @@ import ( "fmt" "time" + "github.com/google/uuid" + "google.golang.org/protobuf/types/known/timestamppb" + common_v1 "github.com/containerish/OpenRegistry/common/v1" github_actions_v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" v1 "github.com/containerish/OpenRegistry/store/v1" "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/google/uuid" - "google.golang.org/protobuf/types/known/timestamppb" ) // DeleteProject implements BuildAutomationStore @@ -19,7 +20,7 @@ func (s *store) DeleteProject(ctx context.Context, project *github_actions_v1.De db. NewDelete(). Model(&types.RepositoryBuildProject{}). - Where("id = ?", project.GetId()). + Where("id = ?", project.GetId().GetValue()). Exec(ctx); err != nil { return fmt.Errorf("ERR_DELETE_PROJECT: %w", err) } diff --git a/vcs/github/actions.go b/vcs/github/actions.go index f23255eb..04f57d3f 100644 --- a/vcs/github/actions.go +++ b/vcs/github/actions.go @@ -9,6 +9,7 @@ import ( "time" "github.com/google/go-github/v56/github" + "gopkg.in/yaml.v3" ) func (gh *ghAppService) doesWorkflowExist(ctx context.Context, client *github.Client, r *github.Repository) bool { @@ -72,7 +73,18 @@ func (gh *ghAppService) createBranch(ctx context.Context, client *github.Client, return nil } -func (gh *ghAppService) createWorkflowFile(ctx context.Context, client *github.Client, r *github.Repository) error { +type WorkflowProperties struct { + RegistryEndpoint string + RepositoryOwner string + RepositoryName string +} + +func (gh *ghAppService) createWorkflowFile( + ctx context.Context, + client *github.Client, + r *github.Repository, + props *WorkflowProperties, +) error { msg := "build(ci): OpenRegistry build and push" tpl, err := template.New("github-actions-workflow").Delims("[[", "]]").Parse(buildAndPushTemplate) @@ -81,13 +93,23 @@ func (gh *ghAppService) createWorkflowFile(ctx context.Context, client *github.C } buf := &bytes.Buffer{} - if err = tpl.Execute(buf, r.GetDefaultBranch()); err != nil { + if err = tpl.Execute(buf, props); err != nil { return fmt.Errorf("ERR_EXECUTE_TEMPLATE: %w", err) } + yamlWorkflow := make(map[any]any) + if err = yaml.Unmarshal(buf.Bytes(), &yamlWorkflow); err != nil { + return fmt.Errorf("ERR_ENCODE_YAML_WORKFLOW: %w", err) + } + + yamlWorkflowBz, err := yaml.Marshal(yamlWorkflow) + if err != nil { + return err + } + opts := &github.RepositoryContentFileOptions{ Message: github.String(msg), - Content: buf.Bytes(), + Content: yamlWorkflowBz, Branch: github.String(gh.automationBranchName), } _, _, err = client.Repositories.CreateFile(ctx, r.GetOwner().GetLogin(), r.GetName(), gh.workflowFilePath, opts) diff --git a/vcs/github/github.go b/vcs/github/github.go index e30694ba..8683699f 100644 --- a/vcs/github/github.go +++ b/vcs/github/github.go @@ -27,6 +27,7 @@ type ghAppService struct { ghAppTransport *ghinstallation.AppsTransport automationBranchName string workflowFilePath string + registryEndpoint string webInterfaceURLs []string env config.Environment } @@ -37,6 +38,7 @@ func NewGithubApp( logger telemetry.Logger, webInterfaceURLs []string, env config.Environment, + registryEndpoint string, ) vcs.VCS { ghAppTransport, ghClient, err := newGHClient(cfg.AppID, cfg.PrivateKeyPem) if err != nil { @@ -53,6 +55,7 @@ func NewGithubApp( automationBranchName: OpenRegistryAutomationBranchName, webInterfaceURLs: webInterfaceURLs, env: env, + registryEndpoint: registryEndpoint, } } @@ -69,68 +72,73 @@ func (gh *ghAppService) ListHandlers() []echo.HandlerFunc { // RegisterRoutes takes in a echo.Group (aka sub router) which is prefix with VCS name // eg: for GitHub, the sub router would be prefixed with "/github" -func (gh *ghAppService) RegisterRoutes(r *echo.Group) { - r.Use( +func (gh *ghAppService) RegisterRoutes(router *echo.Group) { + router.Use( gh.getUsernameMiddleware(), gh.getGitubInstallationID(vcs.HandleAppFinishEndpoint, vcs.HandleSetupCallbackEndpoint), ) - r.Add(http.MethodGet, vcs.ListAuthorisedRepositoriesEndpoint, gh.ListAuthorisedRepositories) - r.Add(http.MethodGet, vcs.HandleSetupCallbackEndpoint, gh.HandleSetupCallback) - r.Add(http.MethodPost, vcs.HandleWebhookEventsEndpoint, gh.HandleWebhookEvents) - r.Add(http.MethodPost, vcs.HandleAppFinishEndpoint, gh.HandleAppFinish) - r.Add(http.MethodPost, vcs.CreateInitialPREndpoint, gh.CreateInitialPR) + router.Add(http.MethodGet, vcs.ListAuthorisedRepositoriesEndpoint, gh.ListAuthorisedRepositories) + router.Add(http.MethodGet, vcs.HandleSetupCallbackEndpoint, gh.HandleSetupCallback) + router.Add(http.MethodPost, vcs.HandleWebhookEventsEndpoint, gh.HandleWebhookEvents) + router.Add(http.MethodPost, vcs.HandleAppFinishEndpoint, gh.HandleAppFinish) + router.Add(http.MethodPost, vcs.CreateInitialPREndpoint, gh.CreateInitialPR) } func (gh *ghAppService) getUsernameMiddleware() echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { + return func(ctx echo.Context) error { + for key, header := range ctx.Request().Header { + color.Green("getUsernameMiddleware %s = %s", key, header) + } + // skip if it's a webhook call - if c.Path() == "/github"+vcs.HandleWebhookEventsEndpoint { - return next(c) + // if c.Path() == "/github"+vcs.HandleWebhookEventsEndpoint || c.Path() == "/github/app/callback" { + if ctx.Path() == "/github"+vcs.HandleWebhookEventsEndpoint { + return next(ctx) } - sessionCookie, err := c.Cookie("session_id") + sessionCookie, err := ctx.Cookie("session_id") if err != nil { - echoErr := c.JSON(http.StatusNotAcceptable, echo.Map{ + echoErr := ctx.JSON(http.StatusNotAcceptable, echo.Map{ "error": err.Error(), "cookie_id": "session_id", }) - gh.logger.Log(c, err).Send() + gh.logger.Log(ctx, err).Send() return echoErr } // session is :, and ":" is url encoded sessionID, err := url.QueryUnescape(sessionCookie.Value) if err != nil { - echoErr := c.JSON(http.StatusNotAcceptable, echo.Map{ + echoErr := ctx.JSON(http.StatusNotAcceptable, echo.Map{ "error": err.Error(), "cookie_id": "session_id", }) - gh.logger.Log(c, err).Send() + gh.logger.Log(ctx, err).Send() return echoErr } userID := strings.Split(sessionID, ":")[1] parsedID, err := uuid.Parse(userID) if err != nil { - echoErr := c.JSON(http.StatusForbidden, echo.Map{ - "error": err.Error(), + echoErr := ctx.JSON(http.StatusForbidden, echo.Map{ + "error": fmt.Errorf("ERR_PARSE_USER_ID: %w", err), }) - gh.logger.Log(c, err).Send() + gh.logger.Log(ctx, err).Send() return echoErr } - user, err := gh.store.GetUserByID(c.Request().Context(), parsedID) + + user, err := gh.store.GetUserByID(ctx.Request().Context(), parsedID) if err != nil { - echoErr := c.JSON(http.StatusNotAcceptable, echo.Map{ - "error": err.Error(), + echoErr := ctx.JSON(http.StatusForbidden, echo.Map{ + "error": fmt.Errorf("ERR_GET_AUTHZ_USER: %w", err), }) - gh.logger.Log(c, err).Send() + gh.logger.Log(ctx, err).Send() return echoErr } - c.Set(string(UsernameContextKey), user.Username) - c.Set(string(UserContextKey), user) - return next(c) + ctx.Set(string(types.UserContextKey), user) + return next(ctx) } } } @@ -141,12 +149,13 @@ func (gh *ghAppService) getGitubInstallationID(skipRoutes ...string) echo.Middle if c.Path() == "/github"+vcs.HandleWebhookEventsEndpoint { return next(c) } - user, ok := c.Get(string(UserContextKey)).(*types.User) + user, ok := c.Get(string(types.UserContextKey)).(*types.User) if !ok { + err := fmt.Errorf("GH_MDW_ERR: username is not present in context") echoErr := c.JSON(http.StatusNotAcceptable, echo.Map{ - "error": "GH_MDW_ERR: username is not present in context", + "error": err.Error(), }) - gh.logger.Log(c, echoErr).Send() + gh.logger.Log(c, err).Send() return echoErr } @@ -162,10 +171,11 @@ func (gh *ghAppService) getGitubInstallationID(skipRoutes ...string) echo.Middle } if user.Identities == nil || user.Identities.GetGitHubIdentity() == nil { + err := fmt.Errorf("GH_MDW_ERR: GitHub identity not found") echoErr := c.JSON(http.StatusBadRequest, echo.Map{ - "error": "GH_MDW_ERR: GitHub identity not found", + "error": err.Error(), }) - gh.logger.Log(c, echoErr).Send() + gh.logger.Log(c, err).Send() return echoErr } @@ -198,10 +208,9 @@ type AuthorizedRepository struct { type ContextKey string const ( - UsernameContextKey ContextKey = "USERNAME" - UserContextKey ContextKey = "USER" - GithubInstallationIDContextKey ContextKey = "GITHUB_INSTALLATION_ID" - WorkflowFilePath = ".github/workflows/openregistry.yml" - OpenRegistryAutomationBranchName = "openregistry-build-automation" - MaxGitHubRedirects = 3 + GithubInstallationIDContextKey ContextKey = "GITHUB_INSTALLATION_ID" + + WorkflowFilePath = ".github/workflows/openregistry.yml" + OpenRegistryAutomationBranchName = "openregistry-build-automation" + MaxGitHubRedirects = 3 ) diff --git a/vcs/github/handlers.go b/vcs/github/handlers.go index ccd76841..94bb3a7b 100644 --- a/vcs/github/handlers.go +++ b/vcs/github/handlers.go @@ -11,14 +11,15 @@ import ( "text/template" "time" - "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/containerish/OpenRegistry/vcs" "github.com/google/go-github/v56/github" "github.com/labstack/echo/v4" + + "github.com/containerish/OpenRegistry/store/v1/types" + "github.com/containerish/OpenRegistry/vcs" ) func (gh *ghAppService) HandleAppFinish(ctx echo.Context) error { - user := ctx.Get(string(UserContextKey)).(*types.User) + user := ctx.Get(string(types.UserContextKey)).(*types.User) installationID, err := strconv.ParseInt(ctx.QueryParam("installation_id"), 10, 64) if err != nil { @@ -83,7 +84,7 @@ func (gh *ghAppService) HandleAppFinish(ctx echo.Context) error { // HandleSetupCallback implements vcs.VCS func (gh *ghAppService) HandleSetupCallback(ctx echo.Context) error { - user := ctx.Get(string(UserContextKey)).(*types.User) + user := ctx.Get(string(types.UserContextKey)).(*types.User) installationID, err := strconv.ParseInt(ctx.QueryParam("installation_id"), 10, 64) if err != nil { @@ -266,6 +267,7 @@ func (gh *ghAppService) ListAuthorisedRepositories(ctx echo.Context) error { func (gh *ghAppService) CreateInitialPR(ctx echo.Context) error { installationID := ctx.Get(string(GithubInstallationIDContextKey)).(int64) + user := ctx.Get(string(types.UserContextKey)).(*types.User) var req vcs.InitialPRRequest if err := json.NewDecoder(ctx.Request().Body).Decode(&req); err != nil { @@ -310,7 +312,17 @@ func (gh *ghAppService) CreateInitialPR(ctx echo.Context) error { return echoErr } - if err = gh.createGitubActionsWorkflow(ctx.Request().Context(), client, &repository); err != nil { + err = gh.createGitubActionsWorkflow( + ctx.Request().Context(), + client, + &repository, + &WorkflowProperties{ + RegistryEndpoint: gh.registryEndpoint, + RepositoryOwner: user.Username, + RepositoryName: req.RepositoryName, + }, + ) + if err != nil { echoErr := ctx.JSON(http.StatusBadRequest, echo.Map{ "error": err.Error(), }) @@ -381,6 +393,7 @@ func (gh *ghAppService) createGitubActionsWorkflow( ctx context.Context, client *github.Client, repo *github.Repository, + props *WorkflowProperties, ) error { ctx, cancel := context.WithTimeout(ctx, time.Second*30) defer cancel() @@ -390,5 +403,5 @@ func (gh *ghAppService) createGitubActionsWorkflow( return err } - return gh.createWorkflowFile(ctx, client, repo) + return gh.createWorkflowFile(ctx, client, repo, props) } diff --git a/vcs/github/workflow.go b/vcs/github/workflow.go index 467bdd18..69ed289d 100644 --- a/vcs/github/workflow.go +++ b/vcs/github/workflow.go @@ -2,7 +2,7 @@ package github const ( buildAndPushTemplate = `name: "Build Container Image" -on: [push, pull_request] +on: [ push, pull_request ] defaults: run: @@ -16,30 +16,25 @@ jobs: name: "Build Container image" runs-on: ubuntu-latest env: - CONTAINER_IMAGE_NAME: openregistry.dev/${{ github.repository }}:${{ github.sha }} + CONTAINER_IMAGE_NAME: "[[.RegistryEndpoint]]/[[.RepositoryOwner]]/[[.RepositoryName]]:${{ github.sha }}" steps: - name: Checkout the branch - uses: actions/checkout@v3 - with: - fetch-depth: 0 - + uses: actions/checkout@v4 - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 id: buildx with: install: true version: latest - - name: Login to OpenRegistry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: - registry: openregistry.dev - username: ${{ github.repository_owner }} + registry: [[.RegistryEndpoint]] + username: [[.RepositoryOwner]] password: ${{ secrets.GITHUB_TOKEN }} - - name: Build image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: context: . file: Dockerfile From d2dc3a4ba6eb70bb076a2ac1b2e092702b7e9442 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Wed, 10 Jan 2024 00:11:31 +0530 Subject: [PATCH 20/23] fix: Filebase PreSignedURL generation Signed-off-by: jay-dee7 --- dfs/filebase/filebase.go | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/dfs/filebase/filebase.go b/dfs/filebase/filebase.go index d9be7456..9669e569 100644 --- a/dfs/filebase/filebase.go +++ b/dfs/filebase/filebase.go @@ -10,10 +10,11 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/s3" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" + oci_digest "github.com/opencontainers/go-digest" + "github.com/containerish/OpenRegistry/config" "github.com/containerish/OpenRegistry/dfs" "github.com/containerish/OpenRegistry/store/v1/types" - oci_digest "github.com/opencontainers/go-digest" ) type filebase struct { @@ -207,12 +208,15 @@ func (fb *filebase) Download(ctx context.Context, path string) (io.ReadCloser, e return resp.Body, nil } + func (fb *filebase) DownloadDir(dfsLink, dir string) error { return nil } + func (fb *filebase) List(path string) ([]*types.Metadata, error) { return nil, nil } + func (fb *filebase) AddImage(ns string, mf, l map[string][]byte) (string, error) { return "", nil } @@ -290,21 +294,8 @@ func (fb *filebase) AbortMultipartUpload(ctx context.Context, layerKey, uploadId } func (fb *filebase) GeneratePresignedURL(ctx context.Context, key string) (string, error) { - opts := &s3.GetObjectInput{ - Bucket: &fb.bucket, - Key: aws.String("layers/" + key), - } - - duration := func(o *s3.PresignOptions) { - o.Expires = time.Minute * 20 - } - - resp, err := fb.preSigner.PresignGetObject(ctx, opts, duration) - if err != nil { - return "", fmt.Errorf("ERR_FILEBASE_GENERATE_PRESIGNED_URL: %w", err) - } - - return resp.URL, nil + // Filebase+IPFS content can be directly resolved over an IPFS gateway + return fmt.Sprintf("%s/%s", fb.config.DFSLinkResolver, key), nil } func (fb *filebase) Config() *config.S3CompatibleDFS { From e13c85ed9d99ed00f3c7b13173348ce3f9c42a73 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Wed, 10 Jan 2024 00:20:50 +0530 Subject: [PATCH 21/23] add: Logs for failed clair requests Signed-off-by: jay-dee7 --- .dockerignore | 1 - auth/github.go | 8 ++-- auth/reset_password.go | 7 +-- auth/server/webauthn_server.go | 26 ++++-------- dfs/ipfs/p2p/p2p.go | 20 +++++---- router/github.go | 25 ++++++++--- router/vuln_scanning_routes.go | 9 ++-- services/yor/clair/v1/server/clair.go | 61 +++++++++++++++------------ vcs/github/github.go | 13 +++--- vcs/github/handlers.go | 2 +- 10 files changed, 91 insertions(+), 81 deletions(-) diff --git a/.dockerignore b/.dockerignore index 4f0222bd..e69de29b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +0,0 @@ -.go-skynet/ diff --git a/auth/github.go b/auth/github.go index 0061a3aa..0422eb51 100644 --- a/auth/github.go +++ b/auth/github.go @@ -8,13 +8,13 @@ import ( "strings" "time" - "github.com/containerish/OpenRegistry/config" - "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/fatih/color" "github.com/google/go-github/v56/github" "github.com/google/uuid" "github.com/labstack/echo/v4" "golang.org/x/oauth2" + + "github.com/containerish/OpenRegistry/config" + "github.com/containerish/OpenRegistry/store/v1/types" ) func (a *auth) LoginWithGithub(ctx echo.Context) error { @@ -201,8 +201,6 @@ func (a *auth) createCookie( HttpOnly: httpOnly, } - color.Red("cookie: %#v", cookie) - if expiresAt.Unix() < time.Now().Unix() { // set cookie deletion cookie.MaxAge = -1 diff --git a/auth/reset_password.go b/auth/reset_password.go index 2a717fa8..c47b153d 100644 --- a/auth/reset_password.go +++ b/auth/reset_password.go @@ -7,12 +7,13 @@ import ( "net/http" "time" - "github.com/containerish/OpenRegistry/services/email" - "github.com/containerish/OpenRegistry/store/v1/types" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" "github.com/jackc/pgx/v4" "github.com/labstack/echo/v4" + + "github.com/containerish/OpenRegistry/services/email" + "github.com/containerish/OpenRegistry/store/v1/types" ) func (a *auth) ResetForgottenPassword(ctx echo.Context) error { @@ -123,7 +124,7 @@ func (a *auth) ResetPassword(ctx echo.Context) error { user, ok := ctx.Get(string(types.UserContextKey)).(*types.User) if !ok { - err := fmt.Errorf("Unauthorized: missing user auth credentials") + err := fmt.Errorf("unauthorized: missing user auth credentials") echoErr := ctx.JSON(http.StatusUnauthorized, echo.Map{ "error": err.Error(), }) diff --git a/auth/server/webauthn_server.go b/auth/server/webauthn_server.go index 7108654c..84f1c6f3 100644 --- a/auth/server/webauthn_server.go +++ b/auth/server/webauthn_server.go @@ -5,10 +5,13 @@ import ( "encoding/json" "fmt" "net/http" - "net/url" "strings" "time" + "github.com/google/uuid" + "github.com/labstack/echo/v4" + "github.com/uptrace/bun" + "github.com/containerish/OpenRegistry/auth" "github.com/containerish/OpenRegistry/auth/webauthn" "github.com/containerish/OpenRegistry/config" @@ -16,9 +19,6 @@ import ( "github.com/containerish/OpenRegistry/store/v1/users" webauthn_store "github.com/containerish/OpenRegistry/store/v1/webauthn" "github.com/containerish/OpenRegistry/telemetry" - "github.com/google/uuid" - "github.com/labstack/echo/v4" - "github.com/uptrace/bun" ) type ( @@ -459,19 +459,11 @@ func (wa *webauthn_server) FinishLogin(ctx echo.Context) error { return echoErr } - domain := "" - url, err := url.Parse(wa.cfg.WebAuthnConfig.GetAllowedURLFromEchoContext(ctx, wa.cfg.Environment)) - if err != nil { - domain = wa.cfg.WebAuthnConfig.RPOrigins[0] - } else { - domain = url.Hostname() - } - sessionIdCookie := auth.CreateCookie(&auth.CreateCookieOptions{ - ExpiresAt: time.Now().Add(time.Hour * 750), //one month + ExpiresAt: time.Now().Add(time.Hour * 750), // one month Name: "session_id", Value: sessionId, - FQDN: domain, + FQDN: wa.cfg.Registry.FQDN, Environment: wa.cfg.Environment, HTTPOnly: false, }) @@ -480,16 +472,16 @@ func (wa *webauthn_server) FinishLogin(ctx echo.Context) error { ExpiresAt: time.Now().Add(time.Hour * 750), Name: auth.AccessCookieKey, Value: accessToken, - FQDN: domain, + FQDN: wa.cfg.Registry.FQDN, Environment: wa.cfg.Environment, HTTPOnly: true, }) refreshTokenCookie := auth.CreateCookie(&auth.CreateCookieOptions{ - ExpiresAt: time.Now().Add(time.Hour * 750), //one month + ExpiresAt: time.Now().Add(time.Hour * 750), // one month Name: auth.RefreshCookKey, Value: refreshToken, - FQDN: domain, + FQDN: wa.cfg.Registry.FQDN, Environment: wa.cfg.Environment, HTTPOnly: true, }) diff --git a/dfs/ipfs/p2p/p2p.go b/dfs/ipfs/p2p/p2p.go index e5ea682a..6325f73c 100644 --- a/dfs/ipfs/p2p/p2p.go +++ b/dfs/ipfs/p2p/p2p.go @@ -10,18 +10,19 @@ import ( "strings" "time" - hexmap "github.com/alphadose/haxmap" + "github.com/alphadose/haxmap" "github.com/aws/aws-sdk-go-v2/aws" s3types "github.com/aws/aws-sdk-go-v2/service/s3/types" - "github.com/containerish/OpenRegistry/config" - "github.com/containerish/OpenRegistry/dfs" - "github.com/containerish/OpenRegistry/store/v1/types" "github.com/fatih/color" "github.com/google/uuid" boxo_files "github.com/ipfs/boxo/files" boxo_path "github.com/ipfs/boxo/path" "github.com/ipfs/kubo/client/rpc" "github.com/multiformats/go-multiaddr" + + "github.com/containerish/OpenRegistry/config" + "github.com/containerish/OpenRegistry/dfs" + "github.com/containerish/OpenRegistry/store/v1/types" ) const ( @@ -33,8 +34,8 @@ type ( ipfsP2p struct { node *rpc.HttpApi config *config.IpfsDFS - uploadSession *hexmap.Map[string, *multipartSession] - uploadParts *hexmap.Map[string, *uploadParts] + uploadSession *haxmap.Map[string, *multipartSession] + uploadParts *haxmap.Map[string, *uploadParts] } multipartSession struct { @@ -87,8 +88,8 @@ func New(config *config.IpfsDFS) dfs.DFS { dfs := &ipfsP2p{ node: node, config: config, - uploadSession: hexmap.New[string, *multipartSession](), - uploadParts: hexmap.New[string, *uploadParts](), + uploadSession: haxmap.New[string, *multipartSession](), + uploadParts: haxmap.New[string, *uploadParts](), } // run garbage collection in background @@ -231,12 +232,15 @@ func (ipfs *ipfsP2p) Download(ctx context.Context, path string) (io.ReadCloser, buf := bytes.NewBuffer(node.RawData()) return io.NopCloser(buf), nil } + func (ipfs *ipfsP2p) DownloadDir(dfsLink, dir string) error { return nil } + func (ipfs *ipfsP2p) List(path string) ([]*types.Metadata, error) { return nil, nil } + func (ipfs *ipfsP2p) AddImage(ns string, mf, l map[string][]byte) (string, error) { return "", nil } diff --git a/router/github.go b/router/github.go index 8937549b..202f5ce6 100644 --- a/router/github.go +++ b/router/github.go @@ -6,17 +6,18 @@ import ( "net/http" "strings" + "github.com/fatih/color" + "github.com/labstack/echo/v4" + "github.com/rs/cors" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" + "github.com/containerish/OpenRegistry/config" github_actions_server "github.com/containerish/OpenRegistry/services/kon/github_actions/v1/server" "github.com/containerish/OpenRegistry/store/v1/automation" "github.com/containerish/OpenRegistry/telemetry" "github.com/containerish/OpenRegistry/vcs" "github.com/containerish/OpenRegistry/vcs/github" - "github.com/fatih/color" - "github.com/labstack/echo/v4" - "github.com/rs/cors" - "golang.org/x/net/http2" - "golang.org/x/net/http2/h2c" ) func RegisterGitHubRoutes( @@ -57,12 +58,22 @@ func RegisterGitHubRoutes( AllowOriginFunc: func(origin string) bool { return strings.HasSuffix(origin, "openregistry.dev") || strings.HasSuffix(origin, "cntr.sh") || - strings.HasSuffix(origin, "openregistry-web.pages.dev") + strings.HasSuffix(origin, "openregistry-web.pages.dev") || + strings.Contains(origin, "localhost") }, AllowedMethods: []string{ http.MethodOptions, http.MethodGet, http.MethodPost, }, - AllowedHeaders: []string{"*"}, + AllowedHeaders: []string{ + "Origin", + "Content-Type", + "Authorization", + "Connect-Protocol-Version", + "Connect-Timeout-Ms", + "Grpc-Timeout", + "X-Grpc-Web", + "X-User-Agent", + }, AllowCredentials: true, Debug: true, }) diff --git a/router/vuln_scanning_routes.go b/router/vuln_scanning_routes.go index cc2d2079..4798f18c 100644 --- a/router/vuln_scanning_routes.go +++ b/router/vuln_scanning_routes.go @@ -6,14 +6,15 @@ import ( "net/http" "strings" - "github.com/containerish/OpenRegistry/config" - "github.com/containerish/OpenRegistry/services/yor/clair/v1/server" - "github.com/containerish/OpenRegistry/store/v1/users" - "github.com/containerish/OpenRegistry/telemetry" "github.com/fatih/color" "github.com/rs/cors" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" + + "github.com/containerish/OpenRegistry/config" + "github.com/containerish/OpenRegistry/services/yor/clair/v1/server" + "github.com/containerish/OpenRegistry/store/v1/users" + "github.com/containerish/OpenRegistry/telemetry" ) func RegisterVulnScaningRoutes( diff --git a/services/yor/clair/v1/server/clair.go b/services/yor/clair/v1/server/clair.go index 8e339f35..039439d0 100644 --- a/services/yor/clair/v1/server/clair.go +++ b/services/yor/clair/v1/server/clair.go @@ -3,14 +3,16 @@ package server import ( "bytes" "context" + "encoding/json" "fmt" "io" "net/http" "github.com/bufbuild/connect-go" - clair_v1 "github.com/containerish/OpenRegistry/services/yor/clair/v1" "github.com/golang-jwt/jwt/v5" "google.golang.org/protobuf/encoding/protojson" + + clair_v1 "github.com/containerish/OpenRegistry/services/yor/clair/v1" ) func (c *clair) EnableVulnerabilityScanning( @@ -40,21 +42,16 @@ func (c *clair) GetVulnerabilityReport( manifestID := req.Msg.GetManifestId() logEvent.Str("manifest", manifestID) - report, err := c.getVulnReport(ctx, manifestID) + reportBz, err := c.getVulnReport(ctx, manifestID) if err != nil { - logEvent.Err(err).Send() + var errMap map[string]any + _ = json.Unmarshal(reportBz, &errMap) + logEvent.Err(err).Any("get_manifest_err", errMap).Send() return nil, connect.NewError(connect.CodeInvalidArgument, err) } - reportBz, err := io.ReadAll(report) - if err != nil { - logEvent.Err(err).Send() - return nil, connect.NewError(connect.CodeInternal, err) - } - defer report.Close() - resp := &clair_v1.GetVulnerabilityReportResponse{} - if err = protojson.Unmarshal(reportBz, resp); err != nil { + if err = (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(reportBz, resp); err != nil { logEvent.Err(err).Send() return nil, connect.NewError(connect.CodeInternal, err) } @@ -105,21 +102,16 @@ func (c *clair) SubmitManifestToScan( Layers: layers, } - result, err := c.submitManifest(ctx, body) + resultBz, err := c.submitManifest(ctx, body) if err != nil { - logEvent.Err(err).Send() + var errMap map[string]any + _ = json.Unmarshal(resultBz, &errMap) + logEvent.Err(err).Any("manifest_submit_err", errMap).Send() return nil, connect.NewError(connect.CodeInvalidArgument, err) } - resultBz, err := io.ReadAll(result) - if err != nil { - logEvent.Err(err).Send() - return nil, connect.NewError(connect.CodeInternal, err) - } - defer result.Close() - msg := &clair_v1.SubmitManifestToScanResponse{} - if err = protojson.Unmarshal(resultBz, msg); err != nil { + if err = (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(resultBz, msg); err != nil { logEvent.Err(err).Send() return nil, connect.NewError(connect.CodeInternal, err) } @@ -129,7 +121,7 @@ func (c *clair) SubmitManifestToScan( return connect.NewResponse(msg), nil } -func (c *clair) getVulnReport(ctx context.Context, manifestID string) (io.ReadCloser, error) { +func (c *clair) getVulnReport(ctx context.Context, manifestID string) ([]byte, error) { uri := fmt.Sprintf("%s/matcher/api/v1/vulnerability_report/%s", c.config.ClairEndpoint, manifestID) req, err := c.newClairRequest(ctx, http.MethodGet, uri, nil) @@ -142,13 +134,23 @@ func (c *clair) getVulnReport(ctx context.Context, manifestID string) (io.ReadCl return nil, err } - return resp.Body, nil + bz, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("ERR_GET_VULN_REPORT: READ_RESPONSE: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode >= 200 && resp.StatusCode <= 299 { + return bz, nil + } + + return bz, fmt.Errorf("ERR_GET_VULN_REPORT: INVALID_RESPONSE: %d", resp.StatusCode) } func (c *clair) submitManifest( ctx context.Context, manifest *clair_v1.ClairIndexManifestRequest, -) (io.ReadCloser, error) { +) ([]byte, error) { uri := fmt.Sprintf("%s/indexer/api/v1/index_report", c.config.ClairEndpoint) bz, err := protojson.Marshal(manifest) @@ -165,12 +167,17 @@ func (c *clair) submitManifest( return nil, err } - if res.StatusCode >= 200 && res.StatusCode <= 300 { - return res.Body, nil + bz, err = io.ReadAll(res.Body) + if err != nil { + return nil, fmt.Errorf("ERR_SUBMIT_MANIFEST_TO_SCAN: READ_RESPONSE: %w", err) } + defer res.Body.Close() - return nil, fmt.Errorf("ERR_SUBMIT_MANIFEST_TO_SCAN: CODE: %d", res.StatusCode) + if res.StatusCode >= 200 && res.StatusCode <= 300 { + return bz, nil + } + return bz, fmt.Errorf("ERR_SUBMIT_MANIFEST_TO_SCAN: CODE: %d", res.StatusCode) } func (c *clair) newClairRequest(ctx context.Context, method string, url string, body io.Reader) (*http.Request, error) { diff --git a/vcs/github/github.go b/vcs/github/github.go index 8683699f..a6e83544 100644 --- a/vcs/github/github.go +++ b/vcs/github/github.go @@ -9,14 +9,15 @@ import ( "time" "github.com/bradleyfalzon/ghinstallation/v2" - "github.com/containerish/OpenRegistry/config" - "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/containerish/OpenRegistry/telemetry" - "github.com/containerish/OpenRegistry/vcs" "github.com/fatih/color" "github.com/google/go-github/v56/github" "github.com/google/uuid" "github.com/labstack/echo/v4" + + "github.com/containerish/OpenRegistry/config" + "github.com/containerish/OpenRegistry/store/v1/types" + "github.com/containerish/OpenRegistry/telemetry" + "github.com/containerish/OpenRegistry/vcs" ) type ghAppService struct { @@ -88,10 +89,6 @@ func (gh *ghAppService) RegisterRoutes(router *echo.Group) { func (gh *ghAppService) getUsernameMiddleware() echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(ctx echo.Context) error { - for key, header := range ctx.Request().Header { - color.Green("getUsernameMiddleware %s = %s", key, header) - } - // skip if it's a webhook call // if c.Path() == "/github"+vcs.HandleWebhookEventsEndpoint || c.Path() == "/github/app/callback" { if ctx.Path() == "/github"+vcs.HandleWebhookEventsEndpoint { diff --git a/vcs/github/handlers.go b/vcs/github/handlers.go index 94bb3a7b..0cde8197 100644 --- a/vcs/github/handlers.go +++ b/vcs/github/handlers.go @@ -307,7 +307,7 @@ func (gh *ghAppService) CreateInitialPR(ctx echo.Context) error { workflowExists := gh.doesWorkflowExist(ctx.Request().Context(), client, &repository) if workflowExists { - echoErr := ctx.NoContent(http.StatusAccepted) + echoErr := ctx.NoContent(http.StatusNoContent) gh.logger.Log(ctx, echoErr).Send() return echoErr } From 09d76e891a2a4bddd3f4d6db385cfe291eecf958 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Mon, 5 Feb 2024 19:52:13 +0530 Subject: [PATCH 22/23] remove: Makefile And add justfile Signed-off-by: jay-dee7 --- .../oci-dist-spec-content-discovery.yml | 17 ++---- .../oci-dist-spec-content-management.yml | 17 ++---- .github/workflows/oci-dist-spec-pull.yml | 3 +- .github/workflows/oci-dist-spec-push.yml | 18 +++--- .../development-environment-setup.md | 57 ++++++++++--------- Makefile => justfile | 6 +- registry/v2/registry.go | 2 +- 7 files changed, 53 insertions(+), 67 deletions(-) rename Makefile => justfile (83%) diff --git a/.github/workflows/oci-dist-spec-content-discovery.yml b/.github/workflows/oci-dist-spec-content-discovery.yml index 9a30cf28..16461087 100644 --- a/.github/workflows/oci-dist-spec-content-discovery.yml +++ b/.github/workflows/oci-dist-spec-content-discovery.yml @@ -1,28 +1,23 @@ name: OCI Distribution Spec - Content Discovery - on: pull_request: push: - branches: - - main + branches: [main] workflow_dispatch: inputs: debug_enabled: type: boolean - description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + description: Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate) required: false default: false - concurrency: group: content-discovery-${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true - env: PGUSER: postgres POSTGRES_DB: open_registry POSTGRES_PASSWORD: Qwerty@123 POSTGRES_USER: postgres - jobs: conformance: runs-on: ubuntu-latest @@ -39,9 +34,9 @@ jobs: --health-interval 10s --health-timeout 5s --health-retries 5 - ports: - - 5432:5432 + ports: [5432:5432] steps: + - run: sudo snap install --edge --classic just - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: @@ -58,7 +53,7 @@ jobs: yq e -i '.dfs.mock.type = "FS"' config.yaml go mod download go build - make certs + just certs ./OpenRegistry migrations init \ --admin-db="postgres" \ --admin-db-username="postgres" \ @@ -93,7 +88,7 @@ jobs: OCI_DEBUG: 0 - name: Setup tmate session if mode is debug and OpenRegistry or OCI Tests Fail uses: mxschmitt/action-tmate@v3 - if: ${{ always() && (github.event_name == 'workflow_dispatch') && inputs.debug_enabled }} + if: ${{ always() && (github.event_name == 'workflow_dispatch') && inputs.debug_enabled }} - name: Set output report name id: vars run: echo "short_commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/oci-dist-spec-content-management.yml b/.github/workflows/oci-dist-spec-content-management.yml index 9d8f17c3..6a3e73d3 100644 --- a/.github/workflows/oci-dist-spec-content-management.yml +++ b/.github/workflows/oci-dist-spec-content-management.yml @@ -1,28 +1,23 @@ name: OCI Distribution Spec - Content Management - on: pull_request: push: - branches: - - main + branches: [main] workflow_dispatch: inputs: debug_enabled: type: boolean - description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + description: Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate) required: false default: false - concurrency: group: content-management-${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true - env: PGUSER: postgres POSTGRES_DB: open_registry POSTGRES_PASSWORD: Qwerty@123 POSTGRES_USER: postgres - jobs: conformance: runs-on: ubuntu-latest @@ -39,9 +34,9 @@ jobs: --health-interval 10s --health-timeout 5s --health-retries 5 - ports: - - 5432:5432 + ports: [5432:5432] steps: + - run: sudo snap install --edge --classic just - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: @@ -58,7 +53,7 @@ jobs: yq e -i '.dfs.mock.type = "FS"' config.yaml go mod download go build - make certs + just certs ./OpenRegistry migrations init \ --admin-db="postgres" \ --admin-db-username="postgres" \ @@ -92,7 +87,7 @@ jobs: OCI_DEBUG: 0 - name: Setup tmate session if mode is debug and OpenRegistry or OCI Tests Fail uses: mxschmitt/action-tmate@v3 - if: ${{ always() && (github.event_name == 'workflow_dispatch') && inputs.debug_enabled }} + if: ${{ always() && (github.event_name == 'workflow_dispatch') && inputs.debug_enabled }} - name: Set output report name id: vars run: echo "short_commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/oci-dist-spec-pull.yml b/.github/workflows/oci-dist-spec-pull.yml index 187691eb..8a551d13 100644 --- a/.github/workflows/oci-dist-spec-pull.yml +++ b/.github/workflows/oci-dist-spec-pull.yml @@ -42,6 +42,7 @@ jobs: ports: - 5432:5432 steps: + - run: sudo snap install --edge --classic just - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: @@ -58,7 +59,7 @@ jobs: yq e -i '.dfs.mock.type = "FS"' config.yaml go mod download go build - make certs + just certs ./OpenRegistry migrations init \ --admin-db="postgres" \ --admin-db-username="postgres" \ diff --git a/.github/workflows/oci-dist-spec-push.yml b/.github/workflows/oci-dist-spec-push.yml index fd7e31ba..223a377a 100644 --- a/.github/workflows/oci-dist-spec-push.yml +++ b/.github/workflows/oci-dist-spec-push.yml @@ -1,28 +1,24 @@ +--- name: OCI Distribution Spec - Push Image - on: pull_request: push: - branches: - - main + branches: [main] workflow_dispatch: inputs: debug_enabled: type: boolean - description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + description: Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate) required: false default: false - concurrency: group: push-${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true - env: PGUSER: postgres POSTGRES_DB: open_registry POSTGRES_PASSWORD: Qwerty@123 POSTGRES_USER: postgres - jobs: conformance: runs-on: ubuntu-latest @@ -39,9 +35,9 @@ jobs: --health-interval 10s --health-timeout 5s --health-retries 5 - ports: - - 5432:5432 + ports: [5432:5432] steps: + - run: sudo snap install --edge --classic just - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: @@ -58,7 +54,7 @@ jobs: yq e -i '.dfs.mock.type = "FS"' config.yaml go mod download go build - make certs + just certs ./OpenRegistry migrations init \ --admin-db="postgres" \ --admin-db-username="postgres" \ @@ -93,7 +89,7 @@ jobs: OCI_DEBUG: 0 - name: Setup tmate session if mode is debug and OpenRegistry or OCI Tests Fail uses: mxschmitt/action-tmate@v3 - if: ${{ always() && (github.event_name == 'workflow_dispatch') && inputs.debug_enabled }} + if: ${{ always() && (github.event_name == 'workflow_dispatch') && inputs.debug_enabled }} - name: Set output report name id: vars run: echo "short_commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT diff --git a/docs/contributing/development-environment-setup.md b/docs/contributing/development-environment-setup.md index 56dfe460..ba2a8460 100644 --- a/docs/contributing/development-environment-setup.md +++ b/docs/contributing/development-environment-setup.md @@ -3,12 +3,14 @@ ## Clone the repository We recommend using the Git method to clone the repository: + ```bash git clone git@github.com:containerish/OpenRegistry.git cd OpenRegistry ``` ## Configuration File + OpenRegistry uses the standard yaml based configuration. This configuration file is named `config.yaml` and can be either in the current directory or `$HOME/.openregistry/config.yaml` directory. Some of the features are disabled by default just to keep the on-boarding process simple. @@ -22,39 +24,39 @@ web_app_url: "http://localhost:3000" web_app_redirect_url: "/" web_app_error_redirect_path: "/auth/unhandled" registry: - dns_address: registry.local - version: master - fqdn: registry.local - host: registry.local - port: 5000 - tls: - enabled: true - key: .certs/openregistry.key - cert: .certs/openregistry.cert - services: - - github - - token + dns_address: registry.local + version: master + fqdn: registry.local + host: registry.local + port: 5000 + tls: + enabled: true + key: .certs/openregistry.key + cert: .certs/openregistry.cert + services: + - github + - token dfs: - s3_any: - access_key: - secret_key: - endpoint: - bucket_name: - dfs_link_resolver: + s3_any: + access_key: + secret_key: + endpoint: + bucket_name: + dfs_link_resolver: database: - kind: postgres - host: 0.0.0.0 - port: 5432 - username: postgres - password: Qwerty@123 - name: open_registry + kind: postgres + host: 0.0.0.0 + port: 5432 + username: postgres + password: Qwerty@123 + name: open_registry ``` If you check the `registry.tls` section, you'll notice that we have enabled the TLS configuration, but we need to generate the TLS certificates before we move forward: ```bash -make certs +just certs ``` ## Database Setup @@ -79,12 +81,13 @@ Exit the Postgres shell. ### Create the tables We have a simple Makefile, which exposes the following commands: + - `migup` - Populate all the migrations, create tables, schema changes - `migdown` - Teardown all the tables, schemas, etc - `cleanup` - Runs `migdown` first and then `migup` Before we begin setting up tables in our database, we need to use another tool called `golang-migrate`. -This is a database migration tool that makes database migrations dead simple. Use either of the following links to +This is a database migration tool that makes database migrations dead simple. Use either of the following links to install `golang-migrate`: - [Homebrew Link](https://formulae.brew.sh/formula/golang-migrate#default) @@ -93,7 +96,7 @@ install `golang-migrate`: To make sure that OpenRegistry can find all the required tables, schemas, etc, run the following command: ```bash -make migup +just migup ``` ```bash diff --git a/Makefile b/justfile similarity index 83% rename from Makefile rename to justfile index 67811ca6..36e1e295 100644 --- a/Makefile +++ b/justfile @@ -1,4 +1,4 @@ -POSTGRESQL_URL='postgres://postgres:postgres@0.0.0.0:5432/open_registry?sslmode=disable' +POSTGRESQL_URL := 'postgres://postgres:postgres@0.0.0.0:5432/open_registry?sslmode=disable' psql_grants: @psql -d open_registry -c 'GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO open_registry_user;' @@ -6,10 +6,6 @@ psql_grants: mock-images: bash ./scripts/mock-images.sh -tools: - pip3 install ggshield pre-commit - pre-commit install - certs: mkdir .certs openssl req -x509 -newkey rsa:4096 -keyout .certs/registry.local -out .certs/registry.local.crt -sha256 -days 365 \ diff --git a/registry/v2/registry.go b/registry/v2/registry.go index 0a8c15c8..2d8fbd44 100644 --- a/registry/v2/registry.go +++ b/registry/v2/registry.go @@ -158,7 +158,6 @@ func (r *registry) Catalog(ctx echo.Context) error { }) r.logger.Log(ctx, echoErr).Send() return echoErr - } // ListTags Content discovery @@ -201,6 +200,7 @@ func (r *registry) ListTags(ctx echo.Context) error { r.logger.Log(ctx, echoErr).Send() return echoErr } + func (r *registry) List(ctx echo.Context) error { return fmt.Errorf("not implemented") } From 5a2ee4ff9d38ce8793ee7e4678440b251ebd3f06 Mon Sep 17 00:00:00 2001 From: jay-dee7 Date: Sun, 13 Oct 2024 14:37:28 +0530 Subject: [PATCH 23/23] chore: Sync & bump Buf Connect RPC packages & implementation Signed-off-by: jay-dee7 --- auth/jwt_middleware.go | 12 +- auth/signin.go | 10 +- auth/signup.go | 7 +- buf.gen.yaml | 17 +- buf.lock | 9 + buf.work.yaml | 3 - buf.yaml | 20 ++ go.mod | 2 +- go.sum | 4 +- protos/buf.lock | 11 -- protos/buf.yaml | 11 -- router/github.go | 4 +- router/vuln_scanning_routes.go | 4 +- .../build_job.connect.go | 174 ++++++++++-------- .../build_logs.connect.go | 59 +++--- .../build_project.connect.go | 105 ++++++----- .../events.connect.go | 105 ----------- .../kon/github_actions/v1/server/build_job.go | 89 +++++---- .../github_actions/v1/server/build_logs.go | 61 +++--- .../github_actions/v1/server/build_project.go | 47 ++--- .../v1/server/github_action_logs.go | 10 +- .../github_actions/v1/server/interceptor.go | 2 +- .../v1/server/interceptor_helpers.go | 7 +- .../kon/github_actions/v1/server/server.go | 7 +- .../clair/v1/clairconnect/clair.connect.go | 82 +++++---- services/yor/clair/v1/server/clair.go | 2 +- services/yor/clair/v1/server/interceptors.go | 7 +- services/yor/clair/v1/server/server.go | 3 +- 28 files changed, 422 insertions(+), 452 deletions(-) create mode 100644 buf.lock delete mode 100644 buf.work.yaml create mode 100644 buf.yaml delete mode 100644 protos/buf.lock delete mode 100644 protos/buf.yaml delete mode 100644 services/kon/github_actions/v1/github_actions_v1connect/events.connect.go diff --git a/auth/jwt_middleware.go b/auth/jwt_middleware.go index cd0cdb73..276c3563 100644 --- a/auth/jwt_middleware.go +++ b/auth/jwt_middleware.go @@ -5,18 +5,20 @@ import ( "net/http" "time" - "github.com/containerish/OpenRegistry/store/v1/types" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" echo_jwt "github.com/labstack/echo-jwt/v4" "github.com/labstack/echo/v4" + + "github.com/containerish/OpenRegistry/store/v1/types" ) const ( - AccessCookieKey = "access_token" - RefreshCookKey = "refresh_token" - Service = "service" - QueryToken = "token" + AccessCookieKey = "access_token" + SessionCookieKey = "session_id" + RefreshCookKey = "refresh_token" + Service = "service" + QueryToken = "token" ) // JWT basically uses the default JWT middleware by echo, but has a slightly different skipper func diff --git a/auth/signin.go b/auth/signin.go index c665a693..cc643044 100644 --- a/auth/signin.go +++ b/auth/signin.go @@ -7,10 +7,11 @@ import ( "net/http" "time" - "github.com/containerish/OpenRegistry/store/v1/types" "github.com/google/uuid" "github.com/jackc/pgx/v4" "github.com/labstack/echo/v4" + + "github.com/containerish/OpenRegistry/store/v1/types" ) func (a *auth) SignIn(ctx echo.Context) error { @@ -170,7 +171,7 @@ func (a *auth) SignIn(ctx echo.Context) error { } sessionId := fmt.Sprintf("%s:%s", id, userFromDb.ID) - sessionCookie := a.createCookie(ctx, "session_id", sessionId, false, time.Now().Add(time.Hour*750)) + sessionCookie := a.createCookie(ctx, SessionCookieKey, sessionId, false, time.Now().Add(time.Hour*750)) accessCookie := a.createCookie(ctx, AccessCookieKey, access, true, time.Now().Add(time.Hour*750)) refreshCookie := a.createCookie(ctx, RefreshCookKey, refresh, true, time.Now().Add(time.Hour*750)) @@ -178,8 +179,9 @@ func (a *auth) SignIn(ctx echo.Context) error { ctx.SetCookie(refreshCookie) ctx.SetCookie(sessionCookie) err = ctx.JSON(http.StatusOK, echo.Map{ - "token": access, - "refresh": refresh, + SessionCookieKey: sessionId, + AccessCookieKey: access, + RefreshCookKey: refresh, }) a.logger.Log(ctx, err).Send() return err diff --git a/auth/signup.go b/auth/signup.go index 407fb130..0c53b506 100644 --- a/auth/signup.go +++ b/auth/signup.go @@ -8,12 +8,13 @@ import ( "strings" "time" + "github.com/google/uuid" + "github.com/labstack/echo/v4" + "github.com/containerish/OpenRegistry/config" "github.com/containerish/OpenRegistry/services/email" store_err "github.com/containerish/OpenRegistry/store/v1" "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/google/uuid" - "github.com/labstack/echo/v4" ) func (a *auth) parseSignUpRequest(ctx echo.Context) (*types.User, error) { @@ -95,7 +96,7 @@ func (a *auth) SignUp(ctx echo.Context) error { if strings.Contains(err.Error(), store_err.ErrDuplicateConstraintEmail) { echoErr := ctx.JSON(http.StatusInternalServerError, echo.Map{ "error": err.Error(), - "message": "this email already taken, try sign in?", + "message": "this email is already taken, try sign in?", }) a.logger.Log(ctx, err).Send() return echoErr diff --git a/buf.gen.yaml b/buf.gen.yaml index 3bfec575..d185fc17 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -1,16 +1,13 @@ -version: v1 +version: v2 managed: enabled: true plugins: - - plugin: buf.build/protocolbuffers/go + - remote: buf.build/protocolbuffers/go out: . - opt: - - paths=source_relative - - plugin: buf.build/bufbuild/validate-go + opt: paths=source_relative + - remote: buf.build/bufbuild/validate-go out: . - opt: - - paths=source_relative - - plugin: buf.build/bufbuild/connect-go + opt: paths=source_relative + - remote: buf.build/connectrpc/go out: . - opt: - - paths=source_relative + opt: paths=source_relative diff --git a/buf.lock b/buf.lock new file mode 100644 index 00000000..4286171e --- /dev/null +++ b/buf.lock @@ -0,0 +1,9 @@ +# Generated by buf. DO NOT EDIT. +version: v2 +deps: + - name: buf.build/envoyproxy/protoc-gen-validate + commit: 6607b10f00ed4a3d98f906807131c44a + digest: b5:ade405ac4328bd0a2cf83c93bcb4bc389d4897afd86a0096df4537b180916882da4e4f0c2d45f0b1554d7a6c87f6c5bc94b71b3555ca71cc31a9a8baed26a9f9 + - name: buf.build/googleapis/googleapis + commit: 5ae7f88519b04fe1965da0f8a375a088 + digest: b5:ac717f02b210c53aeaa5d8801b118cae7a1883dab531034859889622dcb389979ee731ab42192c16c3cdb39b40f2dda72a8c1ebeefa3bcdf95f9e5739dc30cca diff --git a/buf.work.yaml b/buf.work.yaml deleted file mode 100644 index 4bddfe67..00000000 --- a/buf.work.yaml +++ /dev/null @@ -1,3 +0,0 @@ -version: v1 -directories: - - protos diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 00000000..567d9738 --- /dev/null +++ b/buf.yaml @@ -0,0 +1,20 @@ +version: v2 +modules: + - path: protos + name: buf.build/containerish/openregistry +deps: + - buf.build/envoyproxy/protoc-gen-validate + - buf.build/googleapis/googleapis +lint: + use: + - STANDARD + except: + - FIELD_NOT_REQUIRED + - PACKAGE_NO_IMPORT_CYCLE + disallow_comment_ignores: true +breaking: + use: + - FILE + except: + - EXTENSION_NO_DELETE + - FIELD_SAME_DEFAULT diff --git a/go.mod b/go.mod index 1c3d3858..f2045eb5 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.23 toolchain go1.23.0 require ( + connectrpc.com/connect v1.17.0 github.com/alexliesenfeld/health v0.8.0 github.com/alphadose/haxmap v1.4.0 github.com/aws/aws-sdk-go-v2 v1.32.2 @@ -14,7 +15,6 @@ require ( github.com/aws/smithy-go v1.22.0 github.com/axiomhq/axiom-go v0.21.1 github.com/bradleyfalzon/ghinstallation/v2 v2.11.0 - github.com/bufbuild/connect-go v1.10.0 github.com/fatih/color v1.17.0 github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 diff --git a/go.sum b/go.sum index 65e1a5ae..253055e0 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk= +connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= @@ -79,8 +81,6 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bradleyfalzon/ghinstallation/v2 v2.11.0 h1:R9d0v+iobRHSaE4wKUnXFiZp53AL4ED5MzgEMwGTZag= github.com/bradleyfalzon/ghinstallation/v2 v2.11.0/go.mod h1:0LWKQwOHewXO/1acI6TtyE0Xc4ObDb2rFN7eHBAG71M= -github.com/bufbuild/connect-go v1.10.0 h1:QAJ3G9A1OYQW2Jbk3DeoJbkCxuKArrvZgDt47mjdTbg= -github.com/bufbuild/connect-go v1.10.0/go.mod h1:CAIePUgkDR5pAFaylSMtNK45ANQjp9JvpluG20rhpV8= github.com/calebcase/tmpfile v1.0.3 h1:BZrOWZ79gJqQ3XbAQlihYZf/YCV0H4KPIdM5K5oMpJo= github.com/calebcase/tmpfile v1.0.3/go.mod h1:UAUc01aHeC+pudPagY/lWvt2qS9ZO5Zzof6/tIUzqeI= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= diff --git a/protos/buf.lock b/protos/buf.lock deleted file mode 100644 index 4cb0aef5..00000000 --- a/protos/buf.lock +++ /dev/null @@ -1,11 +0,0 @@ -# Generated by buf. DO NOT EDIT. -version: v1 -deps: - - remote: buf.build - owner: envoyproxy - repository: protoc-gen-validate - commit: 6607b10f00ed4a3d98f906807131c44a - - remote: buf.build - owner: googleapis - repository: googleapis - commit: 5ae7f88519b04fe1965da0f8a375a088 diff --git a/protos/buf.yaml b/protos/buf.yaml deleted file mode 100644 index e6b4e5c4..00000000 --- a/protos/buf.yaml +++ /dev/null @@ -1,11 +0,0 @@ -version: v1 -name: buf.build/containerish/openregistry -lint: - use: - - STANDARD -deps: - - buf.build/googleapis/googleapis - - buf.build/envoyproxy/protoc-gen-validate -breaking: - use: - - FILE diff --git a/router/github.go b/router/github.go index 202f5ce6..7e39aac0 100644 --- a/router/github.go +++ b/router/github.go @@ -52,7 +52,7 @@ func RegisterGitHubRoutes( ) go func() { addr := net.JoinHostPort(cfg.Host, fmt.Sprintf("%d", cfg.Port)) - color.Green("connect-go GitHub Automation gRPC service running on: %s", addr) + color.Green("connectrpc GitHub Automation gRPC service running on: %s", addr) ghCors := cors.New(cors.Options{ AllowedOrigins: allowedOrigins, AllowOriginFunc: func(origin string) bool { @@ -79,7 +79,7 @@ func RegisterGitHubRoutes( }) handler := ghCors.Handler(h2c.NewHandler(githubMux, &http2.Server{})) if err := http.ListenAndServe(addr, handler); err != nil { - color.Red("connect-go GitHub Automation service listen error: %s", err) + color.Red("connectrpc GitHub Automation service listen error: %s", err) } }() } diff --git a/router/vuln_scanning_routes.go b/router/vuln_scanning_routes.go index 4798f18c..cb01bf0d 100644 --- a/router/vuln_scanning_routes.go +++ b/router/vuln_scanning_routes.go @@ -63,9 +63,9 @@ func RegisterVulnScaningRoutes( }) handler := h2c.NewHandler(vulnScanningCors.Handler(clairApi), &http2.Server{}) - color.Green("connect-go Clair gRPC service running on: %s", addr) + color.Green("connectrpc Clair gRPC service running on: %s", addr) if err := http.ListenAndServe(addr, handler); err != nil { - color.Red("connect-go listen error: %s", err) + color.Red("connectrpc listen error: %s", err) } }() } diff --git a/services/kon/github_actions/v1/github_actions_v1connect/build_job.connect.go b/services/kon/github_actions/v1/github_actions_v1connect/build_job.connect.go index 26f5817b..0723f9cc 100644 --- a/services/kon/github_actions/v1/github_actions_v1connect/build_job.connect.go +++ b/services/kon/github_actions/v1/github_actions_v1connect/build_job.connect.go @@ -5,9 +5,9 @@ package github_actions_v1connect import ( + connect "connectrpc.com/connect" context "context" errors "errors" - connect_go "github.com/bufbuild/connect-go" v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" http "net/http" strings "strings" @@ -18,7 +18,7 @@ import ( // generated with a version of connect newer than the one compiled into your binary. You can fix the // problem by either regenerating this code with an older version of connect or updating the connect // version compiled into your binary. -const _ = connect_go.IsAtLeastVersion0_1_0 +const _ = connect.IsAtLeastVersion1_13_0 const ( // GithubActionsBuildServiceName is the fully-qualified name of the GithubActionsBuildService @@ -57,16 +57,28 @@ const ( GithubActionsBuildServiceBulkDeleteBuildJobsProcedure = "/services.kon.github_actions.v1.GithubActionsBuildService/BulkDeleteBuildJobs" ) +// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. +var ( + githubActionsBuildServiceServiceDescriptor = v1.File_services_kon_github_actions_v1_build_job_proto.Services().ByName("GithubActionsBuildService") + githubActionsBuildServiceStoreJobMethodDescriptor = githubActionsBuildServiceServiceDescriptor.Methods().ByName("StoreJob") + githubActionsBuildServiceGetBuildJobMethodDescriptor = githubActionsBuildServiceServiceDescriptor.Methods().ByName("GetBuildJob") + githubActionsBuildServiceTriggerBuildMethodDescriptor = githubActionsBuildServiceServiceDescriptor.Methods().ByName("TriggerBuild") + githubActionsBuildServiceCancelBuildMethodDescriptor = githubActionsBuildServiceServiceDescriptor.Methods().ByName("CancelBuild") + githubActionsBuildServiceDeleteJobMethodDescriptor = githubActionsBuildServiceServiceDescriptor.Methods().ByName("DeleteJob") + githubActionsBuildServiceListBuildJobsMethodDescriptor = githubActionsBuildServiceServiceDescriptor.Methods().ByName("ListBuildJobs") + githubActionsBuildServiceBulkDeleteBuildJobsMethodDescriptor = githubActionsBuildServiceServiceDescriptor.Methods().ByName("BulkDeleteBuildJobs") +) + // GithubActionsBuildServiceClient is a client for the // services.kon.github_actions.v1.GithubActionsBuildService service. type GithubActionsBuildServiceClient interface { - StoreJob(context.Context, *connect_go.Request[v1.StoreJobRequest]) (*connect_go.Response[v1.StoreJobResponse], error) - GetBuildJob(context.Context, *connect_go.Request[v1.GetBuildJobRequest]) (*connect_go.Response[v1.GetBuildJobResponse], error) - TriggerBuild(context.Context, *connect_go.Request[v1.TriggerBuildRequest]) (*connect_go.Response[v1.TriggerBuildResponse], error) - CancelBuild(context.Context, *connect_go.Request[v1.CancelBuildRequest]) (*connect_go.Response[v1.CancelBuildResponse], error) - DeleteJob(context.Context, *connect_go.Request[v1.DeleteJobRequest]) (*connect_go.Response[v1.DeleteJobResponse], error) - ListBuildJobs(context.Context, *connect_go.Request[v1.ListBuildJobsRequest]) (*connect_go.Response[v1.ListBuildJobsResponse], error) - BulkDeleteBuildJobs(context.Context, *connect_go.Request[v1.BulkDeleteBuildJobsRequest]) (*connect_go.Response[v1.BulkDeleteBuildJobsResponse], error) + StoreJob(context.Context, *connect.Request[v1.StoreJobRequest]) (*connect.Response[v1.StoreJobResponse], error) + GetBuildJob(context.Context, *connect.Request[v1.GetBuildJobRequest]) (*connect.Response[v1.GetBuildJobResponse], error) + TriggerBuild(context.Context, *connect.Request[v1.TriggerBuildRequest]) (*connect.Response[v1.TriggerBuildResponse], error) + CancelBuild(context.Context, *connect.Request[v1.CancelBuildRequest]) (*connect.Response[v1.CancelBuildResponse], error) + DeleteJob(context.Context, *connect.Request[v1.DeleteJobRequest]) (*connect.Response[v1.DeleteJobResponse], error) + ListBuildJobs(context.Context, *connect.Request[v1.ListBuildJobsRequest]) (*connect.Response[v1.ListBuildJobsResponse], error) + BulkDeleteBuildJobs(context.Context, *connect.Request[v1.BulkDeleteBuildJobsRequest]) (*connect.Response[v1.BulkDeleteBuildJobsResponse], error) } // NewGithubActionsBuildServiceClient constructs a client for the @@ -77,104 +89,111 @@ type GithubActionsBuildServiceClient interface { // // The URL supplied here should be the base URL for the Connect or gRPC server (for example, // http://api.acme.com or https://acme.com/grpc). -func NewGithubActionsBuildServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) GithubActionsBuildServiceClient { +func NewGithubActionsBuildServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) GithubActionsBuildServiceClient { baseURL = strings.TrimRight(baseURL, "/") return &githubActionsBuildServiceClient{ - storeJob: connect_go.NewClient[v1.StoreJobRequest, v1.StoreJobResponse]( + storeJob: connect.NewClient[v1.StoreJobRequest, v1.StoreJobResponse]( httpClient, baseURL+GithubActionsBuildServiceStoreJobProcedure, - opts..., + connect.WithSchema(githubActionsBuildServiceStoreJobMethodDescriptor), + connect.WithClientOptions(opts...), ), - getBuildJob: connect_go.NewClient[v1.GetBuildJobRequest, v1.GetBuildJobResponse]( + getBuildJob: connect.NewClient[v1.GetBuildJobRequest, v1.GetBuildJobResponse]( httpClient, baseURL+GithubActionsBuildServiceGetBuildJobProcedure, - opts..., + connect.WithSchema(githubActionsBuildServiceGetBuildJobMethodDescriptor), + connect.WithClientOptions(opts...), ), - triggerBuild: connect_go.NewClient[v1.TriggerBuildRequest, v1.TriggerBuildResponse]( + triggerBuild: connect.NewClient[v1.TriggerBuildRequest, v1.TriggerBuildResponse]( httpClient, baseURL+GithubActionsBuildServiceTriggerBuildProcedure, - opts..., + connect.WithSchema(githubActionsBuildServiceTriggerBuildMethodDescriptor), + connect.WithClientOptions(opts...), ), - cancelBuild: connect_go.NewClient[v1.CancelBuildRequest, v1.CancelBuildResponse]( + cancelBuild: connect.NewClient[v1.CancelBuildRequest, v1.CancelBuildResponse]( httpClient, baseURL+GithubActionsBuildServiceCancelBuildProcedure, - opts..., + connect.WithSchema(githubActionsBuildServiceCancelBuildMethodDescriptor), + connect.WithClientOptions(opts...), ), - deleteJob: connect_go.NewClient[v1.DeleteJobRequest, v1.DeleteJobResponse]( + deleteJob: connect.NewClient[v1.DeleteJobRequest, v1.DeleteJobResponse]( httpClient, baseURL+GithubActionsBuildServiceDeleteJobProcedure, - opts..., + connect.WithSchema(githubActionsBuildServiceDeleteJobMethodDescriptor), + connect.WithClientOptions(opts...), ), - listBuildJobs: connect_go.NewClient[v1.ListBuildJobsRequest, v1.ListBuildJobsResponse]( + listBuildJobs: connect.NewClient[v1.ListBuildJobsRequest, v1.ListBuildJobsResponse]( httpClient, baseURL+GithubActionsBuildServiceListBuildJobsProcedure, - opts..., + connect.WithSchema(githubActionsBuildServiceListBuildJobsMethodDescriptor), + connect.WithClientOptions(opts...), ), - bulkDeleteBuildJobs: connect_go.NewClient[v1.BulkDeleteBuildJobsRequest, v1.BulkDeleteBuildJobsResponse]( + bulkDeleteBuildJobs: connect.NewClient[v1.BulkDeleteBuildJobsRequest, v1.BulkDeleteBuildJobsResponse]( httpClient, baseURL+GithubActionsBuildServiceBulkDeleteBuildJobsProcedure, - opts..., + connect.WithSchema(githubActionsBuildServiceBulkDeleteBuildJobsMethodDescriptor), + connect.WithClientOptions(opts...), ), } } // githubActionsBuildServiceClient implements GithubActionsBuildServiceClient. type githubActionsBuildServiceClient struct { - storeJob *connect_go.Client[v1.StoreJobRequest, v1.StoreJobResponse] - getBuildJob *connect_go.Client[v1.GetBuildJobRequest, v1.GetBuildJobResponse] - triggerBuild *connect_go.Client[v1.TriggerBuildRequest, v1.TriggerBuildResponse] - cancelBuild *connect_go.Client[v1.CancelBuildRequest, v1.CancelBuildResponse] - deleteJob *connect_go.Client[v1.DeleteJobRequest, v1.DeleteJobResponse] - listBuildJobs *connect_go.Client[v1.ListBuildJobsRequest, v1.ListBuildJobsResponse] - bulkDeleteBuildJobs *connect_go.Client[v1.BulkDeleteBuildJobsRequest, v1.BulkDeleteBuildJobsResponse] + storeJob *connect.Client[v1.StoreJobRequest, v1.StoreJobResponse] + getBuildJob *connect.Client[v1.GetBuildJobRequest, v1.GetBuildJobResponse] + triggerBuild *connect.Client[v1.TriggerBuildRequest, v1.TriggerBuildResponse] + cancelBuild *connect.Client[v1.CancelBuildRequest, v1.CancelBuildResponse] + deleteJob *connect.Client[v1.DeleteJobRequest, v1.DeleteJobResponse] + listBuildJobs *connect.Client[v1.ListBuildJobsRequest, v1.ListBuildJobsResponse] + bulkDeleteBuildJobs *connect.Client[v1.BulkDeleteBuildJobsRequest, v1.BulkDeleteBuildJobsResponse] } // StoreJob calls services.kon.github_actions.v1.GithubActionsBuildService.StoreJob. -func (c *githubActionsBuildServiceClient) StoreJob(ctx context.Context, req *connect_go.Request[v1.StoreJobRequest]) (*connect_go.Response[v1.StoreJobResponse], error) { +func (c *githubActionsBuildServiceClient) StoreJob(ctx context.Context, req *connect.Request[v1.StoreJobRequest]) (*connect.Response[v1.StoreJobResponse], error) { return c.storeJob.CallUnary(ctx, req) } // GetBuildJob calls services.kon.github_actions.v1.GithubActionsBuildService.GetBuildJob. -func (c *githubActionsBuildServiceClient) GetBuildJob(ctx context.Context, req *connect_go.Request[v1.GetBuildJobRequest]) (*connect_go.Response[v1.GetBuildJobResponse], error) { +func (c *githubActionsBuildServiceClient) GetBuildJob(ctx context.Context, req *connect.Request[v1.GetBuildJobRequest]) (*connect.Response[v1.GetBuildJobResponse], error) { return c.getBuildJob.CallUnary(ctx, req) } // TriggerBuild calls services.kon.github_actions.v1.GithubActionsBuildService.TriggerBuild. -func (c *githubActionsBuildServiceClient) TriggerBuild(ctx context.Context, req *connect_go.Request[v1.TriggerBuildRequest]) (*connect_go.Response[v1.TriggerBuildResponse], error) { +func (c *githubActionsBuildServiceClient) TriggerBuild(ctx context.Context, req *connect.Request[v1.TriggerBuildRequest]) (*connect.Response[v1.TriggerBuildResponse], error) { return c.triggerBuild.CallUnary(ctx, req) } // CancelBuild calls services.kon.github_actions.v1.GithubActionsBuildService.CancelBuild. -func (c *githubActionsBuildServiceClient) CancelBuild(ctx context.Context, req *connect_go.Request[v1.CancelBuildRequest]) (*connect_go.Response[v1.CancelBuildResponse], error) { +func (c *githubActionsBuildServiceClient) CancelBuild(ctx context.Context, req *connect.Request[v1.CancelBuildRequest]) (*connect.Response[v1.CancelBuildResponse], error) { return c.cancelBuild.CallUnary(ctx, req) } // DeleteJob calls services.kon.github_actions.v1.GithubActionsBuildService.DeleteJob. -func (c *githubActionsBuildServiceClient) DeleteJob(ctx context.Context, req *connect_go.Request[v1.DeleteJobRequest]) (*connect_go.Response[v1.DeleteJobResponse], error) { +func (c *githubActionsBuildServiceClient) DeleteJob(ctx context.Context, req *connect.Request[v1.DeleteJobRequest]) (*connect.Response[v1.DeleteJobResponse], error) { return c.deleteJob.CallUnary(ctx, req) } // ListBuildJobs calls services.kon.github_actions.v1.GithubActionsBuildService.ListBuildJobs. -func (c *githubActionsBuildServiceClient) ListBuildJobs(ctx context.Context, req *connect_go.Request[v1.ListBuildJobsRequest]) (*connect_go.Response[v1.ListBuildJobsResponse], error) { +func (c *githubActionsBuildServiceClient) ListBuildJobs(ctx context.Context, req *connect.Request[v1.ListBuildJobsRequest]) (*connect.Response[v1.ListBuildJobsResponse], error) { return c.listBuildJobs.CallUnary(ctx, req) } // BulkDeleteBuildJobs calls // services.kon.github_actions.v1.GithubActionsBuildService.BulkDeleteBuildJobs. -func (c *githubActionsBuildServiceClient) BulkDeleteBuildJobs(ctx context.Context, req *connect_go.Request[v1.BulkDeleteBuildJobsRequest]) (*connect_go.Response[v1.BulkDeleteBuildJobsResponse], error) { +func (c *githubActionsBuildServiceClient) BulkDeleteBuildJobs(ctx context.Context, req *connect.Request[v1.BulkDeleteBuildJobsRequest]) (*connect.Response[v1.BulkDeleteBuildJobsResponse], error) { return c.bulkDeleteBuildJobs.CallUnary(ctx, req) } // GithubActionsBuildServiceHandler is an implementation of the // services.kon.github_actions.v1.GithubActionsBuildService service. type GithubActionsBuildServiceHandler interface { - StoreJob(context.Context, *connect_go.Request[v1.StoreJobRequest]) (*connect_go.Response[v1.StoreJobResponse], error) - GetBuildJob(context.Context, *connect_go.Request[v1.GetBuildJobRequest]) (*connect_go.Response[v1.GetBuildJobResponse], error) - TriggerBuild(context.Context, *connect_go.Request[v1.TriggerBuildRequest]) (*connect_go.Response[v1.TriggerBuildResponse], error) - CancelBuild(context.Context, *connect_go.Request[v1.CancelBuildRequest]) (*connect_go.Response[v1.CancelBuildResponse], error) - DeleteJob(context.Context, *connect_go.Request[v1.DeleteJobRequest]) (*connect_go.Response[v1.DeleteJobResponse], error) - ListBuildJobs(context.Context, *connect_go.Request[v1.ListBuildJobsRequest]) (*connect_go.Response[v1.ListBuildJobsResponse], error) - BulkDeleteBuildJobs(context.Context, *connect_go.Request[v1.BulkDeleteBuildJobsRequest]) (*connect_go.Response[v1.BulkDeleteBuildJobsResponse], error) + StoreJob(context.Context, *connect.Request[v1.StoreJobRequest]) (*connect.Response[v1.StoreJobResponse], error) + GetBuildJob(context.Context, *connect.Request[v1.GetBuildJobRequest]) (*connect.Response[v1.GetBuildJobResponse], error) + TriggerBuild(context.Context, *connect.Request[v1.TriggerBuildRequest]) (*connect.Response[v1.TriggerBuildResponse], error) + CancelBuild(context.Context, *connect.Request[v1.CancelBuildRequest]) (*connect.Response[v1.CancelBuildResponse], error) + DeleteJob(context.Context, *connect.Request[v1.DeleteJobRequest]) (*connect.Response[v1.DeleteJobResponse], error) + ListBuildJobs(context.Context, *connect.Request[v1.ListBuildJobsRequest]) (*connect.Response[v1.ListBuildJobsResponse], error) + BulkDeleteBuildJobs(context.Context, *connect.Request[v1.BulkDeleteBuildJobsRequest]) (*connect.Response[v1.BulkDeleteBuildJobsResponse], error) } // NewGithubActionsBuildServiceHandler builds an HTTP handler from the service implementation. It @@ -182,41 +201,48 @@ type GithubActionsBuildServiceHandler interface { // // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. -func NewGithubActionsBuildServiceHandler(svc GithubActionsBuildServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { - githubActionsBuildServiceStoreJobHandler := connect_go.NewUnaryHandler( +func NewGithubActionsBuildServiceHandler(svc GithubActionsBuildServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + githubActionsBuildServiceStoreJobHandler := connect.NewUnaryHandler( GithubActionsBuildServiceStoreJobProcedure, svc.StoreJob, - opts..., + connect.WithSchema(githubActionsBuildServiceStoreJobMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - githubActionsBuildServiceGetBuildJobHandler := connect_go.NewUnaryHandler( + githubActionsBuildServiceGetBuildJobHandler := connect.NewUnaryHandler( GithubActionsBuildServiceGetBuildJobProcedure, svc.GetBuildJob, - opts..., + connect.WithSchema(githubActionsBuildServiceGetBuildJobMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - githubActionsBuildServiceTriggerBuildHandler := connect_go.NewUnaryHandler( + githubActionsBuildServiceTriggerBuildHandler := connect.NewUnaryHandler( GithubActionsBuildServiceTriggerBuildProcedure, svc.TriggerBuild, - opts..., + connect.WithSchema(githubActionsBuildServiceTriggerBuildMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - githubActionsBuildServiceCancelBuildHandler := connect_go.NewUnaryHandler( + githubActionsBuildServiceCancelBuildHandler := connect.NewUnaryHandler( GithubActionsBuildServiceCancelBuildProcedure, svc.CancelBuild, - opts..., + connect.WithSchema(githubActionsBuildServiceCancelBuildMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - githubActionsBuildServiceDeleteJobHandler := connect_go.NewUnaryHandler( + githubActionsBuildServiceDeleteJobHandler := connect.NewUnaryHandler( GithubActionsBuildServiceDeleteJobProcedure, svc.DeleteJob, - opts..., + connect.WithSchema(githubActionsBuildServiceDeleteJobMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - githubActionsBuildServiceListBuildJobsHandler := connect_go.NewUnaryHandler( + githubActionsBuildServiceListBuildJobsHandler := connect.NewUnaryHandler( GithubActionsBuildServiceListBuildJobsProcedure, svc.ListBuildJobs, - opts..., + connect.WithSchema(githubActionsBuildServiceListBuildJobsMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - githubActionsBuildServiceBulkDeleteBuildJobsHandler := connect_go.NewUnaryHandler( + githubActionsBuildServiceBulkDeleteBuildJobsHandler := connect.NewUnaryHandler( GithubActionsBuildServiceBulkDeleteBuildJobsProcedure, svc.BulkDeleteBuildJobs, - opts..., + connect.WithSchema(githubActionsBuildServiceBulkDeleteBuildJobsMethodDescriptor), + connect.WithHandlerOptions(opts...), ) return "/services.kon.github_actions.v1.GithubActionsBuildService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { @@ -243,30 +269,30 @@ func NewGithubActionsBuildServiceHandler(svc GithubActionsBuildServiceHandler, o // UnimplementedGithubActionsBuildServiceHandler returns CodeUnimplemented from all methods. type UnimplementedGithubActionsBuildServiceHandler struct{} -func (UnimplementedGithubActionsBuildServiceHandler) StoreJob(context.Context, *connect_go.Request[v1.StoreJobRequest]) (*connect_go.Response[v1.StoreJobResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.StoreJob is not implemented")) +func (UnimplementedGithubActionsBuildServiceHandler) StoreJob(context.Context, *connect.Request[v1.StoreJobRequest]) (*connect.Response[v1.StoreJobResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.StoreJob is not implemented")) } -func (UnimplementedGithubActionsBuildServiceHandler) GetBuildJob(context.Context, *connect_go.Request[v1.GetBuildJobRequest]) (*connect_go.Response[v1.GetBuildJobResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.GetBuildJob is not implemented")) +func (UnimplementedGithubActionsBuildServiceHandler) GetBuildJob(context.Context, *connect.Request[v1.GetBuildJobRequest]) (*connect.Response[v1.GetBuildJobResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.GetBuildJob is not implemented")) } -func (UnimplementedGithubActionsBuildServiceHandler) TriggerBuild(context.Context, *connect_go.Request[v1.TriggerBuildRequest]) (*connect_go.Response[v1.TriggerBuildResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.TriggerBuild is not implemented")) +func (UnimplementedGithubActionsBuildServiceHandler) TriggerBuild(context.Context, *connect.Request[v1.TriggerBuildRequest]) (*connect.Response[v1.TriggerBuildResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.TriggerBuild is not implemented")) } -func (UnimplementedGithubActionsBuildServiceHandler) CancelBuild(context.Context, *connect_go.Request[v1.CancelBuildRequest]) (*connect_go.Response[v1.CancelBuildResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.CancelBuild is not implemented")) +func (UnimplementedGithubActionsBuildServiceHandler) CancelBuild(context.Context, *connect.Request[v1.CancelBuildRequest]) (*connect.Response[v1.CancelBuildResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.CancelBuild is not implemented")) } -func (UnimplementedGithubActionsBuildServiceHandler) DeleteJob(context.Context, *connect_go.Request[v1.DeleteJobRequest]) (*connect_go.Response[v1.DeleteJobResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.DeleteJob is not implemented")) +func (UnimplementedGithubActionsBuildServiceHandler) DeleteJob(context.Context, *connect.Request[v1.DeleteJobRequest]) (*connect.Response[v1.DeleteJobResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.DeleteJob is not implemented")) } -func (UnimplementedGithubActionsBuildServiceHandler) ListBuildJobs(context.Context, *connect_go.Request[v1.ListBuildJobsRequest]) (*connect_go.Response[v1.ListBuildJobsResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.ListBuildJobs is not implemented")) +func (UnimplementedGithubActionsBuildServiceHandler) ListBuildJobs(context.Context, *connect.Request[v1.ListBuildJobsRequest]) (*connect.Response[v1.ListBuildJobsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.ListBuildJobs is not implemented")) } -func (UnimplementedGithubActionsBuildServiceHandler) BulkDeleteBuildJobs(context.Context, *connect_go.Request[v1.BulkDeleteBuildJobsRequest]) (*connect_go.Response[v1.BulkDeleteBuildJobsResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.BulkDeleteBuildJobs is not implemented")) +func (UnimplementedGithubActionsBuildServiceHandler) BulkDeleteBuildJobs(context.Context, *connect.Request[v1.BulkDeleteBuildJobsRequest]) (*connect.Response[v1.BulkDeleteBuildJobsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GithubActionsBuildService.BulkDeleteBuildJobs is not implemented")) } diff --git a/services/kon/github_actions/v1/github_actions_v1connect/build_logs.connect.go b/services/kon/github_actions/v1/github_actions_v1connect/build_logs.connect.go index 8fcf879f..e6a5def3 100644 --- a/services/kon/github_actions/v1/github_actions_v1connect/build_logs.connect.go +++ b/services/kon/github_actions/v1/github_actions_v1connect/build_logs.connect.go @@ -5,9 +5,9 @@ package github_actions_v1connect import ( + connect "connectrpc.com/connect" context "context" errors "errors" - connect_go "github.com/bufbuild/connect-go" v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" http "net/http" strings "strings" @@ -18,7 +18,7 @@ import ( // generated with a version of connect newer than the one compiled into your binary. You can fix the // problem by either regenerating this code with an older version of connect or updating the connect // version compiled into your binary. -const _ = connect_go.IsAtLeastVersion0_1_0 +const _ = connect.IsAtLeastVersion1_13_0 const ( // GitHubActionsLogsServiceName is the fully-qualified name of the GitHubActionsLogsService service. @@ -41,11 +41,18 @@ const ( GitHubActionsLogsServiceDumpLogsProcedure = "/services.kon.github_actions.v1.GitHubActionsLogsService/DumpLogs" ) +// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. +var ( + gitHubActionsLogsServiceServiceDescriptor = v1.File_services_kon_github_actions_v1_build_logs_proto.Services().ByName("GitHubActionsLogsService") + gitHubActionsLogsServiceStreamWorkflowRunLogsMethodDescriptor = gitHubActionsLogsServiceServiceDescriptor.Methods().ByName("StreamWorkflowRunLogs") + gitHubActionsLogsServiceDumpLogsMethodDescriptor = gitHubActionsLogsServiceServiceDescriptor.Methods().ByName("DumpLogs") +) + // GitHubActionsLogsServiceClient is a client for the // services.kon.github_actions.v1.GitHubActionsLogsService service. type GitHubActionsLogsServiceClient interface { - StreamWorkflowRunLogs(context.Context, *connect_go.Request[v1.StreamWorkflowRunLogsRequest]) (*connect_go.ServerStreamForClient[v1.StreamWorkflowRunLogsResponse], error) - DumpLogs(context.Context, *connect_go.Request[v1.DumpLogsRequest]) (*connect_go.Response[v1.DumpLogsResponse], error) + StreamWorkflowRunLogs(context.Context, *connect.Request[v1.StreamWorkflowRunLogsRequest]) (*connect.ServerStreamForClient[v1.StreamWorkflowRunLogsResponse], error) + DumpLogs(context.Context, *connect.Request[v1.DumpLogsRequest]) (*connect.Response[v1.DumpLogsResponse], error) } // NewGitHubActionsLogsServiceClient constructs a client for the @@ -56,44 +63,46 @@ type GitHubActionsLogsServiceClient interface { // // The URL supplied here should be the base URL for the Connect or gRPC server (for example, // http://api.acme.com or https://acme.com/grpc). -func NewGitHubActionsLogsServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) GitHubActionsLogsServiceClient { +func NewGitHubActionsLogsServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) GitHubActionsLogsServiceClient { baseURL = strings.TrimRight(baseURL, "/") return &gitHubActionsLogsServiceClient{ - streamWorkflowRunLogs: connect_go.NewClient[v1.StreamWorkflowRunLogsRequest, v1.StreamWorkflowRunLogsResponse]( + streamWorkflowRunLogs: connect.NewClient[v1.StreamWorkflowRunLogsRequest, v1.StreamWorkflowRunLogsResponse]( httpClient, baseURL+GitHubActionsLogsServiceStreamWorkflowRunLogsProcedure, - opts..., + connect.WithSchema(gitHubActionsLogsServiceStreamWorkflowRunLogsMethodDescriptor), + connect.WithClientOptions(opts...), ), - dumpLogs: connect_go.NewClient[v1.DumpLogsRequest, v1.DumpLogsResponse]( + dumpLogs: connect.NewClient[v1.DumpLogsRequest, v1.DumpLogsResponse]( httpClient, baseURL+GitHubActionsLogsServiceDumpLogsProcedure, - opts..., + connect.WithSchema(gitHubActionsLogsServiceDumpLogsMethodDescriptor), + connect.WithClientOptions(opts...), ), } } // gitHubActionsLogsServiceClient implements GitHubActionsLogsServiceClient. type gitHubActionsLogsServiceClient struct { - streamWorkflowRunLogs *connect_go.Client[v1.StreamWorkflowRunLogsRequest, v1.StreamWorkflowRunLogsResponse] - dumpLogs *connect_go.Client[v1.DumpLogsRequest, v1.DumpLogsResponse] + streamWorkflowRunLogs *connect.Client[v1.StreamWorkflowRunLogsRequest, v1.StreamWorkflowRunLogsResponse] + dumpLogs *connect.Client[v1.DumpLogsRequest, v1.DumpLogsResponse] } // StreamWorkflowRunLogs calls // services.kon.github_actions.v1.GitHubActionsLogsService.StreamWorkflowRunLogs. -func (c *gitHubActionsLogsServiceClient) StreamWorkflowRunLogs(ctx context.Context, req *connect_go.Request[v1.StreamWorkflowRunLogsRequest]) (*connect_go.ServerStreamForClient[v1.StreamWorkflowRunLogsResponse], error) { +func (c *gitHubActionsLogsServiceClient) StreamWorkflowRunLogs(ctx context.Context, req *connect.Request[v1.StreamWorkflowRunLogsRequest]) (*connect.ServerStreamForClient[v1.StreamWorkflowRunLogsResponse], error) { return c.streamWorkflowRunLogs.CallServerStream(ctx, req) } // DumpLogs calls services.kon.github_actions.v1.GitHubActionsLogsService.DumpLogs. -func (c *gitHubActionsLogsServiceClient) DumpLogs(ctx context.Context, req *connect_go.Request[v1.DumpLogsRequest]) (*connect_go.Response[v1.DumpLogsResponse], error) { +func (c *gitHubActionsLogsServiceClient) DumpLogs(ctx context.Context, req *connect.Request[v1.DumpLogsRequest]) (*connect.Response[v1.DumpLogsResponse], error) { return c.dumpLogs.CallUnary(ctx, req) } // GitHubActionsLogsServiceHandler is an implementation of the // services.kon.github_actions.v1.GitHubActionsLogsService service. type GitHubActionsLogsServiceHandler interface { - StreamWorkflowRunLogs(context.Context, *connect_go.Request[v1.StreamWorkflowRunLogsRequest], *connect_go.ServerStream[v1.StreamWorkflowRunLogsResponse]) error - DumpLogs(context.Context, *connect_go.Request[v1.DumpLogsRequest]) (*connect_go.Response[v1.DumpLogsResponse], error) + StreamWorkflowRunLogs(context.Context, *connect.Request[v1.StreamWorkflowRunLogsRequest], *connect.ServerStream[v1.StreamWorkflowRunLogsResponse]) error + DumpLogs(context.Context, *connect.Request[v1.DumpLogsRequest]) (*connect.Response[v1.DumpLogsResponse], error) } // NewGitHubActionsLogsServiceHandler builds an HTTP handler from the service implementation. It @@ -101,16 +110,18 @@ type GitHubActionsLogsServiceHandler interface { // // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. -func NewGitHubActionsLogsServiceHandler(svc GitHubActionsLogsServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { - gitHubActionsLogsServiceStreamWorkflowRunLogsHandler := connect_go.NewServerStreamHandler( +func NewGitHubActionsLogsServiceHandler(svc GitHubActionsLogsServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + gitHubActionsLogsServiceStreamWorkflowRunLogsHandler := connect.NewServerStreamHandler( GitHubActionsLogsServiceStreamWorkflowRunLogsProcedure, svc.StreamWorkflowRunLogs, - opts..., + connect.WithSchema(gitHubActionsLogsServiceStreamWorkflowRunLogsMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - gitHubActionsLogsServiceDumpLogsHandler := connect_go.NewUnaryHandler( + gitHubActionsLogsServiceDumpLogsHandler := connect.NewUnaryHandler( GitHubActionsLogsServiceDumpLogsProcedure, svc.DumpLogs, - opts..., + connect.WithSchema(gitHubActionsLogsServiceDumpLogsMethodDescriptor), + connect.WithHandlerOptions(opts...), ) return "/services.kon.github_actions.v1.GitHubActionsLogsService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { @@ -127,10 +138,10 @@ func NewGitHubActionsLogsServiceHandler(svc GitHubActionsLogsServiceHandler, opt // UnimplementedGitHubActionsLogsServiceHandler returns CodeUnimplemented from all methods. type UnimplementedGitHubActionsLogsServiceHandler struct{} -func (UnimplementedGitHubActionsLogsServiceHandler) StreamWorkflowRunLogs(context.Context, *connect_go.Request[v1.StreamWorkflowRunLogsRequest], *connect_go.ServerStream[v1.StreamWorkflowRunLogsResponse]) error { - return connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsLogsService.StreamWorkflowRunLogs is not implemented")) +func (UnimplementedGitHubActionsLogsServiceHandler) StreamWorkflowRunLogs(context.Context, *connect.Request[v1.StreamWorkflowRunLogsRequest], *connect.ServerStream[v1.StreamWorkflowRunLogsResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsLogsService.StreamWorkflowRunLogs is not implemented")) } -func (UnimplementedGitHubActionsLogsServiceHandler) DumpLogs(context.Context, *connect_go.Request[v1.DumpLogsRequest]) (*connect_go.Response[v1.DumpLogsResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsLogsService.DumpLogs is not implemented")) +func (UnimplementedGitHubActionsLogsServiceHandler) DumpLogs(context.Context, *connect.Request[v1.DumpLogsRequest]) (*connect.Response[v1.DumpLogsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsLogsService.DumpLogs is not implemented")) } diff --git a/services/kon/github_actions/v1/github_actions_v1connect/build_project.connect.go b/services/kon/github_actions/v1/github_actions_v1connect/build_project.connect.go index 3f7f1890..609c29e8 100644 --- a/services/kon/github_actions/v1/github_actions_v1connect/build_project.connect.go +++ b/services/kon/github_actions/v1/github_actions_v1connect/build_project.connect.go @@ -5,9 +5,9 @@ package github_actions_v1connect import ( + connect "connectrpc.com/connect" context "context" errors "errors" - connect_go "github.com/bufbuild/connect-go" v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" http "net/http" strings "strings" @@ -18,7 +18,7 @@ import ( // generated with a version of connect newer than the one compiled into your binary. You can fix the // problem by either regenerating this code with an older version of connect or updating the connect // version compiled into your binary. -const _ = connect_go.IsAtLeastVersion0_1_0 +const _ = connect.IsAtLeastVersion1_13_0 const ( // GitHubActionsProjectServiceName is the fully-qualified name of the GitHubActionsProjectService @@ -48,13 +48,22 @@ const ( GitHubActionsProjectServiceListProjectsProcedure = "/services.kon.github_actions.v1.GitHubActionsProjectService/ListProjects" ) +// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. +var ( + gitHubActionsProjectServiceServiceDescriptor = v1.File_services_kon_github_actions_v1_build_project_proto.Services().ByName("GitHubActionsProjectService") + gitHubActionsProjectServiceCreateProjectMethodDescriptor = gitHubActionsProjectServiceServiceDescriptor.Methods().ByName("CreateProject") + gitHubActionsProjectServiceGetProjectMethodDescriptor = gitHubActionsProjectServiceServiceDescriptor.Methods().ByName("GetProject") + gitHubActionsProjectServiceDeleteProjectMethodDescriptor = gitHubActionsProjectServiceServiceDescriptor.Methods().ByName("DeleteProject") + gitHubActionsProjectServiceListProjectsMethodDescriptor = gitHubActionsProjectServiceServiceDescriptor.Methods().ByName("ListProjects") +) + // GitHubActionsProjectServiceClient is a client for the // services.kon.github_actions.v1.GitHubActionsProjectService service. type GitHubActionsProjectServiceClient interface { - CreateProject(context.Context, *connect_go.Request[v1.CreateProjectRequest]) (*connect_go.Response[v1.CreateProjectResponse], error) - GetProject(context.Context, *connect_go.Request[v1.GetProjectRequest]) (*connect_go.Response[v1.GetProjectResponse], error) - DeleteProject(context.Context, *connect_go.Request[v1.DeleteProjectRequest]) (*connect_go.Response[v1.DeleteProjectResponse], error) - ListProjects(context.Context, *connect_go.Request[v1.ListProjectsRequest]) (*connect_go.Response[v1.ListProjectsResponse], error) + CreateProject(context.Context, *connect.Request[v1.CreateProjectRequest]) (*connect.Response[v1.CreateProjectResponse], error) + GetProject(context.Context, *connect.Request[v1.GetProjectRequest]) (*connect.Response[v1.GetProjectResponse], error) + DeleteProject(context.Context, *connect.Request[v1.DeleteProjectRequest]) (*connect.Response[v1.DeleteProjectResponse], error) + ListProjects(context.Context, *connect.Request[v1.ListProjectsRequest]) (*connect.Response[v1.ListProjectsResponse], error) } // NewGitHubActionsProjectServiceClient constructs a client for the @@ -65,67 +74,71 @@ type GitHubActionsProjectServiceClient interface { // // The URL supplied here should be the base URL for the Connect or gRPC server (for example, // http://api.acme.com or https://acme.com/grpc). -func NewGitHubActionsProjectServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) GitHubActionsProjectServiceClient { +func NewGitHubActionsProjectServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) GitHubActionsProjectServiceClient { baseURL = strings.TrimRight(baseURL, "/") return &gitHubActionsProjectServiceClient{ - createProject: connect_go.NewClient[v1.CreateProjectRequest, v1.CreateProjectResponse]( + createProject: connect.NewClient[v1.CreateProjectRequest, v1.CreateProjectResponse]( httpClient, baseURL+GitHubActionsProjectServiceCreateProjectProcedure, - opts..., + connect.WithSchema(gitHubActionsProjectServiceCreateProjectMethodDescriptor), + connect.WithClientOptions(opts...), ), - getProject: connect_go.NewClient[v1.GetProjectRequest, v1.GetProjectResponse]( + getProject: connect.NewClient[v1.GetProjectRequest, v1.GetProjectResponse]( httpClient, baseURL+GitHubActionsProjectServiceGetProjectProcedure, - opts..., + connect.WithSchema(gitHubActionsProjectServiceGetProjectMethodDescriptor), + connect.WithClientOptions(opts...), ), - deleteProject: connect_go.NewClient[v1.DeleteProjectRequest, v1.DeleteProjectResponse]( + deleteProject: connect.NewClient[v1.DeleteProjectRequest, v1.DeleteProjectResponse]( httpClient, baseURL+GitHubActionsProjectServiceDeleteProjectProcedure, - opts..., + connect.WithSchema(gitHubActionsProjectServiceDeleteProjectMethodDescriptor), + connect.WithClientOptions(opts...), ), - listProjects: connect_go.NewClient[v1.ListProjectsRequest, v1.ListProjectsResponse]( + listProjects: connect.NewClient[v1.ListProjectsRequest, v1.ListProjectsResponse]( httpClient, baseURL+GitHubActionsProjectServiceListProjectsProcedure, - opts..., + connect.WithSchema(gitHubActionsProjectServiceListProjectsMethodDescriptor), + connect.WithClientOptions(opts...), ), } } // gitHubActionsProjectServiceClient implements GitHubActionsProjectServiceClient. type gitHubActionsProjectServiceClient struct { - createProject *connect_go.Client[v1.CreateProjectRequest, v1.CreateProjectResponse] - getProject *connect_go.Client[v1.GetProjectRequest, v1.GetProjectResponse] - deleteProject *connect_go.Client[v1.DeleteProjectRequest, v1.DeleteProjectResponse] - listProjects *connect_go.Client[v1.ListProjectsRequest, v1.ListProjectsResponse] + createProject *connect.Client[v1.CreateProjectRequest, v1.CreateProjectResponse] + getProject *connect.Client[v1.GetProjectRequest, v1.GetProjectResponse] + deleteProject *connect.Client[v1.DeleteProjectRequest, v1.DeleteProjectResponse] + listProjects *connect.Client[v1.ListProjectsRequest, v1.ListProjectsResponse] } // CreateProject calls services.kon.github_actions.v1.GitHubActionsProjectService.CreateProject. -func (c *gitHubActionsProjectServiceClient) CreateProject(ctx context.Context, req *connect_go.Request[v1.CreateProjectRequest]) (*connect_go.Response[v1.CreateProjectResponse], error) { +func (c *gitHubActionsProjectServiceClient) CreateProject(ctx context.Context, req *connect.Request[v1.CreateProjectRequest]) (*connect.Response[v1.CreateProjectResponse], error) { return c.createProject.CallUnary(ctx, req) } // GetProject calls services.kon.github_actions.v1.GitHubActionsProjectService.GetProject. -func (c *gitHubActionsProjectServiceClient) GetProject(ctx context.Context, req *connect_go.Request[v1.GetProjectRequest]) (*connect_go.Response[v1.GetProjectResponse], error) { +func (c *gitHubActionsProjectServiceClient) GetProject(ctx context.Context, req *connect.Request[v1.GetProjectRequest]) (*connect.Response[v1.GetProjectResponse], error) { return c.getProject.CallUnary(ctx, req) } // DeleteProject calls services.kon.github_actions.v1.GitHubActionsProjectService.DeleteProject. -func (c *gitHubActionsProjectServiceClient) DeleteProject(ctx context.Context, req *connect_go.Request[v1.DeleteProjectRequest]) (*connect_go.Response[v1.DeleteProjectResponse], error) { +func (c *gitHubActionsProjectServiceClient) DeleteProject(ctx context.Context, req *connect.Request[v1.DeleteProjectRequest]) (*connect.Response[v1.DeleteProjectResponse], error) { return c.deleteProject.CallUnary(ctx, req) } // ListProjects calls services.kon.github_actions.v1.GitHubActionsProjectService.ListProjects. -func (c *gitHubActionsProjectServiceClient) ListProjects(ctx context.Context, req *connect_go.Request[v1.ListProjectsRequest]) (*connect_go.Response[v1.ListProjectsResponse], error) { +func (c *gitHubActionsProjectServiceClient) ListProjects(ctx context.Context, req *connect.Request[v1.ListProjectsRequest]) (*connect.Response[v1.ListProjectsResponse], error) { return c.listProjects.CallUnary(ctx, req) } // GitHubActionsProjectServiceHandler is an implementation of the // services.kon.github_actions.v1.GitHubActionsProjectService service. type GitHubActionsProjectServiceHandler interface { - CreateProject(context.Context, *connect_go.Request[v1.CreateProjectRequest]) (*connect_go.Response[v1.CreateProjectResponse], error) - GetProject(context.Context, *connect_go.Request[v1.GetProjectRequest]) (*connect_go.Response[v1.GetProjectResponse], error) - DeleteProject(context.Context, *connect_go.Request[v1.DeleteProjectRequest]) (*connect_go.Response[v1.DeleteProjectResponse], error) - ListProjects(context.Context, *connect_go.Request[v1.ListProjectsRequest]) (*connect_go.Response[v1.ListProjectsResponse], error) + CreateProject(context.Context, *connect.Request[v1.CreateProjectRequest]) (*connect.Response[v1.CreateProjectResponse], error) + GetProject(context.Context, *connect.Request[v1.GetProjectRequest]) (*connect.Response[v1.GetProjectResponse], error) + DeleteProject(context.Context, *connect.Request[v1.DeleteProjectRequest]) (*connect.Response[v1.DeleteProjectResponse], error) + ListProjects(context.Context, *connect.Request[v1.ListProjectsRequest]) (*connect.Response[v1.ListProjectsResponse], error) } // NewGitHubActionsProjectServiceHandler builds an HTTP handler from the service implementation. It @@ -133,26 +146,30 @@ type GitHubActionsProjectServiceHandler interface { // // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. -func NewGitHubActionsProjectServiceHandler(svc GitHubActionsProjectServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { - gitHubActionsProjectServiceCreateProjectHandler := connect_go.NewUnaryHandler( +func NewGitHubActionsProjectServiceHandler(svc GitHubActionsProjectServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + gitHubActionsProjectServiceCreateProjectHandler := connect.NewUnaryHandler( GitHubActionsProjectServiceCreateProjectProcedure, svc.CreateProject, - opts..., + connect.WithSchema(gitHubActionsProjectServiceCreateProjectMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - gitHubActionsProjectServiceGetProjectHandler := connect_go.NewUnaryHandler( + gitHubActionsProjectServiceGetProjectHandler := connect.NewUnaryHandler( GitHubActionsProjectServiceGetProjectProcedure, svc.GetProject, - opts..., + connect.WithSchema(gitHubActionsProjectServiceGetProjectMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - gitHubActionsProjectServiceDeleteProjectHandler := connect_go.NewUnaryHandler( + gitHubActionsProjectServiceDeleteProjectHandler := connect.NewUnaryHandler( GitHubActionsProjectServiceDeleteProjectProcedure, svc.DeleteProject, - opts..., + connect.WithSchema(gitHubActionsProjectServiceDeleteProjectMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - gitHubActionsProjectServiceListProjectsHandler := connect_go.NewUnaryHandler( + gitHubActionsProjectServiceListProjectsHandler := connect.NewUnaryHandler( GitHubActionsProjectServiceListProjectsProcedure, svc.ListProjects, - opts..., + connect.WithSchema(gitHubActionsProjectServiceListProjectsMethodDescriptor), + connect.WithHandlerOptions(opts...), ) return "/services.kon.github_actions.v1.GitHubActionsProjectService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { @@ -173,18 +190,18 @@ func NewGitHubActionsProjectServiceHandler(svc GitHubActionsProjectServiceHandle // UnimplementedGitHubActionsProjectServiceHandler returns CodeUnimplemented from all methods. type UnimplementedGitHubActionsProjectServiceHandler struct{} -func (UnimplementedGitHubActionsProjectServiceHandler) CreateProject(context.Context, *connect_go.Request[v1.CreateProjectRequest]) (*connect_go.Response[v1.CreateProjectResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsProjectService.CreateProject is not implemented")) +func (UnimplementedGitHubActionsProjectServiceHandler) CreateProject(context.Context, *connect.Request[v1.CreateProjectRequest]) (*connect.Response[v1.CreateProjectResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsProjectService.CreateProject is not implemented")) } -func (UnimplementedGitHubActionsProjectServiceHandler) GetProject(context.Context, *connect_go.Request[v1.GetProjectRequest]) (*connect_go.Response[v1.GetProjectResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsProjectService.GetProject is not implemented")) +func (UnimplementedGitHubActionsProjectServiceHandler) GetProject(context.Context, *connect.Request[v1.GetProjectRequest]) (*connect.Response[v1.GetProjectResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsProjectService.GetProject is not implemented")) } -func (UnimplementedGitHubActionsProjectServiceHandler) DeleteProject(context.Context, *connect_go.Request[v1.DeleteProjectRequest]) (*connect_go.Response[v1.DeleteProjectResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsProjectService.DeleteProject is not implemented")) +func (UnimplementedGitHubActionsProjectServiceHandler) DeleteProject(context.Context, *connect.Request[v1.DeleteProjectRequest]) (*connect.Response[v1.DeleteProjectResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsProjectService.DeleteProject is not implemented")) } -func (UnimplementedGitHubActionsProjectServiceHandler) ListProjects(context.Context, *connect_go.Request[v1.ListProjectsRequest]) (*connect_go.Response[v1.ListProjectsResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsProjectService.ListProjects is not implemented")) +func (UnimplementedGitHubActionsProjectServiceHandler) ListProjects(context.Context, *connect.Request[v1.ListProjectsRequest]) (*connect.Response[v1.ListProjectsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubActionsProjectService.ListProjects is not implemented")) } diff --git a/services/kon/github_actions/v1/github_actions_v1connect/events.connect.go b/services/kon/github_actions/v1/github_actions_v1connect/events.connect.go deleted file mode 100644 index 9662c14e..00000000 --- a/services/kon/github_actions/v1/github_actions_v1connect/events.connect.go +++ /dev/null @@ -1,105 +0,0 @@ -// Code generated by protoc-gen-connect-go. DO NOT EDIT. -// -// Source: services/kon/github_actions/v1/events.proto - -package github_actions_v1connect - -import ( - context "context" - errors "errors" - connect_go "github.com/bufbuild/connect-go" - _ "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" - emptypb "google.golang.org/protobuf/types/known/emptypb" - structpb "google.golang.org/protobuf/types/known/structpb" - http "net/http" - strings "strings" -) - -// This is a compile-time assertion to ensure that this generated file and the connect package are -// compatible. If you get a compiler error that this constant is not defined, this code was -// generated with a version of connect newer than the one compiled into your binary. You can fix the -// problem by either regenerating this code with an older version of connect or updating the connect -// version compiled into your binary. -const _ = connect_go.IsAtLeastVersion0_1_0 - -const ( - // GitHubWebhookListenerServiceName is the fully-qualified name of the GitHubWebhookListenerService - // service. - GitHubWebhookListenerServiceName = "services.kon.github_actions.v1.GitHubWebhookListenerService" -) - -// These constants are the fully-qualified names of the RPCs defined in this package. They're -// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. -// -// Note that these are different from the fully-qualified method names used by -// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to -// reflection-formatted method names, remove the leading slash and convert the remaining slash to a -// period. -const ( - // GitHubWebhookListenerServiceListenProcedure is the fully-qualified name of the - // GitHubWebhookListenerService's Listen RPC. - GitHubWebhookListenerServiceListenProcedure = "/services.kon.github_actions.v1.GitHubWebhookListenerService/Listen" -) - -// GitHubWebhookListenerServiceClient is a client for the -// services.kon.github_actions.v1.GitHubWebhookListenerService service. -type GitHubWebhookListenerServiceClient interface { - Listen(context.Context, *connect_go.Request[structpb.Struct]) (*connect_go.Response[emptypb.Empty], error) -} - -// NewGitHubWebhookListenerServiceClient constructs a client for the -// services.kon.github_actions.v1.GitHubWebhookListenerService service. By default, it uses the -// Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends -// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or -// connect.WithGRPCWeb() options. -// -// The URL supplied here should be the base URL for the Connect or gRPC server (for example, -// http://api.acme.com or https://acme.com/grpc). -func NewGitHubWebhookListenerServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) GitHubWebhookListenerServiceClient { - baseURL = strings.TrimRight(baseURL, "/") - return &gitHubWebhookListenerServiceClient{ - listen: connect_go.NewClient[structpb.Struct, emptypb.Empty]( - httpClient, - baseURL+GitHubWebhookListenerServiceListenProcedure, - opts..., - ), - } -} - -// gitHubWebhookListenerServiceClient implements GitHubWebhookListenerServiceClient. -type gitHubWebhookListenerServiceClient struct { - listen *connect_go.Client[structpb.Struct, emptypb.Empty] -} - -// Listen calls services.kon.github_actions.v1.GitHubWebhookListenerService.Listen. -func (c *gitHubWebhookListenerServiceClient) Listen(ctx context.Context, req *connect_go.Request[structpb.Struct]) (*connect_go.Response[emptypb.Empty], error) { - return c.listen.CallUnary(ctx, req) -} - -// GitHubWebhookListenerServiceHandler is an implementation of the -// services.kon.github_actions.v1.GitHubWebhookListenerService service. -type GitHubWebhookListenerServiceHandler interface { - Listen(context.Context, *connect_go.Request[structpb.Struct]) (*connect_go.Response[emptypb.Empty], error) -} - -// NewGitHubWebhookListenerServiceHandler builds an HTTP handler from the service implementation. It -// returns the path on which to mount the handler and the handler itself. -// -// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf -// and JSON codecs. They also support gzip compression. -func NewGitHubWebhookListenerServiceHandler(svc GitHubWebhookListenerServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { - mux := http.NewServeMux() - mux.Handle(GitHubWebhookListenerServiceListenProcedure, connect_go.NewUnaryHandler( - GitHubWebhookListenerServiceListenProcedure, - svc.Listen, - opts..., - )) - return "/services.kon.github_actions.v1.GitHubWebhookListenerService/", mux -} - -// UnimplementedGitHubWebhookListenerServiceHandler returns CodeUnimplemented from all methods. -type UnimplementedGitHubWebhookListenerServiceHandler struct{} - -func (UnimplementedGitHubWebhookListenerServiceHandler) Listen(context.Context, *connect_go.Request[structpb.Struct]) (*connect_go.Response[emptypb.Empty], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.kon.github_actions.v1.GitHubWebhookListenerService.Listen is not implemented")) -} diff --git a/services/kon/github_actions/v1/server/build_job.go b/services/kon/github_actions/v1/server/build_job.go index 14277adb..b9d936fb 100644 --- a/services/kon/github_actions/v1/server/build_job.go +++ b/services/kon/github_actions/v1/server/build_job.go @@ -4,25 +4,26 @@ import ( "context" "fmt" - connect_go "github.com/bufbuild/connect-go" + "connectrpc.com/connect" + "github.com/google/go-github/v56/github" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + common_v1 "github.com/containerish/OpenRegistry/common/v1" v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/google/go-github/v56/github" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) // BulkDeleteBuildJobs implements github_actions_v1connect.GithubActionsBuildServiceHandler func (gha *GitHubActionsServer) BulkDeleteBuildJobs( ctx context.Context, - req *connect_go.Request[v1.BulkDeleteBuildJobsRequest], + req *connect.Request[v1.BulkDeleteBuildJobsRequest], ) ( - *connect_go.Response[v1.BulkDeleteBuildJobsResponse], + *connect.Response[v1.BulkDeleteBuildJobsResponse], error, ) { // githubClient := gha.getGithubClientFromContext(ctx) // if err := req.Msg.Validate(); err != nil { - // return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + // return nil, connect.NewError(connect.CodeInvalidArgument, err) // } // // errList := []error{} @@ -34,16 +35,16 @@ func (gha *GitHubActionsServer) BulkDeleteBuildJobs( // } // // if len(errList) > 0 { - // return nil, connect_go.NewError(connect_go.CodeInternal, fmt.Errorf("%v", errList)) + // return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("%v", errList)) // } // - // return connect_go.NewResponse(&v1.BulkDeleteBuildJobsResponse{ + // return connect.NewResponse(&v1.BulkDeleteBuildJobsResponse{ // Message: fmt.Sprintf("%d build jobs deleted successfully", len(req.Msg.GetJobIds())), // }), nil gha.logger.Debug().Str("procedure", req.Spec().Procedure).Bool("method_not_implemented", true).Send() return nil, - connect_go.NewError( - connect_go.CodeUnimplemented, + connect.NewError( + connect.CodeUnimplemented, fmt.Errorf("bulk job deletion is not supported by GitHub Actions integration"), ) } @@ -51,9 +52,9 @@ func (gha *GitHubActionsServer) BulkDeleteBuildJobs( // CancelBuild implements github_actions_v1connect.GithubActionsBuildServiceHandler func (gha *GitHubActionsServer) CancelBuild( ctx context.Context, - req *connect_go.Request[v1.CancelBuildRequest], + req *connect.Request[v1.CancelBuildRequest], ) ( - *connect_go.Response[v1.CancelBuildResponse], + *connect.Response[v1.CancelBuildResponse], error, ) { logEvent := gha.logger.Debug().Str("procedure", req.Spec().Procedure) @@ -62,7 +63,7 @@ func (gha *GitHubActionsServer) CancelBuild( if err := req.Msg.Validate(); err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } _, err := githubClient.Actions.CancelWorkflowRunByID( @@ -73,11 +74,11 @@ func (gha *GitHubActionsServer) CancelBuild( ) if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } logEvent.Bool("success", true).Send() - return connect_go.NewResponse(&v1.CancelBuildResponse{ + return connect.NewResponse(&v1.CancelBuildResponse{ Message: "build job canceled successfully", }), nil } @@ -87,26 +88,26 @@ func (gha *GitHubActionsServer) CancelBuild( // or deleting them isn't the best we can provide to the user. func (gha *GitHubActionsServer) DeleteJob( ctx context.Context, - req *connect_go.Request[v1.DeleteJobRequest], + req *connect.Request[v1.DeleteJobRequest], ) ( - *connect_go.Response[v1.DeleteJobResponse], + *connect.Response[v1.DeleteJobResponse], error, ) { // githubClient := gha.getGithubClientFromContext(ctx) // user := ctx.Value(OpenRegistryUserContextKey).(*types.User) // if err := req.Msg.Validate(); err != nil { - // return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + // return nil, connect.NewError(connect.CodeInvalidArgument, err) // } // _, err := githubClient.Actions.DeleteWorkflowRun(ctx, user.Username, req.Msg.GetRepo(), req.Msg.GetRunId()) // if err != nil { - // return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + // return nil, connect.NewError(connect.CodeInvalidArgument, err) // } gha.logger.Debug().Str("procedure", req.Spec().Procedure).Bool("method_not_implemented", true).Send() return nil, - connect_go.NewError( - connect_go.CodeUnimplemented, + connect.NewError( + connect.CodeUnimplemented, fmt.Errorf("job deletion is not supported by GitHub Actions integration"), ) } @@ -114,16 +115,16 @@ func (gha *GitHubActionsServer) DeleteJob( // GetBuildJob implements github_actions_v1connect.GithubActionsBuildServiceHandler func (gha *GitHubActionsServer) GetBuildJob( ctx context.Context, - req *connect_go.Request[v1.GetBuildJobRequest], + req *connect.Request[v1.GetBuildJobRequest], ) ( - *connect_go.Response[v1.GetBuildJobResponse], + *connect.Response[v1.GetBuildJobResponse], error, ) { logEvent := gha.logger.Debug().Str("procedure", req.Spec().Procedure) err := req.Msg.Validate() if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } user := ctx.Value(OpenRegistryUserContextKey).(*types.User) @@ -139,10 +140,10 @@ func (gha *GitHubActionsServer) GetBuildJob( ) if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } - resp := connect_go.NewResponse(&v1.GetBuildJobResponse{ + resp := connect.NewResponse(&v1.GetBuildJobResponse{ // Id: job.GetID(), LogsUrl: job.GetLogsURL(), Status: job.GetStatus(), @@ -161,16 +162,16 @@ func (gha *GitHubActionsServer) GetBuildJob( // ListBuildJobs implements github_actions_v1connect.GithubActionsBuildServiceHandler func (gha *GitHubActionsServer) ListBuildJobs( ctx context.Context, - req *connect_go.Request[v1.ListBuildJobsRequest], + req *connect.Request[v1.ListBuildJobsRequest], ) ( - *connect_go.Response[v1.ListBuildJobsResponse], + *connect.Response[v1.ListBuildJobsResponse], error, ) { logEvent := gha.logger.Debug().Str("procedure", req.Spec().Procedure) err := req.Msg.Validate() if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } user := ctx.Value(OpenRegistryUserContextKey).(*types.User) @@ -183,10 +184,9 @@ func (gha *GitHubActionsServer) ListBuildJobs( ListOptions: github.ListOptions{Page: 0, PerPage: 75}, }, ) - if err != nil { logEvent.Err(err).Any("request_body", req.Msg).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } jobs := []*v1.GetBuildJobResponse{} @@ -210,31 +210,31 @@ func (gha *GitHubActionsServer) ListBuildJobs( } logEvent.Bool("success", true).Send() - return connect_go.NewResponse(&v1.ListBuildJobsResponse{Jobs: jobs}), nil + return connect.NewResponse(&v1.ListBuildJobsResponse{Jobs: jobs}), nil } // StoreJob implements github_actions_v1connect.GithubActionsBuildServiceHandler func (gha *GitHubActionsServer) StoreJob( ctx context.Context, - req *connect_go.Request[v1.StoreJobRequest], -) (*connect_go.Response[v1.StoreJobResponse], error) { + req *connect.Request[v1.StoreJobRequest], +) (*connect.Response[v1.StoreJobResponse], error) { // err := req.Msg.Validate() // if err != nil { - // return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + // return nil, connect.NewError(connect.CodeInvalidArgument, err) // } // // req.Msg.TriggeredAt = timestamppb.New(time.Now()) // if err = gha.store.StoreJob(ctx, req.Msg); err != nil { - // return nil, connect_go.NewError(connect_go.CodeInternal, err) + // return nil, connect.NewError(connect.CodeInternal, err) // } - // return connect_go.NewResponse(&v1.StoreJobResponse{ + // return connect.NewResponse(&v1.StoreJobResponse{ // Message: "job stored successfully", // }), nil gha.logger.Debug().Str("procedure", req.Spec().Procedure).Bool("method_not_implemented", true).Send() - return nil, connect_go.NewError( - connect_go.CodeUnimplemented, + return nil, connect.NewError( + connect.CodeUnimplemented, fmt.Errorf("job storing is not supported by GitHub Actions integration"), ) } @@ -242,9 +242,9 @@ func (gha *GitHubActionsServer) StoreJob( // TriggerBuild implements github_actions_v1connect.GithubActionsBuildServiceHandler func (gha *GitHubActionsServer) TriggerBuild( ctx context.Context, - req *connect_go.Request[v1.TriggerBuildRequest], + req *connect.Request[v1.TriggerBuildRequest], ) ( - *connect_go.Response[v1.TriggerBuildResponse], + *connect.Response[v1.TriggerBuildResponse], error, ) { logEvent := gha.logger.Debug().Str("procedure", req.Spec().Procedure) @@ -253,7 +253,7 @@ func (gha *GitHubActionsServer) TriggerBuild( if err := req.Msg.Validate(); err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } _, err := githubClient.Actions.RerunWorkflowByID( @@ -263,14 +263,13 @@ func (gha *GitHubActionsServer) TriggerBuild( 0, // req.Msg.GetRunId(), ) - if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } logEvent.Bool("success", true).Send() - return connect_go.NewResponse(&v1.TriggerBuildResponse{ + return connect.NewResponse(&v1.TriggerBuildResponse{ Message: "job triggered successfully", }), nil } diff --git a/services/kon/github_actions/v1/server/build_logs.go b/services/kon/github_actions/v1/server/build_logs.go index dcaafebe..6a8abd4c 100644 --- a/services/kon/github_actions/v1/server/build_logs.go +++ b/services/kon/github_actions/v1/server/build_logs.go @@ -1,22 +1,22 @@ package server import ( - "net/url" - "archive/zip" "bytes" "context" "fmt" "net/http" + "net/url" "strconv" "strings" "time" + "connectrpc.com/connect" "github.com/bradleyfalzon/ghinstallation/v2" - connect_go "github.com/bufbuild/connect-go" + "github.com/google/go-github/v56/github" + github_actions_v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" github_impl "github.com/containerish/OpenRegistry/vcs/github" - "github.com/google/go-github/v56/github" ) type WorkflowStep struct { @@ -27,8 +27,8 @@ type WorkflowStep struct { func (ghs *GitHubActionsServer) streamPreviousRunLogs( ctx context.Context, - req *connect_go.Request[github_actions_v1.StreamWorkflowRunLogsRequest], - stream *connect_go.ServerStream[github_actions_v1.StreamWorkflowRunLogsResponse], + req *connect.Request[github_actions_v1.StreamWorkflowRunLogsRequest], + stream *connect.ServerStream[github_actions_v1.StreamWorkflowRunLogsResponse], githubClient *github.Client, ) error { logEvent := ghs.logger.Debug().Str("method", "streamPreviousRunLogs") @@ -44,19 +44,19 @@ func (ghs *GitHubActionsServer) streamPreviousRunLogs( ) if err != nil { logEvent.Err(err).Send() - return connect_go.NewError(connect_go.CodeUnavailable, err) + return connect.NewError(connect.CodeUnavailable, err) } if len(runs.WorkflowRuns) < 1 { errMsg := fmt.Errorf("no github actions run found for this id") logEvent.Err(errMsg).Send() - return connect_go.NewError(connect_go.CodeInvalidArgument, errMsg) + return connect.NewError(connect.CodeInvalidArgument, errMsg) } workflowSteps, err := ghs.getLogsToStream(ctx, githubClient, runs.WorkflowRuns[0].GetLogsURL()) if err != nil { logEvent.Err(err).Send() - return connect_go.NewError(connect_go.CodeInvalidArgument, err) + return connect.NewError(connect.CodeInvalidArgument, err) } for _, step := range workflowSteps { @@ -71,12 +71,12 @@ func (ghs *GitHubActionsServer) streamPreviousRunLogs( func (ghs *GitHubActionsServer) StreamWorkflowRunLogs( ctx context.Context, - req *connect_go.Request[github_actions_v1.StreamWorkflowRunLogsRequest], - stream *connect_go.ServerStream[github_actions_v1.StreamWorkflowRunLogsResponse], + req *connect.Request[github_actions_v1.StreamWorkflowRunLogsRequest], + stream *connect.ServerStream[github_actions_v1.StreamWorkflowRunLogsResponse], ) error { logEvent := ghs.logger.Debug().Str("procedure", req.Spec().Procedure) if err := req.Msg.Validate(); err != nil { - return connect_go.NewError(connect_go.CodeInvalidArgument, err) + return connect.NewError(connect.CodeInvalidArgument, err) } logEvent. @@ -89,8 +89,8 @@ func (ghs *GitHubActionsServer) StreamWorkflowRunLogs( if !ok { errMsg := fmt.Errorf("github app installation id not found for user") logEvent.Err(errMsg).Send() - return connect_go.NewError( - connect_go.CodeInvalidArgument, errMsg, + return connect.NewError( + connect.CodeInvalidArgument, errMsg, ) } @@ -106,7 +106,7 @@ func (ghs *GitHubActionsServer) StreamWorkflowRunLogs( err := ghs.waitForJobToFinish(ctx, githubClient, req, stream) if err != nil { logEvent.Err(err).Send() - return connect_go.NewError(connect_go.CodeInvalidArgument, err) + return connect.NewError(connect.CodeInvalidArgument, err) } delete(ghs.activeLogStreamJobs, ghs.getLogsEventKey(req.Msg)) @@ -119,7 +119,7 @@ func (ghs *GitHubActionsServer) StreamWorkflowRunLogs( if !ok { errMsg := fmt.Errorf("missing GitHub App installation ID") logEvent.Err(errMsg).Send() - return connect_go.NewError(connect_go.CodeInternal, errMsg) + return connect.NewError(connect.CodeInternal, errMsg) } client := ghs.refreshGHClient(githubAppInstallation) @@ -134,17 +134,16 @@ func (ghs *GitHubActionsServer) StreamWorkflowRunLogs( }, }, ) - if err != nil { logEvent.Err(err).Send() - return connect_go.NewError(connect_go.CodeInternal, err) + return connect.NewError(connect.CodeInternal, err) } runID := actionRuns.WorkflowRuns[0].GetID() uri, err := ghs.getWorkflowRunLogsURL(ctx, req.Msg.GetRepoOwner(), req.Msg.GetRepoName(), runID) if err != nil { logEvent.Err(err).Send() - return connect_go.NewError(connect_go.CodeNotFound, err) + return connect.NewError(connect.CodeNotFound, err) } workflowSteps, err := ghs.getLogsToStream(ctx, githubClient, uri.String()) @@ -158,7 +157,6 @@ func (ghs *GitHubActionsServer) StreamWorkflowRunLogs( LogMessage: step.Buf.String(), MsgType: github_actions_v1.StreamWorkflowRunMessageType_STREAM_WORKFLOW_RUN_MESSAGE_TYPE_STEP, }) - } logEvent.Bool("success", true).Send() @@ -220,7 +218,6 @@ func (ghs *GitHubActionsServer) retryGetWorkflowRunLogsURL( } return logsUrl, logsErr - } func (ghs *GitHubActionsServer) getWorkflowRunLogsURL( @@ -236,22 +233,22 @@ func (ghs *GitHubActionsServer) getWorkflowRunLogsURL( func (ghs *GitHubActionsServer) DumpLogs( ctx context.Context, - req *connect_go.Request[github_actions_v1.DumpLogsRequest], + req *connect.Request[github_actions_v1.DumpLogsRequest], ) ( - *connect_go.Response[github_actions_v1.DumpLogsResponse], + *connect.Response[github_actions_v1.DumpLogsResponse], error, ) { logEvent := ghs.logger.Debug().Str("procedure", req.Spec().Procedure) if err := req.Msg.Validate(); err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } ghAppInstallationID, ok := ctx.Value(github_impl.GithubInstallationIDContextKey).(int64) if !ok { errMsg := fmt.Errorf("github app installation id not found for user") logEvent.Err(errMsg).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, errMsg) + return nil, connect.NewError(connect.CodeInvalidArgument, errMsg) } githubClient := ghs.refreshGHClient(ghAppInstallationID) @@ -268,19 +265,19 @@ func (ghs *GitHubActionsServer) DumpLogs( ) if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeUnavailable, err) + return nil, connect.NewError(connect.CodeUnavailable, err) } if len(runs.WorkflowRuns) < 1 { errMsg := fmt.Errorf("no github actions run found for this id") logEvent.Err(errMsg).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, errMsg) + return nil, connect.NewError(connect.CodeInvalidArgument, errMsg) } workflowSteps, err := ghs.getLogsToStream(ctx, githubClient, runs.WorkflowRuns[0].GetLogsURL()) if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } var logs []string for _, step := range workflowSteps { @@ -288,7 +285,7 @@ func (ghs *GitHubActionsServer) DumpLogs( } logEvent.Bool("success", true).Send() - return connect_go.NewResponse(&github_actions_v1.DumpLogsResponse{Logs: logs}), nil + return connect.NewResponse(&github_actions_v1.DumpLogsResponse{Logs: logs}), nil } func (ghs *GitHubActionsServer) getLogsEventKey(job *github_actions_v1.StreamWorkflowRunLogsRequest) string { @@ -312,8 +309,8 @@ func (ghs *GitHubActionsServer) getFileInfo(fi *zip.File) (string, int64) { func (ghs *GitHubActionsServer) waitForJobToFinish( ctx context.Context, githubClient *github.Client, - req *connect_go.Request[github_actions_v1.StreamWorkflowRunLogsRequest], - stream *connect_go.ServerStream[github_actions_v1.StreamWorkflowRunLogsResponse], + req *connect.Request[github_actions_v1.StreamWorkflowRunLogsRequest], + stream *connect.ServerStream[github_actions_v1.StreamWorkflowRunLogsResponse], ) error { now := time.Now() logEvent := ghs.logger.Debug(). @@ -330,7 +327,7 @@ func (ghs *GitHubActionsServer) waitForJobToFinish( ) if err != nil { logEvent.Err(err).Send() - return connect_go.NewError(connect_go.CodeInvalidArgument, err) + return connect.NewError(connect.CodeInvalidArgument, err) } logEvent.Str("status", workflowRun.GetStatus()) diff --git a/services/kon/github_actions/v1/server/build_project.go b/services/kon/github_actions/v1/server/build_project.go index b39f32af..8147aad6 100644 --- a/services/kon/github_actions/v1/server/build_project.go +++ b/services/kon/github_actions/v1/server/build_project.go @@ -3,27 +3,28 @@ package server import ( "context" - connect_go "github.com/bufbuild/connect-go" + "connectrpc.com/connect" + "github.com/google/uuid" + "google.golang.org/protobuf/types/known/timestamppb" + common_v1 "github.com/containerish/OpenRegistry/common/v1" github_actions_v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" "github.com/containerish/OpenRegistry/store/v1/types" - "github.com/google/uuid" - "google.golang.org/protobuf/types/known/timestamppb" ) // CreateProject implements github_actions_v1connect.GitHubActionsProjectServiceHandler func (ghs *GitHubActionsServer) CreateProject( ctx context.Context, - req *connect_go.Request[github_actions_v1.CreateProjectRequest], + req *connect.Request[github_actions_v1.CreateProjectRequest], ) ( - *connect_go.Response[github_actions_v1.CreateProjectResponse], + *connect.Response[github_actions_v1.CreateProjectResponse], error, ) { logEvent := ghs.logger.Debug().Str("procedure", req.Spec().Procedure) err := req.Msg.Validate() if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } req.Msg.Id = &common_v1.UUID{ @@ -32,10 +33,10 @@ func (ghs *GitHubActionsServer) CreateProject( req.Msg.CreatedAt = timestamppb.Now() if err = ghs.store.StoreProject(ctx, req.Msg); err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } - resp := connect_go.NewResponse(&github_actions_v1.CreateProjectResponse{ + resp := connect.NewResponse(&github_actions_v1.CreateProjectResponse{ Message: "project created successfully", Id: req.Msg.GetId(), }) @@ -47,24 +48,24 @@ func (ghs *GitHubActionsServer) CreateProject( // DeleteProject implements github_actions_v1connect.GitHubActionsProjectServiceHandler func (ghs *GitHubActionsServer) DeleteProject( ctx context.Context, - req *connect_go.Request[github_actions_v1.DeleteProjectRequest], + req *connect.Request[github_actions_v1.DeleteProjectRequest], ) ( - *connect_go.Response[github_actions_v1.DeleteProjectResponse], + *connect.Response[github_actions_v1.DeleteProjectResponse], error, ) { logEvent := ghs.logger.Debug().Str("procedure", req.Spec().Procedure) err := req.Msg.Validate() if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } if err = ghs.store.DeleteProject(ctx, req.Msg); err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } - resp := connect_go.NewResponse(&github_actions_v1.DeleteProjectResponse{ + resp := connect.NewResponse(&github_actions_v1.DeleteProjectResponse{ Message: "project deleted successfully", }) @@ -75,32 +76,32 @@ func (ghs *GitHubActionsServer) DeleteProject( // GetProject implements github_actions_v1connect.GitHubActionsProjectServiceHandler func (ghs *GitHubActionsServer) GetProject( ctx context.Context, - req *connect_go.Request[github_actions_v1.GetProjectRequest], + req *connect.Request[github_actions_v1.GetProjectRequest], ) ( - *connect_go.Response[github_actions_v1.GetProjectResponse], + *connect.Response[github_actions_v1.GetProjectResponse], error, ) { logEvent := ghs.logger.Debug().Str("procedure", req.Spec().Procedure) if err := req.Msg.Validate(); err != nil { - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } project, err := ghs.store.GetProject(ctx, req.Msg) if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } logEvent.Bool("success", true).Send() - return connect_go.NewResponse(project), nil + return connect.NewResponse(project), nil } // ListProjects implements github_actions_v1connect.GitHubActionsProjectServiceHandler func (ghs *GitHubActionsServer) ListProjects( ctx context.Context, - req *connect_go.Request[github_actions_v1.ListProjectsRequest], + req *connect.Request[github_actions_v1.ListProjectsRequest], ) ( - *connect_go.Response[github_actions_v1.ListProjectsResponse], + *connect.Response[github_actions_v1.ListProjectsResponse], error, ) { logEvent := ghs.logger.Debug().Str("procedure", req.Spec().Procedure) @@ -108,7 +109,7 @@ func (ghs *GitHubActionsServer) ListProjects( err := req.Msg.Validate() if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInvalidArgument, err) + return nil, connect.NewError(connect.CodeInvalidArgument, err) } req.Msg.OwnerId = &common_v1.UUID{ @@ -118,9 +119,9 @@ func (ghs *GitHubActionsServer) ListProjects( projects, err := ghs.store.ListProjects(ctx, req.Msg) if err != nil { logEvent.Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } logEvent.Bool("success", true).Send() - return connect_go.NewResponse(projects), nil + return connect.NewResponse(projects), nil } diff --git a/services/kon/github_actions/v1/server/github_action_logs.go b/services/kon/github_actions/v1/server/github_action_logs.go index 9a6463ec..547c8fc4 100644 --- a/services/kon/github_actions/v1/server/github_action_logs.go +++ b/services/kon/github_actions/v1/server/github_action_logs.go @@ -9,7 +9,7 @@ import ( "net/http" "sort" - connect_go "github.com/bufbuild/connect-go" + "connectrpc.com/connect" "github.com/google/go-github/v56/github" ) @@ -21,14 +21,14 @@ func (ghs *GitHubActionsServer) getLogsToStream( downloadLogsReq, err := http.NewRequestWithContext(ctx, http.MethodGet, logsURL, nil) if err != nil { ghs.logger.Debug().Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } downloadLogsReq.Header.Set("Accept", "application/json") downloadLogsResp, err := githubClient.BareDo(ctx, downloadLogsReq) if err != nil { ghs.logger.Debug().Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } defer downloadLogsResp.Body.Close() @@ -36,14 +36,14 @@ func (ghs *GitHubActionsServer) getLogsToStream( _, err = io.Copy(&buf, downloadLogsResp.Body) if err != nil { ghs.logger.Debug().Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } reader := bytes.NewReader(buf.Bytes()) zipReader, err := zip.NewReader(reader, int64(buf.Len())) if err != nil { ghs.logger.Debug().Err(err).Send() - return nil, connect_go.NewError(connect_go.CodeInternal, err) + return nil, connect.NewError(connect.CodeInternal, err) } logEvent := ghs.logger.Debug().Int("zip_file_count", len(zipReader.File)) diff --git a/services/kon/github_actions/v1/server/interceptor.go b/services/kon/github_actions/v1/server/interceptor.go index d76fc74f..069aec9f 100644 --- a/services/kon/github_actions/v1/server/interceptor.go +++ b/services/kon/github_actions/v1/server/interceptor.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/bufbuild/connect-go" + "connectrpc.com/connect" "github.com/containerish/OpenRegistry/config" "github.com/containerish/OpenRegistry/store/v1/types" diff --git a/services/kon/github_actions/v1/server/interceptor_helpers.go b/services/kon/github_actions/v1/server/interceptor_helpers.go index 4d3cad0f..331b3392 100644 --- a/services/kon/github_actions/v1/server/interceptor_helpers.go +++ b/services/kon/github_actions/v1/server/interceptor_helpers.go @@ -7,11 +7,12 @@ import ( "net/url" "strings" - "github.com/bufbuild/connect-go" - "github.com/containerish/OpenRegistry/auth" - "github.com/containerish/OpenRegistry/telemetry" + "connectrpc.com/connect" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" + + "github.com/containerish/OpenRegistry/auth" + "github.com/containerish/OpenRegistry/telemetry" ) func getTokenFromReq(req connect.AnyRequest, jwtSigningPubKey *rsa.PublicKey) (uuid.UUID, error) { diff --git a/services/kon/github_actions/v1/server/server.go b/services/kon/github_actions/v1/server/server.go index ded25bf2..b25e66cc 100644 --- a/services/kon/github_actions/v1/server/server.go +++ b/services/kon/github_actions/v1/server/server.go @@ -5,16 +5,17 @@ import ( "net/http" "sync" + "connectrpc.com/connect" "github.com/bradleyfalzon/ghinstallation/v2" - "github.com/bufbuild/connect-go" + "github.com/fatih/color" + "github.com/google/go-github/v56/github" + "github.com/containerish/OpenRegistry/config" github_actions_v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1" connect_v1 "github.com/containerish/OpenRegistry/services/kon/github_actions/v1/github_actions_v1connect" "github.com/containerish/OpenRegistry/store/v1/automation" "github.com/containerish/OpenRegistry/telemetry" "github.com/containerish/OpenRegistry/vcs" - "github.com/fatih/color" - "github.com/google/go-github/v56/github" ) type GitHubActionsServer struct { diff --git a/services/yor/clair/v1/clairconnect/clair.connect.go b/services/yor/clair/v1/clairconnect/clair.connect.go index db62506a..3af942a5 100644 --- a/services/yor/clair/v1/clairconnect/clair.connect.go +++ b/services/yor/clair/v1/clairconnect/clair.connect.go @@ -5,9 +5,9 @@ package clairconnect import ( + connect "connectrpc.com/connect" context "context" errors "errors" - connect_go "github.com/bufbuild/connect-go" v1 "github.com/containerish/OpenRegistry/services/yor/clair/v1" http "net/http" strings "strings" @@ -18,7 +18,7 @@ import ( // generated with a version of connect newer than the one compiled into your binary. You can fix the // problem by either regenerating this code with an older version of connect or updating the connect // version compiled into your binary. -const _ = connect_go.IsAtLeastVersion0_1_0 +const _ = connect.IsAtLeastVersion1_13_0 const ( // ClairServiceName is the fully-qualified name of the ClairService service. @@ -44,11 +44,19 @@ const ( ClairServiceEnableVulnerabilityScanningProcedure = "/services.yor.clair.v1.ClairService/EnableVulnerabilityScanning" ) +// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. +var ( + clairServiceServiceDescriptor = v1.File_services_yor_clair_v1_clair_proto.Services().ByName("ClairService") + clairServiceSubmitManifestToScanMethodDescriptor = clairServiceServiceDescriptor.Methods().ByName("SubmitManifestToScan") + clairServiceGetVulnerabilityReportMethodDescriptor = clairServiceServiceDescriptor.Methods().ByName("GetVulnerabilityReport") + clairServiceEnableVulnerabilityScanningMethodDescriptor = clairServiceServiceDescriptor.Methods().ByName("EnableVulnerabilityScanning") +) + // ClairServiceClient is a client for the services.yor.clair.v1.ClairService service. type ClairServiceClient interface { - SubmitManifestToScan(context.Context, *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) - GetVulnerabilityReport(context.Context, *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) - EnableVulnerabilityScanning(context.Context, *connect_go.Request[v1.EnableVulnerabilityScanningRequest]) (*connect_go.Response[v1.EnableVulnerabilityScanningResponse], error) + SubmitManifestToScan(context.Context, *connect.Request[v1.SubmitManifestToScanRequest]) (*connect.Response[v1.SubmitManifestToScanResponse], error) + GetVulnerabilityReport(context.Context, *connect.Request[v1.GetVulnerabilityReportRequest]) (*connect.Response[v1.GetVulnerabilityReportResponse], error) + EnableVulnerabilityScanning(context.Context, *connect.Request[v1.EnableVulnerabilityScanningRequest]) (*connect.Response[v1.EnableVulnerabilityScanningResponse], error) } // NewClairServiceClient constructs a client for the services.yor.clair.v1.ClairService service. By @@ -58,54 +66,57 @@ type ClairServiceClient interface { // // The URL supplied here should be the base URL for the Connect or gRPC server (for example, // http://api.acme.com or https://acme.com/grpc). -func NewClairServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) ClairServiceClient { +func NewClairServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ClairServiceClient { baseURL = strings.TrimRight(baseURL, "/") return &clairServiceClient{ - submitManifestToScan: connect_go.NewClient[v1.SubmitManifestToScanRequest, v1.SubmitManifestToScanResponse]( + submitManifestToScan: connect.NewClient[v1.SubmitManifestToScanRequest, v1.SubmitManifestToScanResponse]( httpClient, baseURL+ClairServiceSubmitManifestToScanProcedure, - opts..., + connect.WithSchema(clairServiceSubmitManifestToScanMethodDescriptor), + connect.WithClientOptions(opts...), ), - getVulnerabilityReport: connect_go.NewClient[v1.GetVulnerabilityReportRequest, v1.GetVulnerabilityReportResponse]( + getVulnerabilityReport: connect.NewClient[v1.GetVulnerabilityReportRequest, v1.GetVulnerabilityReportResponse]( httpClient, baseURL+ClairServiceGetVulnerabilityReportProcedure, - opts..., + connect.WithSchema(clairServiceGetVulnerabilityReportMethodDescriptor), + connect.WithClientOptions(opts...), ), - enableVulnerabilityScanning: connect_go.NewClient[v1.EnableVulnerabilityScanningRequest, v1.EnableVulnerabilityScanningResponse]( + enableVulnerabilityScanning: connect.NewClient[v1.EnableVulnerabilityScanningRequest, v1.EnableVulnerabilityScanningResponse]( httpClient, baseURL+ClairServiceEnableVulnerabilityScanningProcedure, - opts..., + connect.WithSchema(clairServiceEnableVulnerabilityScanningMethodDescriptor), + connect.WithClientOptions(opts...), ), } } // clairServiceClient implements ClairServiceClient. type clairServiceClient struct { - submitManifestToScan *connect_go.Client[v1.SubmitManifestToScanRequest, v1.SubmitManifestToScanResponse] - getVulnerabilityReport *connect_go.Client[v1.GetVulnerabilityReportRequest, v1.GetVulnerabilityReportResponse] - enableVulnerabilityScanning *connect_go.Client[v1.EnableVulnerabilityScanningRequest, v1.EnableVulnerabilityScanningResponse] + submitManifestToScan *connect.Client[v1.SubmitManifestToScanRequest, v1.SubmitManifestToScanResponse] + getVulnerabilityReport *connect.Client[v1.GetVulnerabilityReportRequest, v1.GetVulnerabilityReportResponse] + enableVulnerabilityScanning *connect.Client[v1.EnableVulnerabilityScanningRequest, v1.EnableVulnerabilityScanningResponse] } // SubmitManifestToScan calls services.yor.clair.v1.ClairService.SubmitManifestToScan. -func (c *clairServiceClient) SubmitManifestToScan(ctx context.Context, req *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) { +func (c *clairServiceClient) SubmitManifestToScan(ctx context.Context, req *connect.Request[v1.SubmitManifestToScanRequest]) (*connect.Response[v1.SubmitManifestToScanResponse], error) { return c.submitManifestToScan.CallUnary(ctx, req) } // GetVulnerabilityReport calls services.yor.clair.v1.ClairService.GetVulnerabilityReport. -func (c *clairServiceClient) GetVulnerabilityReport(ctx context.Context, req *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) { +func (c *clairServiceClient) GetVulnerabilityReport(ctx context.Context, req *connect.Request[v1.GetVulnerabilityReportRequest]) (*connect.Response[v1.GetVulnerabilityReportResponse], error) { return c.getVulnerabilityReport.CallUnary(ctx, req) } // EnableVulnerabilityScanning calls services.yor.clair.v1.ClairService.EnableVulnerabilityScanning. -func (c *clairServiceClient) EnableVulnerabilityScanning(ctx context.Context, req *connect_go.Request[v1.EnableVulnerabilityScanningRequest]) (*connect_go.Response[v1.EnableVulnerabilityScanningResponse], error) { +func (c *clairServiceClient) EnableVulnerabilityScanning(ctx context.Context, req *connect.Request[v1.EnableVulnerabilityScanningRequest]) (*connect.Response[v1.EnableVulnerabilityScanningResponse], error) { return c.enableVulnerabilityScanning.CallUnary(ctx, req) } // ClairServiceHandler is an implementation of the services.yor.clair.v1.ClairService service. type ClairServiceHandler interface { - SubmitManifestToScan(context.Context, *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) - GetVulnerabilityReport(context.Context, *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) - EnableVulnerabilityScanning(context.Context, *connect_go.Request[v1.EnableVulnerabilityScanningRequest]) (*connect_go.Response[v1.EnableVulnerabilityScanningResponse], error) + SubmitManifestToScan(context.Context, *connect.Request[v1.SubmitManifestToScanRequest]) (*connect.Response[v1.SubmitManifestToScanResponse], error) + GetVulnerabilityReport(context.Context, *connect.Request[v1.GetVulnerabilityReportRequest]) (*connect.Response[v1.GetVulnerabilityReportResponse], error) + EnableVulnerabilityScanning(context.Context, *connect.Request[v1.EnableVulnerabilityScanningRequest]) (*connect.Response[v1.EnableVulnerabilityScanningResponse], error) } // NewClairServiceHandler builds an HTTP handler from the service implementation. It returns the @@ -113,21 +124,24 @@ type ClairServiceHandler interface { // // By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf // and JSON codecs. They also support gzip compression. -func NewClairServiceHandler(svc ClairServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { - clairServiceSubmitManifestToScanHandler := connect_go.NewUnaryHandler( +func NewClairServiceHandler(svc ClairServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + clairServiceSubmitManifestToScanHandler := connect.NewUnaryHandler( ClairServiceSubmitManifestToScanProcedure, svc.SubmitManifestToScan, - opts..., + connect.WithSchema(clairServiceSubmitManifestToScanMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - clairServiceGetVulnerabilityReportHandler := connect_go.NewUnaryHandler( + clairServiceGetVulnerabilityReportHandler := connect.NewUnaryHandler( ClairServiceGetVulnerabilityReportProcedure, svc.GetVulnerabilityReport, - opts..., + connect.WithSchema(clairServiceGetVulnerabilityReportMethodDescriptor), + connect.WithHandlerOptions(opts...), ) - clairServiceEnableVulnerabilityScanningHandler := connect_go.NewUnaryHandler( + clairServiceEnableVulnerabilityScanningHandler := connect.NewUnaryHandler( ClairServiceEnableVulnerabilityScanningProcedure, svc.EnableVulnerabilityScanning, - opts..., + connect.WithSchema(clairServiceEnableVulnerabilityScanningMethodDescriptor), + connect.WithHandlerOptions(opts...), ) return "/services.yor.clair.v1.ClairService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { @@ -146,14 +160,14 @@ func NewClairServiceHandler(svc ClairServiceHandler, opts ...connect_go.HandlerO // UnimplementedClairServiceHandler returns CodeUnimplemented from all methods. type UnimplementedClairServiceHandler struct{} -func (UnimplementedClairServiceHandler) SubmitManifestToScan(context.Context, *connect_go.Request[v1.SubmitManifestToScanRequest]) (*connect_go.Response[v1.SubmitManifestToScanResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.SubmitManifestToScan is not implemented")) +func (UnimplementedClairServiceHandler) SubmitManifestToScan(context.Context, *connect.Request[v1.SubmitManifestToScanRequest]) (*connect.Response[v1.SubmitManifestToScanResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.SubmitManifestToScan is not implemented")) } -func (UnimplementedClairServiceHandler) GetVulnerabilityReport(context.Context, *connect_go.Request[v1.GetVulnerabilityReportRequest]) (*connect_go.Response[v1.GetVulnerabilityReportResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.GetVulnerabilityReport is not implemented")) +func (UnimplementedClairServiceHandler) GetVulnerabilityReport(context.Context, *connect.Request[v1.GetVulnerabilityReportRequest]) (*connect.Response[v1.GetVulnerabilityReportResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.GetVulnerabilityReport is not implemented")) } -func (UnimplementedClairServiceHandler) EnableVulnerabilityScanning(context.Context, *connect_go.Request[v1.EnableVulnerabilityScanningRequest]) (*connect_go.Response[v1.EnableVulnerabilityScanningResponse], error) { - return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.EnableVulnerabilityScanning is not implemented")) +func (UnimplementedClairServiceHandler) EnableVulnerabilityScanning(context.Context, *connect.Request[v1.EnableVulnerabilityScanningRequest]) (*connect.Response[v1.EnableVulnerabilityScanningResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("services.yor.clair.v1.ClairService.EnableVulnerabilityScanning is not implemented")) } diff --git a/services/yor/clair/v1/server/clair.go b/services/yor/clair/v1/server/clair.go index 039439d0..fbb3b737 100644 --- a/services/yor/clair/v1/server/clair.go +++ b/services/yor/clair/v1/server/clair.go @@ -8,7 +8,7 @@ import ( "io" "net/http" - "github.com/bufbuild/connect-go" + "connectrpc.com/connect" "github.com/golang-jwt/jwt/v5" "google.golang.org/protobuf/encoding/protojson" diff --git a/services/yor/clair/v1/server/interceptors.go b/services/yor/clair/v1/server/interceptors.go index 899eced5..9a1c54ca 100644 --- a/services/yor/clair/v1/server/interceptors.go +++ b/services/yor/clair/v1/server/interceptors.go @@ -8,11 +8,12 @@ import ( "net/url" "strings" - "github.com/bufbuild/connect-go" - "github.com/containerish/OpenRegistry/auth" - "github.com/containerish/OpenRegistry/store/v1/types" + "connectrpc.com/connect" "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" + + "github.com/containerish/OpenRegistry/auth" + "github.com/containerish/OpenRegistry/store/v1/types" ) // NewJWTInterceptor is a UnaryInterceptorFunc that inspects and tries to parse a JWT from the request. diff --git a/services/yor/clair/v1/server/server.go b/services/yor/clair/v1/server/server.go index 28ab1bf8..e592c30b 100644 --- a/services/yor/clair/v1/server/server.go +++ b/services/yor/clair/v1/server/server.go @@ -6,7 +6,8 @@ import ( "sync" "time" - "github.com/bufbuild/connect-go" + "connectrpc.com/connect" + "github.com/containerish/OpenRegistry/config" connect_v1 "github.com/containerish/OpenRegistry/services/yor/clair/v1/clairconnect" "github.com/containerish/OpenRegistry/store/v1/types"