mirror of
https://github.com/rocky-linux/peridot.git
synced 2024-12-22 02:38:30 +00:00
commit
3b19040cfd
.bazelrc.envrc.prod.mustafarockyREADME.md
apollo
BUILD.bazel
cmd
apollo
apollostarter
apolloworker
db
impl/v1
migrate
20210702021142_create_short_codes.down.sql20210702021142_create_short_codes.up.sql20210702021143_create_products.down.sql20210702021143_create_products.up.sql20210702041656_create_advisories.down.sql20210702041656_create_advisories.up.sql20210702041659_create_cves.down.sql20210702041659_create_cves.up.sql20210702041701_create_fixes.down.sql20210702041701_create_fixes.up.sql20210702041756_create_advisory_references.down.sql20210702041756_create_advisory_references.up.sql20210702041956_create_affected_products.down.sql20210702041956_create_affected_products.up.sql20210702043031_create_build_references.down.sql20210702043031_create_build_references.up.sql20210703202420_create_mirror_state.down.sql20210703202420_create_mirror_state.up.sql20210711014759_create_advisory_cves.down.sql20210711014759_create_advisory_cves.up.sql20210711020255_create_advisory_fixes.down.sql20210711020255_create_advisory_fixes.up.sql20210713031253_create_ignored_upstream_packages.down.sql20210713031253_create_ignored_upstream_packages.up.sql20210717040945_create_advisory_rpms.down.sql20210717040945_create_advisory_rpms.up.sql20210803052113_updateinfo_history.down.sql20210803052113_updateinfo_history.up.sql20220913121538_create_reboot_suggested_packages.down.sql20220913121538_create_reboot_suggested_packages.up.sql20220921231425_add_indexes.down.sql20220921231425_add_indexes.up.sql20221020182658_add_content_to_cves.down.sql20221020182658_add_content_to_cves.up.sqlBUILD
proto/v1
BUILD.bazeladvisory.protoaffected_product.protoapollo.protobuild.protocve.protofix.protoshort_code.proto
rherrata
rhsecurity
BUILD.bazelREADME.mdRed-Hat-Security-Data-API.yamlapi_default.goclient.goconfiguration.go
docs
CVE.mdCVEDetailed.mdCVEDetailedAffectedRelease.mdCVEDetailedBugzilla.mdCVEDetailedCvss3.mdCVEDetailedPackageState.mdDefaultApi.md
gen.gomodel_cve.gomodel_cve_detailed.gomodel_cve_detailed_affected_release.gomodel_cve_detailed_bugzilla.gomodel_cve_detailed_cvss3.gomodel_cve_detailed_package_state.goresponse.go
12
.bazelrc
12
.bazelrc
@ -13,11 +13,17 @@ build:inmemory --experimental_inmemory_dotd_files
|
||||
|
||||
# Minimize what is downloaded
|
||||
build:toplevel --config=inmemory
|
||||
build:toplevel --experimental_remote_download_outputs=toplevel
|
||||
build:toplevel --remote_download_outputs=toplevel
|
||||
|
||||
build:remote --config=toplevel
|
||||
build:remote --google_credentials=/tmp/credentials.json
|
||||
build:remote --remote_cache=https://storage.googleapis.com/resf-temporary-bazel-cache
|
||||
build:remote --remote_cache=grpc://buildcache.default.svc.cluster.local:9092
|
||||
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
|
||||
|
||||
common:ci --config=remote
|
||||
|
||||
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)`
|
||||
* peridot - `Modern build system`
|
||||
* secparse - `Errata mirroring and publishing platform`
|
||||
* ui - `Product Errata UI`
|
||||
* apollo - `Errata mirroring and publishing platform`
|
||||
* utils - `Common utilities`
|
||||
* modulemd - `Modulemd parser in Go`
|
||||
|
||||
@ -50,6 +49,6 @@ For best experience use IntelliJ+Bazel but `govendor` creates structure that is
|
||||
#### Vendor Go dependencies
|
||||
`./hack/govendor`
|
||||
#### 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
|
||||
`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 (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"peridot.resf.org/secparse/db/connector"
|
||||
"peridot.resf.org/secparse/impl"
|
||||
apolloconnector "peridot.resf.org/apollo/db/connector"
|
||||
apolloimpl "peridot.resf.org/apollo/impl/v1"
|
||||
"peridot.resf.org/utils"
|
||||
)
|
||||
|
||||
var root = &cobra.Command{
|
||||
Use: "secparse",
|
||||
Use: "apollo",
|
||||
Run: mn,
|
||||
}
|
||||
|
||||
var cnf = utils.NewFlagConfig()
|
||||
|
||||
func init() {
|
||||
cnf.DefaultPort = 9008
|
||||
cnf.DefaultPort = 9100
|
||||
|
||||
dname := "secparse"
|
||||
cnf.DatabaseName = &dname
|
||||
cnf.Name = "secparse"
|
||||
cnf.DatabaseName = utils.Pointer[string]("apollo")
|
||||
cnf.Name = *cnf.DatabaseName
|
||||
|
||||
root.PersistentFlags().String("homepage", "https://errata.build.resf.org", "Frontend root URL")
|
||||
utils.AddFlags(root.PersistentFlags(), cnf)
|
||||
}
|
||||
|
||||
func mn(_ *cobra.Command, _ []string) {
|
||||
impl.NewServer(connector.MustAuto()).Run()
|
||||
apolloimpl.NewServer(apolloconnector.MustAuto()).Run()
|
||||
}
|
||||
|
||||
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",
|
||||
"db.go",
|
||||
],
|
||||
importpath = "peridot.resf.org/secparse/db",
|
||||
importpath = "peridot.resf.org/apollo/db",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//secparse/admin/proto/v1:proto",
|
||||
"//secparse/proto/v1:proto",
|
||||
"//secparse/rpmutils",
|
||||
"//apollo/proto/v1:pb",
|
||||
"//utils",
|
||||
"//vendor/github.com/jmoiron/sqlx/types",
|
||||
"//vendor/github.com/lib/pq",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb: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(
|
||||
name = "connector",
|
||||
srcs = ["connector.go"],
|
||||
importpath = "peridot.resf.org/secparse/db/connector",
|
||||
importpath = "peridot.resf.org/apollo/db/connector",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//secparse/db",
|
||||
"//secparse/db/psql",
|
||||
"//apollo/db",
|
||||
"//apollo/db/psql",
|
||||
"//utils",
|
||||
"//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
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package connector
|
||||
package apolloconnector
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"peridot.resf.org/secparse/db"
|
||||
"peridot.resf.org/secparse/db/psql"
|
||||
apollodb "peridot.resf.org/apollo/db"
|
||||
apollopsql "peridot.resf.org/apollo/db/psql"
|
||||
"peridot.resf.org/utils"
|
||||
)
|
||||
|
||||
// MustAuto automatically returns the correct access interface or fatally fails
|
||||
func MustAuto() db.Access {
|
||||
func MustAuto() apollodb.Access {
|
||||
dbType := utils.GetDbType()
|
||||
switch dbType {
|
||||
case utils.DbPostgres:
|
||||
return psql.New()
|
||||
return apollopsql.New()
|
||||
default:
|
||||
logrus.Fatal("invalid database url supplied")
|
||||
return nil
|
@ -28,21 +28,19 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package db
|
||||
package apollodb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
secparseadminpb "peridot.resf.org/secparse/admin/proto/v1"
|
||||
secparsepb "peridot.resf.org/secparse/proto/v1"
|
||||
"peridot.resf.org/secparse/rpmutils"
|
||||
apollopb "peridot.resf.org/apollo/pb"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func DTOShortCodeToPB(sc *ShortCode) *secparseadminpb.ShortCode {
|
||||
ret := &secparseadminpb.ShortCode{
|
||||
func DTOShortCodeToPB(sc *ShortCode) *apollopb.ShortCode {
|
||||
ret := &apollopb.ShortCode{
|
||||
Code: sc.Code,
|
||||
Mode: secparseadminpb.ShortCodeMode(sc.Mode),
|
||||
}
|
||||
|
||||
if sc.ArchivedAt.Valid {
|
||||
@ -52,8 +50,8 @@ func DTOShortCodeToPB(sc *ShortCode) *secparseadminpb.ShortCode {
|
||||
return ret
|
||||
}
|
||||
|
||||
func DTOListShortCodesToPB(scs []*ShortCode) []*secparseadminpb.ShortCode {
|
||||
var ret []*secparseadminpb.ShortCode
|
||||
func DTOListShortCodesToPB(scs []*ShortCode) []*apollopb.ShortCode {
|
||||
var ret []*apollopb.ShortCode
|
||||
|
||||
for _, v := range scs {
|
||||
ret = append(ret, DTOShortCodeToPB(v))
|
||||
@ -62,16 +60,16 @@ func DTOListShortCodesToPB(scs []*ShortCode) []*secparseadminpb.ShortCode {
|
||||
return ret
|
||||
}
|
||||
|
||||
func DTOAdvisoryToPB(sc *Advisory) *secparsepb.Advisory {
|
||||
func DTOAdvisoryToPB(sc *Advisory) *apollopb.Advisory {
|
||||
var errataType string
|
||||
switch secparsepb.Advisory_Type(sc.Type) {
|
||||
case secparsepb.Advisory_Security:
|
||||
switch apollopb.Advisory_Type(sc.Type) {
|
||||
case apollopb.Advisory_TYPE_SECURITY:
|
||||
errataType = "SA"
|
||||
break
|
||||
case secparsepb.Advisory_BugFix:
|
||||
case apollopb.Advisory_TYPE_BUGFIX:
|
||||
errataType = "BA"
|
||||
break
|
||||
case secparsepb.Advisory_Enhancement:
|
||||
case apollopb.Advisory_TYPE_ENHANCEMENT:
|
||||
errataType = "EA"
|
||||
break
|
||||
default:
|
||||
@ -84,34 +82,67 @@ func DTOAdvisoryToPB(sc *Advisory) *secparsepb.Advisory {
|
||||
publishedAt = timestamppb.New(sc.PublishedAt.Time)
|
||||
}
|
||||
|
||||
ret := &secparsepb.Advisory{
|
||||
Type: secparsepb.Advisory_Type(sc.Type),
|
||||
ret := &apollopb.Advisory{
|
||||
Type: apollopb.Advisory_Type(sc.Type),
|
||||
ShortCode: sc.ShortCodeCode,
|
||||
Name: fmt.Sprintf("%s%s-%d:%d", sc.ShortCodeCode, errataType, sc.Year, sc.Num),
|
||||
Synopsis: sc.Synopsis,
|
||||
Severity: secparsepb.Advisory_Severity(sc.Severity),
|
||||
Severity: apollopb.Advisory_Severity(sc.Severity),
|
||||
Topic: sc.Topic,
|
||||
Description: sc.Description,
|
||||
AffectedProducts: sc.AffectedProducts,
|
||||
Fixes: sc.Fixes,
|
||||
Cves: sc.Cves,
|
||||
Fixes: nil,
|
||||
Cves: []*apollopb.CVE{},
|
||||
References: sc.References,
|
||||
PublishedAt: publishedAt,
|
||||
Rpms: sc.RPMs,
|
||||
Rpms: nil,
|
||||
RebootSuggested: sc.RebootSuggested,
|
||||
}
|
||||
if sc.Solution.Valid {
|
||||
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 {
|
||||
sc.RPMs[i] = rpmutils.Epoch().ReplaceAllString(rpm, "")
|
||||
ret.Rpms[productName].Nvras = append(ret.Rpms[productName].Nvras, nvra)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func DTOListAdvisoriesToPB(scs []*Advisory) []*secparsepb.Advisory {
|
||||
var ret []*secparsepb.Advisory
|
||||
func DTOListAdvisoriesToPB(scs []*Advisory) []*apollopb.Advisory {
|
||||
var ret []*apollopb.Advisory
|
||||
|
||||
for _, v := range scs {
|
||||
ret = append(ret, DTOAdvisoryToPB(v))
|
||||
@ -120,10 +151,9 @@ func DTOListAdvisoriesToPB(scs []*Advisory) []*secparsepb.Advisory {
|
||||
return ret
|
||||
}
|
||||
|
||||
func DTOCVEToPB(cve *CVE) *secparseadminpb.CVE {
|
||||
ret := &secparseadminpb.CVE{
|
||||
Name: cve.ID,
|
||||
State: secparseadminpb.CVEState(cve.State),
|
||||
func DTOCVEToPB(cve *CVE) *apollopb.CVE {
|
||||
ret := &apollopb.CVE{
|
||||
Name: cve.ID,
|
||||
}
|
||||
|
||||
if cve.SourceBy.Valid {
|
||||
@ -136,8 +166,8 @@ func DTOCVEToPB(cve *CVE) *secparseadminpb.CVE {
|
||||
return ret
|
||||
}
|
||||
|
||||
func DTOListCVEsToPB(cves []*CVE) []*secparseadminpb.CVE {
|
||||
var ret []*secparseadminpb.CVE
|
||||
func DTOListCVEsToPB(cves []*CVE) []*apollopb.CVE {
|
||||
var ret []*apollopb.CVE
|
||||
|
||||
for _, v := range cves {
|
||||
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
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package db
|
||||
package apollodb
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"github.com/jmoiron/sqlx/types"
|
||||
"github.com/lib/pq"
|
||||
secparseadminpb "peridot.resf.org/secparse/admin/proto/v1"
|
||||
apollopb "peridot.resf.org/apollo/pb"
|
||||
"peridot.resf.org/utils"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ShortCode is the DTO struct for `resf.secparse.admin.ShortCode`
|
||||
// ShortCode is the DTO struct for `resf.apollo.ShortCode`
|
||||
type ShortCode struct {
|
||||
Code string `db:"code"`
|
||||
Mode int8 `db:"mode"`
|
||||
CreatedAt *time.Time `db:"created_at"`
|
||||
ArchivedAt sql.NullTime `db:"archived_at"`
|
||||
MirrorFromDate sql.NullTime `db:"mirror_from_date"`
|
||||
RedHatProductPrefix sql.NullString `db:"redhat_product_prefix"`
|
||||
Code string `json:"code" db:"code"`
|
||||
Mode int8 `json:"mode" db:"mode"`
|
||||
CreatedAt *time.Time `json:"createdAt" db:"created_at"`
|
||||
ArchivedAt sql.NullTime `json:"archivedAt" db:"archived_at"`
|
||||
}
|
||||
|
||||
// Advisory is the DTO struct for `resf.secparse.Advisory`
|
||||
// Advisory is the DTO struct for `resf.apollo.Advisory`
|
||||
type Advisory struct {
|
||||
ID int64 `db:"id"`
|
||||
CreatedAt *time.Time `db:"created_at"`
|
||||
@ -63,32 +62,40 @@ type Advisory struct {
|
||||
Description string `db:"description"`
|
||||
Solution sql.NullString `db:"solution"`
|
||||
|
||||
RedHatIssuedAt sql.NullTime `db:"redhat_issued_at"`
|
||||
ShortCodeCode string `db:"short_code_code"`
|
||||
PublishedAt sql.NullTime `db:"published_at"`
|
||||
RedHatIssuedAt sql.NullTime `db:"redhat_issued_at"`
|
||||
ShortCodeCode string `db:"short_code_code"`
|
||||
RebootSuggested bool `db:"reboot_suggested"`
|
||||
PublishedAt sql.NullTime `db:"published_at"`
|
||||
|
||||
AffectedProducts pq.StringArray `db:"affected_products"`
|
||||
Fixes pq.StringArray `db:"fixes"`
|
||||
Cves pq.StringArray `db:"cves"`
|
||||
CveIds pq.StringArray `db:"cve_ids"`
|
||||
References pq.StringArray `db:"references"`
|
||||
RPMs pq.StringArray `db:"rpms"`
|
||||
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 {
|
||||
ID string `db:"id"`
|
||||
CreatedAt *time.Time `db:"created_at"`
|
||||
|
||||
State int `db:"state"`
|
||||
AdvisoryId sql.NullInt64 `db:"advisory_id"`
|
||||
ShortCode string `db:"short_code_code"`
|
||||
|
||||
SourceBy sql.NullString `db:"source_by"`
|
||||
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 {
|
||||
ID int64 `db:"id"`
|
||||
ProductID int64 `db:"product_id"`
|
||||
@ -99,29 +106,43 @@ type AffectedProduct struct {
|
||||
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 {
|
||||
ID int64 `db:"id"`
|
||||
Name string `db:"name"`
|
||||
|
||||
CurrentFullVersion string `db:"current_full_version"`
|
||||
RedHatMajorVersion sql.NullInt32 `db:"redhat_major_version"`
|
||||
ShortCode string `db:"short_code_code"`
|
||||
Archs pq.StringArray `db:"archs"`
|
||||
CurrentFullVersion string `db:"current_full_version"`
|
||||
RedHatMajorVersion sql.NullInt32 `db:"redhat_major_version"`
|
||||
ShortCode string `db:"short_code_code"`
|
||||
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 {
|
||||
ID int64 `db:"id"`
|
||||
AffectedProductId int64 `db:"affected_product_id"`
|
||||
Rpm string `db:"rpm"`
|
||||
SrcRpm string `db:"src_rpm"`
|
||||
CveID string `db:"cve_id"`
|
||||
KojiID string `db:"koji_id"`
|
||||
ID int64 `db:"id"`
|
||||
AffectedProductId int64 `db:"affected_product_id"`
|
||||
Rpm string `db:"rpm"`
|
||||
SrcRpm string `db:"src_rpm"`
|
||||
CveID string `db:"cve_id"`
|
||||
Sha256Sum string `db:"sha256_sum"`
|
||||
KojiID sql.NullString `db:"koji_id"`
|
||||
PeridotID sql.NullString `db:"peridot_id"`
|
||||
}
|
||||
|
||||
type Fix struct {
|
||||
ID int64 `db:"id"`
|
||||
Ticket sql.NullString `db:"ticket"`
|
||||
SourceBy sql.NullString `db:"source_by"`
|
||||
SourceLink sql.NullString `db:"source_link"`
|
||||
Description sql.NullString `db:"description"`
|
||||
}
|
||||
|
||||
@ -132,8 +153,9 @@ type AdvisoryReference struct {
|
||||
}
|
||||
|
||||
type MirrorState struct {
|
||||
ShortCode string `db:"short_code_code"`
|
||||
LastSync sql.NullTime `db:"last_sync"`
|
||||
ShortCode string `db:"short_code_code"`
|
||||
LastSync sql.NullTime `db:"last_sync"`
|
||||
ErrataAfter sql.NullTime `db:"errata_after"`
|
||||
}
|
||||
|
||||
type AdvisoryCVE struct {
|
||||
@ -148,21 +170,27 @@ type AdvisoryFix struct {
|
||||
|
||||
type IgnoredUpstreamPackage struct {
|
||||
ID int64 `db:"id"`
|
||||
ShortCode string `db:"short_code_code"`
|
||||
ProductID int64 `db:"product_id"`
|
||||
Package string `db:"package"`
|
||||
}
|
||||
|
||||
type RebootSuggestedPackage struct {
|
||||
CreatedAt *time.Time `db:"created_at"`
|
||||
Name string `db:"name"`
|
||||
}
|
||||
|
||||
type AdvisoryRPM struct {
|
||||
AdvisoryID int64 `db:"advisory_id"`
|
||||
Name string `db:"name"`
|
||||
ProductID int64 `db:"product_id"`
|
||||
}
|
||||
|
||||
type Access interface {
|
||||
GetAllShortCodes() ([]*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
|
||||
// mustafa: It is in my opinion better to accept the same struct
|
||||
// to create and update it.
|
||||
@ -179,11 +207,12 @@ type Access interface {
|
||||
GetAdvisoryByCodeAndYearAndNum(code string, year int, num int) (*Advisory, error)
|
||||
|
||||
GetAllUnresolvedCVEs() ([]*CVE, error)
|
||||
GetAllCVEsWithAllProductsFixed() ([]*CVE, error)
|
||||
GetPendingAffectedProducts() ([]*AffectedProduct, error)
|
||||
GetAllCVEsFixedDownstream() ([]*CVE, error)
|
||||
GetCVEByID(id string) (*CVE, error)
|
||||
CreateCVE(cveId string, state secparseadminpb.CVEState, shortCode string, sourceBy *string, sourceLink *string) (*CVE, error)
|
||||
UpdateCVEState(cve string, state secparseadminpb.CVEState) error
|
||||
GetAllCVEs() ([]*CVE, 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)
|
||||
GetProductByNameAndShortCode(product string, code string) (*Product, error)
|
||||
@ -193,25 +222,29 @@ type Access interface {
|
||||
GetAllAffectedProductsByCVE(cve string) ([]*AffectedProduct, error)
|
||||
GetAffectedProductByCVEAndPackage(cve string, pkg 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)
|
||||
UpdateAffectedProductStateAndPackageAndAdvisory(id int64, state int, pkg string, advisory *string) 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
|
||||
GetMirrorStateLastSync(code string) (*time.Time, error)
|
||||
GetMirrorState(code string) (*MirrorState, 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
|
||||
|
||||
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
|
||||
AddAdvisoryFix(advisoryId int64, fixId int64) 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)
|
||||
UseTransaction(tx utils.Tx) Access
|
@ -3,11 +3,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
go_library(
|
||||
name = "mock",
|
||||
srcs = ["mock.go"],
|
||||
importpath = "peridot.resf.org/secparse/db/mock",
|
||||
importpath = "peridot.resf.org/apollo/db/mock",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//secparse/admin/proto/v1:proto",
|
||||
"//secparse/db",
|
||||
"//apollo/db",
|
||||
"//apollo/proto/v1:pb",
|
||||
"//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
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package mock
|
||||
package apollomock
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
secparseadminpb "peridot.resf.org/secparse/admin/proto/v1"
|
||||
"peridot.resf.org/secparse/db"
|
||||
"github.com/jmoiron/sqlx/types"
|
||||
apollodb "peridot.resf.org/apollo/db"
|
||||
apollopb "peridot.resf.org/apollo/pb"
|
||||
"peridot.resf.org/utils"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Access struct {
|
||||
ShortCodes []*db.ShortCode
|
||||
Advisories []*db.Advisory
|
||||
Cves []*db.CVE
|
||||
Fixes []*db.Fix
|
||||
AdvisoryReferences []*db.AdvisoryReference
|
||||
Products []*db.Product
|
||||
AffectedProducts []*db.AffectedProduct
|
||||
BuildReferences []*db.BuildReference
|
||||
MirrorStates []*db.MirrorState
|
||||
AdvisoryCVEs []*db.AdvisoryCVE
|
||||
AdvisoryFixes []*db.AdvisoryFix
|
||||
IgnoredUpstreamPackages []*db.IgnoredUpstreamPackage
|
||||
AdvisoryRPMs []*db.AdvisoryRPM
|
||||
ShortCodes []*apollodb.ShortCode
|
||||
Advisories []*apollodb.Advisory
|
||||
Cves []*apollodb.CVE
|
||||
Fixes []*apollodb.Fix
|
||||
AdvisoryReferences []*apollodb.AdvisoryReference
|
||||
Products []*apollodb.Product
|
||||
AffectedProducts []*apollodb.AffectedProduct
|
||||
BuildReferences []*apollodb.BuildReference
|
||||
MirrorStates []*apollodb.MirrorState
|
||||
AdvisoryCVEs []*apollodb.AdvisoryCVE
|
||||
AdvisoryFixes []*apollodb.AdvisoryFix
|
||||
IgnoredUpstreamPackages []*apollodb.IgnoredUpstreamPackage
|
||||
RebootSuggestedPackages []*apollodb.RebootSuggestedPackage
|
||||
AdvisoryRPMs []*apollodb.AdvisoryRPM
|
||||
}
|
||||
|
||||
func New() *Access {
|
||||
return &Access{
|
||||
ShortCodes: []*db.ShortCode{},
|
||||
Advisories: []*db.Advisory{},
|
||||
Cves: []*db.CVE{},
|
||||
Fixes: []*db.Fix{},
|
||||
AdvisoryReferences: []*db.AdvisoryReference{},
|
||||
Products: []*db.Product{},
|
||||
AffectedProducts: []*db.AffectedProduct{},
|
||||
BuildReferences: []*db.BuildReference{},
|
||||
MirrorStates: []*db.MirrorState{},
|
||||
AdvisoryCVEs: []*db.AdvisoryCVE{},
|
||||
AdvisoryFixes: []*db.AdvisoryFix{},
|
||||
IgnoredUpstreamPackages: []*db.IgnoredUpstreamPackage{},
|
||||
AdvisoryRPMs: []*db.AdvisoryRPM{},
|
||||
ShortCodes: []*apollodb.ShortCode{},
|
||||
Advisories: []*apollodb.Advisory{},
|
||||
Cves: []*apollodb.CVE{},
|
||||
Fixes: []*apollodb.Fix{},
|
||||
AdvisoryReferences: []*apollodb.AdvisoryReference{},
|
||||
Products: []*apollodb.Product{},
|
||||
AffectedProducts: []*apollodb.AffectedProduct{},
|
||||
BuildReferences: []*apollodb.BuildReference{},
|
||||
MirrorStates: []*apollodb.MirrorState{},
|
||||
AdvisoryCVEs: []*apollodb.AdvisoryCVE{},
|
||||
AdvisoryFixes: []*apollodb.AdvisoryFix{},
|
||||
IgnoredUpstreamPackages: []*apollodb.IgnoredUpstreamPackage{},
|
||||
RebootSuggestedPackages: []*apollodb.RebootSuggestedPackage{},
|
||||
AdvisoryRPMs: []*apollodb.AdvisoryRPM{},
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Access) GetAllShortCodes() ([]*db.ShortCode, error) {
|
||||
func (a *Access) GetAllShortCodes() ([]*apollodb.ShortCode, error) {
|
||||
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 {
|
||||
if val.Code == code {
|
||||
return val, nil
|
||||
@ -87,24 +90,22 @@ func (a *Access) GetShortCodeByCode(code string) (*db.ShortCode, error) {
|
||||
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()
|
||||
|
||||
shortCode := db.ShortCode{
|
||||
Code: code,
|
||||
Mode: int8(mode),
|
||||
CreatedAt: &now,
|
||||
ArchivedAt: sql.NullTime{},
|
||||
MirrorFromDate: sql.NullTime{},
|
||||
RedHatProductPrefix: sql.NullString{},
|
||||
shortCode := apollodb.ShortCode{
|
||||
Code: code,
|
||||
Mode: int8(mode),
|
||||
CreatedAt: &now,
|
||||
ArchivedAt: sql.NullTime{},
|
||||
}
|
||||
a.ShortCodes = append(a.ShortCodes, &shortCode)
|
||||
|
||||
return &shortCode, nil
|
||||
}
|
||||
|
||||
func (a *Access) getAdvisoriesWithJoin(filter func(*db.Advisory) bool) []*db.Advisory {
|
||||
var advisories []*db.Advisory
|
||||
func (a *Access) getAdvisoriesWithJoin(filter func(*apollodb.Advisory) bool) []*apollodb.Advisory {
|
||||
var advisories []*apollodb.Advisory
|
||||
for _, val := range a.Advisories {
|
||||
if filter(val) {
|
||||
advisories = append(advisories, val)
|
||||
@ -193,9 +194,30 @@ func (a *Access) getAdvisoriesWithJoin(filter func(*db.Advisory) bool) []*db.Adv
|
||||
return advisories
|
||||
}
|
||||
|
||||
func (a *Access) GetAllAdvisories(publishedOnly bool) ([]*db.Advisory, error) {
|
||||
return a.getAdvisoriesWithJoin(func(advisory *db.Advisory) bool {
|
||||
if publishedOnly {
|
||||
func (a *Access) GetAllAdvisories(filters *apollopb.AdvisoryFilters, page int32, limit int32) ([]*apollodb.Advisory, error) {
|
||||
return a.getAdvisoriesWithJoin(func(advisory *apollodb.Advisory) bool {
|
||||
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 {
|
||||
return false
|
||||
}
|
||||
@ -205,8 +227,8 @@ func (a *Access) GetAllAdvisories(publishedOnly bool) ([]*db.Advisory, error) {
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (a *Access) GetAdvisoryByCodeAndYearAndNum(code string, year int, num int) (*db.Advisory, error) {
|
||||
advisories := a.getAdvisoriesWithJoin(func(advisory *db.Advisory) bool {
|
||||
func (a *Access) GetAdvisoryByCodeAndYearAndNum(code string, year int, num int) (*apollodb.Advisory, error) {
|
||||
advisories := a.getAdvisoriesWithJoin(func(advisory *apollodb.Advisory) bool {
|
||||
if advisory.ShortCodeCode == code && advisory.Year == year && advisory.Num == num {
|
||||
return true
|
||||
}
|
||||
@ -220,14 +242,14 @@ func (a *Access) GetAdvisoryByCodeAndYearAndNum(code string, year int, num int)
|
||||
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
|
||||
if len(a.Advisories) > 0 {
|
||||
lastId = a.Advisories[len(a.Advisories)-1].ID + 1
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
ret := &db.Advisory{
|
||||
ret := &apollodb.Advisory{
|
||||
ID: lastId,
|
||||
CreatedAt: &now,
|
||||
Year: advisory.Year,
|
||||
@ -246,7 +268,7 @@ func (a *Access) CreateAdvisory(advisory *db.Advisory) (*db.Advisory, error) {
|
||||
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 {
|
||||
if val.ID == advisory.ID {
|
||||
val.Year = advisory.Year
|
||||
@ -267,47 +289,58 @@ func (a *Access) UpdateAdvisory(advisory *db.Advisory) (*db.Advisory, error) {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (a *Access) GetAllUnresolvedCVEs() ([]*db.CVE, error) {
|
||||
var cves []*db.CVE
|
||||
func (a *Access) GetAllUnresolvedCVEs() ([]*apollodb.CVE, error) {
|
||||
var cves []*apollodb.CVE
|
||||
var addedCVEIds []string
|
||||
|
||||
for _, cve := range a.Cves {
|
||||
switch cve.State {
|
||||
case
|
||||
int(secparseadminpb.CVEState_NewFromUpstream),
|
||||
int(secparseadminpb.CVEState_NewOriginal):
|
||||
for _, affectedProduct := range a.AffectedProducts {
|
||||
if affectedProduct.CveID.String == cve.ID {
|
||||
switch affectedProduct.State {
|
||||
case
|
||||
int(apollopb.AffectedProduct_STATE_UNDER_INVESTIGATION_UPSTREAM),
|
||||
int(apollopb.AffectedProduct_STATE_UNDER_INVESTIGATION_DOWNSTREAM),
|
||||
int(apollopb.AffectedProduct_STATE_AFFECTED_UPSTREAM),
|
||||
int(apollopb.AffectedProduct_STATE_AFFECTED_DOWNSTREAM):
|
||||
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)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return cves, nil
|
||||
}
|
||||
|
||||
func (a *Access) GetAllCVEsWithAllProductsFixed() ([]*db.CVE, error) {
|
||||
var cves []*db.CVE
|
||||
var fixedAffectedProducts []*db.AffectedProduct
|
||||
func (a *Access) GetPendingAffectedProducts() ([]*apollodb.AffectedProduct, error) {
|
||||
var ret []*apollodb.AffectedProduct
|
||||
|
||||
for _, affectedProduct := range a.AffectedProducts {
|
||||
switch affectedProduct.State {
|
||||
case
|
||||
int(secparseadminpb.AffectedProductState_FixedUpstream),
|
||||
int(secparseadminpb.AffectedProductState_WillNotFixUpstream),
|
||||
int(secparseadminpb.AffectedProductState_WillNotFixDownstream),
|
||||
int(secparseadminpb.AffectedProductState_OutOfSupportScope):
|
||||
fixedAffectedProducts = append(fixedAffectedProducts, affectedProduct)
|
||||
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 {
|
||||
switch cve.State {
|
||||
case
|
||||
int(secparseadminpb.CVEState_NewFromUpstream),
|
||||
int(secparseadminpb.CVEState_NewOriginal),
|
||||
int(secparseadminpb.CVEState_ResolvedUpstream),
|
||||
int(secparseadminpb.CVEState_ResolvedDownstream):
|
||||
for _, fixed := range fixedAffectedProducts {
|
||||
if fixed.CveID.String == cve.ID {
|
||||
cves = append(cves, cve)
|
||||
for _, affectedProduct := range a.AffectedProducts {
|
||||
if affectedProduct.CveID.String == cve.ID {
|
||||
if affectedProduct.State == int(apollopb.AffectedProduct_STATE_FIXED_DOWNSTREAM) {
|
||||
nCve := *cve
|
||||
nCve.AffectedProductId = sql.NullInt64{Valid: true, Int64: affectedProduct.ID}
|
||||
cves = append(cves, &nCve)
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -317,19 +350,7 @@ func (a *Access) GetAllCVEsWithAllProductsFixed() ([]*db.CVE, error) {
|
||||
return cves, nil
|
||||
}
|
||||
|
||||
func (a *Access) GetAllCVEsFixedDownstream() ([]*db.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) {
|
||||
func (a *Access) GetCVEByID(id string) (*apollodb.CVE, error) {
|
||||
for _, cve := range a.Cves {
|
||||
if cve.ID == id {
|
||||
return cve, nil
|
||||
@ -339,7 +360,11 @@ func (a *Access) GetCVEByID(id string) (*db.CVE, error) {
|
||||
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 sl sql.NullString
|
||||
|
||||
@ -354,32 +379,33 @@ func (a *Access) CreateCVE(cveId string, state secparseadminpb.CVEState, shortCo
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
cve := &db.CVE{
|
||||
cve := &apollodb.CVE{
|
||||
ID: cveId,
|
||||
CreatedAt: &now,
|
||||
State: int(state),
|
||||
AdvisoryId: sql.NullInt64{},
|
||||
ShortCode: shortCode,
|
||||
SourceBy: sby,
|
||||
SourceLink: sl,
|
||||
Content: content,
|
||||
}
|
||||
a.Cves = append(a.Cves, cve)
|
||||
|
||||
return cve, nil
|
||||
}
|
||||
|
||||
func (a *Access) UpdateCVEState(cve string, state secparseadminpb.CVEState) error {
|
||||
for _, c := range a.Cves {
|
||||
if c.ID == cve {
|
||||
c.State = int(state)
|
||||
func (a *Access) SetCVEContent(cveId string, content types.JSONText) error {
|
||||
for _, cve := range a.Cves {
|
||||
if cve.ID == cveId {
|
||||
cve.Content = types.NullJSONText{Valid: true, JSONText: content}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (a *Access) GetProductsByShortCode(code string) ([]*db.Product, error) {
|
||||
var products []*db.Product
|
||||
func (a *Access) GetProductsByShortCode(code string) ([]*apollodb.Product, error) {
|
||||
var products []*apollodb.Product
|
||||
|
||||
for _, product := range a.Products {
|
||||
if product.ShortCode == code {
|
||||
@ -390,7 +416,7 @@ func (a *Access) GetProductsByShortCode(code string) ([]*db.Product, error) {
|
||||
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 {
|
||||
if product.Name == name && product.ShortCode == code {
|
||||
return product, nil
|
||||
@ -400,7 +426,7 @@ func (a *Access) GetProductByNameAndShortCode(name string, code string) (*db.Pro
|
||||
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 {
|
||||
if product.ID == id {
|
||||
return product, nil
|
||||
@ -410,7 +436,7 @@ func (a *Access) GetProductByID(id int64) (*db.Product, error) {
|
||||
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
|
||||
if len(a.Products) > 0 {
|
||||
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
|
||||
}
|
||||
|
||||
product := &db.Product{
|
||||
ID: lastId,
|
||||
Name: name,
|
||||
CurrentFullVersion: currentFullVersion,
|
||||
RedHatMajorVersion: rhmv,
|
||||
ShortCode: code,
|
||||
Archs: archs,
|
||||
product := &apollodb.Product{
|
||||
ID: lastId,
|
||||
Name: name,
|
||||
CurrentFullVersion: currentFullVersion,
|
||||
RedHatMajorVersion: rhmv,
|
||||
ShortCode: code,
|
||||
Archs: archs,
|
||||
MirrorFromDate: sql.NullTime{},
|
||||
RedHatProductPrefix: sql.NullString{},
|
||||
}
|
||||
a.Products = append(a.Products, product)
|
||||
|
||||
return product, nil
|
||||
}
|
||||
|
||||
func (a *Access) GetAllAffectedProductsByCVE(cve string) ([]*db.AffectedProduct, error) {
|
||||
var affectedProducts []*db.AffectedProduct
|
||||
func (a *Access) GetAllAffectedProductsByCVE(cve string) ([]*apollodb.AffectedProduct, error) {
|
||||
var affectedProducts []*apollodb.AffectedProduct
|
||||
|
||||
for _, affectedProduct := range a.AffectedProducts {
|
||||
if affectedProduct.CveID.String == cve {
|
||||
@ -447,7 +475,7 @@ func (a *Access) GetAllAffectedProductsByCVE(cve string) ([]*db.AffectedProduct,
|
||||
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 {
|
||||
if affectedProduct.CveID.String == cve && affectedProduct.Package == pkg {
|
||||
return affectedProduct, nil
|
||||
@ -457,7 +485,7 @@ func (a *Access) GetAffectedProductByCVEAndPackage(cve string, pkg string) (*db.
|
||||
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 {
|
||||
if affectedProduct.Advisory.String == advisory {
|
||||
return affectedProduct, nil
|
||||
@ -467,7 +495,17 @@ func (a *Access) GetAffectedProductByAdvisory(advisory string) (*db.AffectedProd
|
||||
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
|
||||
if len(a.AffectedProducts) > 0 {
|
||||
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
|
||||
}
|
||||
|
||||
affectedProduct := &db.AffectedProduct{
|
||||
affectedProduct := &apollodb.AffectedProduct{
|
||||
ID: lastId,
|
||||
ProductID: productId,
|
||||
CveID: sql.NullString{Valid: true, String: cveId},
|
||||
@ -529,15 +567,17 @@ func (a *Access) DeleteAffectedProduct(id int64) error {
|
||||
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
|
||||
if len(a.Fixes) > 0 {
|
||||
lastId = a.Fixes[len(a.Fixes)-1].ID + 1
|
||||
}
|
||||
|
||||
fix := &db.Fix{
|
||||
fix := &apollodb.Fix{
|
||||
ID: lastId,
|
||||
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},
|
||||
}
|
||||
a.Fixes = append(a.Fixes, fix)
|
||||
@ -545,13 +585,13 @@ func (a *Access) CreateFix(ticket string, description string) (int64, error) {
|
||||
return lastId, nil
|
||||
}
|
||||
|
||||
func (a *Access) GetMirrorStateLastSync(code string) (*time.Time, error) {
|
||||
var lastSync *time.Time
|
||||
func (a *Access) GetMirrorState(code string) (*apollodb.MirrorState, error) {
|
||||
var lastSync *apollodb.MirrorState
|
||||
|
||||
for _, mirrorState := range a.MirrorStates {
|
||||
if mirrorState.ShortCode == code {
|
||||
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,
|
||||
LastSync: sql.NullTime{Valid: true, Time: *lastSync},
|
||||
}
|
||||
@ -582,19 +622,62 @@ func (a *Access) UpdateMirrorState(code string, lastSync *time.Time) error {
|
||||
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
|
||||
if len(a.BuildReferences) > 0 {
|
||||
lastId = a.BuildReferences[len(a.BuildReferences)-1].ID + 1
|
||||
}
|
||||
|
||||
buildReference := &db.BuildReference{
|
||||
buildReference := &apollodb.BuildReference{
|
||||
ID: lastId,
|
||||
AffectedProductId: affectedProductId,
|
||||
Rpm: rpm,
|
||||
SrcRpm: srcRpm,
|
||||
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)
|
||||
@ -608,7 +691,7 @@ func (a *Access) CreateAdvisoryReference(advisoryId int64, url string) error {
|
||||
lastId = a.AdvisoryReferences[len(a.AdvisoryReferences)-1].ID + 1
|
||||
}
|
||||
|
||||
advisoryReference := &db.AdvisoryReference{
|
||||
advisoryReference := &apollodb.AdvisoryReference{
|
||||
ID: lastId,
|
||||
URL: url,
|
||||
AdvisoryId: advisoryId,
|
||||
@ -618,11 +701,11 @@ func (a *Access) CreateAdvisoryReference(advisoryId int64, url string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Access) GetAllIgnoredPackagesByShortCode(code string) ([]string, error) {
|
||||
func (a *Access) GetAllIgnoredPackagesByProductID(productID int64) ([]string, error) {
|
||||
var packages []string
|
||||
|
||||
for _, ignoredPackage := range a.IgnoredUpstreamPackages {
|
||||
if ignoredPackage.ShortCode == code {
|
||||
if ignoredPackage.ProductID == productID {
|
||||
packages = append(packages, ignoredPackage.Package)
|
||||
}
|
||||
}
|
||||
@ -630,8 +713,18 @@ func (a *Access) GetAllIgnoredPackagesByShortCode(code string) ([]string, error)
|
||||
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 {
|
||||
advisoryFix := &db.AdvisoryFix{
|
||||
advisoryFix := &apollodb.AdvisoryFix{
|
||||
AdvisoryID: advisoryId,
|
||||
FixID: fixId,
|
||||
}
|
||||
@ -641,7 +734,7 @@ func (a *Access) AddAdvisoryFix(advisoryId int64, fixId int64) error {
|
||||
}
|
||||
|
||||
func (a *Access) AddAdvisoryCVE(advisoryId int64, cveId string) error {
|
||||
advisoryCVE := &db.AdvisoryCVE{
|
||||
advisoryCVE := &apollodb.AdvisoryCVE{
|
||||
AdvisoryID: advisoryId,
|
||||
CveID: cveId,
|
||||
}
|
||||
@ -650,10 +743,11 @@ func (a *Access) AddAdvisoryCVE(advisoryId int64, cveId string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Access) AddAdvisoryRPM(advisoryId int64, name string) error {
|
||||
advisoryRPM := &db.AdvisoryRPM{
|
||||
func (a *Access) AddAdvisoryRPM(advisoryId int64, name string, productID int64) error {
|
||||
advisoryRPM := &apollodb.AdvisoryRPM{
|
||||
AdvisoryID: advisoryId,
|
||||
Name: name,
|
||||
ProductID: productID,
|
||||
}
|
||||
a.AdvisoryRPMs = append(a.AdvisoryRPMs, advisoryRPM)
|
||||
|
||||
@ -664,6 +758,6 @@ func (a *Access) Begin() (utils.Tx, error) {
|
||||
return &utils.MockTx{}, nil
|
||||
}
|
||||
|
||||
func (a *Access) UseTransaction(_ utils.Tx) db.Access {
|
||||
func (a *Access) UseTransaction(_ utils.Tx) apollodb.Access {
|
||||
return a
|
||||
}
|
@ -3,12 +3,13 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
go_library(
|
||||
name = "psql",
|
||||
srcs = ["psql.go"],
|
||||
importpath = "peridot.resf.org/secparse/db/psql",
|
||||
importpath = "peridot.resf.org/apollo/db/psql",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//secparse/admin/proto/v1:proto",
|
||||
"//secparse/db",
|
||||
"//apollo/db",
|
||||
"//apollo/proto/v1:pb",
|
||||
"//utils",
|
||||
"//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",
|
||||
"server.go",
|
||||
],
|
||||
importpath = "peridot.resf.org/secparse/impl",
|
||||
importpath = "peridot.resf.org/apollo/impl/v1",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//secparse/db",
|
||||
"//secparse/proto/v1:proto",
|
||||
"//secparse/rpmutils",
|
||||
"//apollo/db",
|
||||
"//apollo/proto/v1:pb",
|
||||
"//apollo/rpmutils",
|
||||
"//proto:common",
|
||||
"//utils",
|
||||
"//vendor/github.com/gorilla/feeds",
|
||||
"//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//codes",
|
||||
"@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
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package impl
|
||||
package apolloimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
hydraclient "github.com/ory/hydra-client-go/client"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc"
|
||||
"net/url"
|
||||
secparseadminpb "peridot.resf.org/secparse/admin/proto/v1"
|
||||
"peridot.resf.org/secparse/db"
|
||||
"peridot.resf.org/servicecatalog"
|
||||
apollodb "peridot.resf.org/apollo/db"
|
||||
apollopb "peridot.resf.org/apollo/pb"
|
||||
commonpb "peridot.resf.org/common"
|
||||
"peridot.resf.org/utils"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
secparseadminpb.UnimplementedSecparseAdminServer
|
||||
apollopb.UnimplementedApolloServiceServer
|
||||
|
||||
log *logrus.Logger
|
||||
db db.Access
|
||||
hydra *hydraclient.OryHydra
|
||||
log *logrus.Logger
|
||||
db apollodb.Access
|
||||
rssFeedTitle string
|
||||
rssFeedDescription string
|
||||
homepage string
|
||||
}
|
||||
|
||||
func NewServer(db db.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,
|
||||
})
|
||||
|
||||
func NewServer(db apollodb.Access) *Server {
|
||||
return &Server{
|
||||
log: logrus.New(),
|
||||
db: db,
|
||||
hydra: hydraSDK,
|
||||
log: logrus.New(),
|
||||
db: db,
|
||||
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) {
|
||||
n := utils.EndInterceptor
|
||||
n = utils.AuthInterceptor(s.hydra, nil, []string{}, true, n)
|
||||
|
||||
return n(ctx, req, usi, handler)
|
||||
}
|
||||
@ -82,18 +73,22 @@ func (s *Server) Run() {
|
||||
Interceptor: s.interceptor,
|
||||
},
|
||||
func(r *utils.Register) {
|
||||
err := secparseadminpb.RegisterSecparseAdminHandlerFromEndpoint(
|
||||
r.Context,
|
||||
r.Mux,
|
||||
r.Endpoint,
|
||||
r.Options,
|
||||
)
|
||||
if err != nil {
|
||||
s.log.Fatalf("could not register handler - %s", err)
|
||||
endpoints := []utils.GrpcEndpointRegister{
|
||||
commonpb.RegisterHealthCheckServiceHandlerFromEndpoint,
|
||||
apollopb.RegisterApolloServiceHandlerFromEndpoint,
|
||||
}
|
||||
|
||||
for _, endpoint := range endpoints {
|
||||
err := endpoint(r.Context, r.Mux, r.Endpoint, r.Options)
|
||||
if err != nil {
|
||||
s.log.Fatalf("could not register handler - %v", err)
|
||||
}
|
||||
}
|
||||
},
|
||||
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,
|
||||
mode numeric not null,
|
||||
mirror_from_date timestamp,
|
||||
redhat_product_prefix text,
|
||||
|
||||
created_at timestamp default now() not null,
|
||||
archived_at timestamp
|
@ -32,11 +32,20 @@
|
||||
|
||||
create table products
|
||||
(
|
||||
id bigserial primary key,
|
||||
name text not null,
|
||||
current_full_version text not null,
|
||||
redhat_major_version numeric,
|
||||
short_code_code text references short_codes (code) not null,
|
||||
archs text[] not null,
|
||||
eol_at timestamp
|
||||
id bigserial primary key,
|
||||
name text not null,
|
||||
current_full_version text not null,
|
||||
redhat_major_version numeric,
|
||||
short_code_code text references short_codes (code) not null,
|
||||
archs text[] not null,
|
||||
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
|
||||
)
|
@ -32,20 +32,21 @@
|
||||
|
||||
create table advisories
|
||||
(
|
||||
id bigserial primary key not null,
|
||||
created_at timestamp default now() not null,
|
||||
id bigserial primary key not null,
|
||||
created_at timestamp default now() not null,
|
||||
|
||||
year numeric not null,
|
||||
num numeric not null,
|
||||
year numeric not null,
|
||||
num numeric not null,
|
||||
|
||||
synopsis text not null,
|
||||
topic text not null,
|
||||
severity numeric not null,
|
||||
type numeric not null,
|
||||
description text not null,
|
||||
solution text null,
|
||||
synopsis text not null,
|
||||
topic text not null,
|
||||
severity numeric not null,
|
||||
type numeric not null,
|
||||
description text not null,
|
||||
solution text null,
|
||||
|
||||
redhat_issued_at timestamp null,
|
||||
short_code_code text references short_codes (code) not null,
|
||||
published_at timestamp null
|
||||
redhat_issued_at timestamp null,
|
||||
short_code_code text references short_codes (code) not null,
|
||||
reboot_suggested bool default false not null,
|
||||
published_at timestamp null
|
||||
)
|
@ -34,7 +34,6 @@ create table cves
|
||||
(
|
||||
id text primary key,
|
||||
created_at timestamp default now() not null,
|
||||
state numeric not null,
|
||||
short_code_code text references short_codes (code) not null,
|
||||
|
||||
source_by text,
|
@ -32,7 +32,9 @@
|
||||
|
||||
create table fixes
|
||||
(
|
||||
id bigserial primary key,
|
||||
ticket text,
|
||||
description text
|
||||
id bigserial primary key,
|
||||
ticket text,
|
||||
source_by text,
|
||||
source_link text,
|
||||
description text
|
||||
)
|
@ -32,11 +32,12 @@
|
||||
|
||||
create table build_references
|
||||
(
|
||||
id bigserial primary key,
|
||||
affected_product_id bigint references affected_products (id),
|
||||
rpm text not null,
|
||||
src_rpm text not null,
|
||||
cve_id text references cves (id) not null,
|
||||
koji_id text,
|
||||
peridot_id text
|
||||
id bigserial primary key,
|
||||
affected_product_id bigint references affected_products (id),
|
||||
rpm text not null,
|
||||
src_rpm text not null,
|
||||
cve_id text references cves (id) not null,
|
||||
sha256_sum text not null,
|
||||
koji_id text,
|
||||
peridot_id text
|
||||
)
|
@ -32,6 +32,7 @@
|
||||
|
||||
create table mirror_state
|
||||
(
|
||||
short_code_code text references short_codes (code) primary key,
|
||||
last_sync timestamp
|
||||
short_code_code text references short_codes (code) primary key,
|
||||
last_sync timestamp,
|
||||
errata_after timestamp
|
||||
);
|
@ -32,7 +32,7 @@
|
||||
|
||||
create table ignored_upstream_packages
|
||||
(
|
||||
id bigserial primary key,
|
||||
short_code_code text references short_codes (code) not null,
|
||||
package text not null
|
||||
id bigserial primary key,
|
||||
product_id bigint references products (id) not null,
|
||||
package text not null
|
||||
);
|
@ -32,8 +32,9 @@
|
||||
|
||||
create table advisory_rpms
|
||||
(
|
||||
advisory_id bigint references advisories (id) not null,
|
||||
name text not null,
|
||||
advisory_id bigint references advisories (id) 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("@io_bazel_rules_go//go:def.bzl", "go_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("@openapi_tools_generator_bazel//:defs.bzl", "openapi_generator")
|
||||
|
||||
proto_library(
|
||||
name = "secparsepb_proto",
|
||||
name = "apollopb_proto",
|
||||
srcs = [
|
||||
"advisory.proto",
|
||||
"secparse.proto",
|
||||
"affected_product.proto",
|
||||
"apollo.proto",
|
||||
"build.proto",
|
||||
"cve.proto",
|
||||
"fix.proto",
|
||||
"short_code.proto",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//proto:commonpb_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//:wrappers_proto",
|
||||
"@go_googleapis//google/api:annotations_proto",
|
||||
"@go_googleapis//google/api:httpbody_proto",
|
||||
],
|
||||
)
|
||||
|
||||
go_proto_library(
|
||||
name = "secparsepb_go_proto",
|
||||
name = "apollopb_go_proto",
|
||||
compilers = [
|
||||
"//:go_apiv2",
|
||||
"//:go_grpc",
|
||||
"//:go_validate",
|
||||
"@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway",
|
||||
],
|
||||
importpath = "peridot.resf.org/secparse/proto/v1",
|
||||
proto = ":secparsepb_proto",
|
||||
importpath = "peridot.resf.org/apollo/pb",
|
||||
proto = ":apollopb_proto",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//proto:common",
|
||||
"@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:httpbody_go_proto",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "pb",
|
||||
embed = [":apollopb_go_proto"],
|
||||
importpath = "peridot.resf.org/apollo/pb",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
protoc_gen_openapiv2(
|
||||
name = "openapi",
|
||||
proto = ":secparsepb_proto",
|
||||
proto = ":apollopb_proto",
|
||||
simple_operation_ids = True,
|
||||
single_output = True,
|
||||
)
|
||||
@ -53,10 +63,3 @@ openapi_generator(
|
||||
spec = ":openapi",
|
||||
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";
|
||||
|
||||
package resf.secparse;
|
||||
package resf.apollo.v1;
|
||||
|
||||
import "google/protobuf/timestamp.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
|
||||
//
|
||||
// Product advisory
|
||||
message Advisory {
|
||||
enum Type {
|
||||
UnknownType = 0;
|
||||
Security = 1;
|
||||
BugFix = 2;
|
||||
Enhancement = 3;
|
||||
TYPE_UNKNOWN = 0;
|
||||
TYPE_SECURITY = 1;
|
||||
TYPE_BUGFIX = 2;
|
||||
TYPE_ENHANCEMENT = 3;
|
||||
}
|
||||
|
||||
// Type
|
||||
@ -42,11 +47,11 @@ message Advisory {
|
||||
string synopsis = 4;
|
||||
|
||||
enum Severity {
|
||||
UnknownSeverity = 0;
|
||||
Low = 1;
|
||||
Moderate = 2;
|
||||
Important = 3;
|
||||
Critical = 4;
|
||||
SEVERITY_UNKNOWN = 0;
|
||||
SEVERITY_LOW = 1;
|
||||
SEVERITY_MODERATE = 2;
|
||||
SEVERITY_IMPORTANT = 3;
|
||||
SEVERITY_CRITICAL = 4;
|
||||
}
|
||||
|
||||
// Severity
|
||||
@ -78,12 +83,12 @@ message Advisory {
|
||||
// Fixes
|
||||
//
|
||||
// A list of tickets from upstream bug trackers
|
||||
repeated string fixes = 10;
|
||||
repeated Fix fixes = 10;
|
||||
|
||||
// CVEs
|
||||
//
|
||||
// A list of CVEs assigned to this advisory
|
||||
repeated string cves = 11;
|
||||
repeated CVE cves = 11;
|
||||
|
||||
// References
|
||||
//
|
||||
@ -98,60 +103,10 @@ message Advisory {
|
||||
// RPMs
|
||||
//
|
||||
// Affected RPMs
|
||||
repeated string rpms = 14;
|
||||
}
|
||||
map<string, RPMs> rpms = 14;
|
||||
|
||||
// ListAdvisoriesRequest
|
||||
//
|
||||
// Request body for `ListAdvisories`
|
||||
// All fields are optional
|
||||
message ListAdvisoriesRequest {
|
||||
// Product
|
||||
// Reboot suggested
|
||||
//
|
||||
// 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;
|
||||
// Whether a system reboot should be suggested after applying this advisory
|
||||
bool reboot_suggested = 15;
|
||||
}
|
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",
|
||||
"mock.go",
|
||||
],
|
||||
importpath = "peridot.resf.org/secparse/rherrata",
|
||||
importpath = "peridot.resf.org/apollo/rherrata",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//secparse/proto/v1:proto",
|
||||
"//apollo/proto/v1:pb",
|
||||
"//vendor/github.com/PuerkitoBio/goquery",
|
||||
"//vendor/github.com/go-chi/chi",
|
||||
"//vendor/github.com/gocolly/colly/v2:colly",
|
||||
@ -24,7 +24,7 @@ go_test(
|
||||
data = glob(["testdata/**"]),
|
||||
embed = [":rherrata"],
|
||||
deps = [
|
||||
"//secparse/proto/v1:proto",
|
||||
"//apollo/proto/v1:pb",
|
||||
"//vendor/github.com/stretchr/testify/require",
|
||||
],
|
||||
)
|
@ -38,7 +38,7 @@ import (
|
||||
|
||||
type APIService interface {
|
||||
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
|
||||
@ -54,9 +54,9 @@ func NewClient() *API {
|
||||
client: &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
},
|
||||
userAgent: "secparse/rherrata/0.1",
|
||||
userAgent: "apollo/rherrata/0.2",
|
||||
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"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var internalAfterDates = map[string]string{
|
||||
"8.4": "2021-04-29T00:00:00Z",
|
||||
"9.0": "2022-05-17T00:00:00Z",
|
||||
}
|
||||
|
||||
type CompactErrata struct {
|
||||
@ -61,7 +63,7 @@ type internalAdvisoriesResponse struct {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -71,12 +73,14 @@ func (a *API) GetAdvisories(currentVersion string) ([]*CompactErrata, error) {
|
||||
usableVersion := strings.Replace(currentVersion, ".", "%5C.", -1)
|
||||
fq2 := fmt.Sprintf("portal_product_filter:Red%%5C+Hat%%5C+Enterprise%%5C+Linux%%7C*%%7C%s%%7C*", usableVersion)
|
||||
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))
|
||||
}
|
||||
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)
|
||||
if err != nil {
|
@ -35,7 +35,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/gocolly/colly/v2"
|
||||
secparsepb "peridot.resf.org/secparse/proto/v1"
|
||||
apollopb "peridot.resf.org/apollo/pb"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -62,8 +62,8 @@ type UpdatedPackages struct {
|
||||
|
||||
type Errata struct {
|
||||
Synopsis string
|
||||
Type secparsepb.Advisory_Type
|
||||
Severity secparsepb.Advisory_Severity
|
||||
Type apollopb.Advisory_Type
|
||||
Severity apollopb.Advisory_Severity
|
||||
Topic []string
|
||||
Description []string
|
||||
Solution []string
|
||||
@ -178,9 +178,9 @@ func (a *API) GetErrata(advisory string) (*Errata, error) {
|
||||
c.OnHTML("div#type-severity", func(element *colly.HTMLElement) {
|
||||
typeSeverity := strings.Split(element.DOM.Find("p").Text(), ":")
|
||||
if typeSeverity[0] == "Product Enhancement Advisory" {
|
||||
errata.Type = secparsepb.Advisory_Enhancement
|
||||
errata.Type = apollopb.Advisory_TYPE_ENHANCEMENT
|
||||
} else if typeSeverity[0] == "Bug Fix Advisory" {
|
||||
errata.Type = secparsepb.Advisory_BugFix
|
||||
errata.Type = apollopb.Advisory_TYPE_BUGFIX
|
||||
} else {
|
||||
if len(typeSeverity) != 2 {
|
||||
err = errors.New("invalid type/severity")
|
||||
@ -195,28 +195,28 @@ func (a *API) GetErrata(advisory string) (*Errata, error) {
|
||||
|
||||
switch strings.TrimSpace(typeSplit[0]) {
|
||||
case "Security":
|
||||
errata.Type = secparsepb.Advisory_Security
|
||||
errata.Type = apollopb.Advisory_TYPE_SECURITY
|
||||
break
|
||||
case "BugFix":
|
||||
errata.Type = secparsepb.Advisory_BugFix
|
||||
errata.Type = apollopb.Advisory_TYPE_BUGFIX
|
||||
break
|
||||
case "Enhancement":
|
||||
errata.Type = secparsepb.Advisory_Enhancement
|
||||
errata.Type = apollopb.Advisory_TYPE_ENHANCEMENT
|
||||
break
|
||||
}
|
||||
|
||||
switch strings.TrimSpace(typeSeverity[1]) {
|
||||
case "Low":
|
||||
errata.Severity = secparsepb.Advisory_Low
|
||||
errata.Severity = apollopb.Advisory_SEVERITY_LOW
|
||||
break
|
||||
case "Moderate":
|
||||
errata.Severity = secparsepb.Advisory_Moderate
|
||||
errata.Severity = apollopb.Advisory_SEVERITY_MODERATE
|
||||
break
|
||||
case "Important":
|
||||
errata.Severity = secparsepb.Advisory_Important
|
||||
errata.Severity = apollopb.Advisory_SEVERITY_IMPORTANT
|
||||
break
|
||||
case "Critical":
|
||||
errata.Severity = secparsepb.Advisory_Critical
|
||||
errata.Severity = apollopb.Advisory_SEVERITY_CRITICAL
|
||||
break
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ package rherrata
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"io/ioutil"
|
||||
secparsepb "peridot.resf.org/secparse/proto/v1"
|
||||
apollopb "peridot.resf.org/apollo/pb"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -53,7 +53,7 @@ func TestRHBA20212759(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
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.Equal(t, "An update for firefox is now available for Red Hat Enterprise Linux 8.", errata.Topic[0])
|
||||
require.Len(t, errata.Description, 3)
|
||||
@ -95,8 +95,8 @@ func TestRHBA20212743(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, "Important: firefox security update", errata.Synopsis)
|
||||
require.Equal(t, secparsepb.Advisory_Security, errata.Type)
|
||||
require.Equal(t, secparsepb.Advisory_Important, errata.Severity)
|
||||
require.Equal(t, apollopb.Advisory_TYPE_SECURITY, errata.Type)
|
||||
require.Equal(t, apollopb.Advisory_SEVERITY_IMPORTANT, errata.Severity)
|
||||
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, "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",
|
||||
"utils.go",
|
||||
],
|
||||
importpath = "peridot.resf.org/secparse/rhsecurity",
|
||||
importpath = "peridot.resf.org/apollo/rhsecurity",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//vendor/golang.org/x/oauth2"],
|
||||
)
|
@ -1,4 +1,6 @@
|
||||
openapi: 3.0.0
|
||||
x-stoplight:
|
||||
id: yjn90w5p8y4ly
|
||||
info:
|
||||
title: Red Hat Security Data API
|
||||
version: '1.0'
|
||||
@ -63,7 +65,7 @@ paths:
|
||||
name: cwe
|
||||
description: CVEs with CWE
|
||||
- schema:
|
||||
type: string
|
||||
type: number
|
||||
in: query
|
||||
name: cvss_score
|
||||
description: CVEs with CVSS score greater than or equal to this value
|
||||
@ -181,7 +183,7 @@ components:
|
||||
type: string
|
||||
minLength: 1
|
||||
cvss_score:
|
||||
type: string
|
||||
type: number
|
||||
cvss_scoring_vector:
|
||||
type: string
|
||||
CWE:
|
@ -61,12 +61,11 @@ type DefaultApi interface {
|
||||
type DefaultApiService service
|
||||
|
||||
type ApiGetCveRequest struct {
|
||||
ctx _context.Context
|
||||
ctx _context.Context
|
||||
ApiService DefaultApi
|
||||
cVE string
|
||||
cVE string
|
||||
}
|
||||
|
||||
|
||||
func (r ApiGetCveRequest) Execute() (CVEDetailed, *_nethttp.Response, error) {
|
||||
return r.ApiService.GetCveExecute(r)
|
||||
}
|
||||
@ -81,8 +80,8 @@ func (r ApiGetCveRequest) Execute() (CVEDetailed, *_nethttp.Response, error) {
|
||||
func (a *DefaultApiService) GetCve(ctx _context.Context, cVE string) ApiGetCveRequest {
|
||||
return ApiGetCveRequest{
|
||||
ApiService: a,
|
||||
ctx: ctx,
|
||||
cVE: cVE,
|
||||
ctx: ctx,
|
||||
cVE: cVE,
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,21 +166,21 @@ func (a *DefaultApiService) GetCveExecute(r ApiGetCveRequest) (CVEDetailed, *_ne
|
||||
}
|
||||
|
||||
type ApiGetCvesRequest struct {
|
||||
ctx _context.Context
|
||||
ApiService DefaultApi
|
||||
before *string
|
||||
after *string
|
||||
ids *string
|
||||
bug *string
|
||||
advisory *string
|
||||
severity *string
|
||||
package_ *string
|
||||
product *string
|
||||
cwe *string
|
||||
cvssScore *string
|
||||
cvss3Score *string
|
||||
page *float32
|
||||
perPage *float32
|
||||
ctx _context.Context
|
||||
ApiService DefaultApi
|
||||
before *string
|
||||
after *string
|
||||
ids *string
|
||||
bug *string
|
||||
advisory *string
|
||||
severity *string
|
||||
package_ *string
|
||||
product *string
|
||||
cwe *string
|
||||
cvssScore *float32
|
||||
cvss3Score *string
|
||||
page *float32
|
||||
perPage *float32
|
||||
createdDaysAgo *float32
|
||||
}
|
||||
|
||||
@ -221,7 +220,7 @@ func (r ApiGetCvesRequest) Cwe(cwe string) ApiGetCvesRequest {
|
||||
r.cwe = &cwe
|
||||
return r
|
||||
}
|
||||
func (r ApiGetCvesRequest) CvssScore(cvssScore string) ApiGetCvesRequest {
|
||||
func (r ApiGetCvesRequest) CvssScore(cvssScore float32) ApiGetCvesRequest {
|
||||
r.cvssScore = &cvssScore
|
||||
return r
|
||||
}
|
||||
@ -255,7 +254,7 @@ func (r ApiGetCvesRequest) Execute() ([]CVE, *_nethttp.Response, error) {
|
||||
func (a *DefaultApiService) GetCves(ctx _context.Context) ApiGetCvesRequest {
|
||||
return ApiGetCvesRequest{
|
||||
ApiService: a,
|
||||
ctx: ctx,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
@ -78,9 +78,9 @@ type ServerVariable struct {
|
||||
|
||||
// ServerConfiguration stores the information about a server
|
||||
type ServerConfiguration struct {
|
||||
URL string
|
||||
URL string
|
||||
Description string
|
||||
Variables map[string]ServerVariable
|
||||
Variables map[string]ServerVariable
|
||||
}
|
||||
|
||||
// ServerConfigurations stores multiple ServerConfiguration items
|
||||
@ -101,17 +101,16 @@ type Configuration struct {
|
||||
// NewConfiguration returns a new Configuration object
|
||||
func NewConfiguration() *Configuration {
|
||||
cfg := &Configuration{
|
||||
DefaultHeader: make(map[string]string),
|
||||
UserAgent: "OpenAPI-Generator/1.0.0/go",
|
||||
Debug: false,
|
||||
Servers: ServerConfigurations{
|
||||
DefaultHeader: make(map[string]string),
|
||||
UserAgent: "OpenAPI-Generator/1.0.0/go",
|
||||
Debug: false,
|
||||
Servers: ServerConfigurations{
|
||||
{
|
||||
URL: "https://access.redhat.com/hydra/rest/securitydata",
|
||||
URL: "https://access.redhat.com/hydra/rest/securitydata",
|
||||
Description: "No description provided",
|
||||
},
|
||||
},
|
||||
OperationServers: map[string]ServerConfigurations{
|
||||
},
|
||||
OperationServers: map[string]ServerConfigurations{},
|
||||
}
|
||||
return cfg
|
||||
}
|
@ -10,7 +10,7 @@ Name | Type | Description | Notes
|
||||
**Advisories** | **[]string** | |
|
||||
**Bugzilla** | **string** | |
|
||||
**BugzillaDescription** | **string** | |
|
||||
**CvssScore** | Pointer to **string** | | [optional]
|
||||
**CvssScore** | Pointer to **float32** | | [optional]
|
||||
**CvssScoringVector** | Pointer to **string** | | [optional]
|
||||
**CWE** | **string** | |
|
||||
**AffectedPackages** | **[]string** | |
|
||||
@ -159,20 +159,20 @@ SetBugzillaDescription sets BugzillaDescription field to given value.
|
||||
|
||||
### GetCvssScore
|
||||
|
||||
`func (o *CVE) GetCvssScore() string`
|
||||
`func (o *CVE) GetCvssScore() float32`
|
||||
|
||||
GetCvssScore returns the CvssScore field if non-nil, zero value otherwise.
|
||||
|
||||
### 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
|
||||
and a boolean to check if the value has been set.
|
||||
|
||||
### SetCvssScore
|
||||
|
||||
`func (o *CVE) SetCvssScore(v string)`
|
||||
`func (o *CVE) SetCvssScore(v float32)`
|
||||
|
||||
SetCvssScore sets CvssScore field to given value.
|
||||
|
@ -110,7 +110,7 @@ func main() {
|
||||
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)
|
||||
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)
|
||||
page := float32(8.14) // float32 | CVEs for page number (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 |
|
||||
**product** | **string** | CVEs which affect the product. The parameter supports Perl compatible regular expressions. |
|
||||
**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 |
|
||||
**page** | **float32** | CVEs for page number |
|
||||
**perPage** | **float32** | Number of CVEs to return per page |
|
@ -17,19 +17,19 @@ import (
|
||||
|
||||
// CVE CVE model used in listing
|
||||
type CVE struct {
|
||||
CVE string `json:"CVE"`
|
||||
Severity string `json:"severity"`
|
||||
PublicDate string `json:"public_date"`
|
||||
Advisories []string `json:"advisories"`
|
||||
Bugzilla string `json:"bugzilla"`
|
||||
BugzillaDescription string `json:"bugzilla_description"`
|
||||
CvssScore *string `json:"cvss_score,omitempty"`
|
||||
CvssScoringVector *string `json:"cvss_scoring_vector,omitempty"`
|
||||
CWE string `json:"CWE"`
|
||||
AffectedPackages []string `json:"affected_packages"`
|
||||
ResourceUrl string `json:"resource_url"`
|
||||
Cvss3ScoringVector string `json:"cvss3_scoring_vector"`
|
||||
Cvss3Score string `json:"cvss3_score"`
|
||||
CVE string `json:"CVE"`
|
||||
Severity string `json:"severity"`
|
||||
PublicDate string `json:"public_date"`
|
||||
Advisories []string `json:"advisories"`
|
||||
Bugzilla string `json:"bugzilla"`
|
||||
BugzillaDescription string `json:"bugzilla_description"`
|
||||
CvssScore *float32 `json:"cvss_score,omitempty"`
|
||||
CvssScoringVector *string `json:"cvss_scoring_vector,omitempty"`
|
||||
CWE string `json:"CWE"`
|
||||
AffectedPackages []string `json:"affected_packages"`
|
||||
ResourceUrl string `json:"resource_url"`
|
||||
Cvss3ScoringVector string `json:"cvss3_scoring_vector"`
|
||||
Cvss3Score string `json:"cvss3_score"`
|
||||
}
|
||||
|
||||
// NewCVE instantiates a new CVE object
|
||||
@ -73,7 +73,7 @@ func (o *CVE) GetCVE() string {
|
||||
// GetCVEOk returns a tuple with the CVE field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetCVEOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.CVE, true
|
||||
@ -97,7 +97,7 @@ func (o *CVE) GetSeverity() string {
|
||||
// GetSeverityOk returns a tuple with the Severity field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetSeverityOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Severity, true
|
||||
@ -121,7 +121,7 @@ func (o *CVE) GetPublicDate() string {
|
||||
// GetPublicDateOk returns a tuple with the PublicDate field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetPublicDateOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.PublicDate, true
|
||||
@ -145,7 +145,7 @@ func (o *CVE) GetAdvisories() []string {
|
||||
// GetAdvisoriesOk returns a tuple with the Advisories field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetAdvisoriesOk() (*[]string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Advisories, true
|
||||
@ -169,7 +169,7 @@ func (o *CVE) GetBugzilla() string {
|
||||
// GetBugzillaOk returns a tuple with the Bugzilla field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetBugzillaOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Bugzilla, true
|
||||
@ -193,7 +193,7 @@ func (o *CVE) GetBugzillaDescription() string {
|
||||
// GetBugzillaDescriptionOk returns a tuple with the BugzillaDescription field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetBugzillaDescriptionOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.BugzillaDescription, true
|
||||
@ -205,9 +205,9 @@ func (o *CVE) SetBugzillaDescription(v string) {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var ret string
|
||||
var ret float32
|
||||
return ret
|
||||
}
|
||||
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
|
||||
// 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 {
|
||||
return nil, false
|
||||
}
|
||||
@ -231,8 +231,8 @@ func (o *CVE) HasCvssScore() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// SetCvssScore gets a reference to the given string and assigns it to the CvssScore field.
|
||||
func (o *CVE) SetCvssScore(v string) {
|
||||
// SetCvssScore gets a reference to the given float32 and assigns it to the CvssScore field.
|
||||
func (o *CVE) SetCvssScore(v float32) {
|
||||
o.CvssScore = &v
|
||||
}
|
||||
|
||||
@ -281,7 +281,7 @@ func (o *CVE) GetCWE() string {
|
||||
// GetCWEOk returns a tuple with the CWE field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetCWEOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.CWE, true
|
||||
@ -305,7 +305,7 @@ func (o *CVE) GetAffectedPackages() []string {
|
||||
// GetAffectedPackagesOk returns a tuple with the AffectedPackages field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetAffectedPackagesOk() (*[]string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.AffectedPackages, true
|
||||
@ -329,7 +329,7 @@ func (o *CVE) GetResourceUrl() string {
|
||||
// GetResourceUrlOk returns a tuple with the ResourceUrl field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetResourceUrlOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.ResourceUrl, true
|
||||
@ -353,7 +353,7 @@ func (o *CVE) GetCvss3ScoringVector() string {
|
||||
// GetCvss3ScoringVectorOk returns a tuple with the Cvss3ScoringVector field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetCvss3ScoringVectorOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Cvss3ScoringVector, true
|
||||
@ -377,7 +377,7 @@ func (o *CVE) GetCvss3Score() string {
|
||||
// GetCvss3ScoreOk returns a tuple with the Cvss3Score field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVE) GetCvss3ScoreOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Cvss3Score, true
|
||||
@ -467,5 +467,3 @@ func (v *NullableCVE) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
@ -17,17 +17,17 @@ import (
|
||||
|
||||
// CVEDetailed CVE model used when retrieving a specific CVE
|
||||
type CVEDetailed struct {
|
||||
ThreatSeverity string `json:"threat_severity"`
|
||||
PublicDate string `json:"public_date"`
|
||||
Bugzilla CVEDetailedBugzilla `json:"bugzilla"`
|
||||
Cvss3 CVEDetailedCvss3 `json:"cvss3"`
|
||||
Cwe string `json:"cwe"`
|
||||
Details []string `json:"details"`
|
||||
Acknowledgement string `json:"acknowledgement"`
|
||||
ThreatSeverity string `json:"threat_severity"`
|
||||
PublicDate string `json:"public_date"`
|
||||
Bugzilla CVEDetailedBugzilla `json:"bugzilla"`
|
||||
Cvss3 CVEDetailedCvss3 `json:"cvss3"`
|
||||
Cwe string `json:"cwe"`
|
||||
Details []string `json:"details"`
|
||||
Acknowledgement string `json:"acknowledgement"`
|
||||
AffectedRelease *[]CVEDetailedAffectedRelease `json:"affected_release,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Csaw bool `json:"csaw"`
|
||||
PackageState *[]CVEDetailedPackageState `json:"package_state,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Csaw bool `json:"csaw"`
|
||||
PackageState *[]CVEDetailedPackageState `json:"package_state,omitempty"`
|
||||
}
|
||||
|
||||
// NewCVEDetailed instantiates a new CVEDetailed object
|
||||
@ -69,7 +69,7 @@ func (o *CVEDetailed) GetThreatSeverity() string {
|
||||
// GetThreatSeverityOk returns a tuple with the ThreatSeverity field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailed) GetThreatSeverityOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.ThreatSeverity, true
|
||||
@ -93,7 +93,7 @@ func (o *CVEDetailed) GetPublicDate() string {
|
||||
// GetPublicDateOk returns a tuple with the PublicDate field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailed) GetPublicDateOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.PublicDate, true
|
||||
@ -117,7 +117,7 @@ func (o *CVEDetailed) GetBugzilla() CVEDetailedBugzilla {
|
||||
// GetBugzillaOk returns a tuple with the Bugzilla field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailed) GetBugzillaOk() (*CVEDetailedBugzilla, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Bugzilla, true
|
||||
@ -141,7 +141,7 @@ func (o *CVEDetailed) GetCvss3() CVEDetailedCvss3 {
|
||||
// GetCvss3Ok returns a tuple with the Cvss3 field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailed) GetCvss3Ok() (*CVEDetailedCvss3, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Cvss3, true
|
||||
@ -165,7 +165,7 @@ func (o *CVEDetailed) GetCwe() string {
|
||||
// GetCweOk returns a tuple with the Cwe field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailed) GetCweOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Cwe, true
|
||||
@ -189,7 +189,7 @@ func (o *CVEDetailed) GetDetails() []string {
|
||||
// GetDetailsOk returns a tuple with the Details field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailed) GetDetailsOk() (*[]string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Details, true
|
||||
@ -213,7 +213,7 @@ func (o *CVEDetailed) GetAcknowledgement() string {
|
||||
// GetAcknowledgementOk returns a tuple with the Acknowledgement field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailed) GetAcknowledgementOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Acknowledgement, true
|
||||
@ -269,7 +269,7 @@ func (o *CVEDetailed) GetName() string {
|
||||
// GetNameOk returns a tuple with the Name field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailed) GetNameOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Name, true
|
||||
@ -293,7 +293,7 @@ func (o *CVEDetailed) GetCsaw() bool {
|
||||
// GetCsawOk returns a tuple with the Csaw field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailed) GetCsawOk() (*bool, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Csaw, true
|
||||
@ -409,5 +409,3 @@ func (v *NullableCVEDetailed) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,11 @@ import (
|
||||
|
||||
// CVEDetailedAffectedRelease struct for CVEDetailedAffectedRelease
|
||||
type CVEDetailedAffectedRelease struct {
|
||||
ProductName string `json:"product_name"`
|
||||
ReleaseDate string `json:"release_date"`
|
||||
Advisory string `json:"advisory"`
|
||||
Cpe string `json:"cpe"`
|
||||
Package *string `json:"package,omitempty"`
|
||||
ProductName string `json:"product_name"`
|
||||
ReleaseDate string `json:"release_date"`
|
||||
Advisory string `json:"advisory"`
|
||||
Cpe string `json:"cpe"`
|
||||
Package *string `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
// NewCVEDetailedAffectedRelease instantiates a new CVEDetailedAffectedRelease object
|
||||
@ -58,7 +58,7 @@ func (o *CVEDetailedAffectedRelease) GetProductName() string {
|
||||
// GetProductNameOk returns a tuple with the ProductName field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedAffectedRelease) GetProductNameOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.ProductName, true
|
||||
@ -82,7 +82,7 @@ func (o *CVEDetailedAffectedRelease) GetReleaseDate() string {
|
||||
// GetReleaseDateOk returns a tuple with the ReleaseDate field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedAffectedRelease) GetReleaseDateOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.ReleaseDate, true
|
||||
@ -106,7 +106,7 @@ func (o *CVEDetailedAffectedRelease) GetAdvisory() string {
|
||||
// GetAdvisoryOk returns a tuple with the Advisory field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedAffectedRelease) GetAdvisoryOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Advisory, true
|
||||
@ -130,7 +130,7 @@ func (o *CVEDetailedAffectedRelease) GetCpe() string {
|
||||
// GetCpeOk returns a tuple with the Cpe field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedAffectedRelease) GetCpeOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Cpe, true
|
||||
@ -228,5 +228,3 @@ func (v *NullableCVEDetailedAffectedRelease) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,8 @@ import (
|
||||
// CVEDetailedBugzilla struct for CVEDetailedBugzilla
|
||||
type CVEDetailedBugzilla struct {
|
||||
Description string `json:"description"`
|
||||
Id string `json:"id"`
|
||||
Url string `json:"url"`
|
||||
Id string `json:"id"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
// NewCVEDetailedBugzilla instantiates a new CVEDetailedBugzilla object
|
||||
@ -55,7 +55,7 @@ func (o *CVEDetailedBugzilla) GetDescription() string {
|
||||
// GetDescriptionOk returns a tuple with the Description field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedBugzilla) GetDescriptionOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Description, true
|
||||
@ -79,7 +79,7 @@ func (o *CVEDetailedBugzilla) GetId() string {
|
||||
// GetIdOk returns a tuple with the Id field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedBugzilla) GetIdOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Id, true
|
||||
@ -103,7 +103,7 @@ func (o *CVEDetailedBugzilla) GetUrl() string {
|
||||
// GetUrlOk returns a tuple with the Url field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedBugzilla) GetUrlOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Url, true
|
||||
@ -163,5 +163,3 @@ func (v *NullableCVEDetailedBugzilla) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,9 @@ import (
|
||||
|
||||
// CVEDetailedCvss3 struct for CVEDetailedCvss3
|
||||
type CVEDetailedCvss3 struct {
|
||||
Cvss3BaseScore string `json:"cvss3_base_score"`
|
||||
Cvss3BaseScore string `json:"cvss3_base_score"`
|
||||
Cvss3ScoringVector string `json:"cvss3_scoring_vector"`
|
||||
Status string `json:"status"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// NewCVEDetailedCvss3 instantiates a new CVEDetailedCvss3 object
|
||||
@ -55,7 +55,7 @@ func (o *CVEDetailedCvss3) GetCvss3BaseScore() string {
|
||||
// GetCvss3BaseScoreOk returns a tuple with the Cvss3BaseScore field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedCvss3) GetCvss3BaseScoreOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Cvss3BaseScore, true
|
||||
@ -79,7 +79,7 @@ func (o *CVEDetailedCvss3) GetCvss3ScoringVector() string {
|
||||
// GetCvss3ScoringVectorOk returns a tuple with the Cvss3ScoringVector field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedCvss3) GetCvss3ScoringVectorOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Cvss3ScoringVector, true
|
||||
@ -103,7 +103,7 @@ func (o *CVEDetailedCvss3) GetStatus() string {
|
||||
// GetStatusOk returns a tuple with the Status field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedCvss3) GetStatusOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Status, true
|
||||
@ -163,5 +163,3 @@ func (v *NullableCVEDetailedCvss3) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,9 @@ import (
|
||||
// CVEDetailedPackageState struct for CVEDetailedPackageState
|
||||
type CVEDetailedPackageState struct {
|
||||
ProductName string `json:"product_name"`
|
||||
FixState string `json:"fix_state"`
|
||||
FixState string `json:"fix_state"`
|
||||
PackageName string `json:"package_name"`
|
||||
Cpe string `json:"cpe"`
|
||||
Cpe string `json:"cpe"`
|
||||
}
|
||||
|
||||
// NewCVEDetailedPackageState instantiates a new CVEDetailedPackageState object
|
||||
@ -57,7 +57,7 @@ func (o *CVEDetailedPackageState) GetProductName() string {
|
||||
// GetProductNameOk returns a tuple with the ProductName field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedPackageState) GetProductNameOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.ProductName, true
|
||||
@ -81,7 +81,7 @@ func (o *CVEDetailedPackageState) GetFixState() string {
|
||||
// GetFixStateOk returns a tuple with the FixState field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedPackageState) GetFixStateOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.FixState, true
|
||||
@ -105,7 +105,7 @@ func (o *CVEDetailedPackageState) GetPackageName() string {
|
||||
// GetPackageNameOk returns a tuple with the PackageName field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedPackageState) GetPackageNameOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.PackageName, true
|
||||
@ -129,7 +129,7 @@ func (o *CVEDetailedPackageState) GetCpe() string {
|
||||
// GetCpeOk returns a tuple with the Cpe field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *CVEDetailedPackageState) GetCpeOk() (*string, bool) {
|
||||
if o == nil {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Cpe, true
|
||||
@ -192,5 +192,3 @@ func (v *NullableCVEDetailedPackageState) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
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