Skip to content

Commit 1cee815

Browse files
committed
ROX-27618: Add env var to disable RHEL lineage usage (#1764)
1 parent 3931238 commit 1cee815

File tree

3 files changed

+124
-48
lines changed

3 files changed

+124
-48
lines changed

database/pgsql/rhelv2_layer.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/stackrox/rox/pkg/utils"
1616
"github.com/stackrox/scanner/database"
1717
"github.com/stackrox/scanner/database/metrics"
18+
"github.com/stackrox/scanner/pkg/env"
1819
)
1920

2021
func (pgSQL *pgSQL) InsertRHELv2Layer(layer *database.RHELv2Layer) error {
@@ -46,11 +47,18 @@ func (pgSQL *pgSQL) InsertRHELv2Layer(layer *database.RHELv2Layer) error {
4647
func (pgSQL *pgSQL) insertRHELv2Layer(tx *sql.Tx, layer *database.RHELv2Layer) error {
4748
defer metrics.ObserveQueryTime("insertRHELv2Layer", "layer", time.Now())
4849

49-
_, err := tx.Exec(insertRHELv2Layer, layer.Hash, layer.ParentHash, layer.Dist, pq.Array(layer.CPEs), layer.Lineage, layer.ParentLineage)
50+
var lineage string
51+
var parentLineage string
52+
if env.RHLineage.Enabled() {
53+
lineage = layer.Lineage
54+
parentLineage = layer.ParentLineage
55+
}
56+
57+
_, err := tx.Exec(insertRHELv2Layer, layer.Hash, layer.ParentHash, layer.Dist, pq.Array(layer.CPEs), lineage, parentLineage)
5058
return err
5159
}
5260

53-
func (pgSQL *pgSQL) insertRHELv2Packages(tx *sql.Tx, layer string, pkgs []*database.RHELv2Package, lineage string) error {
61+
func (pgSQL *pgSQL) insertRHELv2Packages(tx *sql.Tx, layer string, pkgs []*database.RHELv2Package, layerLineage string) error {
5462
// Sort packages to avoid potential deadlock.
5563
// Sort by the unique index (name, version, module, arch).
5664
sort.SliceStable(pkgs, func(i, j int) bool {
@@ -80,6 +88,11 @@ func (pgSQL *pgSQL) insertRHELv2Packages(tx *sql.Tx, layer string, pkgs []*datab
8088
}
8189
}
8290

91+
var lineage string
92+
if env.RHLineage.Enabled() {
93+
lineage = layerLineage
94+
}
95+
8396
for _, pkg := range pkgs {
8497
if pkg.Name == "" {
8598
continue
@@ -112,7 +125,12 @@ func (pgSQL *pgSQL) GetRHELv2Layers(layerHash, layerLineage string) ([]*database
112125
return nil, handleError("GetRHELv2Layers.Begin()", err)
113126
}
114127

115-
rows, err := tx.Query(searchRHELv2Layers, layerHash, layerLineage)
128+
var lineage string
129+
if env.RHLineage.Enabled() {
130+
lineage = layerLineage
131+
}
132+
133+
rows, err := tx.Query(searchRHELv2Layers, layerHash, lineage)
116134
if err != nil {
117135
return nil, err
118136
}
@@ -177,7 +195,12 @@ func (pgSQL *pgSQL) populatePackages(tx *sql.Tx, layers []*database.RHELv2Layer)
177195
func (pgSQL *pgSQL) getPackagesByLayer(tx *sql.Tx, layer *database.RHELv2Layer) error {
178196
defer metrics.ObserveQueryTime("getRHELv2Layers", "packagesByLayer", time.Now())
179197

180-
rows, err := tx.Query(searchRHELv2Package, layer.Hash, layer.Lineage)
198+
var lineage string
199+
if env.RHLineage.Enabled() {
200+
lineage = layer.Lineage
201+
}
202+
203+
rows, err := tx.Query(searchRHELv2Package, layer.Hash, lineage)
181204
if err != nil {
182205
return err
183206
}

database/pgsql/rhelv2_layer_test.go

Lines changed: 90 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88

99
"github.com/stackrox/scanner/database"
10+
"github.com/stackrox/scanner/pkg/env"
1011
"github.com/stretchr/testify/assert"
1112
"github.com/stretchr/testify/require"
1213
)
@@ -199,31 +200,12 @@ func TestGetRHELv2Layers(t *testing.T) {
199200
// TestRHELv2LayerLineage verifies that data for duplicate layers with different parent
200201
// layers (lineage) is pulled correctly.
201202
func TestRHELv2LayerLineage(t *testing.T) {
202-
datastore, err := openDatabaseForTest("RHELv2LayerLineage", false)
203-
if err != nil {
204-
t.Error(err)
205-
return
206-
}
207-
defer datastore.Close()
208-
209-
// Two 'fake' images will be created, each with 3 layers, the DB will resemble:
210-
// id | hash | parent_hash | dist | cpes | lineage | parent_lineage
211-
// ----+-----------------+-----------------+--------+----------------+-----------+----------------
212-
// 1 | sha256:base | | rhel:8 | | |
213-
// 2 | sha256:layer1-a | sha256:base | rhel:8 | {cpe-a,cpe2-a} | lineage |
214-
// 3 | sha256:layer1-b | sha256:base | rhel:8 | {cpe-b,cpe2-b} | lineage |
215-
// 4 | sha256:leaf | sha256:layer1-a | rhel:8 | | lineage-a | lineage
216-
// 5 | sha256:leaf | sha256:layer1-b | rhel:8 | | lineage-b | lineage
217-
218203
// base layers
219204
base := &database.RHELv2Layer{
220205
Hash: "sha256:base",
221206
Dist: "rhel:8",
222207
}
223208

224-
err = datastore.InsertRHELv2Layer(base)
225-
require.NoError(t, err)
226-
227209
layer1a := &database.RHELv2Layer{
228210
Hash: "sha256:layer1-a",
229211
Lineage: "lineage",
@@ -250,11 +232,6 @@ func TestRHELv2LayerLineage(t *testing.T) {
250232
CPEs: []string{"cpe-b", "cpe2-b"},
251233
}
252234

253-
err = datastore.InsertRHELv2Layer(layer1a)
254-
require.NoError(t, err)
255-
err = datastore.InsertRHELv2Layer(layer1b)
256-
require.NoError(t, err)
257-
258235
leafa := &database.RHELv2Layer{
259236
Hash: "sha256:leaf", // for this test all leafs should have same digest
260237
Lineage: "lineage-a", // lineage is specific to layer A
@@ -268,34 +245,103 @@ func TestRHELv2LayerLineage(t *testing.T) {
268245
leafb.Lineage = "lineage-b"
269246
leafb.ParentHash = "sha256:layer1-b"
270247

271-
err = datastore.InsertRHELv2Layer(leafa)
272-
require.NoError(t, err)
273-
err = datastore.InsertRHELv2Layer(leafb)
274-
require.NoError(t, err)
248+
prepDataStore := func(t *testing.T, name string) *pgSQL {
249+
datastore, err := openDatabaseForTest("RHELv2LayerLineage_enabled", false)
250+
require.NoError(t, err)
251+
252+
err = datastore.InsertRHELv2Layer(base)
253+
require.NoError(t, err)
254+
err = datastore.InsertRHELv2Layer(layer1a)
255+
require.NoError(t, err)
256+
err = datastore.InsertRHELv2Layer(layer1b)
257+
require.NoError(t, err)
258+
err = datastore.InsertRHELv2Layer(leafa)
259+
require.NoError(t, err)
260+
err = datastore.InsertRHELv2Layer(leafb)
261+
require.NoError(t, err)
262+
263+
return datastore
264+
}
275265

276-
assertLayersEqual := func(t *testing.T, expected, actual *database.RHELv2Layer) {
266+
assertLayersEqual := func(t *testing.T, expected, actual *database.RHELv2Layer, skipLineage bool) {
277267
resetPackageIDs(actual)
278268
assert.Equal(t, expected.Hash, actual.Hash, "Hash mismatch")
279-
assert.Equal(t, expected.Lineage, actual.Lineage, "Lineage mismatch")
280269
assert.Equal(t, expected.CPEs, actual.CPEs, "CPEs mistmatch")
281270
assert.Equal(t, expected.Pkgs, actual.Pkgs, "Pkgs mismatch")
282-
}
283-
284-
layers, err := datastore.GetRHELv2Layers("sha256:leaf", "lineage-a")
285-
require.NoError(t, err)
286-
require.Len(t, layers, 3)
287271

288-
assertLayersEqual(t, base, layers[0])
289-
assertLayersEqual(t, layer1a, layers[1])
290-
assertLayersEqual(t, leafa, layers[2])
272+
expectedLineage := expected.Lineage
273+
if skipLineage {
274+
expectedLineage = ""
275+
}
276+
assert.Equal(t, expectedLineage, actual.Lineage, "Lineage mismatch")
277+
}
291278

292-
layers, err = datastore.GetRHELv2Layers("sha256:leaf", "lineage-b")
293-
require.NoError(t, err)
294-
require.Len(t, layers, 3)
279+
t.Run("enabled", func(t *testing.T) {
280+
t.Setenv(env.RHLineage.EnvVar(), "true")
281+
282+
datastore := prepDataStore(t, "RHELv2LayerLineage_enabled")
283+
defer datastore.Close()
284+
285+
// The DB will resemble:
286+
// id | hash | parent_hash | dist | cpes | lineage | parent_lineage
287+
// ----+-----------------+-----------------+--------+----------------+-----------+----------------
288+
// 1 | sha256:base | | rhel:8 | | |
289+
// 2 | sha256:layer1-a | sha256:base | rhel:8 | {cpe-a,cpe2-a} | lineage |
290+
// 3 | sha256:layer1-b | sha256:base | rhel:8 | {cpe-b,cpe2-b} | lineage |
291+
// 4 | sha256:leaf | sha256:layer1-a | rhel:8 | | lineage-a | lineage
292+
// 5 | sha256:leaf | sha256:layer1-b | rhel:8 | | lineage-b | lineage
293+
294+
layers, err := datastore.GetRHELv2Layers("sha256:leaf", "lineage-a")
295+
require.NoError(t, err)
296+
require.Len(t, layers, 3)
297+
298+
assertLayersEqual(t, base, layers[0], false)
299+
assertLayersEqual(t, layer1a, layers[1], false)
300+
assertLayersEqual(t, leafa, layers[2], false)
301+
302+
layers, err = datastore.GetRHELv2Layers("sha256:leaf", "lineage-b")
303+
require.NoError(t, err)
304+
require.Len(t, layers, 3)
305+
306+
assertLayersEqual(t, base, layers[0], false)
307+
assertLayersEqual(t, layer1b, layers[1], false)
308+
assertLayersEqual(t, leafb, layers[2], false)
309+
})
310+
311+
t.Run("disable", func(t *testing.T) {
312+
t.Setenv(env.RHLineage.EnvVar(), "false")
313+
314+
datastore := prepDataStore(t, "RHELv2LayerLineage_disabled")
315+
defer datastore.Close()
316+
317+
// The DB will resemble:
318+
// id | hash | parent_hash | dist | cpes | lineage | parent_lineage
319+
// ----+-----------------+-----------------+--------+----------------+---------+----------------
320+
// 1 | sha256:base | | rhel:8 | | |
321+
// 2 | sha256:layer1-a | sha256:base | rhel:8 | {cpe-a,cpe2-a} | |
322+
// 3 | sha256:layer1-b | sha256:base | rhel:8 | {cpe-b,cpe2-b} | |
323+
// 4 | sha256:leaf | sha256:layer1-a | rhel:8 | | |
324+
//
325+
// Note: only the first leaf layer will be inserted (due to the insert
326+
// query 'ON CONFLICT DO NOTHING' clause)
327+
328+
layers, err := datastore.GetRHELv2Layers("sha256:leaf", "lineage-a")
329+
require.NoError(t, err)
330+
require.Len(t, layers, 3)
331+
332+
assertLayersEqual(t, base, layers[0], true)
333+
assertLayersEqual(t, layer1a, layers[1], true)
334+
assertLayersEqual(t, leafa, layers[2], true)
335+
336+
layers, err = datastore.GetRHELv2Layers("sha256:leaf", "lineage-b")
337+
require.NoError(t, err)
338+
require.Len(t, layers, 3)
339+
340+
assertLayersEqual(t, base, layers[0], true)
341+
assertLayersEqual(t, layer1a, layers[1], true) // the bug, would expect layer1b to be here
342+
assertLayersEqual(t, leafb, layers[2], true)
343+
})
295344

296-
assertLayersEqual(t, base, layers[0])
297-
assertLayersEqual(t, layer1b, layers[1])
298-
assertLayersEqual(t, leafb, layers[2])
299345
}
300346

301347
// resetPackageIDs sets all package IDs to 0. Package IDs are DB sequence numbers

pkg/env/list.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,11 @@ var (
4444
// LegacyNVDLoader when true will cause the loader to pull NVD data using
4545
// the NVD Legacy Data Feeds, if false will pull from the NVD 2.0 API.
4646
LegacyNVDLoader = RegisterBooleanSetting("ROX_LEGACY_NVD_LOADER", false)
47+
48+
// RHLineage when true will cause all parent layers (a.k.a lineage) to be considered when
49+
// storing scan results for RHEL image layers.
50+
//
51+
// Setting this to false will cause known scan inaccuracies and should only be disabled as a
52+
// temporary measure to address unforeseen stability issues.
53+
RHLineage = RegisterBooleanSetting("ROX_RHEL_LINEAGE", true)
4754
)

0 commit comments

Comments
 (0)