mirror of
https://github.com/rocky-linux/peridot.git
synced 2024-12-24 03:28:28 +00:00
commit
3b19040cfd
12
.bazelrc
12
.bazelrc
@ -13,11 +13,17 @@ build:inmemory --experimental_inmemory_dotd_files
|
|||||||
|
|
||||||
# Minimize what is downloaded
|
# Minimize what is downloaded
|
||||||
build:toplevel --config=inmemory
|
build:toplevel --config=inmemory
|
||||||
build:toplevel --experimental_remote_download_outputs=toplevel
|
build:toplevel --remote_download_outputs=toplevel
|
||||||
|
|
||||||
build:remote --config=toplevel
|
build:remote --config=toplevel
|
||||||
build:remote --google_credentials=/tmp/credentials.json
|
build:remote --remote_cache=grpc://buildcache.default.svc.cluster.local:9092
|
||||||
build:remote --remote_cache=https://storage.googleapis.com/resf-temporary-bazel-cache
|
build:remote --experimental_remote_downloader=grpc://buildcache.default.svc.cluster.local:9092
|
||||||
|
build:remote --noremote_upload_local_results
|
||||||
|
build:remote --remote_timeout=3600
|
||||||
|
build:remote --bes_results_url=https://bz.build.resf.org/invocation/
|
||||||
|
build:remote --bes_backend=grpc://buildbuddy-grpc.default.svc.cluster.local:1985
|
||||||
run:remote --experimental_remote_download_outputs=all --noexperimental_inmemory_jdeps_files --noexperimental_inmemory_dotd_files
|
run:remote --experimental_remote_download_outputs=all --noexperimental_inmemory_jdeps_files --noexperimental_inmemory_dotd_files
|
||||||
|
|
||||||
|
common:ci --config=remote
|
||||||
|
|
||||||
build --stamp=true
|
build --stamp=true
|
||||||
|
6
.envrc.prod.mustafarocky
Normal file
6
.envrc.prod.mustafarocky
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
unset STABLE_LOCAL_ENVIRONMENT STABLE_OCI_REGISTRY STABLE_OCI_REGISTRY_REPO STABLE_OCI_REGISTRY_NO_NESTED_SUPPORT_IN_2022_SHAME_ON_YOU_AWS STABLE_SITE
|
||||||
|
|
||||||
|
export STABLE_STAGE="-prod"
|
||||||
|
export STABLE_REGISTRY_SECRET="none"
|
||||||
|
export STABLE_OCI_REGISTRY="docker.io"
|
||||||
|
export STABLE_OCI_REGISTRY_REPO="mustafarocky"
|
@ -6,8 +6,7 @@ __Other components pending__
|
|||||||
|
|
||||||
* publisher - `Composer for Peridot (currently only includes legacy mode)`
|
* publisher - `Composer for Peridot (currently only includes legacy mode)`
|
||||||
* peridot - `Modern build system`
|
* peridot - `Modern build system`
|
||||||
* secparse - `Errata mirroring and publishing platform`
|
* apollo - `Errata mirroring and publishing platform`
|
||||||
* ui - `Product Errata UI`
|
|
||||||
* utils - `Common utilities`
|
* utils - `Common utilities`
|
||||||
* modulemd - `Modulemd parser in Go`
|
* modulemd - `Modulemd parser in Go`
|
||||||
|
|
||||||
@ -50,6 +49,6 @@ For best experience use IntelliJ+Bazel but `govendor` creates structure that is
|
|||||||
#### Vendor Go dependencies
|
#### Vendor Go dependencies
|
||||||
`./hack/govendor`
|
`./hack/govendor`
|
||||||
#### Run UI in development mode
|
#### Run UI in development mode
|
||||||
`ibazel run //TARGET:TARGET.server` - example: `ibazel run //secparse/ui:secparse.server`
|
`ibazel run //TARGET:TARGET.server` - example: `ibazel run //apollo/ui:apollo.server`
|
||||||
#### Find UI server targets
|
#### Find UI server targets
|
||||||
`bazel query 'attr(tags, "byc_frontend_server", //...)'`
|
`bazel query 'attr(tags, "byc_frontend_server", //...)'`
|
||||||
|
21
apollo/cmd/apollo/BUILD.bazel
Normal file
21
apollo/cmd/apollo/BUILD.bazel
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "apollo_lib",
|
||||||
|
srcs = ["main.go"],
|
||||||
|
importpath = "peridot.resf.org/apollo/cmd/apollo",
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
deps = [
|
||||||
|
"//apollo/db/connector",
|
||||||
|
"//apollo/impl/v1:impl",
|
||||||
|
"//utils",
|
||||||
|
"//vendor/github.com/sirupsen/logrus",
|
||||||
|
"//vendor/github.com/spf13/cobra",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "apollo",
|
||||||
|
embed = [":apollo_lib"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
19
apollo/cmd/apollo/ci/BUILD.bazel
Normal file
19
apollo/cmd/apollo/ci/BUILD.bazel
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
load("//rules_byc:defs.bzl", "BYCDEPLOY_OUTS_MIGRATE", "container", "peridot_k8s")
|
||||||
|
|
||||||
|
container(
|
||||||
|
base = "//bases/bazel/go",
|
||||||
|
files = [
|
||||||
|
"//apollo/cmd/apollo",
|
||||||
|
],
|
||||||
|
image_name = "apollo",
|
||||||
|
tars_to_layer = [
|
||||||
|
"//apollo/migrate",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
peridot_k8s(
|
||||||
|
name = "apollo",
|
||||||
|
src = "deploy.jsonnet",
|
||||||
|
outs = BYCDEPLOY_OUTS_MIGRATE,
|
||||||
|
deps = ["//ci"],
|
||||||
|
)
|
48
apollo/cmd/apollo/ci/deploy.jsonnet
Normal file
48
apollo/cmd/apollo/ci/deploy.jsonnet
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
local bycdeploy = import 'ci/bycdeploy.jsonnet';
|
||||||
|
local db = import 'ci/db.jsonnet';
|
||||||
|
local kubernetes = import 'ci/kubernetes.jsonnet';
|
||||||
|
local temporal = import 'ci/temporal.jsonnet';
|
||||||
|
local utils = import 'ci/utils.jsonnet';
|
||||||
|
|
||||||
|
bycdeploy.new({
|
||||||
|
name: 'apollo',
|
||||||
|
replicas: 1,
|
||||||
|
dbname: 'apollo',
|
||||||
|
backend: true,
|
||||||
|
migrate: true,
|
||||||
|
legacyDb: true,
|
||||||
|
command: '/bundle/apollo',
|
||||||
|
image: kubernetes.tag('apollo'),
|
||||||
|
tag: kubernetes.version,
|
||||||
|
dsn: {
|
||||||
|
name: 'APOLLO_DATABASE_URL',
|
||||||
|
value: db.dsn_legacy('apollo'),
|
||||||
|
},
|
||||||
|
requests: if kubernetes.prod() then {
|
||||||
|
cpu: '0.5',
|
||||||
|
memory: '512M',
|
||||||
|
},
|
||||||
|
ports: [
|
||||||
|
{
|
||||||
|
name: 'http',
|
||||||
|
containerPort: 9100,
|
||||||
|
protocol: 'TCP',
|
||||||
|
expose: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'grpc',
|
||||||
|
containerPort: 9101,
|
||||||
|
protocol: 'TCP',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
health: {
|
||||||
|
port: 9100,
|
||||||
|
},
|
||||||
|
env: [
|
||||||
|
{
|
||||||
|
name: 'APOLLO_PRODUCTION',
|
||||||
|
value: if kubernetes.dev() then 'false' else 'true',
|
||||||
|
},
|
||||||
|
$.dsn,
|
||||||
|
] + temporal.kube_env('APOLLO'),
|
||||||
|
})
|
@ -33,30 +33,30 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"peridot.resf.org/secparse/db/connector"
|
apolloconnector "peridot.resf.org/apollo/db/connector"
|
||||||
"peridot.resf.org/secparse/impl"
|
apolloimpl "peridot.resf.org/apollo/impl/v1"
|
||||||
"peridot.resf.org/utils"
|
"peridot.resf.org/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var root = &cobra.Command{
|
var root = &cobra.Command{
|
||||||
Use: "secparse",
|
Use: "apollo",
|
||||||
Run: mn,
|
Run: mn,
|
||||||
}
|
}
|
||||||
|
|
||||||
var cnf = utils.NewFlagConfig()
|
var cnf = utils.NewFlagConfig()
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cnf.DefaultPort = 9008
|
cnf.DefaultPort = 9100
|
||||||
|
|
||||||
dname := "secparse"
|
cnf.DatabaseName = utils.Pointer[string]("apollo")
|
||||||
cnf.DatabaseName = &dname
|
cnf.Name = *cnf.DatabaseName
|
||||||
cnf.Name = "secparse"
|
|
||||||
|
|
||||||
|
root.PersistentFlags().String("homepage", "https://errata.build.resf.org", "Frontend root URL")
|
||||||
utils.AddFlags(root.PersistentFlags(), cnf)
|
utils.AddFlags(root.PersistentFlags(), cnf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mn(_ *cobra.Command, _ []string) {
|
func mn(_ *cobra.Command, _ []string) {
|
||||||
impl.NewServer(connector.MustAuto()).Run()
|
apolloimpl.NewServer(apolloconnector.MustAuto()).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
24
apollo/cmd/apollostarter/BUILD.bazel
Normal file
24
apollo/cmd/apollostarter/BUILD.bazel
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "apollostarter_lib",
|
||||||
|
srcs = ["main.go"],
|
||||||
|
importpath = "peridot.resf.org/apollo/cmd/apollostarter",
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
deps = [
|
||||||
|
"//apollo/db/connector",
|
||||||
|
"//apollo/worker",
|
||||||
|
"//proto:common",
|
||||||
|
"//temporalutils",
|
||||||
|
"//utils",
|
||||||
|
"//vendor/github.com/sirupsen/logrus",
|
||||||
|
"//vendor/github.com/spf13/cobra",
|
||||||
|
"//vendor/go.temporal.io/sdk/client",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "apollostarter",
|
||||||
|
embed = [":apollostarter_lib"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
18
apollo/cmd/apollostarter/ci/BUILD.bazel
Normal file
18
apollo/cmd/apollostarter/ci/BUILD.bazel
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
load("//rules_byc:defs.bzl", "BYCDEPLOY_OUTS_MIGRATE", "container", "peridot_k8s")
|
||||||
|
|
||||||
|
container(
|
||||||
|
base = "//bases/bazel/go",
|
||||||
|
files = [
|
||||||
|
"//apollo/cmd/apollostarter",
|
||||||
|
],
|
||||||
|
image_name = "apollostarter",
|
||||||
|
)
|
||||||
|
|
||||||
|
peridot_k8s(
|
||||||
|
name = "apollostarter",
|
||||||
|
src = "deploy.jsonnet",
|
||||||
|
outs = BYCDEPLOY_OUTS_MIGRATE,
|
||||||
|
deps = [
|
||||||
|
"//ci",
|
||||||
|
],
|
||||||
|
)
|
46
apollo/cmd/apollostarter/ci/deploy.jsonnet
Normal file
46
apollo/cmd/apollostarter/ci/deploy.jsonnet
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
local bycdeploy = import 'ci/bycdeploy.jsonnet';
|
||||||
|
local db = import 'ci/db.jsonnet';
|
||||||
|
local kubernetes = import 'ci/kubernetes.jsonnet';
|
||||||
|
local temporal = import 'ci/temporal.jsonnet';
|
||||||
|
local utils = import 'ci/utils.jsonnet';
|
||||||
|
|
||||||
|
local site = std.extVar('site');
|
||||||
|
|
||||||
|
bycdeploy.new({
|
||||||
|
name: 'apollostarter',
|
||||||
|
replicas: 1,
|
||||||
|
dbname: 'apollo',
|
||||||
|
backend: true,
|
||||||
|
migrate: true,
|
||||||
|
migrate_command: ['/bin/sh'],
|
||||||
|
migrate_args: ['-c', 'exit 0'],
|
||||||
|
legacyDb: true,
|
||||||
|
command: '/bundle/apollostarter',
|
||||||
|
image: kubernetes.tag('apollostarter'),
|
||||||
|
tag: kubernetes.version,
|
||||||
|
dsn: {
|
||||||
|
name: 'APOLLOSTARTER_DATABASE_URL',
|
||||||
|
value: db.dsn_legacy('apollo', false, 'apollostarter'),
|
||||||
|
},
|
||||||
|
requests: if kubernetes.prod() then {
|
||||||
|
cpu: '1',
|
||||||
|
memory: '2G',
|
||||||
|
},
|
||||||
|
ports: [
|
||||||
|
{
|
||||||
|
name: 'http',
|
||||||
|
containerPort: 31209,
|
||||||
|
protocol: 'TCP',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
health: {
|
||||||
|
port: 31209,
|
||||||
|
},
|
||||||
|
env: [
|
||||||
|
{
|
||||||
|
name: 'APOLLOSTARTER_PRODUCTION',
|
||||||
|
value: if kubernetes.dev() then 'false' else 'true',
|
||||||
|
},
|
||||||
|
$.dsn,
|
||||||
|
] + temporal.kube_env('APOLLOSTARTER'),
|
||||||
|
})
|
153
apollo/cmd/apollostarter/main.go
Normal file
153
apollo/cmd/apollostarter/main.go
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
// Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
|
||||||
|
// Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
|
||||||
|
// Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
// may be used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"go.temporal.io/sdk/client"
|
||||||
|
"log"
|
||||||
|
apolloconnector "peridot.resf.org/apollo/db/connector"
|
||||||
|
"peridot.resf.org/apollo/worker"
|
||||||
|
commonpb "peridot.resf.org/common"
|
||||||
|
"peridot.resf.org/temporalutils"
|
||||||
|
"peridot.resf.org/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var root = &cobra.Command{
|
||||||
|
Use: "apollostarter",
|
||||||
|
Run: mn,
|
||||||
|
}
|
||||||
|
|
||||||
|
var cnf = utils.NewFlagConfig()
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cnf.DefaultPort = 31209
|
||||||
|
|
||||||
|
cnf.DatabaseName = utils.Pointer[string]("apollo")
|
||||||
|
cnf.Name = "apollostarter"
|
||||||
|
|
||||||
|
temporalutils.AddFlags(root.PersistentFlags())
|
||||||
|
utils.AddFlags(root.PersistentFlags(), cnf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mn(_ *cobra.Command, _ []string) {
|
||||||
|
c, err := temporalutils.NewClient(client.Options{})
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalln("unable to create Temporal client", err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
db := apolloconnector.MustAuto()
|
||||||
|
|
||||||
|
w, err := worker.NewWorker(&worker.NewWorkerInput{
|
||||||
|
Temporal: c,
|
||||||
|
Database: db,
|
||||||
|
TaskQueue: "apollo-v1-main-queue",
|
||||||
|
})
|
||||||
|
defer w.Client.Close()
|
||||||
|
|
||||||
|
// Poll Red Hat for new CVEs and advisories every two hours
|
||||||
|
cveWfOpts := client.StartWorkflowOptions{
|
||||||
|
ID: "cron_cve_mirror",
|
||||||
|
TaskQueue: w.TaskQueue,
|
||||||
|
CronSchedule: "0 */2 * * *",
|
||||||
|
}
|
||||||
|
_, err = w.Client.ExecuteWorkflow(context.Background(), cveWfOpts, w.WorkflowController.PollRedHatCVEsWorkflow)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to start cve workflow: %v", err)
|
||||||
|
}
|
||||||
|
errataWfOpts := client.StartWorkflowOptions{
|
||||||
|
ID: "cron_errata_mirror",
|
||||||
|
TaskQueue: w.TaskQueue,
|
||||||
|
CronSchedule: "0 */2 * * *",
|
||||||
|
}
|
||||||
|
_, err = w.Client.ExecuteWorkflow(context.Background(), errataWfOpts, w.WorkflowController.PollRedHatErrataWorkflow)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to start errata workflow: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Poll unresolved CVE status and update every hour
|
||||||
|
cveStatusWfOpts := client.StartWorkflowOptions{
|
||||||
|
ID: "cron_cve_status",
|
||||||
|
TaskQueue: w.TaskQueue,
|
||||||
|
CronSchedule: "0 */1 * * *",
|
||||||
|
}
|
||||||
|
_, err = w.Client.ExecuteWorkflow(context.Background(), cveStatusWfOpts, w.WorkflowController.UpdateCVEStateWorkflow)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to start cve status workflow: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if CVE is fixed downstream every 10 minutes
|
||||||
|
cveDownstreamWfOpts := client.StartWorkflowOptions{
|
||||||
|
ID: "cron_cve_downstream",
|
||||||
|
TaskQueue: w.TaskQueue,
|
||||||
|
CronSchedule: "*/10 * * * *",
|
||||||
|
}
|
||||||
|
_, err = w.Client.ExecuteWorkflow(context.Background(), cveDownstreamWfOpts, w.WorkflowController.DownstreamCVECheckWorkflow)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to start cve downstream workflow: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto create advisory for fixed CVEs every 30 minutes
|
||||||
|
cveAdvisoryWfOpts := client.StartWorkflowOptions{
|
||||||
|
ID: "cron_cve_advisory",
|
||||||
|
TaskQueue: w.TaskQueue,
|
||||||
|
CronSchedule: "*/10 * * * *",
|
||||||
|
}
|
||||||
|
_, err = w.Client.ExecuteWorkflow(context.Background(), cveAdvisoryWfOpts, w.WorkflowController.AutoCreateAdvisoryWorkflow)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to start cve advisory workflow: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// only added so we get a health endpoint
|
||||||
|
s := utils.NewGRPCServer(
|
||||||
|
nil,
|
||||||
|
func(r *utils.Register) {
|
||||||
|
err := commonpb.RegisterHealthCheckServiceHandlerFromEndpoint(r.Context, r.Mux, r.Endpoint, r.Options)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("could not register health service: %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
func(r *utils.RegisterServer) {
|
||||||
|
commonpb.RegisterHealthCheckServiceServer(r.Server, &utils.HealthServer{})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
s.WaitGroup.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
utils.Main()
|
||||||
|
if err := root.Execute(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
27
apollo/cmd/apolloworker/BUILD.bazel
Normal file
27
apollo/cmd/apolloworker/BUILD.bazel
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "apolloworker_lib",
|
||||||
|
srcs = ["main.go"],
|
||||||
|
importpath = "peridot.resf.org/apollo/cmd/apolloworker",
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
deps = [
|
||||||
|
"//apollo/db/connector",
|
||||||
|
"//apollo/rherrata",
|
||||||
|
"//apollo/rhsecurity",
|
||||||
|
"//apollo/worker",
|
||||||
|
"//apollo/workflow",
|
||||||
|
"//proto:common",
|
||||||
|
"//temporalutils",
|
||||||
|
"//utils",
|
||||||
|
"//vendor/github.com/sirupsen/logrus",
|
||||||
|
"//vendor/github.com/spf13/cobra",
|
||||||
|
"//vendor/go.temporal.io/sdk/client",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "apolloworker",
|
||||||
|
embed = [":apolloworker_lib"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
18
apollo/cmd/apolloworker/ci/BUILD.bazel
Normal file
18
apollo/cmd/apolloworker/ci/BUILD.bazel
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
load("//rules_byc:defs.bzl", "BYCDEPLOY_OUTS_MIGRATE", "container", "peridot_k8s")
|
||||||
|
|
||||||
|
container(
|
||||||
|
base = "//bases/bazel/go",
|
||||||
|
files = [
|
||||||
|
"//apollo/cmd/apolloworker",
|
||||||
|
],
|
||||||
|
image_name = "apolloworker",
|
||||||
|
)
|
||||||
|
|
||||||
|
peridot_k8s(
|
||||||
|
name = "apolloworker",
|
||||||
|
src = "deploy.jsonnet",
|
||||||
|
outs = BYCDEPLOY_OUTS_MIGRATE,
|
||||||
|
deps = [
|
||||||
|
"//ci",
|
||||||
|
],
|
||||||
|
)
|
46
apollo/cmd/apolloworker/ci/deploy.jsonnet
Normal file
46
apollo/cmd/apolloworker/ci/deploy.jsonnet
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
local bycdeploy = import 'ci/bycdeploy.jsonnet';
|
||||||
|
local db = import 'ci/db.jsonnet';
|
||||||
|
local kubernetes = import 'ci/kubernetes.jsonnet';
|
||||||
|
local temporal = import 'ci/temporal.jsonnet';
|
||||||
|
local utils = import 'ci/utils.jsonnet';
|
||||||
|
|
||||||
|
local site = std.extVar('site');
|
||||||
|
|
||||||
|
bycdeploy.new({
|
||||||
|
name: 'apolloworker',
|
||||||
|
replicas: 1,
|
||||||
|
dbname: 'apollo',
|
||||||
|
backend: true,
|
||||||
|
migrate: true,
|
||||||
|
migrate_command: ['/bin/sh'],
|
||||||
|
migrate_args: ['-c', 'exit 0'],
|
||||||
|
legacyDb: true,
|
||||||
|
command: '/bundle/apolloworker',
|
||||||
|
image: kubernetes.tag('apolloworker'),
|
||||||
|
tag: kubernetes.version,
|
||||||
|
dsn: {
|
||||||
|
name: 'APOLLOWORKER_DATABASE_URL',
|
||||||
|
value: db.dsn_legacy('apollo', false, 'apolloworker'),
|
||||||
|
},
|
||||||
|
requests: if kubernetes.prod() then {
|
||||||
|
cpu: '1',
|
||||||
|
memory: '2G',
|
||||||
|
},
|
||||||
|
ports: [
|
||||||
|
{
|
||||||
|
name: 'http',
|
||||||
|
containerPort: 29209,
|
||||||
|
protocol: 'TCP',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
health: {
|
||||||
|
port: 29209,
|
||||||
|
},
|
||||||
|
env: [
|
||||||
|
{
|
||||||
|
name: 'APOLLOWORKER_PRODUCTION',
|
||||||
|
value: if kubernetes.dev() then 'false' else 'true',
|
||||||
|
},
|
||||||
|
$.dsn,
|
||||||
|
] + temporal.kube_env('APOLLOWORKER'),
|
||||||
|
})
|
143
apollo/cmd/apolloworker/main.go
Normal file
143
apollo/cmd/apolloworker/main.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
// Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
|
||||||
|
// Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
|
||||||
|
// Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
// may be used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"go.temporal.io/sdk/client"
|
||||||
|
"log"
|
||||||
|
apolloconnector "peridot.resf.org/apollo/db/connector"
|
||||||
|
"peridot.resf.org/apollo/rherrata"
|
||||||
|
"peridot.resf.org/apollo/rhsecurity"
|
||||||
|
"peridot.resf.org/apollo/worker"
|
||||||
|
"peridot.resf.org/apollo/workflow"
|
||||||
|
commonpb "peridot.resf.org/common"
|
||||||
|
"peridot.resf.org/temporalutils"
|
||||||
|
"peridot.resf.org/utils"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var root = &cobra.Command{
|
||||||
|
Use: "apolloworker",
|
||||||
|
Run: mn,
|
||||||
|
}
|
||||||
|
|
||||||
|
var cnf = utils.NewFlagConfig()
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cnf.DefaultPort = 29209
|
||||||
|
|
||||||
|
cnf.DatabaseName = utils.Pointer[string]("apollo")
|
||||||
|
cnf.Name = "apolloworker"
|
||||||
|
|
||||||
|
pflags := root.PersistentFlags()
|
||||||
|
pflags.String("vendor", "Rocky Enterprise Software Foundation", "Vendor name that is publishing the advisories")
|
||||||
|
|
||||||
|
temporalutils.AddFlags(root.PersistentFlags())
|
||||||
|
utils.AddFlags(root.PersistentFlags(), cnf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mn(_ *cobra.Command, _ []string) {
|
||||||
|
c, err := temporalutils.NewClient(client.Options{})
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalln("unable to create Temporal client", err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
db := apolloconnector.MustAuto()
|
||||||
|
|
||||||
|
options := []workflow.Option{
|
||||||
|
workflow.WithSecurityAPI(rhsecurity.NewAPIClient(rhsecurity.NewConfiguration()).DefaultApi),
|
||||||
|
workflow.WithErrataAPI(rherrata.NewClient()),
|
||||||
|
}
|
||||||
|
|
||||||
|
w, err := worker.NewWorker(
|
||||||
|
&worker.NewWorkerInput{
|
||||||
|
Temporal: c,
|
||||||
|
Database: db,
|
||||||
|
TaskQueue: "apollo-v1-main-queue",
|
||||||
|
},
|
||||||
|
options...,
|
||||||
|
)
|
||||||
|
defer w.Client.Close()
|
||||||
|
|
||||||
|
w.Worker.RegisterWorkflow(w.WorkflowController.AutoCreateAdvisoryWorkflow)
|
||||||
|
w.Worker.RegisterWorkflow(w.WorkflowController.DownstreamCVECheckWorkflow)
|
||||||
|
w.Worker.RegisterWorkflow(w.WorkflowController.PollRedHatCVEsWorkflow)
|
||||||
|
w.Worker.RegisterWorkflow(w.WorkflowController.PollRedHatErrataWorkflow)
|
||||||
|
w.Worker.RegisterWorkflow(w.WorkflowController.UpdateCVEStateWorkflow)
|
||||||
|
|
||||||
|
w.Worker.RegisterActivity(w.WorkflowController.AutoCreateAdvisoryActivity)
|
||||||
|
w.Worker.RegisterActivity(w.WorkflowController.GetAllShortCodesActivity)
|
||||||
|
w.Worker.RegisterActivity(w.WorkflowController.DownstreamCVECheckActivity)
|
||||||
|
w.Worker.RegisterActivity(w.WorkflowController.PollCVEProcessShortCodeActivity)
|
||||||
|
w.Worker.RegisterActivity(w.WorkflowController.ProcessRedHatErrataShortCodeActivity)
|
||||||
|
w.Worker.RegisterActivity(w.WorkflowController.UpdateCVEStateActivity)
|
||||||
|
|
||||||
|
w.Worker.RegisterWorkflow(w.WorkflowController.CollectCVEDataWorkflow)
|
||||||
|
w.Worker.RegisterActivity(w.WorkflowController.CollectCVEDataActivity)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
w.Run()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
// only added so we get a health endpoint
|
||||||
|
s := utils.NewGRPCServer(
|
||||||
|
nil,
|
||||||
|
func(r *utils.Register) {
|
||||||
|
err := commonpb.RegisterHealthCheckServiceHandlerFromEndpoint(r.Context, r.Mux, r.Endpoint, r.Options)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("could not register health service: %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
func(r *utils.RegisterServer) {
|
||||||
|
commonpb.RegisterHealthCheckServiceServer(r.Server, &utils.HealthServer{})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
s.WaitGroup.Wait()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
utils.Main()
|
||||||
|
if err := root.Execute(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
@ -6,13 +6,12 @@ go_library(
|
|||||||
"convert.go",
|
"convert.go",
|
||||||
"db.go",
|
"db.go",
|
||||||
],
|
],
|
||||||
importpath = "peridot.resf.org/secparse/db",
|
importpath = "peridot.resf.org/apollo/db",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//secparse/admin/proto/v1:proto",
|
"//apollo/proto/v1:pb",
|
||||||
"//secparse/proto/v1:proto",
|
|
||||||
"//secparse/rpmutils",
|
|
||||||
"//utils",
|
"//utils",
|
||||||
|
"//vendor/github.com/jmoiron/sqlx/types",
|
||||||
"//vendor/github.com/lib/pq",
|
"//vendor/github.com/lib/pq",
|
||||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||||
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
|
"@org_golang_google_protobuf//types/known/wrapperspb:go_default_library",
|
@ -3,11 +3,11 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||||||
go_library(
|
go_library(
|
||||||
name = "connector",
|
name = "connector",
|
||||||
srcs = ["connector.go"],
|
srcs = ["connector.go"],
|
||||||
importpath = "peridot.resf.org/secparse/db/connector",
|
importpath = "peridot.resf.org/apollo/db/connector",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//secparse/db",
|
"//apollo/db",
|
||||||
"//secparse/db/psql",
|
"//apollo/db/psql",
|
||||||
"//utils",
|
"//utils",
|
||||||
"//vendor/github.com/sirupsen/logrus",
|
"//vendor/github.com/sirupsen/logrus",
|
||||||
],
|
],
|
@ -28,21 +28,21 @@
|
|||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package connector
|
package apolloconnector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"peridot.resf.org/secparse/db"
|
apollodb "peridot.resf.org/apollo/db"
|
||||||
"peridot.resf.org/secparse/db/psql"
|
apollopsql "peridot.resf.org/apollo/db/psql"
|
||||||
"peridot.resf.org/utils"
|
"peridot.resf.org/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MustAuto automatically returns the correct access interface or fatally fails
|
// MustAuto automatically returns the correct access interface or fatally fails
|
||||||
func MustAuto() db.Access {
|
func MustAuto() apollodb.Access {
|
||||||
dbType := utils.GetDbType()
|
dbType := utils.GetDbType()
|
||||||
switch dbType {
|
switch dbType {
|
||||||
case utils.DbPostgres:
|
case utils.DbPostgres:
|
||||||
return psql.New()
|
return apollopsql.New()
|
||||||
default:
|
default:
|
||||||
logrus.Fatal("invalid database url supplied")
|
logrus.Fatal("invalid database url supplied")
|
||||||
return nil
|
return nil
|
@ -28,21 +28,19 @@
|
|||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package db
|
package apollodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||||
secparseadminpb "peridot.resf.org/secparse/admin/proto/v1"
|
apollopb "peridot.resf.org/apollo/pb"
|
||||||
secparsepb "peridot.resf.org/secparse/proto/v1"
|
"strings"
|
||||||
"peridot.resf.org/secparse/rpmutils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func DTOShortCodeToPB(sc *ShortCode) *secparseadminpb.ShortCode {
|
func DTOShortCodeToPB(sc *ShortCode) *apollopb.ShortCode {
|
||||||
ret := &secparseadminpb.ShortCode{
|
ret := &apollopb.ShortCode{
|
||||||
Code: sc.Code,
|
Code: sc.Code,
|
||||||
Mode: secparseadminpb.ShortCodeMode(sc.Mode),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if sc.ArchivedAt.Valid {
|
if sc.ArchivedAt.Valid {
|
||||||
@ -52,8 +50,8 @@ func DTOShortCodeToPB(sc *ShortCode) *secparseadminpb.ShortCode {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func DTOListShortCodesToPB(scs []*ShortCode) []*secparseadminpb.ShortCode {
|
func DTOListShortCodesToPB(scs []*ShortCode) []*apollopb.ShortCode {
|
||||||
var ret []*secparseadminpb.ShortCode
|
var ret []*apollopb.ShortCode
|
||||||
|
|
||||||
for _, v := range scs {
|
for _, v := range scs {
|
||||||
ret = append(ret, DTOShortCodeToPB(v))
|
ret = append(ret, DTOShortCodeToPB(v))
|
||||||
@ -62,16 +60,16 @@ func DTOListShortCodesToPB(scs []*ShortCode) []*secparseadminpb.ShortCode {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func DTOAdvisoryToPB(sc *Advisory) *secparsepb.Advisory {
|
func DTOAdvisoryToPB(sc *Advisory) *apollopb.Advisory {
|
||||||
var errataType string
|
var errataType string
|
||||||
switch secparsepb.Advisory_Type(sc.Type) {
|
switch apollopb.Advisory_Type(sc.Type) {
|
||||||
case secparsepb.Advisory_Security:
|
case apollopb.Advisory_TYPE_SECURITY:
|
||||||
errataType = "SA"
|
errataType = "SA"
|
||||||
break
|
break
|
||||||
case secparsepb.Advisory_BugFix:
|
case apollopb.Advisory_TYPE_BUGFIX:
|
||||||
errataType = "BA"
|
errataType = "BA"
|
||||||
break
|
break
|
||||||
case secparsepb.Advisory_Enhancement:
|
case apollopb.Advisory_TYPE_ENHANCEMENT:
|
||||||
errataType = "EA"
|
errataType = "EA"
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@ -84,34 +82,67 @@ func DTOAdvisoryToPB(sc *Advisory) *secparsepb.Advisory {
|
|||||||
publishedAt = timestamppb.New(sc.PublishedAt.Time)
|
publishedAt = timestamppb.New(sc.PublishedAt.Time)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := &secparsepb.Advisory{
|
ret := &apollopb.Advisory{
|
||||||
Type: secparsepb.Advisory_Type(sc.Type),
|
Type: apollopb.Advisory_Type(sc.Type),
|
||||||
ShortCode: sc.ShortCodeCode,
|
ShortCode: sc.ShortCodeCode,
|
||||||
Name: fmt.Sprintf("%s%s-%d:%d", sc.ShortCodeCode, errataType, sc.Year, sc.Num),
|
Name: fmt.Sprintf("%s%s-%d:%d", sc.ShortCodeCode, errataType, sc.Year, sc.Num),
|
||||||
Synopsis: sc.Synopsis,
|
Synopsis: sc.Synopsis,
|
||||||
Severity: secparsepb.Advisory_Severity(sc.Severity),
|
Severity: apollopb.Advisory_Severity(sc.Severity),
|
||||||
Topic: sc.Topic,
|
Topic: sc.Topic,
|
||||||
Description: sc.Description,
|
Description: sc.Description,
|
||||||
AffectedProducts: sc.AffectedProducts,
|
AffectedProducts: sc.AffectedProducts,
|
||||||
Fixes: sc.Fixes,
|
Fixes: nil,
|
||||||
Cves: sc.Cves,
|
Cves: []*apollopb.CVE{},
|
||||||
References: sc.References,
|
References: sc.References,
|
||||||
PublishedAt: publishedAt,
|
PublishedAt: publishedAt,
|
||||||
Rpms: sc.RPMs,
|
Rpms: nil,
|
||||||
|
RebootSuggested: sc.RebootSuggested,
|
||||||
}
|
}
|
||||||
if sc.Solution.Valid {
|
if sc.Solution.Valid {
|
||||||
ret.Solution = &wrapperspb.StringValue{Value: sc.Solution.String}
|
ret.Solution = &wrapperspb.StringValue{Value: sc.Solution.String}
|
||||||
}
|
}
|
||||||
|
for _, cve := range sc.Cves {
|
||||||
|
split := strings.SplitN(cve, ":::", 6)
|
||||||
|
ret.Cves = append(ret.Cves, &apollopb.CVE{
|
||||||
|
Name: split[2],
|
||||||
|
SourceBy: wrapperspb.String(split[0]),
|
||||||
|
SourceLink: wrapperspb.String(split[1]),
|
||||||
|
Cvss3ScoringVector: wrapperspb.String(split[3]),
|
||||||
|
Cvss3BaseScore: wrapperspb.String(split[4]),
|
||||||
|
Cwe: wrapperspb.String(split[5]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(sc.Fixes) > 0 {
|
||||||
|
ret.Fixes = []*apollopb.Fix{}
|
||||||
|
}
|
||||||
|
for _, fix := range sc.Fixes {
|
||||||
|
split := strings.SplitN(fix, ":::", 4)
|
||||||
|
ret.Fixes = append(ret.Fixes, &apollopb.Fix{
|
||||||
|
Ticket: wrapperspb.String(split[0]),
|
||||||
|
SourceBy: wrapperspb.String(split[1]),
|
||||||
|
SourceLink: wrapperspb.String(split[2]),
|
||||||
|
Description: wrapperspb.String(split[3]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(sc.RPMs) > 0 {
|
||||||
|
ret.Rpms = map[string]*apollopb.RPMs{}
|
||||||
|
}
|
||||||
|
for _, rpm := range sc.RPMs {
|
||||||
|
split := strings.SplitN(rpm, ":::", 2)
|
||||||
|
nvra := split[0]
|
||||||
|
productName := split[1]
|
||||||
|
if ret.Rpms[productName] == nil {
|
||||||
|
ret.Rpms[productName] = &apollopb.RPMs{}
|
||||||
|
}
|
||||||
|
|
||||||
for i, rpm := range sc.RPMs {
|
ret.Rpms[productName].Nvras = append(ret.Rpms[productName].Nvras, nvra)
|
||||||
sc.RPMs[i] = rpmutils.Epoch().ReplaceAllString(rpm, "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func DTOListAdvisoriesToPB(scs []*Advisory) []*secparsepb.Advisory {
|
func DTOListAdvisoriesToPB(scs []*Advisory) []*apollopb.Advisory {
|
||||||
var ret []*secparsepb.Advisory
|
var ret []*apollopb.Advisory
|
||||||
|
|
||||||
for _, v := range scs {
|
for _, v := range scs {
|
||||||
ret = append(ret, DTOAdvisoryToPB(v))
|
ret = append(ret, DTOAdvisoryToPB(v))
|
||||||
@ -120,10 +151,9 @@ func DTOListAdvisoriesToPB(scs []*Advisory) []*secparsepb.Advisory {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func DTOCVEToPB(cve *CVE) *secparseadminpb.CVE {
|
func DTOCVEToPB(cve *CVE) *apollopb.CVE {
|
||||||
ret := &secparseadminpb.CVE{
|
ret := &apollopb.CVE{
|
||||||
Name: cve.ID,
|
Name: cve.ID,
|
||||||
State: secparseadminpb.CVEState(cve.State),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if cve.SourceBy.Valid {
|
if cve.SourceBy.Valid {
|
||||||
@ -136,8 +166,8 @@ func DTOCVEToPB(cve *CVE) *secparseadminpb.CVE {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func DTOListCVEsToPB(cves []*CVE) []*secparseadminpb.CVE {
|
func DTOListCVEsToPB(cves []*CVE) []*apollopb.CVE {
|
||||||
var ret []*secparseadminpb.CVE
|
var ret []*apollopb.CVE
|
||||||
|
|
||||||
for _, v := range cves {
|
for _, v := range cves {
|
||||||
ret = append(ret, DTOCVEToPB(v))
|
ret = append(ret, DTOCVEToPB(v))
|
@ -28,27 +28,26 @@
|
|||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package db
|
package apollodb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"github.com/jmoiron/sqlx/types"
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
secparseadminpb "peridot.resf.org/secparse/admin/proto/v1"
|
apollopb "peridot.resf.org/apollo/pb"
|
||||||
"peridot.resf.org/utils"
|
"peridot.resf.org/utils"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ShortCode is the DTO struct for `resf.secparse.admin.ShortCode`
|
// ShortCode is the DTO struct for `resf.apollo.ShortCode`
|
||||||
type ShortCode struct {
|
type ShortCode struct {
|
||||||
Code string `db:"code"`
|
Code string `json:"code" db:"code"`
|
||||||
Mode int8 `db:"mode"`
|
Mode int8 `json:"mode" db:"mode"`
|
||||||
CreatedAt *time.Time `db:"created_at"`
|
CreatedAt *time.Time `json:"createdAt" db:"created_at"`
|
||||||
ArchivedAt sql.NullTime `db:"archived_at"`
|
ArchivedAt sql.NullTime `json:"archivedAt" db:"archived_at"`
|
||||||
MirrorFromDate sql.NullTime `db:"mirror_from_date"`
|
|
||||||
RedHatProductPrefix sql.NullString `db:"redhat_product_prefix"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advisory is the DTO struct for `resf.secparse.Advisory`
|
// Advisory is the DTO struct for `resf.apollo.Advisory`
|
||||||
type Advisory struct {
|
type Advisory struct {
|
||||||
ID int64 `db:"id"`
|
ID int64 `db:"id"`
|
||||||
CreatedAt *time.Time `db:"created_at"`
|
CreatedAt *time.Time `db:"created_at"`
|
||||||
@ -65,30 +64,38 @@ type Advisory struct {
|
|||||||
|
|
||||||
RedHatIssuedAt sql.NullTime `db:"redhat_issued_at"`
|
RedHatIssuedAt sql.NullTime `db:"redhat_issued_at"`
|
||||||
ShortCodeCode string `db:"short_code_code"`
|
ShortCodeCode string `db:"short_code_code"`
|
||||||
|
RebootSuggested bool `db:"reboot_suggested"`
|
||||||
PublishedAt sql.NullTime `db:"published_at"`
|
PublishedAt sql.NullTime `db:"published_at"`
|
||||||
|
|
||||||
AffectedProducts pq.StringArray `db:"affected_products"`
|
AffectedProducts pq.StringArray `db:"affected_products"`
|
||||||
Fixes pq.StringArray `db:"fixes"`
|
Fixes pq.StringArray `db:"fixes"`
|
||||||
Cves pq.StringArray `db:"cves"`
|
Cves pq.StringArray `db:"cves"`
|
||||||
|
CveIds pq.StringArray `db:"cve_ids"`
|
||||||
References pq.StringArray `db:"references"`
|
References pq.StringArray `db:"references"`
|
||||||
RPMs pq.StringArray `db:"rpms"`
|
RPMs pq.StringArray `db:"rpms"`
|
||||||
BuildArtifacts pq.StringArray `db:"build_artifacts"`
|
BuildArtifacts pq.StringArray `db:"build_artifacts"`
|
||||||
|
|
||||||
|
// Only used for list/search queries
|
||||||
|
Total int64 `json:"total" db:"total"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CVE is the DTO struct for `resf.secparse.admin.CVE`
|
// CVE is the DTO struct for `resf.apollo.CVE`
|
||||||
type CVE struct {
|
type CVE struct {
|
||||||
ID string `db:"id"`
|
ID string `db:"id"`
|
||||||
CreatedAt *time.Time `db:"created_at"`
|
CreatedAt *time.Time `db:"created_at"`
|
||||||
|
|
||||||
State int `db:"state"`
|
|
||||||
AdvisoryId sql.NullInt64 `db:"advisory_id"`
|
AdvisoryId sql.NullInt64 `db:"advisory_id"`
|
||||||
ShortCode string `db:"short_code_code"`
|
ShortCode string `db:"short_code_code"`
|
||||||
|
|
||||||
SourceBy sql.NullString `db:"source_by"`
|
SourceBy sql.NullString `db:"source_by"`
|
||||||
SourceLink sql.NullString `db:"source_link"`
|
SourceLink sql.NullString `db:"source_link"`
|
||||||
|
|
||||||
|
Content types.NullJSONText `db:"content"`
|
||||||
|
|
||||||
|
AffectedProductId sql.NullInt64 `db:"affected_product_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AffectedProduct is the DTO struct for `ctlriq.secparse.admin.AffectedProduct`
|
// AffectedProduct is the DTO struct for `resf.apollo.AffectedProduct`
|
||||||
type AffectedProduct struct {
|
type AffectedProduct struct {
|
||||||
ID int64 `db:"id"`
|
ID int64 `db:"id"`
|
||||||
ProductID int64 `db:"product_id"`
|
ProductID int64 `db:"product_id"`
|
||||||
@ -99,7 +106,7 @@ type AffectedProduct struct {
|
|||||||
Advisory sql.NullString `db:"advisory"`
|
Advisory sql.NullString `db:"advisory"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Product is the DTO struct for `ctlriq.secparse.admin.Product`
|
// Product is the DTO struct for `resf.apollo.Product`
|
||||||
type Product struct {
|
type Product struct {
|
||||||
ID int64 `db:"id"`
|
ID int64 `db:"id"`
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
@ -108,6 +115,16 @@ type Product struct {
|
|||||||
RedHatMajorVersion sql.NullInt32 `db:"redhat_major_version"`
|
RedHatMajorVersion sql.NullInt32 `db:"redhat_major_version"`
|
||||||
ShortCode string `db:"short_code_code"`
|
ShortCode string `db:"short_code_code"`
|
||||||
Archs pq.StringArray `db:"archs"`
|
Archs pq.StringArray `db:"archs"`
|
||||||
|
MirrorFromDate sql.NullTime `json:"mirrorFromDate" db:"mirror_from_date"`
|
||||||
|
RedHatProductPrefix sql.NullString `json:"redHatProductPrefix" db:"redhat_product_prefix"`
|
||||||
|
Cpe sql.NullString `json:"cpe" db:"cpe"`
|
||||||
|
EolAt sql.NullTime `json:"eolAt" db:"eol_at"`
|
||||||
|
|
||||||
|
BuildSystem string `json:"buildSystem" db:"build_system"`
|
||||||
|
BuildSystemEndpoint string `json:"buildSystemEndpoint" db:"build_system_endpoint"`
|
||||||
|
KojiCompose sql.NullString `json:"kojiCompose" db:"koji_compose"`
|
||||||
|
KojiModuleCompose sql.NullString `json:"kojiModuleCompose" db:"koji_module_compose"`
|
||||||
|
PeridotProjectID sql.NullString `json:"peridotProjectID" db:"peridot_project_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BuildReference struct {
|
type BuildReference struct {
|
||||||
@ -116,12 +133,16 @@ type BuildReference struct {
|
|||||||
Rpm string `db:"rpm"`
|
Rpm string `db:"rpm"`
|
||||||
SrcRpm string `db:"src_rpm"`
|
SrcRpm string `db:"src_rpm"`
|
||||||
CveID string `db:"cve_id"`
|
CveID string `db:"cve_id"`
|
||||||
KojiID string `db:"koji_id"`
|
Sha256Sum string `db:"sha256_sum"`
|
||||||
|
KojiID sql.NullString `db:"koji_id"`
|
||||||
|
PeridotID sql.NullString `db:"peridot_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fix struct {
|
type Fix struct {
|
||||||
ID int64 `db:"id"`
|
ID int64 `db:"id"`
|
||||||
Ticket sql.NullString `db:"ticket"`
|
Ticket sql.NullString `db:"ticket"`
|
||||||
|
SourceBy sql.NullString `db:"source_by"`
|
||||||
|
SourceLink sql.NullString `db:"source_link"`
|
||||||
Description sql.NullString `db:"description"`
|
Description sql.NullString `db:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +155,7 @@ type AdvisoryReference struct {
|
|||||||
type MirrorState struct {
|
type MirrorState struct {
|
||||||
ShortCode string `db:"short_code_code"`
|
ShortCode string `db:"short_code_code"`
|
||||||
LastSync sql.NullTime `db:"last_sync"`
|
LastSync sql.NullTime `db:"last_sync"`
|
||||||
|
ErrataAfter sql.NullTime `db:"errata_after"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AdvisoryCVE struct {
|
type AdvisoryCVE struct {
|
||||||
@ -148,21 +170,27 @@ type AdvisoryFix struct {
|
|||||||
|
|
||||||
type IgnoredUpstreamPackage struct {
|
type IgnoredUpstreamPackage struct {
|
||||||
ID int64 `db:"id"`
|
ID int64 `db:"id"`
|
||||||
ShortCode string `db:"short_code_code"`
|
ProductID int64 `db:"product_id"`
|
||||||
Package string `db:"package"`
|
Package string `db:"package"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RebootSuggestedPackage struct {
|
||||||
|
CreatedAt *time.Time `db:"created_at"`
|
||||||
|
Name string `db:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
type AdvisoryRPM struct {
|
type AdvisoryRPM struct {
|
||||||
AdvisoryID int64 `db:"advisory_id"`
|
AdvisoryID int64 `db:"advisory_id"`
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
|
ProductID int64 `db:"product_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Access interface {
|
type Access interface {
|
||||||
GetAllShortCodes() ([]*ShortCode, error)
|
GetAllShortCodes() ([]*ShortCode, error)
|
||||||
GetShortCodeByCode(code string) (*ShortCode, error)
|
GetShortCodeByCode(code string) (*ShortCode, error)
|
||||||
CreateShortCode(code string, mode secparseadminpb.ShortCodeMode) (*ShortCode, error)
|
CreateShortCode(code string, mode apollopb.ShortCode_Mode) (*ShortCode, error)
|
||||||
|
|
||||||
GetAllAdvisories(publishedOnly bool) ([]*Advisory, error)
|
GetAllAdvisories(filters *apollopb.AdvisoryFilters, page int32, limit int32) ([]*Advisory, error)
|
||||||
// Advisory is a broad entity with lots of fields
|
// Advisory is a broad entity with lots of fields
|
||||||
// mustafa: It is in my opinion better to accept the same struct
|
// mustafa: It is in my opinion better to accept the same struct
|
||||||
// to create and update it.
|
// to create and update it.
|
||||||
@ -179,11 +207,12 @@ type Access interface {
|
|||||||
GetAdvisoryByCodeAndYearAndNum(code string, year int, num int) (*Advisory, error)
|
GetAdvisoryByCodeAndYearAndNum(code string, year int, num int) (*Advisory, error)
|
||||||
|
|
||||||
GetAllUnresolvedCVEs() ([]*CVE, error)
|
GetAllUnresolvedCVEs() ([]*CVE, error)
|
||||||
GetAllCVEsWithAllProductsFixed() ([]*CVE, error)
|
GetPendingAffectedProducts() ([]*AffectedProduct, error)
|
||||||
GetAllCVEsFixedDownstream() ([]*CVE, error)
|
GetAllCVEsFixedDownstream() ([]*CVE, error)
|
||||||
GetCVEByID(id string) (*CVE, error)
|
GetCVEByID(id string) (*CVE, error)
|
||||||
CreateCVE(cveId string, state secparseadminpb.CVEState, shortCode string, sourceBy *string, sourceLink *string) (*CVE, error)
|
GetAllCVEs() ([]*CVE, error)
|
||||||
UpdateCVEState(cve string, state secparseadminpb.CVEState) error
|
CreateCVE(cveId string, shortCode string, sourceBy *string, sourceLink *string, content types.NullJSONText) (*CVE, error)
|
||||||
|
SetCVEContent(cveId string, content types.JSONText) error
|
||||||
|
|
||||||
GetProductsByShortCode(code string) ([]*Product, error)
|
GetProductsByShortCode(code string) ([]*Product, error)
|
||||||
GetProductByNameAndShortCode(product string, code string) (*Product, error)
|
GetProductByNameAndShortCode(product string, code string) (*Product, error)
|
||||||
@ -193,25 +222,29 @@ type Access interface {
|
|||||||
GetAllAffectedProductsByCVE(cve string) ([]*AffectedProduct, error)
|
GetAllAffectedProductsByCVE(cve string) ([]*AffectedProduct, error)
|
||||||
GetAffectedProductByCVEAndPackage(cve string, pkg string) (*AffectedProduct, error)
|
GetAffectedProductByCVEAndPackage(cve string, pkg string) (*AffectedProduct, error)
|
||||||
GetAffectedProductByAdvisory(advisory string) (*AffectedProduct, error)
|
GetAffectedProductByAdvisory(advisory string) (*AffectedProduct, error)
|
||||||
|
GetAffectedProductByID(id int64) (*AffectedProduct, error)
|
||||||
CreateAffectedProduct(productId int64, cveId string, state int, version string, pkg string, advisory *string) (*AffectedProduct, error)
|
CreateAffectedProduct(productId int64, cveId string, state int, version string, pkg string, advisory *string) (*AffectedProduct, error)
|
||||||
UpdateAffectedProductStateAndPackageAndAdvisory(id int64, state int, pkg string, advisory *string) error
|
UpdateAffectedProductStateAndPackageAndAdvisory(id int64, state int, pkg string, advisory *string) error
|
||||||
DeleteAffectedProduct(id int64) error
|
DeleteAffectedProduct(id int64) error
|
||||||
|
|
||||||
CreateFix(ticket string, description string) (int64, error)
|
CreateFix(ticket string, sourceBy string, sourceLink string, description string) (int64, error)
|
||||||
|
|
||||||
// This will return nil rather than an error if no rows are found
|
// This will return nil rather than an error if no rows are found
|
||||||
GetMirrorStateLastSync(code string) (*time.Time, error)
|
GetMirrorState(code string) (*MirrorState, error)
|
||||||
UpdateMirrorState(code string, lastSync *time.Time) error
|
UpdateMirrorState(code string, lastSync *time.Time) error
|
||||||
|
UpdateMirrorStateErrata(code string, lastSync *time.Time) error
|
||||||
|
GetMaxLastSync() (*time.Time, error)
|
||||||
|
|
||||||
CreateBuildReference(affectedProductId int64, rpm string, srcRpm string, cveId string, kojiId string) (*BuildReference, error)
|
CreateBuildReference(affectedProductId int64, rpm string, srcRpm string, cveId string, sha256Sum string, kojiId *string, peridotId *string) (*BuildReference, error)
|
||||||
CreateAdvisoryReference(advisoryId int64, url string) error
|
CreateAdvisoryReference(advisoryId int64, url string) error
|
||||||
|
|
||||||
GetAllIgnoredPackagesByShortCode(code string) ([]string, error)
|
GetAllIgnoredPackagesByProductID(productID int64) ([]string, error)
|
||||||
|
GetAllRebootSuggestedPackages() ([]string, error)
|
||||||
|
|
||||||
// These add methods is treated like an upsert. They're only added if one doesn't exist
|
// These add methods is treated like an upsert. They're only added if one doesn't exist
|
||||||
AddAdvisoryFix(advisoryId int64, fixId int64) error
|
AddAdvisoryFix(advisoryId int64, fixId int64) error
|
||||||
AddAdvisoryCVE(advisoryId int64, cveId string) error
|
AddAdvisoryCVE(advisoryId int64, cveId string) error
|
||||||
AddAdvisoryRPM(advisoryId int64, name string) error
|
AddAdvisoryRPM(advisoryId int64, name string, productID int64) error
|
||||||
|
|
||||||
Begin() (utils.Tx, error)
|
Begin() (utils.Tx, error)
|
||||||
UseTransaction(tx utils.Tx) Access
|
UseTransaction(tx utils.Tx) Access
|
@ -3,11 +3,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||||||
go_library(
|
go_library(
|
||||||
name = "mock",
|
name = "mock",
|
||||||
srcs = ["mock.go"],
|
srcs = ["mock.go"],
|
||||||
importpath = "peridot.resf.org/secparse/db/mock",
|
importpath = "peridot.resf.org/apollo/db/mock",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//secparse/admin/proto/v1:proto",
|
"//apollo/db",
|
||||||
"//secparse/db",
|
"//apollo/proto/v1:pb",
|
||||||
"//utils",
|
"//utils",
|
||||||
|
"//vendor/github.com/jmoiron/sqlx/types",
|
||||||
],
|
],
|
||||||
)
|
)
|
@ -28,56 +28,59 @@
|
|||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package mock
|
package apollomock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
secparseadminpb "peridot.resf.org/secparse/admin/proto/v1"
|
"github.com/jmoiron/sqlx/types"
|
||||||
"peridot.resf.org/secparse/db"
|
apollodb "peridot.resf.org/apollo/db"
|
||||||
|
apollopb "peridot.resf.org/apollo/pb"
|
||||||
"peridot.resf.org/utils"
|
"peridot.resf.org/utils"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Access struct {
|
type Access struct {
|
||||||
ShortCodes []*db.ShortCode
|
ShortCodes []*apollodb.ShortCode
|
||||||
Advisories []*db.Advisory
|
Advisories []*apollodb.Advisory
|
||||||
Cves []*db.CVE
|
Cves []*apollodb.CVE
|
||||||
Fixes []*db.Fix
|
Fixes []*apollodb.Fix
|
||||||
AdvisoryReferences []*db.AdvisoryReference
|
AdvisoryReferences []*apollodb.AdvisoryReference
|
||||||
Products []*db.Product
|
Products []*apollodb.Product
|
||||||
AffectedProducts []*db.AffectedProduct
|
AffectedProducts []*apollodb.AffectedProduct
|
||||||
BuildReferences []*db.BuildReference
|
BuildReferences []*apollodb.BuildReference
|
||||||
MirrorStates []*db.MirrorState
|
MirrorStates []*apollodb.MirrorState
|
||||||
AdvisoryCVEs []*db.AdvisoryCVE
|
AdvisoryCVEs []*apollodb.AdvisoryCVE
|
||||||
AdvisoryFixes []*db.AdvisoryFix
|
AdvisoryFixes []*apollodb.AdvisoryFix
|
||||||
IgnoredUpstreamPackages []*db.IgnoredUpstreamPackage
|
IgnoredUpstreamPackages []*apollodb.IgnoredUpstreamPackage
|
||||||
AdvisoryRPMs []*db.AdvisoryRPM
|
RebootSuggestedPackages []*apollodb.RebootSuggestedPackage
|
||||||
|
AdvisoryRPMs []*apollodb.AdvisoryRPM
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *Access {
|
func New() *Access {
|
||||||
return &Access{
|
return &Access{
|
||||||
ShortCodes: []*db.ShortCode{},
|
ShortCodes: []*apollodb.ShortCode{},
|
||||||
Advisories: []*db.Advisory{},
|
Advisories: []*apollodb.Advisory{},
|
||||||
Cves: []*db.CVE{},
|
Cves: []*apollodb.CVE{},
|
||||||
Fixes: []*db.Fix{},
|
Fixes: []*apollodb.Fix{},
|
||||||
AdvisoryReferences: []*db.AdvisoryReference{},
|
AdvisoryReferences: []*apollodb.AdvisoryReference{},
|
||||||
Products: []*db.Product{},
|
Products: []*apollodb.Product{},
|
||||||
AffectedProducts: []*db.AffectedProduct{},
|
AffectedProducts: []*apollodb.AffectedProduct{},
|
||||||
BuildReferences: []*db.BuildReference{},
|
BuildReferences: []*apollodb.BuildReference{},
|
||||||
MirrorStates: []*db.MirrorState{},
|
MirrorStates: []*apollodb.MirrorState{},
|
||||||
AdvisoryCVEs: []*db.AdvisoryCVE{},
|
AdvisoryCVEs: []*apollodb.AdvisoryCVE{},
|
||||||
AdvisoryFixes: []*db.AdvisoryFix{},
|
AdvisoryFixes: []*apollodb.AdvisoryFix{},
|
||||||
IgnoredUpstreamPackages: []*db.IgnoredUpstreamPackage{},
|
IgnoredUpstreamPackages: []*apollodb.IgnoredUpstreamPackage{},
|
||||||
AdvisoryRPMs: []*db.AdvisoryRPM{},
|
RebootSuggestedPackages: []*apollodb.RebootSuggestedPackage{},
|
||||||
|
AdvisoryRPMs: []*apollodb.AdvisoryRPM{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetAllShortCodes() ([]*db.ShortCode, error) {
|
func (a *Access) GetAllShortCodes() ([]*apollodb.ShortCode, error) {
|
||||||
return a.ShortCodes, nil
|
return a.ShortCodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetShortCodeByCode(code string) (*db.ShortCode, error) {
|
func (a *Access) GetShortCodeByCode(code string) (*apollodb.ShortCode, error) {
|
||||||
for _, val := range a.ShortCodes {
|
for _, val := range a.ShortCodes {
|
||||||
if val.Code == code {
|
if val.Code == code {
|
||||||
return val, nil
|
return val, nil
|
||||||
@ -87,24 +90,22 @@ func (a *Access) GetShortCodeByCode(code string) (*db.ShortCode, error) {
|
|||||||
return nil, sql.ErrNoRows
|
return nil, sql.ErrNoRows
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) CreateShortCode(code string, mode secparseadminpb.ShortCodeMode) (*db.ShortCode, error) {
|
func (a *Access) CreateShortCode(code string, mode apollopb.ShortCode_Mode) (*apollodb.ShortCode, error) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
shortCode := db.ShortCode{
|
shortCode := apollodb.ShortCode{
|
||||||
Code: code,
|
Code: code,
|
||||||
Mode: int8(mode),
|
Mode: int8(mode),
|
||||||
CreatedAt: &now,
|
CreatedAt: &now,
|
||||||
ArchivedAt: sql.NullTime{},
|
ArchivedAt: sql.NullTime{},
|
||||||
MirrorFromDate: sql.NullTime{},
|
|
||||||
RedHatProductPrefix: sql.NullString{},
|
|
||||||
}
|
}
|
||||||
a.ShortCodes = append(a.ShortCodes, &shortCode)
|
a.ShortCodes = append(a.ShortCodes, &shortCode)
|
||||||
|
|
||||||
return &shortCode, nil
|
return &shortCode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) getAdvisoriesWithJoin(filter func(*db.Advisory) bool) []*db.Advisory {
|
func (a *Access) getAdvisoriesWithJoin(filter func(*apollodb.Advisory) bool) []*apollodb.Advisory {
|
||||||
var advisories []*db.Advisory
|
var advisories []*apollodb.Advisory
|
||||||
for _, val := range a.Advisories {
|
for _, val := range a.Advisories {
|
||||||
if filter(val) {
|
if filter(val) {
|
||||||
advisories = append(advisories, val)
|
advisories = append(advisories, val)
|
||||||
@ -193,9 +194,30 @@ func (a *Access) getAdvisoriesWithJoin(filter func(*db.Advisory) bool) []*db.Adv
|
|||||||
return advisories
|
return advisories
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetAllAdvisories(publishedOnly bool) ([]*db.Advisory, error) {
|
func (a *Access) GetAllAdvisories(filters *apollopb.AdvisoryFilters, page int32, limit int32) ([]*apollodb.Advisory, error) {
|
||||||
return a.getAdvisoriesWithJoin(func(advisory *db.Advisory) bool {
|
return a.getAdvisoriesWithJoin(func(advisory *apollodb.Advisory) bool {
|
||||||
if publishedOnly {
|
if filters.Product != nil {
|
||||||
|
if !utils.StrContains(filters.Product.Value, advisory.AffectedProducts) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if advisory.PublishedAt.Valid {
|
||||||
|
if filters.Before != nil {
|
||||||
|
if advisory.PublishedAt.Time.After(filters.Before.AsTime()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if filters.After != nil {
|
||||||
|
if advisory.PublishedAt.Time.Before(filters.After.AsTime()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if filters.IncludeUnpublished != nil {
|
||||||
|
if !filters.IncludeUnpublished.Value && !advisory.PublishedAt.Valid {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if !advisory.PublishedAt.Valid {
|
if !advisory.PublishedAt.Valid {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -205,8 +227,8 @@ func (a *Access) GetAllAdvisories(publishedOnly bool) ([]*db.Advisory, error) {
|
|||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetAdvisoryByCodeAndYearAndNum(code string, year int, num int) (*db.Advisory, error) {
|
func (a *Access) GetAdvisoryByCodeAndYearAndNum(code string, year int, num int) (*apollodb.Advisory, error) {
|
||||||
advisories := a.getAdvisoriesWithJoin(func(advisory *db.Advisory) bool {
|
advisories := a.getAdvisoriesWithJoin(func(advisory *apollodb.Advisory) bool {
|
||||||
if advisory.ShortCodeCode == code && advisory.Year == year && advisory.Num == num {
|
if advisory.ShortCodeCode == code && advisory.Year == year && advisory.Num == num {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -220,14 +242,14 @@ func (a *Access) GetAdvisoryByCodeAndYearAndNum(code string, year int, num int)
|
|||||||
return advisories[0], nil
|
return advisories[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) CreateAdvisory(advisory *db.Advisory) (*db.Advisory, error) {
|
func (a *Access) CreateAdvisory(advisory *apollodb.Advisory) (*apollodb.Advisory, error) {
|
||||||
var lastId int64 = 1
|
var lastId int64 = 1
|
||||||
if len(a.Advisories) > 0 {
|
if len(a.Advisories) > 0 {
|
||||||
lastId = a.Advisories[len(a.Advisories)-1].ID + 1
|
lastId = a.Advisories[len(a.Advisories)-1].ID + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
ret := &db.Advisory{
|
ret := &apollodb.Advisory{
|
||||||
ID: lastId,
|
ID: lastId,
|
||||||
CreatedAt: &now,
|
CreatedAt: &now,
|
||||||
Year: advisory.Year,
|
Year: advisory.Year,
|
||||||
@ -246,7 +268,7 @@ func (a *Access) CreateAdvisory(advisory *db.Advisory) (*db.Advisory, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) UpdateAdvisory(advisory *db.Advisory) (*db.Advisory, error) {
|
func (a *Access) UpdateAdvisory(advisory *apollodb.Advisory) (*apollodb.Advisory, error) {
|
||||||
for _, val := range a.Advisories {
|
for _, val := range a.Advisories {
|
||||||
if val.ID == advisory.ID {
|
if val.ID == advisory.ID {
|
||||||
val.Year = advisory.Year
|
val.Year = advisory.Year
|
||||||
@ -267,47 +289,58 @@ func (a *Access) UpdateAdvisory(advisory *db.Advisory) (*db.Advisory, error) {
|
|||||||
return nil, sql.ErrNoRows
|
return nil, sql.ErrNoRows
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetAllUnresolvedCVEs() ([]*db.CVE, error) {
|
func (a *Access) GetAllUnresolvedCVEs() ([]*apollodb.CVE, error) {
|
||||||
var cves []*db.CVE
|
var cves []*apollodb.CVE
|
||||||
|
var addedCVEIds []string
|
||||||
|
|
||||||
for _, cve := range a.Cves {
|
for _, cve := range a.Cves {
|
||||||
switch cve.State {
|
|
||||||
case
|
|
||||||
int(secparseadminpb.CVEState_NewFromUpstream),
|
|
||||||
int(secparseadminpb.CVEState_NewOriginal):
|
|
||||||
cves = append(cves, cve)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cves, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Access) GetAllCVEsWithAllProductsFixed() ([]*db.CVE, error) {
|
|
||||||
var cves []*db.CVE
|
|
||||||
var fixedAffectedProducts []*db.AffectedProduct
|
|
||||||
|
|
||||||
for _, affectedProduct := range a.AffectedProducts {
|
for _, affectedProduct := range a.AffectedProducts {
|
||||||
|
if affectedProduct.CveID.String == cve.ID {
|
||||||
switch affectedProduct.State {
|
switch affectedProduct.State {
|
||||||
case
|
case
|
||||||
int(secparseadminpb.AffectedProductState_FixedUpstream),
|
int(apollopb.AffectedProduct_STATE_UNDER_INVESTIGATION_UPSTREAM),
|
||||||
int(secparseadminpb.AffectedProductState_WillNotFixUpstream),
|
int(apollopb.AffectedProduct_STATE_UNDER_INVESTIGATION_DOWNSTREAM),
|
||||||
int(secparseadminpb.AffectedProductState_WillNotFixDownstream),
|
int(apollopb.AffectedProduct_STATE_AFFECTED_UPSTREAM),
|
||||||
int(secparseadminpb.AffectedProductState_OutOfSupportScope):
|
int(apollopb.AffectedProduct_STATE_AFFECTED_DOWNSTREAM):
|
||||||
fixedAffectedProducts = append(fixedAffectedProducts, affectedProduct)
|
nCve := *cve
|
||||||
|
nCve.AffectedProductId = sql.NullInt64{Valid: true, Int64: affectedProduct.ID}
|
||||||
|
cves = append(cves, &nCve)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, cve := range a.Cves {
|
||||||
|
if !utils.StrContains(cve.ID, addedCVEIds) {
|
||||||
|
cves = append(cves, cve)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return cves, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetPendingAffectedProducts() ([]*apollodb.AffectedProduct, error) {
|
||||||
|
var ret []*apollodb.AffectedProduct
|
||||||
|
|
||||||
|
for _, affectedProduct := range a.AffectedProducts {
|
||||||
|
if affectedProduct.State == int(apollopb.AffectedProduct_STATE_FIXED_UPSTREAM) {
|
||||||
|
ret = append(ret, affectedProduct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllCVEsFixedDownstream() ([]*apollodb.CVE, error) {
|
||||||
|
var cves []*apollodb.CVE
|
||||||
|
|
||||||
for _, cve := range a.Cves {
|
for _, cve := range a.Cves {
|
||||||
switch cve.State {
|
for _, affectedProduct := range a.AffectedProducts {
|
||||||
case
|
if affectedProduct.CveID.String == cve.ID {
|
||||||
int(secparseadminpb.CVEState_NewFromUpstream),
|
if affectedProduct.State == int(apollopb.AffectedProduct_STATE_FIXED_DOWNSTREAM) {
|
||||||
int(secparseadminpb.CVEState_NewOriginal),
|
nCve := *cve
|
||||||
int(secparseadminpb.CVEState_ResolvedUpstream),
|
nCve.AffectedProductId = sql.NullInt64{Valid: true, Int64: affectedProduct.ID}
|
||||||
int(secparseadminpb.CVEState_ResolvedDownstream):
|
cves = append(cves, &nCve)
|
||||||
for _, fixed := range fixedAffectedProducts {
|
|
||||||
if fixed.CveID.String == cve.ID {
|
|
||||||
cves = append(cves, cve)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -317,19 +350,7 @@ func (a *Access) GetAllCVEsWithAllProductsFixed() ([]*db.CVE, error) {
|
|||||||
return cves, nil
|
return cves, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetAllCVEsFixedDownstream() ([]*db.CVE, error) {
|
func (a *Access) GetCVEByID(id string) (*apollodb.CVE, error) {
|
||||||
var cves []*db.CVE
|
|
||||||
|
|
||||||
for _, cve := range a.Cves {
|
|
||||||
if cve.State == int(secparseadminpb.CVEState_ResolvedDownstream) {
|
|
||||||
cves = append(cves, cve)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cves, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Access) GetCVEByID(id string) (*db.CVE, error) {
|
|
||||||
for _, cve := range a.Cves {
|
for _, cve := range a.Cves {
|
||||||
if cve.ID == id {
|
if cve.ID == id {
|
||||||
return cve, nil
|
return cve, nil
|
||||||
@ -339,7 +360,11 @@ func (a *Access) GetCVEByID(id string) (*db.CVE, error) {
|
|||||||
return nil, sql.ErrNoRows
|
return nil, sql.ErrNoRows
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) CreateCVE(cveId string, state secparseadminpb.CVEState, shortCode string, sourceBy *string, sourceLink *string) (*db.CVE, error) {
|
func (a *Access) GetAllCVEs() ([]*apollodb.CVE, error) {
|
||||||
|
return a.Cves, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateCVE(cveId string, shortCode string, sourceBy *string, sourceLink *string, content types.NullJSONText) (*apollodb.CVE, error) {
|
||||||
var sby sql.NullString
|
var sby sql.NullString
|
||||||
var sl sql.NullString
|
var sl sql.NullString
|
||||||
|
|
||||||
@ -354,32 +379,33 @@ func (a *Access) CreateCVE(cveId string, state secparseadminpb.CVEState, shortCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
cve := &db.CVE{
|
cve := &apollodb.CVE{
|
||||||
ID: cveId,
|
ID: cveId,
|
||||||
CreatedAt: &now,
|
CreatedAt: &now,
|
||||||
State: int(state),
|
|
||||||
AdvisoryId: sql.NullInt64{},
|
AdvisoryId: sql.NullInt64{},
|
||||||
ShortCode: shortCode,
|
ShortCode: shortCode,
|
||||||
SourceBy: sby,
|
SourceBy: sby,
|
||||||
SourceLink: sl,
|
SourceLink: sl,
|
||||||
|
Content: content,
|
||||||
}
|
}
|
||||||
a.Cves = append(a.Cves, cve)
|
a.Cves = append(a.Cves, cve)
|
||||||
|
|
||||||
return cve, nil
|
return cve, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) UpdateCVEState(cve string, state secparseadminpb.CVEState) error {
|
func (a *Access) SetCVEContent(cveId string, content types.JSONText) error {
|
||||||
for _, c := range a.Cves {
|
for _, cve := range a.Cves {
|
||||||
if c.ID == cve {
|
if cve.ID == cveId {
|
||||||
c.State = int(state)
|
cve.Content = types.NullJSONText{Valid: true, JSONText: content}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Access) GetProductsByShortCode(code string) ([]*db.Product, error) {
|
return sql.ErrNoRows
|
||||||
var products []*db.Product
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetProductsByShortCode(code string) ([]*apollodb.Product, error) {
|
||||||
|
var products []*apollodb.Product
|
||||||
|
|
||||||
for _, product := range a.Products {
|
for _, product := range a.Products {
|
||||||
if product.ShortCode == code {
|
if product.ShortCode == code {
|
||||||
@ -390,7 +416,7 @@ func (a *Access) GetProductsByShortCode(code string) ([]*db.Product, error) {
|
|||||||
return products, nil
|
return products, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetProductByNameAndShortCode(name string, code string) (*db.Product, error) {
|
func (a *Access) GetProductByNameAndShortCode(name string, code string) (*apollodb.Product, error) {
|
||||||
for _, product := range a.Products {
|
for _, product := range a.Products {
|
||||||
if product.Name == name && product.ShortCode == code {
|
if product.Name == name && product.ShortCode == code {
|
||||||
return product, nil
|
return product, nil
|
||||||
@ -400,7 +426,7 @@ func (a *Access) GetProductByNameAndShortCode(name string, code string) (*db.Pro
|
|||||||
return nil, sql.ErrNoRows
|
return nil, sql.ErrNoRows
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetProductByID(id int64) (*db.Product, error) {
|
func (a *Access) GetProductByID(id int64) (*apollodb.Product, error) {
|
||||||
for _, product := range a.Products {
|
for _, product := range a.Products {
|
||||||
if product.ID == id {
|
if product.ID == id {
|
||||||
return product, nil
|
return product, nil
|
||||||
@ -410,7 +436,7 @@ func (a *Access) GetProductByID(id int64) (*db.Product, error) {
|
|||||||
return nil, sql.ErrNoRows
|
return nil, sql.ErrNoRows
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) CreateProduct(name string, currentFullVersion string, redHatMajorVersion *int32, code string, archs []string) (*db.Product, error) {
|
func (a *Access) CreateProduct(name string, currentFullVersion string, redHatMajorVersion *int32, code string, archs []string) (*apollodb.Product, error) {
|
||||||
var lastId int64 = 1
|
var lastId int64 = 1
|
||||||
if len(a.Products) > 0 {
|
if len(a.Products) > 0 {
|
||||||
lastId = a.Products[len(a.Products)-1].ID + 1
|
lastId = a.Products[len(a.Products)-1].ID + 1
|
||||||
@ -422,21 +448,23 @@ func (a *Access) CreateProduct(name string, currentFullVersion string, redHatMaj
|
|||||||
rhmv.Valid = true
|
rhmv.Valid = true
|
||||||
}
|
}
|
||||||
|
|
||||||
product := &db.Product{
|
product := &apollodb.Product{
|
||||||
ID: lastId,
|
ID: lastId,
|
||||||
Name: name,
|
Name: name,
|
||||||
CurrentFullVersion: currentFullVersion,
|
CurrentFullVersion: currentFullVersion,
|
||||||
RedHatMajorVersion: rhmv,
|
RedHatMajorVersion: rhmv,
|
||||||
ShortCode: code,
|
ShortCode: code,
|
||||||
Archs: archs,
|
Archs: archs,
|
||||||
|
MirrorFromDate: sql.NullTime{},
|
||||||
|
RedHatProductPrefix: sql.NullString{},
|
||||||
}
|
}
|
||||||
a.Products = append(a.Products, product)
|
a.Products = append(a.Products, product)
|
||||||
|
|
||||||
return product, nil
|
return product, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetAllAffectedProductsByCVE(cve string) ([]*db.AffectedProduct, error) {
|
func (a *Access) GetAllAffectedProductsByCVE(cve string) ([]*apollodb.AffectedProduct, error) {
|
||||||
var affectedProducts []*db.AffectedProduct
|
var affectedProducts []*apollodb.AffectedProduct
|
||||||
|
|
||||||
for _, affectedProduct := range a.AffectedProducts {
|
for _, affectedProduct := range a.AffectedProducts {
|
||||||
if affectedProduct.CveID.String == cve {
|
if affectedProduct.CveID.String == cve {
|
||||||
@ -447,7 +475,7 @@ func (a *Access) GetAllAffectedProductsByCVE(cve string) ([]*db.AffectedProduct,
|
|||||||
return affectedProducts, nil
|
return affectedProducts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetAffectedProductByCVEAndPackage(cve string, pkg string) (*db.AffectedProduct, error) {
|
func (a *Access) GetAffectedProductByCVEAndPackage(cve string, pkg string) (*apollodb.AffectedProduct, error) {
|
||||||
for _, affectedProduct := range a.AffectedProducts {
|
for _, affectedProduct := range a.AffectedProducts {
|
||||||
if affectedProduct.CveID.String == cve && affectedProduct.Package == pkg {
|
if affectedProduct.CveID.String == cve && affectedProduct.Package == pkg {
|
||||||
return affectedProduct, nil
|
return affectedProduct, nil
|
||||||
@ -457,7 +485,7 @@ func (a *Access) GetAffectedProductByCVEAndPackage(cve string, pkg string) (*db.
|
|||||||
return nil, sql.ErrNoRows
|
return nil, sql.ErrNoRows
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetAffectedProductByAdvisory(advisory string) (*db.AffectedProduct, error) {
|
func (a *Access) GetAffectedProductByAdvisory(advisory string) (*apollodb.AffectedProduct, error) {
|
||||||
for _, affectedProduct := range a.AffectedProducts {
|
for _, affectedProduct := range a.AffectedProducts {
|
||||||
if affectedProduct.Advisory.String == advisory {
|
if affectedProduct.Advisory.String == advisory {
|
||||||
return affectedProduct, nil
|
return affectedProduct, nil
|
||||||
@ -467,7 +495,17 @@ func (a *Access) GetAffectedProductByAdvisory(advisory string) (*db.AffectedProd
|
|||||||
return nil, sql.ErrNoRows
|
return nil, sql.ErrNoRows
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) CreateAffectedProduct(productId int64, cveId string, state int, version string, pkg string, advisory *string) (*db.AffectedProduct, error) {
|
func (a *Access) GetAffectedProductByID(id int64) (*apollodb.AffectedProduct, error) {
|
||||||
|
for _, affectedProduct := range a.AffectedProducts {
|
||||||
|
if affectedProduct.ID == id {
|
||||||
|
return affectedProduct, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, sql.ErrNoRows
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateAffectedProduct(productId int64, cveId string, state int, version string, pkg string, advisory *string) (*apollodb.AffectedProduct, error) {
|
||||||
var lastId int64 = 1
|
var lastId int64 = 1
|
||||||
if len(a.AffectedProducts) > 0 {
|
if len(a.AffectedProducts) > 0 {
|
||||||
lastId = a.AffectedProducts[len(a.AffectedProducts)-1].ID + 1
|
lastId = a.AffectedProducts[len(a.AffectedProducts)-1].ID + 1
|
||||||
@ -479,7 +517,7 @@ func (a *Access) CreateAffectedProduct(productId int64, cveId string, state int,
|
|||||||
adv.Valid = true
|
adv.Valid = true
|
||||||
}
|
}
|
||||||
|
|
||||||
affectedProduct := &db.AffectedProduct{
|
affectedProduct := &apollodb.AffectedProduct{
|
||||||
ID: lastId,
|
ID: lastId,
|
||||||
ProductID: productId,
|
ProductID: productId,
|
||||||
CveID: sql.NullString{Valid: true, String: cveId},
|
CveID: sql.NullString{Valid: true, String: cveId},
|
||||||
@ -529,15 +567,17 @@ func (a *Access) DeleteAffectedProduct(id int64) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) CreateFix(ticket string, description string) (int64, error) {
|
func (a *Access) CreateFix(ticket string, sourceBy string, sourceLink string, description string) (int64, error) {
|
||||||
var lastId int64 = 1
|
var lastId int64 = 1
|
||||||
if len(a.Fixes) > 0 {
|
if len(a.Fixes) > 0 {
|
||||||
lastId = a.Fixes[len(a.Fixes)-1].ID + 1
|
lastId = a.Fixes[len(a.Fixes)-1].ID + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fix := &db.Fix{
|
fix := &apollodb.Fix{
|
||||||
ID: lastId,
|
ID: lastId,
|
||||||
Ticket: sql.NullString{Valid: true, String: ticket},
|
Ticket: sql.NullString{Valid: true, String: ticket},
|
||||||
|
SourceBy: sql.NullString{Valid: true, String: sourceBy},
|
||||||
|
SourceLink: sql.NullString{Valid: true, String: sourceLink},
|
||||||
Description: sql.NullString{Valid: true, String: description},
|
Description: sql.NullString{Valid: true, String: description},
|
||||||
}
|
}
|
||||||
a.Fixes = append(a.Fixes, fix)
|
a.Fixes = append(a.Fixes, fix)
|
||||||
@ -545,13 +585,13 @@ func (a *Access) CreateFix(ticket string, description string) (int64, error) {
|
|||||||
return lastId, nil
|
return lastId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetMirrorStateLastSync(code string) (*time.Time, error) {
|
func (a *Access) GetMirrorState(code string) (*apollodb.MirrorState, error) {
|
||||||
var lastSync *time.Time
|
var lastSync *apollodb.MirrorState
|
||||||
|
|
||||||
for _, mirrorState := range a.MirrorStates {
|
for _, mirrorState := range a.MirrorStates {
|
||||||
if mirrorState.ShortCode == code {
|
if mirrorState.ShortCode == code {
|
||||||
if mirrorState.LastSync.Valid {
|
if mirrorState.LastSync.Valid {
|
||||||
lastSync = &mirrorState.LastSync.Time
|
lastSync = mirrorState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -573,7 +613,7 @@ func (a *Access) UpdateMirrorState(code string, lastSync *time.Time) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mirrorState := &db.MirrorState{
|
mirrorState := &apollodb.MirrorState{
|
||||||
ShortCode: code,
|
ShortCode: code,
|
||||||
LastSync: sql.NullTime{Valid: true, Time: *lastSync},
|
LastSync: sql.NullTime{Valid: true, Time: *lastSync},
|
||||||
}
|
}
|
||||||
@ -582,19 +622,62 @@ func (a *Access) UpdateMirrorState(code string, lastSync *time.Time) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) CreateBuildReference(affectedProductId int64, rpm string, srcRpm string, cveId string, kojiId string) (*db.BuildReference, error) {
|
func (a *Access) UpdateMirrorStateErrata(code string, lastSync *time.Time) error {
|
||||||
|
for _, mirrorState := range a.MirrorStates {
|
||||||
|
if mirrorState.ShortCode == code {
|
||||||
|
mirrorState.ErrataAfter.Time = *lastSync
|
||||||
|
mirrorState.ErrataAfter.Valid = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mirrorState := &apollodb.MirrorState{
|
||||||
|
ShortCode: code,
|
||||||
|
ErrataAfter: sql.NullTime{Valid: true, Time: *lastSync},
|
||||||
|
}
|
||||||
|
a.MirrorStates = append(a.MirrorStates, mirrorState)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetMaxLastSync() (*time.Time, error) {
|
||||||
|
var maxLastSync *time.Time
|
||||||
|
|
||||||
|
for _, mirrorState := range a.MirrorStates {
|
||||||
|
if mirrorState.LastSync.Valid {
|
||||||
|
if maxLastSync == nil || mirrorState.LastSync.Time.After(*maxLastSync) {
|
||||||
|
maxLastSync = &mirrorState.LastSync.Time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxLastSync == nil {
|
||||||
|
return nil, sql.ErrNoRows
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxLastSync, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateBuildReference(affectedProductId int64, rpm string, srcRpm string, cveId string, sha256Sum string, kojiId *string, peridotId *string) (*apollodb.BuildReference, error) {
|
||||||
var lastId int64 = 1
|
var lastId int64 = 1
|
||||||
if len(a.BuildReferences) > 0 {
|
if len(a.BuildReferences) > 0 {
|
||||||
lastId = a.BuildReferences[len(a.BuildReferences)-1].ID + 1
|
lastId = a.BuildReferences[len(a.BuildReferences)-1].ID + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
buildReference := &db.BuildReference{
|
buildReference := &apollodb.BuildReference{
|
||||||
ID: lastId,
|
ID: lastId,
|
||||||
AffectedProductId: affectedProductId,
|
AffectedProductId: affectedProductId,
|
||||||
Rpm: rpm,
|
Rpm: rpm,
|
||||||
SrcRpm: srcRpm,
|
SrcRpm: srcRpm,
|
||||||
CveID: cveId,
|
CveID: cveId,
|
||||||
KojiID: kojiId,
|
Sha256Sum: sha256Sum,
|
||||||
|
}
|
||||||
|
if kojiId != nil {
|
||||||
|
buildReference.KojiID = sql.NullString{Valid: true, String: *kojiId}
|
||||||
|
}
|
||||||
|
if peridotId != nil {
|
||||||
|
buildReference.PeridotID = sql.NullString{Valid: true, String: *peridotId}
|
||||||
}
|
}
|
||||||
|
|
||||||
a.BuildReferences = append(a.BuildReferences, buildReference)
|
a.BuildReferences = append(a.BuildReferences, buildReference)
|
||||||
@ -608,7 +691,7 @@ func (a *Access) CreateAdvisoryReference(advisoryId int64, url string) error {
|
|||||||
lastId = a.AdvisoryReferences[len(a.AdvisoryReferences)-1].ID + 1
|
lastId = a.AdvisoryReferences[len(a.AdvisoryReferences)-1].ID + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
advisoryReference := &db.AdvisoryReference{
|
advisoryReference := &apollodb.AdvisoryReference{
|
||||||
ID: lastId,
|
ID: lastId,
|
||||||
URL: url,
|
URL: url,
|
||||||
AdvisoryId: advisoryId,
|
AdvisoryId: advisoryId,
|
||||||
@ -618,11 +701,11 @@ func (a *Access) CreateAdvisoryReference(advisoryId int64, url string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) GetAllIgnoredPackagesByShortCode(code string) ([]string, error) {
|
func (a *Access) GetAllIgnoredPackagesByProductID(productID int64) ([]string, error) {
|
||||||
var packages []string
|
var packages []string
|
||||||
|
|
||||||
for _, ignoredPackage := range a.IgnoredUpstreamPackages {
|
for _, ignoredPackage := range a.IgnoredUpstreamPackages {
|
||||||
if ignoredPackage.ShortCode == code {
|
if ignoredPackage.ProductID == productID {
|
||||||
packages = append(packages, ignoredPackage.Package)
|
packages = append(packages, ignoredPackage.Package)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -630,8 +713,18 @@ func (a *Access) GetAllIgnoredPackagesByShortCode(code string) ([]string, error)
|
|||||||
return packages, nil
|
return packages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllRebootSuggestedPackages() ([]string, error) {
|
||||||
|
var packages []string
|
||||||
|
|
||||||
|
for _, p := range a.RebootSuggestedPackages {
|
||||||
|
packages = append(packages, p.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return packages, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Access) AddAdvisoryFix(advisoryId int64, fixId int64) error {
|
func (a *Access) AddAdvisoryFix(advisoryId int64, fixId int64) error {
|
||||||
advisoryFix := &db.AdvisoryFix{
|
advisoryFix := &apollodb.AdvisoryFix{
|
||||||
AdvisoryID: advisoryId,
|
AdvisoryID: advisoryId,
|
||||||
FixID: fixId,
|
FixID: fixId,
|
||||||
}
|
}
|
||||||
@ -641,7 +734,7 @@ func (a *Access) AddAdvisoryFix(advisoryId int64, fixId int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) AddAdvisoryCVE(advisoryId int64, cveId string) error {
|
func (a *Access) AddAdvisoryCVE(advisoryId int64, cveId string) error {
|
||||||
advisoryCVE := &db.AdvisoryCVE{
|
advisoryCVE := &apollodb.AdvisoryCVE{
|
||||||
AdvisoryID: advisoryId,
|
AdvisoryID: advisoryId,
|
||||||
CveID: cveId,
|
CveID: cveId,
|
||||||
}
|
}
|
||||||
@ -650,10 +743,11 @@ func (a *Access) AddAdvisoryCVE(advisoryId int64, cveId string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) AddAdvisoryRPM(advisoryId int64, name string) error {
|
func (a *Access) AddAdvisoryRPM(advisoryId int64, name string, productID int64) error {
|
||||||
advisoryRPM := &db.AdvisoryRPM{
|
advisoryRPM := &apollodb.AdvisoryRPM{
|
||||||
AdvisoryID: advisoryId,
|
AdvisoryID: advisoryId,
|
||||||
Name: name,
|
Name: name,
|
||||||
|
ProductID: productID,
|
||||||
}
|
}
|
||||||
a.AdvisoryRPMs = append(a.AdvisoryRPMs, advisoryRPM)
|
a.AdvisoryRPMs = append(a.AdvisoryRPMs, advisoryRPM)
|
||||||
|
|
||||||
@ -664,6 +758,6 @@ func (a *Access) Begin() (utils.Tx, error) {
|
|||||||
return &utils.MockTx{}, nil
|
return &utils.MockTx{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Access) UseTransaction(_ utils.Tx) db.Access {
|
func (a *Access) UseTransaction(_ utils.Tx) apollodb.Access {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
@ -3,12 +3,13 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||||||
go_library(
|
go_library(
|
||||||
name = "psql",
|
name = "psql",
|
||||||
srcs = ["psql.go"],
|
srcs = ["psql.go"],
|
||||||
importpath = "peridot.resf.org/secparse/db/psql",
|
importpath = "peridot.resf.org/apollo/db/psql",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//secparse/admin/proto/v1:proto",
|
"//apollo/db",
|
||||||
"//secparse/db",
|
"//apollo/proto/v1:pb",
|
||||||
"//utils",
|
"//utils",
|
||||||
"//vendor/github.com/jmoiron/sqlx",
|
"//vendor/github.com/jmoiron/sqlx",
|
||||||
|
"//vendor/github.com/jmoiron/sqlx/types",
|
||||||
],
|
],
|
||||||
)
|
)
|
802
apollo/db/psql/psql.go
Normal file
802
apollo/db/psql/psql.go
Normal file
@ -0,0 +1,802 @@
|
|||||||
|
// Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
|
||||||
|
// Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
|
||||||
|
// Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
// may be used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package apollopsql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"github.com/jmoiron/sqlx/types"
|
||||||
|
apollodb "peridot.resf.org/apollo/db"
|
||||||
|
apollopb "peridot.resf.org/apollo/pb"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"peridot.resf.org/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Access struct {
|
||||||
|
db *sqlx.DB
|
||||||
|
query utils.SqlQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Access {
|
||||||
|
pgx := utils.PgInitx()
|
||||||
|
return &Access{
|
||||||
|
db: pgx,
|
||||||
|
query: pgx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllShortCodes() ([]*apollodb.ShortCode, error) {
|
||||||
|
var shortCodes []*apollodb.ShortCode
|
||||||
|
err := a.query.Select(
|
||||||
|
&shortCodes,
|
||||||
|
`
|
||||||
|
select
|
||||||
|
code,
|
||||||
|
mode,
|
||||||
|
created_at,
|
||||||
|
archived_at
|
||||||
|
from short_codes
|
||||||
|
order by created_at desc
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return shortCodes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetShortCodeByCode(code string) (*apollodb.ShortCode, error) {
|
||||||
|
var shortCode apollodb.ShortCode
|
||||||
|
err := a.query.Get(&shortCode, "select code, mode, created_at from short_codes where code = $1", code)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &shortCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateShortCode(code string, mode apollopb.ShortCode_Mode) (*apollodb.ShortCode, error) {
|
||||||
|
var shortCode apollodb.ShortCode
|
||||||
|
err := a.query.Get(&shortCode, "insert into short_codes (code, mode) values ($1, $2) returning code, mode, created_at", code, int(mode))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &shortCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllAdvisories(filters *apollopb.AdvisoryFilters, page int32, limit int32) ([]*apollodb.Advisory, error) {
|
||||||
|
if filters == nil {
|
||||||
|
filters = &apollopb.AdvisoryFilters{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var advisories []*apollodb.Advisory
|
||||||
|
err := a.query.Select(
|
||||||
|
&advisories,
|
||||||
|
`
|
||||||
|
select
|
||||||
|
q1.*
|
||||||
|
from
|
||||||
|
(
|
||||||
|
select
|
||||||
|
a.id,
|
||||||
|
a.created_at,
|
||||||
|
a.year,
|
||||||
|
a.num,
|
||||||
|
a.synopsis,
|
||||||
|
a.topic,
|
||||||
|
a.severity,
|
||||||
|
a.type,
|
||||||
|
a.description,
|
||||||
|
a.solution,
|
||||||
|
a.redhat_issued_at,
|
||||||
|
a.short_code_code,
|
||||||
|
a.reboot_suggested,
|
||||||
|
a.published_at,
|
||||||
|
array_remove(array_agg(distinct p.name), NULL) as affected_products,
|
||||||
|
(select array_agg(distinct(
|
||||||
|
case when c.content is null then c.source_by || ':::' || c.source_link || ':::' || c.id || ':::::::::'
|
||||||
|
else c.source_by || ':::' || c.source_link || ':::' || c.id || ':::' || jsonb_extract_path_text(c.content, 'cvss3', 'cvss3_scoring_vector') || ':::' || jsonb_extract_path_text(c.content, 'cvss3', 'cvss3_base_score') || ':::' || jsonb_extract_path_text(c.content, 'cwe')
|
||||||
|
end
|
||||||
|
)) from advisory_cves ac inner join cves c on c.id = ac.cve_id where ac.advisory_id = a.id) as cves,
|
||||||
|
(select array_agg(distinct(url)) from advisory_references where advisory_id = a.id) as references,
|
||||||
|
case when $4 :: bool = true then array(select distinct concat(rpm, ':::', src_rpm) from build_references where affected_product_id in (select id from affected_products where advisory = 'RH' || (case when a.type=1 then 'SA' when a.type=2 then 'BA' else 'EA' end) || '-' || a.year || ':' || a.num))
|
||||||
|
else array [] :: text[]
|
||||||
|
end as build_artifacts,
|
||||||
|
case when $7 :: bool = true then array(select distinct(ar.name || ':::' || p.name) from advisory_rpms ar inner join products p on p.id = ar.product_id where advisory_id = a.id)
|
||||||
|
else array [] :: text[]
|
||||||
|
end as rpms,
|
||||||
|
count(a.*) over() as total
|
||||||
|
from advisories a
|
||||||
|
inner join affected_products ap on ap.advisory = 'RH' || (case when a.type=1 then 'SA' when a.type=2 then 'BA' else 'EA' end) || '-' || a.year || ':' || a.num
|
||||||
|
inner join products p on ap.product_id = p.id
|
||||||
|
where
|
||||||
|
($1 :: text is null or p.name = $1 :: text)
|
||||||
|
and ($2 :: timestamp is null or a.published_at < $2 :: timestamp)
|
||||||
|
and ($3 :: timestamp is null or a.published_at > $3 :: timestamp)
|
||||||
|
and (a.published_at is not null or $4 :: bool = true)
|
||||||
|
and ($6 :: text is null or a.synopsis ilike '%' || $6 :: text || '%')
|
||||||
|
and ($9 :: numeric = 0 or a.severity = $9 :: numeric)
|
||||||
|
and ($10 :: numeric = 0 or a.type = $10 :: numeric)
|
||||||
|
group by a.id
|
||||||
|
order by a.published_at desc
|
||||||
|
limit $11 offset $12
|
||||||
|
) as q1
|
||||||
|
where
|
||||||
|
($8 :: text is null or ((q1.synopsis ilike '%' || $8 :: text || '%') or (q1.topic ilike '%' || $8 :: text || '%') or (q1.description ilike '%' || $8 :: text || '%') or (q1.solution ilike '%' || $8 :: text || '%') or exists (select from unnest(q1.cves) e where e ilike '%' || $8 :: text || '%')))
|
||||||
|
and ($5 :: text is null or exists (select from unnest(q1.cves) e where e ilike '%' || $5 :: text || '%'))
|
||||||
|
`,
|
||||||
|
utils.StringValueToNullString(filters.Product),
|
||||||
|
utils.TimestampToNullTime(filters.Before),
|
||||||
|
utils.TimestampToNullTime(filters.After),
|
||||||
|
utils.BoolValueP(filters.IncludeUnpublished),
|
||||||
|
utils.StringValueToNullString(filters.Cve),
|
||||||
|
utils.StringValueToNullString(filters.Synopsis),
|
||||||
|
utils.BoolValueP(filters.IncludeRpms),
|
||||||
|
utils.StringValueToNullString(filters.Keyword),
|
||||||
|
int32(filters.Severity),
|
||||||
|
int32(filters.Type),
|
||||||
|
utils.UnlimitedLimit(limit),
|
||||||
|
utils.GetOffset(page, limit),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return advisories, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAdvisoryByCodeAndYearAndNum(code string, year int, num int) (*apollodb.Advisory, error) {
|
||||||
|
var advisory apollodb.Advisory
|
||||||
|
err := a.query.Get(
|
||||||
|
&advisory,
|
||||||
|
`
|
||||||
|
select
|
||||||
|
a.id,
|
||||||
|
a.created_at,
|
||||||
|
a.year,
|
||||||
|
a.num,
|
||||||
|
a.synopsis,
|
||||||
|
a.topic,
|
||||||
|
a.severity,
|
||||||
|
a.type,
|
||||||
|
a.description,
|
||||||
|
a.solution,
|
||||||
|
a.redhat_issued_at,
|
||||||
|
a.short_code_code,
|
||||||
|
a.reboot_suggested,
|
||||||
|
a.published_at,
|
||||||
|
array_remove(array_agg(distinct p.name), NULL) as affected_products,
|
||||||
|
(select array_agg(distinct(f.ticket || ':::' || f.source_by || ':::' || f.source_link || ':::' || f.description)) from advisory_fixes adf inner join fixes f on f.id = adf.fix_id where adf.advisory_id = a.id) as fixes,
|
||||||
|
(select array_agg(distinct(
|
||||||
|
case when c.content is null then c.source_by || ':::' || c.source_link || ':::' || c.id || ':::::::::'
|
||||||
|
else c.source_by || ':::' || c.source_link || ':::' || c.id || ':::' || jsonb_extract_path_text(c.content, 'cvss3', 'cvss3_scoring_vector') || ':::' || jsonb_extract_path_text(c.content, 'cvss3', 'cvss3_base_score') || ':::' || jsonb_extract_path_text(c.content, 'cwe')
|
||||||
|
end
|
||||||
|
)) from advisory_cves ac inner join cves c on c.id = ac.cve_id where ac.advisory_id = a.id) as cves,
|
||||||
|
(select array_agg(distinct(url)) from advisory_references where advisory_id = a.id) as references,
|
||||||
|
(select array_agg(distinct(ar.name || ':::' || p.name)) from advisory_rpms ar inner join products p on p.id = ar.product_id where advisory_id = a.id) as rpms
|
||||||
|
from advisories a
|
||||||
|
inner join affected_products ap on ap.advisory = 'RH' || (case when a.type=1 then 'SA' when a.type=2 then 'BA' else 'EA' end) || '-' || a.year || ':' || a.num
|
||||||
|
inner join products p on ap.product_id = p.id
|
||||||
|
where
|
||||||
|
a.year = $1
|
||||||
|
and a.num = $2
|
||||||
|
and a.short_code_code = $3
|
||||||
|
group by a.id
|
||||||
|
`,
|
||||||
|
year,
|
||||||
|
num,
|
||||||
|
code,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &advisory, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateAdvisory(advisory *apollodb.Advisory) (*apollodb.Advisory, error) {
|
||||||
|
var ret apollodb.Advisory
|
||||||
|
|
||||||
|
var redHatIssuedAt *time.Time
|
||||||
|
var publishedAt *time.Time
|
||||||
|
|
||||||
|
if advisory.RedHatIssuedAt.Valid {
|
||||||
|
redHatIssuedAt = &advisory.RedHatIssuedAt.Time
|
||||||
|
}
|
||||||
|
if advisory.PublishedAt.Valid {
|
||||||
|
publishedAt = &advisory.PublishedAt.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
err := a.query.Get(
|
||||||
|
&ret,
|
||||||
|
`
|
||||||
|
insert into advisories
|
||||||
|
(year, num, synopsis, topic, severity, type, description, solution,
|
||||||
|
redhat_issued_at, short_code_code, reboot_suggested, published_at)
|
||||||
|
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||||
|
returning
|
||||||
|
id,
|
||||||
|
created_at,
|
||||||
|
year,
|
||||||
|
num,
|
||||||
|
synopsis,
|
||||||
|
topic,
|
||||||
|
severity,
|
||||||
|
type,
|
||||||
|
description,
|
||||||
|
solution,
|
||||||
|
redhat_issued_at,
|
||||||
|
short_code_code,
|
||||||
|
reboot_suggested,
|
||||||
|
published_at
|
||||||
|
`,
|
||||||
|
advisory.Year,
|
||||||
|
advisory.Num,
|
||||||
|
advisory.Synopsis,
|
||||||
|
advisory.Topic,
|
||||||
|
advisory.Severity,
|
||||||
|
advisory.Type,
|
||||||
|
advisory.Description,
|
||||||
|
advisory.Solution,
|
||||||
|
redHatIssuedAt,
|
||||||
|
advisory.ShortCodeCode,
|
||||||
|
advisory.RebootSuggested,
|
||||||
|
publishedAt,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) UpdateAdvisory(advisory *apollodb.Advisory) (*apollodb.Advisory, error) {
|
||||||
|
var ret apollodb.Advisory
|
||||||
|
|
||||||
|
var publishedAt *time.Time
|
||||||
|
|
||||||
|
if advisory.PublishedAt.Valid {
|
||||||
|
publishedAt = &advisory.PublishedAt.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
err := a.query.Get(
|
||||||
|
&ret,
|
||||||
|
`
|
||||||
|
update advisories
|
||||||
|
set
|
||||||
|
year = $1,
|
||||||
|
num = $2,
|
||||||
|
synopsis = $3,
|
||||||
|
topic = $4,
|
||||||
|
severity = $5,
|
||||||
|
type = $6,
|
||||||
|
description = $7,
|
||||||
|
solution = $8,
|
||||||
|
short_code_code = $9,
|
||||||
|
reboot_suggested = $10,
|
||||||
|
published_at = $11
|
||||||
|
where
|
||||||
|
id = $12
|
||||||
|
returning
|
||||||
|
id,
|
||||||
|
created_at,
|
||||||
|
year,
|
||||||
|
num,
|
||||||
|
synopsis,
|
||||||
|
topic,
|
||||||
|
severity,
|
||||||
|
type,
|
||||||
|
description,
|
||||||
|
solution,
|
||||||
|
redhat_issued_at,
|
||||||
|
short_code_code,
|
||||||
|
reboot_suggested,
|
||||||
|
published_at
|
||||||
|
`,
|
||||||
|
advisory.Year,
|
||||||
|
advisory.Num,
|
||||||
|
advisory.Synopsis,
|
||||||
|
advisory.Topic,
|
||||||
|
advisory.Severity,
|
||||||
|
advisory.Type,
|
||||||
|
advisory.Description,
|
||||||
|
advisory.Solution,
|
||||||
|
advisory.ShortCodeCode,
|
||||||
|
advisory.RebootSuggested,
|
||||||
|
publishedAt,
|
||||||
|
advisory.ID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllUnresolvedCVEs() ([]*apollodb.CVE, error) {
|
||||||
|
var cves []*apollodb.CVE
|
||||||
|
err := a.query.Select(
|
||||||
|
&cves,
|
||||||
|
`
|
||||||
|
select
|
||||||
|
c.id,
|
||||||
|
c.created_at,
|
||||||
|
c.short_code_code,
|
||||||
|
c.source_by,
|
||||||
|
c.source_link,
|
||||||
|
c.content,
|
||||||
|
ap.id as affected_product_id
|
||||||
|
from cves c
|
||||||
|
left join affected_products ap on ap.cve_id = c.id
|
||||||
|
where (ap.state is null or ap.state in (1, 2, 8, 9))
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cves, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetPendingAffectedProducts() ([]*apollodb.AffectedProduct, error) {
|
||||||
|
var ret []*apollodb.AffectedProduct
|
||||||
|
err := a.query.Select(
|
||||||
|
&ret,
|
||||||
|
`
|
||||||
|
select
|
||||||
|
ap.id,
|
||||||
|
ap.product_id,
|
||||||
|
ap.cve_id,
|
||||||
|
ap.state,
|
||||||
|
ap.version,
|
||||||
|
ap.package,
|
||||||
|
ap.advisory
|
||||||
|
from affected_products ap
|
||||||
|
where ap.state = 3
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllCVEsFixedDownstream() ([]*apollodb.CVE, error) {
|
||||||
|
var cves []*apollodb.CVE
|
||||||
|
err := a.query.Select(
|
||||||
|
&cves,
|
||||||
|
`
|
||||||
|
select
|
||||||
|
c.id,
|
||||||
|
c.created_at,
|
||||||
|
c.short_code_code,
|
||||||
|
c.source_by,
|
||||||
|
c.source_link,
|
||||||
|
c.content,
|
||||||
|
ap.id as affected_product_id
|
||||||
|
from cves c
|
||||||
|
inner join affected_products ap on ap.cve_id = c.id
|
||||||
|
where
|
||||||
|
ap.state = 4
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cves, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetCVEByID(id string) (*apollodb.CVE, error) {
|
||||||
|
var cve apollodb.CVE
|
||||||
|
err := a.query.Get(&cve, "select id, created_at, short_code_code, source_by, source_link, content from cves where id = $1", id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cve, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllCVEs() ([]*apollodb.CVE, error) {
|
||||||
|
var cves []*apollodb.CVE
|
||||||
|
err := a.query.Select(&cves, "select id, created_at, short_code_code, source_by, source_link, content from cves")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cves, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateCVE(cveId string, shortCode string, sourceBy *string, sourceLink *string, content types.NullJSONText) (*apollodb.CVE, error) {
|
||||||
|
var cve apollodb.CVE
|
||||||
|
err := a.query.Get(&cve, "insert into cves (id, short_code_code, source_by, source_link, content) values ($1, $2, $3, $4, $5) returning id, created_at, short_code_code, source_by, source_link, content", cveId, shortCode, sourceBy, sourceLink, content)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cve, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) SetCVEContent(cveId string, content types.JSONText) error {
|
||||||
|
_, err := a.query.Exec("update cves set content = $1 where id = $2", content, cveId)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetProductsByShortCode(code string) ([]*apollodb.Product, error) {
|
||||||
|
var products []*apollodb.Product
|
||||||
|
err := a.query.Select(
|
||||||
|
&products,
|
||||||
|
`
|
||||||
|
select
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
current_full_version,
|
||||||
|
redhat_major_version,
|
||||||
|
short_code_code,
|
||||||
|
archs,
|
||||||
|
mirror_from_date,
|
||||||
|
redhat_product_prefix,
|
||||||
|
cpe,
|
||||||
|
eol_at,
|
||||||
|
build_system,
|
||||||
|
build_system_endpoint,
|
||||||
|
koji_compose,
|
||||||
|
koji_module_compose,
|
||||||
|
peridot_project_id
|
||||||
|
from products
|
||||||
|
where
|
||||||
|
short_code_code = $1
|
||||||
|
and (eol_at < now() or eol_at is null)
|
||||||
|
`,
|
||||||
|
code,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return products, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetProductByNameAndShortCode(name string, code string) (*apollodb.Product, error) {
|
||||||
|
var product apollodb.Product
|
||||||
|
err := a.query.Get(
|
||||||
|
&product,
|
||||||
|
`
|
||||||
|
select
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
current_full_version,
|
||||||
|
redhat_major_version,
|
||||||
|
short_code_code,
|
||||||
|
archs,
|
||||||
|
mirror_from_date,
|
||||||
|
redhat_product_prefix,
|
||||||
|
cpe,
|
||||||
|
eol_at,
|
||||||
|
build_system,
|
||||||
|
build_system_endpoint,
|
||||||
|
koji_compose,
|
||||||
|
koji_module_compose,
|
||||||
|
peridot_project_id
|
||||||
|
from products
|
||||||
|
where
|
||||||
|
name = $1
|
||||||
|
and short_code_code = $2
|
||||||
|
`,
|
||||||
|
name,
|
||||||
|
code,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &product, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetProductByID(id int64) (*apollodb.Product, error) {
|
||||||
|
var product apollodb.Product
|
||||||
|
err := a.query.Get(
|
||||||
|
&product,
|
||||||
|
`
|
||||||
|
select
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
current_full_version,
|
||||||
|
redhat_major_version,
|
||||||
|
short_code_code,
|
||||||
|
archs,
|
||||||
|
mirror_from_date,
|
||||||
|
redhat_product_prefix,
|
||||||
|
cpe,
|
||||||
|
eol_at,
|
||||||
|
build_system,
|
||||||
|
build_system_endpoint,
|
||||||
|
koji_compose,
|
||||||
|
koji_module_compose,
|
||||||
|
peridot_project_id
|
||||||
|
from products
|
||||||
|
where
|
||||||
|
id = $1
|
||||||
|
`,
|
||||||
|
id,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &product, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateProduct(name string, currentFullVersion string, redHatMajorVersion *int32, code string, archs []string) (*apollodb.Product, error) {
|
||||||
|
var product apollodb.Product
|
||||||
|
err := a.query.Get(&product, "insert into products (name, current_full_version, redhat_major_version, short_code_code, archs) values ($1, $2, $3, $4) returning id, name, current_full_version, redhat_major_version, short_code_code, archs", name, currentFullVersion, redHatMajorVersion, code, archs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &product, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllAffectedProductsByCVE(cve string) ([]*apollodb.AffectedProduct, error) {
|
||||||
|
var affectedProducts []*apollodb.AffectedProduct
|
||||||
|
err := a.query.Select(&affectedProducts, "select id, product_id, cve_id, state, version, package, advisory from affected_products where cve_id = $1", cve)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return affectedProducts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAffectedProductByCVEAndPackage(cve string, pkg string) (*apollodb.AffectedProduct, error) {
|
||||||
|
var affectedProduct apollodb.AffectedProduct
|
||||||
|
err := a.query.Get(&affectedProduct, "select id, product_id, cve_id, state, version, package, advisory from affected_products where cve_id = $1 and package = $2", cve, pkg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &affectedProduct, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAffectedProductByAdvisory(advisory string) (*apollodb.AffectedProduct, error) {
|
||||||
|
var affectedProduct apollodb.AffectedProduct
|
||||||
|
err := a.query.Get(&affectedProduct, "select id, product_id, cve_id, state, version, package, advisory from affected_products where advisory = $1", advisory)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &affectedProduct, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAffectedProductByID(id int64) (*apollodb.AffectedProduct, error) {
|
||||||
|
var affectedProduct apollodb.AffectedProduct
|
||||||
|
err := a.query.Get(&affectedProduct, "select id, product_id, cve_id, state, version, package, advisory from affected_products where id = $1", id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &affectedProduct, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateAffectedProduct(productId int64, cveId string, state int, version string, pkg string, advisory *string) (*apollodb.AffectedProduct, error) {
|
||||||
|
var affectedProduct apollodb.AffectedProduct
|
||||||
|
err := a.query.Get(&affectedProduct, "insert into affected_products (product_id, cve_id, state, version, package, advisory) values ($1, $2, $3, $4, $5, $6) returning id, product_id, cve_id, state, version, package, advisory", productId, cveId, state, version, pkg, advisory)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &affectedProduct, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) UpdateAffectedProductStateAndPackageAndAdvisory(id int64, state int, pkg string, advisory *string) error {
|
||||||
|
_, err := a.query.Exec(
|
||||||
|
`
|
||||||
|
update affected_products
|
||||||
|
set
|
||||||
|
state = $1,
|
||||||
|
package = $2,
|
||||||
|
advisory = $3
|
||||||
|
where id = $4
|
||||||
|
`,
|
||||||
|
state,
|
||||||
|
pkg,
|
||||||
|
advisory,
|
||||||
|
id,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) DeleteAffectedProduct(id int64) error {
|
||||||
|
_, err := a.query.Exec(
|
||||||
|
`
|
||||||
|
delete from affected_products
|
||||||
|
where id = $1
|
||||||
|
`,
|
||||||
|
id,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateFix(ticket string, sourceBy string, sourceLink, description string) (int64, error) {
|
||||||
|
var id int64
|
||||||
|
err := a.query.Get(&id, "insert into fixes (ticket, source_by, source_link, description) values ($1, $2, $3, $4) returning id", ticket, sourceBy, sourceLink, description)
|
||||||
|
return id, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetMirrorState(code string) (*apollodb.MirrorState, error) {
|
||||||
|
var lastSync apollodb.MirrorState
|
||||||
|
err := a.query.Get(&lastSync, "select short_code_code, last_sync, errata_after from mirror_state where short_code_code = $1", code)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &lastSync, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) UpdateMirrorState(code string, lastSync *time.Time) error {
|
||||||
|
_, err := a.query.Exec(
|
||||||
|
`
|
||||||
|
insert into mirror_state (short_code_code, last_sync)
|
||||||
|
values ($1, $2)
|
||||||
|
on conflict (short_code_code) do
|
||||||
|
update
|
||||||
|
set last_sync = EXCLUDED.last_sync
|
||||||
|
`,
|
||||||
|
code,
|
||||||
|
lastSync,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) UpdateMirrorStateErrata(code string, lastSync *time.Time) error {
|
||||||
|
_, err := a.query.Exec(
|
||||||
|
`
|
||||||
|
insert into mirror_state (short_code_code, errata_after)
|
||||||
|
values ($1, $2)
|
||||||
|
on conflict (short_code_code) do
|
||||||
|
update
|
||||||
|
set errata_after = EXCLUDED.errata_after
|
||||||
|
`,
|
||||||
|
code,
|
||||||
|
lastSync,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetMaxLastSync() (*time.Time, error) {
|
||||||
|
var lastSync time.Time
|
||||||
|
err := a.query.Get(&lastSync, "select max(last_sync) from mirror_state")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &lastSync, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateBuildReference(affectedProductId int64, rpm string, srcRpm string, cveId string, sha256Sum string, kojiId *string, peridotId *string) (*apollodb.BuildReference, error) {
|
||||||
|
var buildReference apollodb.BuildReference
|
||||||
|
err := a.query.Get(
|
||||||
|
&buildReference,
|
||||||
|
`
|
||||||
|
insert into build_references
|
||||||
|
(affected_product_id, rpm, src_rpm, cve_id, sha256_sum, koji_id, peridot_id)
|
||||||
|
values ($1, $2, $3, $4, $5, $6, $7)
|
||||||
|
returning id, affected_product_id, rpm, src_rpm, cve_id, sha256_sum, koji_id, peridot_id
|
||||||
|
`,
|
||||||
|
affectedProductId,
|
||||||
|
rpm,
|
||||||
|
srcRpm,
|
||||||
|
cveId,
|
||||||
|
sha256Sum,
|
||||||
|
kojiId,
|
||||||
|
peridotId,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &buildReference, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) CreateAdvisoryReference(advisoryId int64, url string) error {
|
||||||
|
_, err := a.query.Exec("insert into advisory_references (advisory_id, url) values ($1, $2)", advisoryId, url)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllIgnoredPackagesByProductID(productID int64) ([]string, error) {
|
||||||
|
var packages []string
|
||||||
|
err := a.query.Select(&packages, "select package from ignored_upstream_packages where product_id = $1", productID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return packages, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) GetAllRebootSuggestedPackages() ([]string, error) {
|
||||||
|
var packages []string
|
||||||
|
err := a.query.Select(&packages, "select name from reboot_suggested_packages")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return packages, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) AddAdvisoryFix(advisoryId int64, fixId int64) error {
|
||||||
|
_, err := a.query.Exec("insert into advisory_fixes (advisory_id, fix_id) values ($1, $2) on conflict do nothing", advisoryId, fixId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) AddAdvisoryCVE(advisoryId int64, cveId string) error {
|
||||||
|
_, err := a.query.Exec("insert into advisory_cves (advisory_id, cve_id) values ($1, $2) on conflict do nothing", advisoryId, cveId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) AddAdvisoryRPM(advisoryId int64, name string, productID int64) error {
|
||||||
|
_, err := a.query.Exec("insert into advisory_rpms (advisory_id, name, product_id) values ($1, $2, $3) on conflict do nothing", advisoryId, name, productID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) Begin() (utils.Tx, error) {
|
||||||
|
tx, err := a.db.Beginx()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Access) UseTransaction(tx utils.Tx) apollodb.Access {
|
||||||
|
newAccess := *a
|
||||||
|
newAccess.query = tx
|
||||||
|
|
||||||
|
return &newAccess
|
||||||
|
}
|
@ -6,16 +6,21 @@ go_library(
|
|||||||
"advisory.go",
|
"advisory.go",
|
||||||
"server.go",
|
"server.go",
|
||||||
],
|
],
|
||||||
importpath = "peridot.resf.org/secparse/impl",
|
importpath = "peridot.resf.org/apollo/impl/v1",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//secparse/db",
|
"//apollo/db",
|
||||||
"//secparse/proto/v1:proto",
|
"//apollo/proto/v1:pb",
|
||||||
"//secparse/rpmutils",
|
"//apollo/rpmutils",
|
||||||
|
"//proto:common",
|
||||||
"//utils",
|
"//utils",
|
||||||
|
"//vendor/github.com/gorilla/feeds",
|
||||||
"//vendor/github.com/sirupsen/logrus",
|
"//vendor/github.com/sirupsen/logrus",
|
||||||
|
"//vendor/github.com/spf13/viper",
|
||||||
|
"@go_googleapis//google/api:httpbody_go_proto",
|
||||||
"@org_golang_google_grpc//:go_default_library",
|
"@org_golang_google_grpc//:go_default_library",
|
||||||
"@org_golang_google_grpc//codes",
|
"@org_golang_google_grpc//codes",
|
||||||
"@org_golang_google_grpc//status",
|
"@org_golang_google_grpc//status",
|
||||||
|
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
182
apollo/impl/v1/advisory.go
Normal file
182
apollo/impl/v1/advisory.go
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
// Copyright (c) All respective contributors to the Peridot Project. All rights reserved.
|
||||||
|
// Copyright (c) 2021-2022 Rocky Enterprise Software Foundation, Inc. All rights reserved.
|
||||||
|
// Copyright (c) 2021-2022 Ctrl IQ, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
// this list of conditions and the following disclaimer in the documentation
|
||||||
|
// and/or other materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
// may be used to endorse or promote products derived from this software without
|
||||||
|
// specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
package apolloimpl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gorilla/feeds"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"google.golang.org/genproto/googleapis/api/httpbody"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
apollodb "peridot.resf.org/apollo/db"
|
||||||
|
apollopb "peridot.resf.org/apollo/pb"
|
||||||
|
"peridot.resf.org/apollo/rpmutils"
|
||||||
|
"peridot.resf.org/utils"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) ListAdvisories(_ context.Context, req *apollopb.ListAdvisoriesRequest) (*apollopb.ListAdvisoriesResponse, error) {
|
||||||
|
if err := req.ValidateAll(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if req.Filters != nil {
|
||||||
|
req.Filters.IncludeUnpublished = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
page := utils.MinPage(req.Page)
|
||||||
|
limit := utils.MinLimit(req.Limit)
|
||||||
|
ret, err := s.db.GetAllAdvisories(req.Filters, page, limit)
|
||||||
|
if err != nil {
|
||||||
|
s.log.Errorf("could not get advisories, error: %s", err)
|
||||||
|
return nil, status.Error(codes.Internal, "failed to list advisories")
|
||||||
|
}
|
||||||
|
total := int64(0)
|
||||||
|
if len(ret) > 0 {
|
||||||
|
total = ret[0].Total
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastUpdatedPb *timestamppb.Timestamp
|
||||||
|
lastUpdated, err := s.db.GetMaxLastSync()
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
s.log.Errorf("could not get last sync time, error: %s", err)
|
||||||
|
return nil, status.Error(codes.Internal, "failed to get last updated")
|
||||||
|
}
|
||||||
|
if lastUpdated != nil {
|
||||||
|
lastUpdatedPb = timestamppb.New(*lastUpdated)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &apollopb.ListAdvisoriesResponse{
|
||||||
|
Advisories: apollodb.DTOListAdvisoriesToPB(ret),
|
||||||
|
Total: total,
|
||||||
|
Page: page,
|
||||||
|
Size: limit,
|
||||||
|
LastUpdated: lastUpdatedPb,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) ListAdvisoriesRSS(_ context.Context, req *apollopb.ListAdvisoriesRSSRequest) (*httpbody.HttpBody, error) {
|
||||||
|
if err := req.ValidateAll(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if req.Filters == nil {
|
||||||
|
req.Filters = &apollopb.AdvisoryFilters{}
|
||||||
|
}
|
||||||
|
req.Filters.IncludeUnpublished = nil
|
||||||
|
|
||||||
|
ret, err := s.db.GetAllAdvisories(req.Filters, 0, 25)
|
||||||
|
if err != nil {
|
||||||
|
s.log.Errorf("could not get advisories, error: %s", err)
|
||||||
|
return nil, status.Error(codes.Internal, "failed to list advisories")
|
||||||
|
}
|
||||||
|
total := int64(0)
|
||||||
|
if len(ret) > 0 {
|
||||||
|
total = ret[0].Total
|
||||||
|
}
|
||||||
|
|
||||||
|
var updated time.Time
|
||||||
|
if total != 0 {
|
||||||
|
updated = ret[0].PublishedAt.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
feed := &feeds.Feed{
|
||||||
|
Title: "Apollo Security RSS Feed",
|
||||||
|
Link: &feeds.Link{Href: s.homepage},
|
||||||
|
Description: "Security advisories issued using Apollo Errata Management",
|
||||||
|
Author: &feeds.Author{
|
||||||
|
Name: "Rocky Enterprise Software Foundation, Inc.",
|
||||||
|
Email: "releng@rockylinux.org",
|
||||||
|
},
|
||||||
|
Updated: updated,
|
||||||
|
Items: []*feeds.Item{},
|
||||||
|
Copyright: "(C) Rocky Enterprise Software Foundation, Inc. 2022. All rights reserved. CVE sources are copyright of their respective owners.",
|
||||||
|
}
|
||||||
|
if s.rssFeedTitle != "" {
|
||||||
|
feed.Title = s.rssFeedTitle
|
||||||
|
}
|
||||||
|
if s.rssFeedDescription != "" {
|
||||||
|
feed.Description = s.rssFeedDescription
|
||||||
|
}
|
||||||
|
for _, a := range ret {
|
||||||
|
dtoToPB := apollodb.DTOAdvisoryToPB(a)
|
||||||
|
item := &feeds.Item{
|
||||||
|
Title: fmt.Sprintf("%s: %s", dtoToPB.Name, a.Synopsis),
|
||||||
|
Link: &feeds.Link{Href: fmt.Sprintf("%s/%s", s.homepage, dtoToPB.Name)},
|
||||||
|
Description: a.Topic,
|
||||||
|
Id: fmt.Sprintf("%d", a.ID),
|
||||||
|
Created: a.PublishedAt.Time,
|
||||||
|
}
|
||||||
|
feed.Items = append(feed.Items, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
rss, err := feed.ToRss()
|
||||||
|
if err != nil {
|
||||||
|
s.log.Errorf("could not generate RSS feed, error: %s", err)
|
||||||
|
return nil, status.Error(codes.Internal, "failed to generate RSS feed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &httpbody.HttpBody{
|
||||||
|
ContentType: "application/rss+xml",
|
||||||
|
Data: []byte(rss),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetAdvisory(_ context.Context, req *apollopb.GetAdvisoryRequest) (*apollopb.GetAdvisoryResponse, error) {
|
||||||
|
if err := req.ValidateAll(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
advisoryId := rpmutils.AdvisoryId().FindStringSubmatch(req.Id)
|
||||||
|
code := advisoryId[1]
|
||||||
|
year, err := strconv.Atoi(advisoryId[3])
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "invalid year")
|
||||||
|
}
|
||||||
|
num, err := strconv.Atoi(advisoryId[4])
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "invalid num")
|
||||||
|
}
|
||||||
|
|
||||||
|
advisory, err := s.db.GetAdvisoryByCodeAndYearAndNum(code, year, num)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
}
|
||||||
|
if err != nil || !advisory.PublishedAt.Valid {
|
||||||
|
return nil, utils.CouldNotFindObject
|
||||||
|
}
|
||||||
|
|
||||||
|
return &apollopb.GetAdvisoryResponse{
|
||||||
|
Advisory: apollodb.DTOAdvisoryToPB(advisory),
|
||||||
|
}, nil
|
||||||
|
}
|
@ -28,50 +28,41 @@
|
|||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package impl
|
package apolloimpl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
hydraclient "github.com/ory/hydra-client-go/client"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"net/url"
|
apollodb "peridot.resf.org/apollo/db"
|
||||||
secparseadminpb "peridot.resf.org/secparse/admin/proto/v1"
|
apollopb "peridot.resf.org/apollo/pb"
|
||||||
"peridot.resf.org/secparse/db"
|
commonpb "peridot.resf.org/common"
|
||||||
"peridot.resf.org/servicecatalog"
|
|
||||||
"peridot.resf.org/utils"
|
"peridot.resf.org/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
secparseadminpb.UnimplementedSecparseAdminServer
|
apollopb.UnimplementedApolloServiceServer
|
||||||
|
|
||||||
log *logrus.Logger
|
log *logrus.Logger
|
||||||
db db.Access
|
db apollodb.Access
|
||||||
hydra *hydraclient.OryHydra
|
rssFeedTitle string
|
||||||
|
rssFeedDescription string
|
||||||
|
homepage string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(db db.Access) *Server {
|
func NewServer(db apollodb.Access) *Server {
|
||||||
publicURL, err := url.Parse(servicecatalog.HydraPublic())
|
|
||||||
if err != nil {
|
|
||||||
logrus.Fatalf("failed to parse hydra public url: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hydraSDK := hydraclient.NewHTTPClientWithConfig(nil, &hydraclient.TransportConfig{
|
|
||||||
Schemes: []string{publicURL.Scheme},
|
|
||||||
Host: publicURL.Host,
|
|
||||||
BasePath: publicURL.Path,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &Server{
|
return &Server{
|
||||||
log: logrus.New(),
|
log: logrus.New(),
|
||||||
db: db,
|
db: db,
|
||||||
hydra: hydraSDK,
|
rssFeedTitle: "RESF Errata Feed",
|
||||||
|
rssFeedDescription: "Advisories issued by the Rocky Enterprise Software Foundation",
|
||||||
|
homepage: viper.GetString("homepage"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) interceptor(ctx context.Context, req interface{}, usi *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
func (s *Server) interceptor(ctx context.Context, req interface{}, usi *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||||
n := utils.EndInterceptor
|
n := utils.EndInterceptor
|
||||||
n = utils.AuthInterceptor(s.hydra, nil, []string{}, true, n)
|
|
||||||
|
|
||||||
return n(ctx, req, usi, handler)
|
return n(ctx, req, usi, handler)
|
||||||
}
|
}
|
||||||
@ -82,18 +73,22 @@ func (s *Server) Run() {
|
|||||||
Interceptor: s.interceptor,
|
Interceptor: s.interceptor,
|
||||||
},
|
},
|
||||||
func(r *utils.Register) {
|
func(r *utils.Register) {
|
||||||
err := secparseadminpb.RegisterSecparseAdminHandlerFromEndpoint(
|
endpoints := []utils.GrpcEndpointRegister{
|
||||||
r.Context,
|
commonpb.RegisterHealthCheckServiceHandlerFromEndpoint,
|
||||||
r.Mux,
|
apollopb.RegisterApolloServiceHandlerFromEndpoint,
|
||||||
r.Endpoint,
|
}
|
||||||
r.Options,
|
|
||||||
)
|
for _, endpoint := range endpoints {
|
||||||
|
err := endpoint(r.Context, r.Mux, r.Endpoint, r.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Fatalf("could not register handler - %s", err)
|
s.log.Fatalf("could not register handler - %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
func(r *utils.RegisterServer) {
|
func(r *utils.RegisterServer) {
|
||||||
secparseadminpb.RegisterSecparseAdminServer(r.Server, s)
|
commonpb.RegisterHealthCheckServiceServer(r.Server, &utils.HealthServer{})
|
||||||
|
|
||||||
|
apollopb.RegisterApolloServiceServer(r.Server, s)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -34,8 +34,6 @@ create table short_codes
|
|||||||
(
|
(
|
||||||
code text not null primary key,
|
code text not null primary key,
|
||||||
mode numeric not null,
|
mode numeric not null,
|
||||||
mirror_from_date timestamp,
|
|
||||||
redhat_product_prefix text,
|
|
||||||
|
|
||||||
created_at timestamp default now() not null,
|
created_at timestamp default now() not null,
|
||||||
archived_at timestamp
|
archived_at timestamp
|
@ -38,5 +38,14 @@ create table products
|
|||||||
redhat_major_version numeric,
|
redhat_major_version numeric,
|
||||||
short_code_code text references short_codes (code) not null,
|
short_code_code text references short_codes (code) not null,
|
||||||
archs text[] not null,
|
archs text[] not null,
|
||||||
eol_at timestamp
|
mirror_from_date timestamp,
|
||||||
|
redhat_product_prefix text,
|
||||||
|
cpe text,
|
||||||
|
eol_at timestamp,
|
||||||
|
|
||||||
|
build_system text not null,
|
||||||
|
build_system_endpoint text not null,
|
||||||
|
koji_compose text,
|
||||||
|
koji_module_compose text,
|
||||||
|
peridot_project_id text
|
||||||
)
|
)
|
@ -47,5 +47,6 @@ create table advisories
|
|||||||
|
|
||||||
redhat_issued_at timestamp null,
|
redhat_issued_at timestamp null,
|
||||||
short_code_code text references short_codes (code) not null,
|
short_code_code text references short_codes (code) not null,
|
||||||
|
reboot_suggested bool default false not null,
|
||||||
published_at timestamp null
|
published_at timestamp null
|
||||||
)
|
)
|
@ -34,7 +34,6 @@ create table cves
|
|||||||
(
|
(
|
||||||
id text primary key,
|
id text primary key,
|
||||||
created_at timestamp default now() not null,
|
created_at timestamp default now() not null,
|
||||||
state numeric not null,
|
|
||||||
short_code_code text references short_codes (code) not null,
|
short_code_code text references short_codes (code) not null,
|
||||||
|
|
||||||
source_by text,
|
source_by text,
|
@ -34,5 +34,7 @@ create table fixes
|
|||||||
(
|
(
|
||||||
id bigserial primary key,
|
id bigserial primary key,
|
||||||
ticket text,
|
ticket text,
|
||||||
|
source_by text,
|
||||||
|
source_link text,
|
||||||
description text
|
description text
|
||||||
)
|
)
|
@ -37,6 +37,7 @@ create table build_references
|
|||||||
rpm text not null,
|
rpm text not null,
|
||||||
src_rpm text not null,
|
src_rpm text not null,
|
||||||
cve_id text references cves (id) not null,
|
cve_id text references cves (id) not null,
|
||||||
|
sha256_sum text not null,
|
||||||
koji_id text,
|
koji_id text,
|
||||||
peridot_id text
|
peridot_id text
|
||||||
)
|
)
|
@ -33,5 +33,6 @@
|
|||||||
create table mirror_state
|
create table mirror_state
|
||||||
(
|
(
|
||||||
short_code_code text references short_codes (code) primary key,
|
short_code_code text references short_codes (code) primary key,
|
||||||
last_sync timestamp
|
last_sync timestamp,
|
||||||
|
errata_after timestamp
|
||||||
);
|
);
|
@ -33,6 +33,6 @@
|
|||||||
create table ignored_upstream_packages
|
create table ignored_upstream_packages
|
||||||
(
|
(
|
||||||
id bigserial primary key,
|
id bigserial primary key,
|
||||||
short_code_code text references short_codes (code) not null,
|
product_id bigint references products (id) not null,
|
||||||
package text not null
|
package text not null
|
||||||
);
|
);
|
@ -34,6 +34,7 @@ create table advisory_rpms
|
|||||||
(
|
(
|
||||||
advisory_id bigint references advisories (id) not null,
|
advisory_id bigint references advisories (id) not null,
|
||||||
name text not null,
|
name text not null,
|
||||||
|
product_id bigint references products (id) not null,
|
||||||
|
|
||||||
unique (advisory_id, name)
|
unique (advisory_id, name)
|
||||||
)
|
)
|
@ -0,0 +1 @@
|
|||||||
|
drop table reboot_suggested_packages;
|
@ -0,0 +1,6 @@
|
|||||||
|
create table reboot_suggested_packages
|
||||||
|
(
|
||||||
|
created_at timestamp default now() not null,
|
||||||
|
|
||||||
|
name text unique not null
|
||||||
|
)
|
9
apollo/migrate/20220921231425_add_indexes.down.sql
Normal file
9
apollo/migrate/20220921231425_add_indexes.down.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
drop index affected_products_advisoryx;
|
||||||
|
drop index affected_products_product_idx;
|
||||||
|
drop index advisory_fixes_advisory_idx;
|
||||||
|
drop index advisory_fixes_fix_idx;
|
||||||
|
drop index advisory_cves_advisory_idx;
|
||||||
|
drop index advisory_cves_cve_idx;
|
||||||
|
drop index advisory_references_advisory_idx;
|
||||||
|
drop index advisory_rpms_advisory_idx;
|
||||||
|
drop index advisory_rpms_product_idx;
|
9
apollo/migrate/20220921231425_add_indexes.up.sql
Normal file
9
apollo/migrate/20220921231425_add_indexes.up.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
create index affected_products_advisoryx on affected_products (advisory);
|
||||||
|
create index affected_products_product_idx on affected_products (product_id);
|
||||||
|
create index advisory_fixes_advisory_idx on advisory_fixes (advisory_id);
|
||||||
|
create index advisory_fixes_fix_idx on advisory_fixes (fix_id);
|
||||||
|
create index advisory_cves_advisory_idx on advisory_cves (advisory_id);
|
||||||
|
create index advisory_cves_cve_idx on advisory_cves (cve_id);
|
||||||
|
create index advisory_references_advisory_idx on advisory_references (advisory_id);
|
||||||
|
create index advisory_rpms_advisory_idx on advisory_rpms (advisory_id);
|
||||||
|
create index advisory_rpms_product_idx on advisory_rpms (product_id);
|
@ -0,0 +1 @@
|
|||||||
|
alter table cves drop column content;
|
1
apollo/migrate/20221020182658_add_content_to_cves.up.sql
Normal file
1
apollo/migrate/20221020182658_add_content_to_cves.up.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
alter table cves add column content jsonb;
|
@ -1,48 +1,58 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
load("@rules_proto//proto:defs.bzl", "proto_library")
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
||||||
load("@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2:defs.bzl", "protoc_gen_openapiv2")
|
load("@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2:defs.bzl", "protoc_gen_openapiv2")
|
||||||
load("@openapi_tools_generator_bazel//:defs.bzl", "openapi_generator")
|
load("@openapi_tools_generator_bazel//:defs.bzl", "openapi_generator")
|
||||||
|
|
||||||
proto_library(
|
proto_library(
|
||||||
name = "secparsepb_proto",
|
name = "apollopb_proto",
|
||||||
srcs = [
|
srcs = [
|
||||||
"advisory.proto",
|
"advisory.proto",
|
||||||
"secparse.proto",
|
"affected_product.proto",
|
||||||
|
"apollo.proto",
|
||||||
|
"build.proto",
|
||||||
|
"cve.proto",
|
||||||
|
"fix.proto",
|
||||||
|
"short_code.proto",
|
||||||
],
|
],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//proto:commonpb_proto",
|
|
||||||
"@com_envoyproxy_protoc_gen_validate//validate:validate_proto",
|
"@com_envoyproxy_protoc_gen_validate//validate:validate_proto",
|
||||||
"@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_proto",
|
|
||||||
"@com_google_protobuf//:timestamp_proto",
|
"@com_google_protobuf//:timestamp_proto",
|
||||||
"@com_google_protobuf//:wrappers_proto",
|
"@com_google_protobuf//:wrappers_proto",
|
||||||
"@go_googleapis//google/api:annotations_proto",
|
"@go_googleapis//google/api:annotations_proto",
|
||||||
|
"@go_googleapis//google/api:httpbody_proto",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
go_proto_library(
|
go_proto_library(
|
||||||
name = "secparsepb_go_proto",
|
name = "apollopb_go_proto",
|
||||||
compilers = [
|
compilers = [
|
||||||
"//:go_apiv2",
|
"//:go_apiv2",
|
||||||
"//:go_grpc",
|
"//:go_grpc",
|
||||||
"//:go_validate",
|
"//:go_validate",
|
||||||
"@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway",
|
"@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway",
|
||||||
],
|
],
|
||||||
importpath = "peridot.resf.org/secparse/proto/v1",
|
importpath = "peridot.resf.org/apollo/pb",
|
||||||
proto = ":secparsepb_proto",
|
proto = ":apollopb_proto",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//proto:common",
|
|
||||||
"@com_envoyproxy_protoc_gen_validate//validate:validate_go_proto",
|
"@com_envoyproxy_protoc_gen_validate//validate:validate_go_proto",
|
||||||
"@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto",
|
|
||||||
"@go_googleapis//google/api:annotations_go_proto",
|
"@go_googleapis//google/api:annotations_go_proto",
|
||||||
|
"@go_googleapis//google/api:httpbody_go_proto",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "pb",
|
||||||
|
embed = [":apollopb_go_proto"],
|
||||||
|
importpath = "peridot.resf.org/apollo/pb",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
protoc_gen_openapiv2(
|
protoc_gen_openapiv2(
|
||||||
name = "openapi",
|
name = "openapi",
|
||||||
proto = ":secparsepb_proto",
|
proto = ":apollopb_proto",
|
||||||
simple_operation_ids = True,
|
simple_operation_ids = True,
|
||||||
single_output = True,
|
single_output = True,
|
||||||
)
|
)
|
||||||
@ -53,10 +63,3 @@ openapi_generator(
|
|||||||
spec = ":openapi",
|
spec = ":openapi",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "proto",
|
|
||||||
embed = [":secparsepb_go_proto"],
|
|
||||||
importpath = "peridot.resf.org/secparse/proto/v1",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
@ -1,22 +1,27 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package resf.secparse;
|
package resf.apollo.v1;
|
||||||
|
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
import "google/protobuf/wrappers.proto";
|
import "google/protobuf/wrappers.proto";
|
||||||
import "validate/validate.proto";
|
import "apollo/proto/v1/cve.proto";
|
||||||
|
import "apollo/proto/v1/fix.proto";
|
||||||
|
|
||||||
option go_package = "peridot.resf.org/secparse/proto/v1;secparsepb";
|
option go_package = "peridot.resf.org/apollo/pb;apollopb";
|
||||||
|
|
||||||
|
message RPMs {
|
||||||
|
repeated string nvras = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Advisory
|
// Advisory
|
||||||
//
|
//
|
||||||
// Product advisory
|
// Product advisory
|
||||||
message Advisory {
|
message Advisory {
|
||||||
enum Type {
|
enum Type {
|
||||||
UnknownType = 0;
|
TYPE_UNKNOWN = 0;
|
||||||
Security = 1;
|
TYPE_SECURITY = 1;
|
||||||
BugFix = 2;
|
TYPE_BUGFIX = 2;
|
||||||
Enhancement = 3;
|
TYPE_ENHANCEMENT = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
@ -42,11 +47,11 @@ message Advisory {
|
|||||||
string synopsis = 4;
|
string synopsis = 4;
|
||||||
|
|
||||||
enum Severity {
|
enum Severity {
|
||||||
UnknownSeverity = 0;
|
SEVERITY_UNKNOWN = 0;
|
||||||
Low = 1;
|
SEVERITY_LOW = 1;
|
||||||
Moderate = 2;
|
SEVERITY_MODERATE = 2;
|
||||||
Important = 3;
|
SEVERITY_IMPORTANT = 3;
|
||||||
Critical = 4;
|
SEVERITY_CRITICAL = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Severity
|
// Severity
|
||||||
@ -78,12 +83,12 @@ message Advisory {
|
|||||||
// Fixes
|
// Fixes
|
||||||
//
|
//
|
||||||
// A list of tickets from upstream bug trackers
|
// A list of tickets from upstream bug trackers
|
||||||
repeated string fixes = 10;
|
repeated Fix fixes = 10;
|
||||||
|
|
||||||
// CVEs
|
// CVEs
|
||||||
//
|
//
|
||||||
// A list of CVEs assigned to this advisory
|
// A list of CVEs assigned to this advisory
|
||||||
repeated string cves = 11;
|
repeated CVE cves = 11;
|
||||||
|
|
||||||
// References
|
// References
|
||||||
//
|
//
|
||||||
@ -98,60 +103,10 @@ message Advisory {
|
|||||||
// RPMs
|
// RPMs
|
||||||
//
|
//
|
||||||
// Affected RPMs
|
// Affected RPMs
|
||||||
repeated string rpms = 14;
|
map<string, RPMs> rpms = 14;
|
||||||
}
|
|
||||||
|
// Reboot suggested
|
||||||
// ListAdvisoriesRequest
|
//
|
||||||
//
|
// Whether a system reboot should be suggested after applying this advisory
|
||||||
// Request body for `ListAdvisories`
|
bool reboot_suggested = 15;
|
||||||
// All fields are optional
|
|
||||||
message ListAdvisoriesRequest {
|
|
||||||
// Product
|
|
||||||
//
|
|
||||||
// The product to fetch advisories for
|
|
||||||
// For example: Rocky Linux, RL or Rocky
|
|
||||||
string product = 1;
|
|
||||||
|
|
||||||
// Version
|
|
||||||
//
|
|
||||||
// The version to fetch advisories for
|
|
||||||
// For example: 8.3 or 8.4
|
|
||||||
string version = 2;
|
|
||||||
|
|
||||||
// Before
|
|
||||||
//
|
|
||||||
// Advisories published before timestamp
|
|
||||||
google.protobuf.Timestamp before = 3;
|
|
||||||
|
|
||||||
// After
|
|
||||||
//
|
|
||||||
// Advisories published after timestamp
|
|
||||||
google.protobuf.Timestamp after = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListAdvisoriesResponse
|
|
||||||
//
|
|
||||||
// Response body for `ListAdvisories`
|
|
||||||
message ListAdvisoriesResponse {
|
|
||||||
repeated Advisory advisories = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAdvisoryRequest
|
|
||||||
//
|
|
||||||
// Request body for `GetAdvisory`
|
|
||||||
message GetAdvisoryRequest {
|
|
||||||
// ID
|
|
||||||
//
|
|
||||||
// Errata ID
|
|
||||||
// Example: RLSA:2021-1515
|
|
||||||
string id = 1 [(validate.rules).string = {
|
|
||||||
pattern: "^(.+)([SEB]A)-([0-9]{4}):([0-9]+)$",
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAdvisoryResponse
|
|
||||||
//
|
|
||||||
// Response body for `GetAdvisory`
|
|
||||||
message GetAdvisoryResponse {
|
|
||||||
Advisory advisory = 1;
|
|
||||||
}
|
}
|
41
apollo/proto/v1/affected_product.proto
Normal file
41
apollo/proto/v1/affected_product.proto
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package resf.apollo.v1;
|
||||||
|
|
||||||
|
import "google/protobuf/wrappers.proto";
|
||||||
|
|
||||||
|
option go_package = "peridot.resf.org/apollo/pb;apollopb";
|
||||||
|
|
||||||
|
message AffectedProduct {
|
||||||
|
int64 product_id = 1;
|
||||||
|
google.protobuf.StringValue cve_id = 2;
|
||||||
|
string version = 3;
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
STATE_UNKNOWN = 0;
|
||||||
|
// CVE only affects downstream
|
||||||
|
STATE_UNDER_INVESTIGATION_DOWNSTREAM = 1;
|
||||||
|
// CVE affecting upstream and a fix still hasn't been issued
|
||||||
|
STATE_UNDER_INVESTIGATION_UPSTREAM = 2;
|
||||||
|
// CVE has been fixed upstream
|
||||||
|
STATE_FIXED_UPSTREAM = 3;
|
||||||
|
// CVE has been fixed downstream
|
||||||
|
// At this stage the CVE can be included in errata
|
||||||
|
STATE_FIXED_DOWNSTREAM = 4;
|
||||||
|
// CVE will NOT be fixed upstream
|
||||||
|
STATE_WILL_NOT_FIX_UPSTREAM = 5;
|
||||||
|
// CVE will NOT be fixed downstream
|
||||||
|
// This will probably never happen with Core, but may happen for SIGs
|
||||||
|
STATE_WILL_NOT_FIX_DOWNSTREAM = 6;
|
||||||
|
// CVE is out of support scope
|
||||||
|
STATE_OUT_OF_SUPPORT_SCOPE = 7;
|
||||||
|
// CVE affects product and upstream is working on a fix
|
||||||
|
STATE_AFFECTED_UPSTREAM = 8;
|
||||||
|
// CVE affects product and a fix is being worked out
|
||||||
|
STATE_AFFECTED_DOWNSTREAM = 9;
|
||||||
|
}
|
||||||
|
State state = 4;
|
||||||
|
|
||||||
|
string package = 5;
|
||||||
|
google.protobuf.StringValue advisory = 6;
|
||||||
|
}
|
161
apollo/proto/v1/apollo.proto
Normal file
161
apollo/proto/v1/apollo.proto
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package resf.apollo.v1;
|
||||||
|
|
||||||
|
import "google/api/annotations.proto";
|
||||||
|
import "google/api/httpbody.proto";
|
||||||
|
import "google/protobuf/wrappers.proto";
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
import "validate/validate.proto";
|
||||||
|
import "apollo/proto/v1/advisory.proto";
|
||||||
|
|
||||||
|
option go_package = "peridot.resf.org/apollo/pb;apollopb";
|
||||||
|
|
||||||
|
service ApolloService {
|
||||||
|
// ListAdvisories
|
||||||
|
//
|
||||||
|
// Return a list of advisories by given filters.
|
||||||
|
// No filters returns all advisories
|
||||||
|
// This method is paginated
|
||||||
|
rpc ListAdvisories (ListAdvisoriesRequest) returns (ListAdvisoriesResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/v2/advisories"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAdvisoriesRSS
|
||||||
|
//
|
||||||
|
// Same as ListAdvisories but returns an RSS feed
|
||||||
|
// Only returns 25 latest advisories
|
||||||
|
// Supports filters
|
||||||
|
rpc ListAdvisoriesRSS (ListAdvisoriesRSSRequest) returns (google.api.HttpBody) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/v2/advisories:rss"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAdvisory
|
||||||
|
//
|
||||||
|
// Returns an advisory with given ID if found, else returns NotFound
|
||||||
|
rpc GetAdvisory (GetAdvisoryRequest) returns (GetAdvisoryResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/v2/advisories/{id=*}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message AdvisoryFilters {
|
||||||
|
// Product
|
||||||
|
//
|
||||||
|
// The product to fetch advisories for
|
||||||
|
// For example: Rocky Linux 8
|
||||||
|
google.protobuf.StringValue product = 1;
|
||||||
|
|
||||||
|
// Before
|
||||||
|
//
|
||||||
|
// Advisories published before timestamp
|
||||||
|
google.protobuf.Timestamp before = 2;
|
||||||
|
|
||||||
|
// After
|
||||||
|
//
|
||||||
|
// Advisories published after timestamp
|
||||||
|
google.protobuf.Timestamp after = 3;
|
||||||
|
|
||||||
|
// Include unpublished
|
||||||
|
//
|
||||||
|
// Whether to include unpublished advisories
|
||||||
|
// apollo/impl never respects this, but internal services
|
||||||
|
// may rely on this
|
||||||
|
google.protobuf.BoolValue include_unpublished = 4;
|
||||||
|
|
||||||
|
// CVE
|
||||||
|
//
|
||||||
|
// Only return advisories with given CVE
|
||||||
|
google.protobuf.StringValue cve = 5;
|
||||||
|
|
||||||
|
// Synopsis
|
||||||
|
//
|
||||||
|
// Only return advisories if synopsis contains given text
|
||||||
|
google.protobuf.StringValue synopsis = 6;
|
||||||
|
|
||||||
|
// Include RPMs
|
||||||
|
//
|
||||||
|
// Includes RPMs in list response (slow)
|
||||||
|
google.protobuf.BoolValue include_rpms = 7;
|
||||||
|
|
||||||
|
// Keyword
|
||||||
|
//
|
||||||
|
// Searches all fields for given keyword
|
||||||
|
google.protobuf.StringValue keyword = 8;
|
||||||
|
|
||||||
|
// Severity
|
||||||
|
//
|
||||||
|
// Only return advisories with given severity
|
||||||
|
Advisory.Severity severity = 9;
|
||||||
|
|
||||||
|
// Type
|
||||||
|
//
|
||||||
|
// Only return advisories with given type
|
||||||
|
Advisory.Type type = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAdvisoriesRequest
|
||||||
|
//
|
||||||
|
// Request body for `ListAdvisories`
|
||||||
|
// All fields are optional
|
||||||
|
message ListAdvisoriesRequest {
|
||||||
|
// Filters for the given query
|
||||||
|
// No filters returns all advisories
|
||||||
|
AdvisoryFilters filters = 1;
|
||||||
|
|
||||||
|
int32 page = 2;
|
||||||
|
int32 limit = 3 [(validate.rules).int32.lte = 100];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAdvisoriesResponse
|
||||||
|
//
|
||||||
|
// Response body for `ListAdvisories`
|
||||||
|
message ListAdvisoriesResponse {
|
||||||
|
repeated Advisory advisories = 1;
|
||||||
|
|
||||||
|
// Total packages from server
|
||||||
|
int64 total = 2;
|
||||||
|
|
||||||
|
// Limit from request
|
||||||
|
int32 size = 3;
|
||||||
|
|
||||||
|
// Current page
|
||||||
|
int32 page = 4;
|
||||||
|
|
||||||
|
// Last updated
|
||||||
|
google.protobuf.Timestamp last_updated = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListAdvisoriesRSSRequest
|
||||||
|
// Request body for `ListAdvisoriesRSS`
|
||||||
|
// All fields are optional
|
||||||
|
message ListAdvisoriesRSSRequest {
|
||||||
|
// Filters for the given query
|
||||||
|
// No filters returns all advisories
|
||||||
|
AdvisoryFilters filters = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAdvisoryRequest
|
||||||
|
//
|
||||||
|
// Request body for `GetAdvisory`
|
||||||
|
message GetAdvisoryRequest {
|
||||||
|
// ID
|
||||||
|
//
|
||||||
|
// Errata ID
|
||||||
|
// Example: RLSA:2021-1515
|
||||||
|
string id = 1 [(validate.rules).string = {
|
||||||
|
pattern: "^(.+)([SEB]A)-([0-9]{4}):([0-9]+)$",
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAdvisoryResponse
|
||||||
|
//
|
||||||
|
// Response body for `GetAdvisory`
|
||||||
|
message GetAdvisoryResponse {
|
||||||
|
Advisory advisory = 1;
|
||||||
|
}
|
13
apollo/proto/v1/build.proto
Normal file
13
apollo/proto/v1/build.proto
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package resf.apollo.v1;
|
||||||
|
|
||||||
|
option go_package = "peridot.resf.org/apollo/pb;apollopb";
|
||||||
|
|
||||||
|
enum BuildStatus {
|
||||||
|
BUILD_STATUS_UNKNOWN = 0;
|
||||||
|
BUILD_STATUS_FIXED = 1;
|
||||||
|
BUILD_STATUS_NOT_FIXED = 2;
|
||||||
|
BUILD_STATUS_WILL_NOT_FIX = 3;
|
||||||
|
BUILD_STATUS_SKIP = 4;
|
||||||
|
}
|
28
apollo/proto/v1/cve.proto
Normal file
28
apollo/proto/v1/cve.proto
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package resf.apollo.v1;
|
||||||
|
|
||||||
|
import "google/protobuf/wrappers.proto";
|
||||||
|
|
||||||
|
option go_package = "peridot.resf.org/apollo/pb;apollopb";
|
||||||
|
|
||||||
|
message CVE {
|
||||||
|
string name = 1;
|
||||||
|
|
||||||
|
google.protobuf.StringValue source_by = 2;
|
||||||
|
google.protobuf.StringValue source_link = 3;
|
||||||
|
|
||||||
|
google.protobuf.StringValue cvss3_scoring_vector = 4;
|
||||||
|
google.protobuf.StringValue cvss3_base_score = 5;
|
||||||
|
google.protobuf.StringValue cwe = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListUnresolvedCVEsRequest {}
|
||||||
|
message ListUnresolvedCVEsResponse {
|
||||||
|
repeated CVE cves = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListFixedCVEsRequest {}
|
||||||
|
message ListFixedCVEsResponse {
|
||||||
|
repeated CVE cves = 1;
|
||||||
|
}
|
14
apollo/proto/v1/fix.proto
Normal file
14
apollo/proto/v1/fix.proto
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package resf.apollo.v1;
|
||||||
|
|
||||||
|
import "google/protobuf/wrappers.proto";
|
||||||
|
|
||||||
|
option go_package = "peridot.resf.org/apollo/pb;apollopb";
|
||||||
|
|
||||||
|
message Fix {
|
||||||
|
google.protobuf.StringValue ticket = 1;
|
||||||
|
google.protobuf.StringValue source_by = 2;
|
||||||
|
google.protobuf.StringValue source_link = 3;
|
||||||
|
google.protobuf.StringValue description = 4;
|
||||||
|
}
|
29
apollo/proto/v1/short_code.proto
Normal file
29
apollo/proto/v1/short_code.proto
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package resf.apollo.v1;
|
||||||
|
|
||||||
|
option go_package = "peridot.resf.org/apollo/pb;apollopb";
|
||||||
|
|
||||||
|
message ShortCode {
|
||||||
|
// Code
|
||||||
|
//
|
||||||
|
// Full short code
|
||||||
|
string code = 1;
|
||||||
|
|
||||||
|
enum Mode {
|
||||||
|
MODE_UNKNOWN = 0;
|
||||||
|
MODE_PUBLISH = 1;
|
||||||
|
MODE_MIRROR = 2;
|
||||||
|
}
|
||||||
|
// Mode
|
||||||
|
//
|
||||||
|
// Mode for short code
|
||||||
|
// Currently only publish and mirror is supported
|
||||||
|
Mode mode = 2;
|
||||||
|
|
||||||
|
// Archived
|
||||||
|
//
|
||||||
|
// Whether the short code is archived or not
|
||||||
|
// An archived short code CANNOT be used to issue errata
|
||||||
|
bool archived = 3;
|
||||||
|
}
|
@ -8,10 +8,10 @@ go_library(
|
|||||||
"errata.go",
|
"errata.go",
|
||||||
"mock.go",
|
"mock.go",
|
||||||
],
|
],
|
||||||
importpath = "peridot.resf.org/secparse/rherrata",
|
importpath = "peridot.resf.org/apollo/rherrata",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//secparse/proto/v1:proto",
|
"//apollo/proto/v1:pb",
|
||||||
"//vendor/github.com/PuerkitoBio/goquery",
|
"//vendor/github.com/PuerkitoBio/goquery",
|
||||||
"//vendor/github.com/go-chi/chi",
|
"//vendor/github.com/go-chi/chi",
|
||||||
"//vendor/github.com/gocolly/colly/v2:colly",
|
"//vendor/github.com/gocolly/colly/v2:colly",
|
||||||
@ -24,7 +24,7 @@ go_test(
|
|||||||
data = glob(["testdata/**"]),
|
data = glob(["testdata/**"]),
|
||||||
embed = [":rherrata"],
|
embed = [":rherrata"],
|
||||||
deps = [
|
deps = [
|
||||||
"//secparse/proto/v1:proto",
|
"//apollo/proto/v1:pb",
|
||||||
"//vendor/github.com/stretchr/testify/require",
|
"//vendor/github.com/stretchr/testify/require",
|
||||||
],
|
],
|
||||||
)
|
)
|
@ -38,7 +38,7 @@ import (
|
|||||||
|
|
||||||
type APIService interface {
|
type APIService interface {
|
||||||
GetErrata(advisory string) (*Errata, error)
|
GetErrata(advisory string) (*Errata, error)
|
||||||
GetAdvisories(currentVersion string) ([]*CompactErrata, error)
|
GetAdvisories(currentVersion string, after *time.Time) ([]*CompactErrata, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// API is the APIService implementation. Should not be used directly
|
// API is the APIService implementation. Should not be used directly
|
||||||
@ -54,9 +54,9 @@ func NewClient() *API {
|
|||||||
client: &http.Client{
|
client: &http.Client{
|
||||||
Timeout: 30 * time.Second,
|
Timeout: 30 * time.Second,
|
||||||
},
|
},
|
||||||
userAgent: "secparse/rherrata/0.1",
|
userAgent: "apollo/rherrata/0.2",
|
||||||
baseURLErrata: "https://access.redhat.com/errata",
|
baseURLErrata: "https://access.redhat.com/errata",
|
||||||
baseURLAPI: "https://api.access.redhat.com/rs/search",
|
baseURLAPI: "https://access.redhat.com/hydra/rest/search/kcs",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -35,10 +35,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var internalAfterDates = map[string]string{
|
var internalAfterDates = map[string]string{
|
||||||
"8.4": "2021-04-29T00:00:00Z",
|
"8.4": "2021-04-29T00:00:00Z",
|
||||||
|
"9.0": "2022-05-17T00:00:00Z",
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompactErrata struct {
|
type CompactErrata struct {
|
||||||
@ -61,7 +63,7 @@ type internalAdvisoriesResponse struct {
|
|||||||
Response *internalAdvisoriesInnerResponse `json:"response"`
|
Response *internalAdvisoriesInnerResponse `json:"response"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) GetAdvisories(currentVersion string) ([]*CompactErrata, error) {
|
func (a *API) GetAdvisories(currentVersion string, after *time.Time) ([]*CompactErrata, error) {
|
||||||
req, err := a.newRequest("GET", a.baseURLAPI, nil)
|
req, err := a.newRequest("GET", a.baseURLAPI, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -71,12 +73,14 @@ func (a *API) GetAdvisories(currentVersion string) ([]*CompactErrata, error) {
|
|||||||
usableVersion := strings.Replace(currentVersion, ".", "%5C.", -1)
|
usableVersion := strings.Replace(currentVersion, ".", "%5C.", -1)
|
||||||
fq2 := fmt.Sprintf("portal_product_filter:Red%%5C+Hat%%5C+Enterprise%%5C+Linux%%7C*%%7C%s%%7C*", usableVersion)
|
fq2 := fmt.Sprintf("portal_product_filter:Red%%5C+Hat%%5C+Enterprise%%5C+Linux%%7C*%%7C%s%%7C*", usableVersion)
|
||||||
var fq3 string
|
var fq3 string
|
||||||
if afterDate := internalAfterDates[currentVersion]; afterDate != "" {
|
if after != nil {
|
||||||
|
fq3 = "&fq=" + url.QueryEscape(fmt.Sprintf("portal_publication_date:[%s TO NOW]", after.Format(time.RFC3339)))
|
||||||
|
} else if afterDate := internalAfterDates[currentVersion]; afterDate != "" {
|
||||||
fq3 = "&fq=" + url.QueryEscape(fmt.Sprintf("portal_publication_date:[%s TO NOW]", afterDate))
|
fq3 = "&fq=" + url.QueryEscape(fmt.Sprintf("portal_publication_date:[%s TO NOW]", afterDate))
|
||||||
}
|
}
|
||||||
req.URL.RawQuery = fmt.Sprintf("fq=%s&fq=%s%s&q=*:*&rows=1000&sort=portal_publication_date+desc&start=0", fq1, fq2, fq3)
|
req.URL.RawQuery = fmt.Sprintf("fq=%s&fq=%s%s&q=*:*&rows=10000&sort=portal_publication_date+desc&start=0", fq1, fq2, fq3)
|
||||||
|
|
||||||
req.Header.Set("Accept", "application/vnd.redhat.solr+json")
|
req.Header.Set("Accept", "application/json")
|
||||||
|
|
||||||
res, err := a.client.Do(req)
|
res, err := a.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
@ -35,7 +35,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/PuerkitoBio/goquery"
|
"github.com/PuerkitoBio/goquery"
|
||||||
"github.com/gocolly/colly/v2"
|
"github.com/gocolly/colly/v2"
|
||||||
secparsepb "peridot.resf.org/secparse/proto/v1"
|
apollopb "peridot.resf.org/apollo/pb"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -62,8 +62,8 @@ type UpdatedPackages struct {
|
|||||||
|
|
||||||
type Errata struct {
|
type Errata struct {
|
||||||
Synopsis string
|
Synopsis string
|
||||||
Type secparsepb.Advisory_Type
|
Type apollopb.Advisory_Type
|
||||||
Severity secparsepb.Advisory_Severity
|
Severity apollopb.Advisory_Severity
|
||||||
Topic []string
|
Topic []string
|
||||||
Description []string
|
Description []string
|
||||||
Solution []string
|
Solution []string
|
||||||
@ -178,9 +178,9 @@ func (a *API) GetErrata(advisory string) (*Errata, error) {
|
|||||||
c.OnHTML("div#type-severity", func(element *colly.HTMLElement) {
|
c.OnHTML("div#type-severity", func(element *colly.HTMLElement) {
|
||||||
typeSeverity := strings.Split(element.DOM.Find("p").Text(), ":")
|
typeSeverity := strings.Split(element.DOM.Find("p").Text(), ":")
|
||||||
if typeSeverity[0] == "Product Enhancement Advisory" {
|
if typeSeverity[0] == "Product Enhancement Advisory" {
|
||||||
errata.Type = secparsepb.Advisory_Enhancement
|
errata.Type = apollopb.Advisory_TYPE_ENHANCEMENT
|
||||||
} else if typeSeverity[0] == "Bug Fix Advisory" {
|
} else if typeSeverity[0] == "Bug Fix Advisory" {
|
||||||
errata.Type = secparsepb.Advisory_BugFix
|
errata.Type = apollopb.Advisory_TYPE_BUGFIX
|
||||||
} else {
|
} else {
|
||||||
if len(typeSeverity) != 2 {
|
if len(typeSeverity) != 2 {
|
||||||
err = errors.New("invalid type/severity")
|
err = errors.New("invalid type/severity")
|
||||||
@ -195,28 +195,28 @@ func (a *API) GetErrata(advisory string) (*Errata, error) {
|
|||||||
|
|
||||||
switch strings.TrimSpace(typeSplit[0]) {
|
switch strings.TrimSpace(typeSplit[0]) {
|
||||||
case "Security":
|
case "Security":
|
||||||
errata.Type = secparsepb.Advisory_Security
|
errata.Type = apollopb.Advisory_TYPE_SECURITY
|
||||||
break
|
break
|
||||||
case "BugFix":
|
case "BugFix":
|
||||||
errata.Type = secparsepb.Advisory_BugFix
|
errata.Type = apollopb.Advisory_TYPE_BUGFIX
|
||||||
break
|
break
|
||||||
case "Enhancement":
|
case "Enhancement":
|
||||||
errata.Type = secparsepb.Advisory_Enhancement
|
errata.Type = apollopb.Advisory_TYPE_ENHANCEMENT
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
switch strings.TrimSpace(typeSeverity[1]) {
|
switch strings.TrimSpace(typeSeverity[1]) {
|
||||||
case "Low":
|
case "Low":
|
||||||
errata.Severity = secparsepb.Advisory_Low
|
errata.Severity = apollopb.Advisory_SEVERITY_LOW
|
||||||
break
|
break
|
||||||
case "Moderate":
|
case "Moderate":
|
||||||
errata.Severity = secparsepb.Advisory_Moderate
|
errata.Severity = apollopb.Advisory_SEVERITY_MODERATE
|
||||||
break
|
break
|
||||||
case "Important":
|
case "Important":
|
||||||
errata.Severity = secparsepb.Advisory_Important
|
errata.Severity = apollopb.Advisory_SEVERITY_IMPORTANT
|
||||||
break
|
break
|
||||||
case "Critical":
|
case "Critical":
|
||||||
errata.Severity = secparsepb.Advisory_Critical
|
errata.Severity = apollopb.Advisory_SEVERITY_CRITICAL
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -33,7 +33,7 @@ package rherrata
|
|||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
secparsepb "peridot.resf.org/secparse/proto/v1"
|
apollopb "peridot.resf.org/apollo/pb"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ func TestRHBA20212759(t *testing.T) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
require.Equal(t, "firefox bugfix update", errata.Synopsis)
|
require.Equal(t, "firefox bugfix update", errata.Synopsis)
|
||||||
require.Equal(t, secparsepb.Advisory_BugFix, errata.Type)
|
require.Equal(t, apollopb.Advisory_TYPE_BUGFIX, errata.Type)
|
||||||
require.Len(t, errata.Topic, 1)
|
require.Len(t, errata.Topic, 1)
|
||||||
require.Equal(t, "An update for firefox is now available for Red Hat Enterprise Linux 8.", errata.Topic[0])
|
require.Equal(t, "An update for firefox is now available for Red Hat Enterprise Linux 8.", errata.Topic[0])
|
||||||
require.Len(t, errata.Description, 3)
|
require.Len(t, errata.Description, 3)
|
||||||
@ -95,8 +95,8 @@ func TestRHBA20212743(t *testing.T) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
require.Equal(t, "Important: firefox security update", errata.Synopsis)
|
require.Equal(t, "Important: firefox security update", errata.Synopsis)
|
||||||
require.Equal(t, secparsepb.Advisory_Security, errata.Type)
|
require.Equal(t, apollopb.Advisory_TYPE_SECURITY, errata.Type)
|
||||||
require.Equal(t, secparsepb.Advisory_Important, errata.Severity)
|
require.Equal(t, apollopb.Advisory_SEVERITY_IMPORTANT, errata.Severity)
|
||||||
require.Len(t, errata.Topic, 2)
|
require.Len(t, errata.Topic, 2)
|
||||||
require.Equal(t, "An update for firefox is now available for Red Hat Enterprise Linux 8.", errata.Topic[0])
|
require.Equal(t, "An update for firefox is now available for Red Hat Enterprise Linux 8.", errata.Topic[0])
|
||||||
require.Equal(t, "Red Hat Product Security has rated this update as having a security impact of Important. A Common Vulnerability Scoring System (CVSS) base score, which gives a detailed severity rating, is available for each vulnerability from the CVE link(s) in the References section.", errata.Topic[1])
|
require.Equal(t, "Red Hat Product Security has rated this update as having a security impact of Important. A Common Vulnerability Scoring System (CVSS) base score, which gives a detailed severity rating, is available for each vulnerability from the CVE link(s) in the References section.", errata.Topic[1])
|
@ -16,7 +16,7 @@ go_library(
|
|||||||
"response.go",
|
"response.go",
|
||||||
"utils.go",
|
"utils.go",
|
||||||
],
|
],
|
||||||
importpath = "peridot.resf.org/secparse/rhsecurity",
|
importpath = "peridot.resf.org/apollo/rhsecurity",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = ["//vendor/golang.org/x/oauth2"],
|
deps = ["//vendor/golang.org/x/oauth2"],
|
||||||
)
|
)
|
@ -1,4 +1,6 @@
|
|||||||
openapi: 3.0.0
|
openapi: 3.0.0
|
||||||
|
x-stoplight:
|
||||||
|
id: yjn90w5p8y4ly
|
||||||
info:
|
info:
|
||||||
title: Red Hat Security Data API
|
title: Red Hat Security Data API
|
||||||
version: '1.0'
|
version: '1.0'
|
||||||
@ -63,7 +65,7 @@ paths:
|
|||||||
name: cwe
|
name: cwe
|
||||||
description: CVEs with CWE
|
description: CVEs with CWE
|
||||||
- schema:
|
- schema:
|
||||||
type: string
|
type: number
|
||||||
in: query
|
in: query
|
||||||
name: cvss_score
|
name: cvss_score
|
||||||
description: CVEs with CVSS score greater than or equal to this value
|
description: CVEs with CVSS score greater than or equal to this value
|
||||||
@ -181,7 +183,7 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
cvss_score:
|
cvss_score:
|
||||||
type: string
|
type: number
|
||||||
cvss_scoring_vector:
|
cvss_scoring_vector:
|
||||||
type: string
|
type: string
|
||||||
CWE:
|
CWE:
|
@ -66,7 +66,6 @@ type ApiGetCveRequest struct {
|
|||||||
cVE string
|
cVE string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (r ApiGetCveRequest) Execute() (CVEDetailed, *_nethttp.Response, error) {
|
func (r ApiGetCveRequest) Execute() (CVEDetailed, *_nethttp.Response, error) {
|
||||||
return r.ApiService.GetCveExecute(r)
|
return r.ApiService.GetCveExecute(r)
|
||||||
}
|
}
|
||||||
@ -178,7 +177,7 @@ type ApiGetCvesRequest struct {
|
|||||||
package_ *string
|
package_ *string
|
||||||
product *string
|
product *string
|
||||||
cwe *string
|
cwe *string
|
||||||
cvssScore *string
|
cvssScore *float32
|
||||||
cvss3Score *string
|
cvss3Score *string
|
||||||
page *float32
|
page *float32
|
||||||
perPage *float32
|
perPage *float32
|
||||||
@ -221,7 +220,7 @@ func (r ApiGetCvesRequest) Cwe(cwe string) ApiGetCvesRequest {
|
|||||||
r.cwe = &cwe
|
r.cwe = &cwe
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
func (r ApiGetCvesRequest) CvssScore(cvssScore string) ApiGetCvesRequest {
|
func (r ApiGetCvesRequest) CvssScore(cvssScore float32) ApiGetCvesRequest {
|
||||||
r.cvssScore = &cvssScore
|
r.cvssScore = &cvssScore
|
||||||
return r
|
return r
|
||||||
}
|
}
|
@ -110,8 +110,7 @@ func NewConfiguration() *Configuration {
|
|||||||
Description: "No description provided",
|
Description: "No description provided",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
OperationServers: map[string]ServerConfigurations{
|
OperationServers: map[string]ServerConfigurations{},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
@ -10,7 +10,7 @@ Name | Type | Description | Notes
|
|||||||
**Advisories** | **[]string** | |
|
**Advisories** | **[]string** | |
|
||||||
**Bugzilla** | **string** | |
|
**Bugzilla** | **string** | |
|
||||||
**BugzillaDescription** | **string** | |
|
**BugzillaDescription** | **string** | |
|
||||||
**CvssScore** | Pointer to **string** | | [optional]
|
**CvssScore** | Pointer to **float32** | | [optional]
|
||||||
**CvssScoringVector** | Pointer to **string** | | [optional]
|
**CvssScoringVector** | Pointer to **string** | | [optional]
|
||||||
**CWE** | **string** | |
|
**CWE** | **string** | |
|
||||||
**AffectedPackages** | **[]string** | |
|
**AffectedPackages** | **[]string** | |
|
||||||
@ -159,20 +159,20 @@ SetBugzillaDescription sets BugzillaDescription field to given value.
|
|||||||
|
|
||||||
### GetCvssScore
|
### GetCvssScore
|
||||||
|
|
||||||
`func (o *CVE) GetCvssScore() string`
|
`func (o *CVE) GetCvssScore() float32`
|
||||||
|
|
||||||
GetCvssScore returns the CvssScore field if non-nil, zero value otherwise.
|
GetCvssScore returns the CvssScore field if non-nil, zero value otherwise.
|
||||||
|
|
||||||
### GetCvssScoreOk
|
### GetCvssScoreOk
|
||||||
|
|
||||||
`func (o *CVE) GetCvssScoreOk() (*string, bool)`
|
`func (o *CVE) GetCvssScoreOk() (*float32, bool)`
|
||||||
|
|
||||||
GetCvssScoreOk returns a tuple with the CvssScore field if it's non-nil, zero value otherwise
|
GetCvssScoreOk returns a tuple with the CvssScore field if it's non-nil, zero value otherwise
|
||||||
and a boolean to check if the value has been set.
|
and a boolean to check if the value has been set.
|
||||||
|
|
||||||
### SetCvssScore
|
### SetCvssScore
|
||||||
|
|
||||||
`func (o *CVE) SetCvssScore(v string)`
|
`func (o *CVE) SetCvssScore(v float32)`
|
||||||
|
|
||||||
SetCvssScore sets CvssScore field to given value.
|
SetCvssScore sets CvssScore field to given value.
|
||||||
|
|
@ -110,7 +110,7 @@ func main() {
|
|||||||
package_ := "package__example" // string | CVEs which affect the package (optional)
|
package_ := "package__example" // string | CVEs which affect the package (optional)
|
||||||
product := "product_example" // string | CVEs which affect the product. The parameter supports Perl compatible regular expressions. (optional)
|
product := "product_example" // string | CVEs which affect the product. The parameter supports Perl compatible regular expressions. (optional)
|
||||||
cwe := "cwe_example" // string | CVEs with CWE (optional)
|
cwe := "cwe_example" // string | CVEs with CWE (optional)
|
||||||
cvssScore := "cvssScore_example" // string | CVEs with CVSS score greater than or equal to this value (optional)
|
cvssScore := float32(8.14) // float32 | CVEs with CVSS score greater than or equal to this value (optional)
|
||||||
cvss3Score := "cvss3Score_example" // string | CVEs with CVSSv3 score greater than or equal to this value (optional)
|
cvss3Score := "cvss3Score_example" // string | CVEs with CVSSv3 score greater than or equal to this value (optional)
|
||||||
page := float32(8.14) // float32 | CVEs for page number (optional)
|
page := float32(8.14) // float32 | CVEs for page number (optional)
|
||||||
perPage := float32(8.14) // float32 | Number of CVEs to return per page (optional)
|
perPage := float32(8.14) // float32 | Number of CVEs to return per page (optional)
|
||||||
@ -148,7 +148,7 @@ Name | Type | Description | Notes
|
|||||||
**package_** | **string** | CVEs which affect the package |
|
**package_** | **string** | CVEs which affect the package |
|
||||||
**product** | **string** | CVEs which affect the product. The parameter supports Perl compatible regular expressions. |
|
**product** | **string** | CVEs which affect the product. The parameter supports Perl compatible regular expressions. |
|
||||||
**cwe** | **string** | CVEs with CWE |
|
**cwe** | **string** | CVEs with CWE |
|
||||||
**cvssScore** | **string** | CVEs with CVSS score greater than or equal to this value |
|
**cvssScore** | **float32** | CVEs with CVSS score greater than or equal to this value |
|
||||||
**cvss3Score** | **string** | CVEs with CVSSv3 score greater than or equal to this value |
|
**cvss3Score** | **string** | CVEs with CVSSv3 score greater than or equal to this value |
|
||||||
**page** | **float32** | CVEs for page number |
|
**page** | **float32** | CVEs for page number |
|
||||||
**perPage** | **float32** | Number of CVEs to return per page |
|
**perPage** | **float32** | Number of CVEs to return per page |
|
@ -23,7 +23,7 @@ type CVE struct {
|
|||||||
Advisories []string `json:"advisories"`
|
Advisories []string `json:"advisories"`
|
||||||
Bugzilla string `json:"bugzilla"`
|
Bugzilla string `json:"bugzilla"`
|
||||||
BugzillaDescription string `json:"bugzilla_description"`
|
BugzillaDescription string `json:"bugzilla_description"`
|
||||||
CvssScore *string `json:"cvss_score,omitempty"`
|
CvssScore *float32 `json:"cvss_score,omitempty"`
|
||||||
CvssScoringVector *string `json:"cvss_scoring_vector,omitempty"`
|
CvssScoringVector *string `json:"cvss_scoring_vector,omitempty"`
|
||||||
CWE string `json:"CWE"`
|
CWE string `json:"CWE"`
|
||||||
AffectedPackages []string `json:"affected_packages"`
|
AffectedPackages []string `json:"affected_packages"`
|
||||||
@ -205,9 +205,9 @@ func (o *CVE) SetBugzillaDescription(v string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCvssScore returns the CvssScore field value if set, zero value otherwise.
|
// GetCvssScore returns the CvssScore field value if set, zero value otherwise.
|
||||||
func (o *CVE) GetCvssScore() string {
|
func (o *CVE) GetCvssScore() float32 {
|
||||||
if o == nil || o.CvssScore == nil {
|
if o == nil || o.CvssScore == nil {
|
||||||
var ret string
|
var ret float32
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
return *o.CvssScore
|
return *o.CvssScore
|
||||||
@ -215,7 +215,7 @@ func (o *CVE) GetCvssScore() string {
|
|||||||
|
|
||||||
// GetCvssScoreOk returns a tuple with the CvssScore field value if set, nil otherwise
|
// GetCvssScoreOk returns a tuple with the CvssScore field value if set, nil otherwise
|
||||||
// and a boolean to check if the value has been set.
|
// and a boolean to check if the value has been set.
|
||||||
func (o *CVE) GetCvssScoreOk() (*string, bool) {
|
func (o *CVE) GetCvssScoreOk() (*float32, bool) {
|
||||||
if o == nil || o.CvssScore == nil {
|
if o == nil || o.CvssScore == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
@ -231,8 +231,8 @@ func (o *CVE) HasCvssScore() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCvssScore gets a reference to the given string and assigns it to the CvssScore field.
|
// SetCvssScore gets a reference to the given float32 and assigns it to the CvssScore field.
|
||||||
func (o *CVE) SetCvssScore(v string) {
|
func (o *CVE) SetCvssScore(v float32) {
|
||||||
o.CvssScore = &v
|
o.CvssScore = &v
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,5 +467,3 @@ func (v *NullableCVE) UnmarshalJSON(src []byte) error {
|
|||||||
v.isSet = true
|
v.isSet = true
|
||||||
return json.Unmarshal(src, &v.value)
|
return json.Unmarshal(src, &v.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -409,5 +409,3 @@ func (v *NullableCVEDetailed) UnmarshalJSON(src []byte) error {
|
|||||||
v.isSet = true
|
v.isSet = true
|
||||||
return json.Unmarshal(src, &v.value)
|
return json.Unmarshal(src, &v.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -228,5 +228,3 @@ func (v *NullableCVEDetailedAffectedRelease) UnmarshalJSON(src []byte) error {
|
|||||||
v.isSet = true
|
v.isSet = true
|
||||||
return json.Unmarshal(src, &v.value)
|
return json.Unmarshal(src, &v.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,5 +163,3 @@ func (v *NullableCVEDetailedBugzilla) UnmarshalJSON(src []byte) error {
|
|||||||
v.isSet = true
|
v.isSet = true
|
||||||
return json.Unmarshal(src, &v.value)
|
return json.Unmarshal(src, &v.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,5 +163,3 @@ func (v *NullableCVEDetailedCvss3) UnmarshalJSON(src []byte) error {
|
|||||||
v.isSet = true
|
v.isSet = true
|
||||||
return json.Unmarshal(src, &v.value)
|
return json.Unmarshal(src, &v.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,5 +192,3 @@ func (v *NullableCVEDetailedPackageState) UnmarshalJSON(src []byte) error {
|
|||||||
v.isSet = true
|
v.isSet = true
|
||||||
return json.Unmarshal(src, &v.value)
|
return json.Unmarshal(src, &v.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user