mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 07:40:48 -08:00
feat(secret): add line from dockerfile where secret was added to secret result (#2780)
Co-authored-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
@@ -134,8 +134,9 @@ func ApplyLayers(layers []types.BlobInfo) types.ArtifactDetail {
|
||||
// Apply secrets
|
||||
for _, secret := range layer.Secrets {
|
||||
l := types.Layer{
|
||||
Digest: layer.Digest,
|
||||
DiffID: layer.DiffID,
|
||||
Digest: layer.Digest,
|
||||
DiffID: layer.DiffID,
|
||||
CreatedBy: layer.CreatedBy,
|
||||
}
|
||||
secretsMap = mergeSecrets(secretsMap, secret, l)
|
||||
}
|
||||
@@ -178,13 +179,7 @@ func ApplyLayers(layers []types.BlobInfo) types.ArtifactDetail {
|
||||
return nil
|
||||
})
|
||||
|
||||
lastDiffID := layers[len(layers)-1].DiffID
|
||||
for _, s := range secretsMap {
|
||||
for i, finding := range s.Findings {
|
||||
if finding.Layer.DiffID != lastDiffID {
|
||||
s.Findings[i].Deleted = true // This secret is deleted in the upper layer
|
||||
}
|
||||
}
|
||||
mergedLayer.Secrets = append(mergedLayer.Secrets, s)
|
||||
}
|
||||
|
||||
|
||||
@@ -335,6 +335,7 @@ func TestApplyLayers(t *testing.T) {
|
||||
SchemaVersion: 2,
|
||||
Digest: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
DiffID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
|
||||
CreatedBy: "Line_1",
|
||||
Secrets: []types.Secret{
|
||||
{
|
||||
FilePath: "usr/secret.txt",
|
||||
@@ -368,6 +369,7 @@ func TestApplyLayers(t *testing.T) {
|
||||
SchemaVersion: 2,
|
||||
Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819",
|
||||
CreatedBy: "Line_2",
|
||||
Secrets: []types.Secret{
|
||||
{
|
||||
FilePath: "usr/secret.txt",
|
||||
@@ -422,6 +424,7 @@ func TestApplyLayers(t *testing.T) {
|
||||
SchemaVersion: 2,
|
||||
Digest: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
DiffID: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
|
||||
CreatedBy: "Line_3",
|
||||
WhiteoutFiles: []string{
|
||||
"usr/secret.txt",
|
||||
},
|
||||
@@ -437,13 +440,13 @@ func TestApplyLayers(t *testing.T) {
|
||||
Category: "GitHub",
|
||||
Severity: "CRITICAL",
|
||||
Title: "GitHub Personal Access Token",
|
||||
Deleted: true,
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
Match: "GITHUB_PAT=****************************************",
|
||||
Layer: types.Layer{
|
||||
Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819",
|
||||
Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819",
|
||||
CreatedBy: "Line_2",
|
||||
},
|
||||
Code: types.Code{
|
||||
Lines: []types.Line{
|
||||
@@ -463,13 +466,13 @@ func TestApplyLayers(t *testing.T) {
|
||||
Category: "AWS",
|
||||
Severity: "CRITICAL",
|
||||
Title: "AWS Access Key ID",
|
||||
Deleted: true,
|
||||
StartLine: 2,
|
||||
EndLine: 2,
|
||||
Match: "AWS_ACCESS_KEY_ID=********************",
|
||||
Layer: types.Layer{
|
||||
Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819",
|
||||
Digest: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
DiffID: "sha256:aad63a9339440e7c3e1fff2b988991b9bfb81280042fa7f39a5e327023056819",
|
||||
CreatedBy: "Line_2",
|
||||
},
|
||||
Code: types.Code{
|
||||
Lines: []types.Line{
|
||||
|
||||
@@ -37,6 +37,11 @@ type Artifact struct {
|
||||
artifactOption artifact.Option
|
||||
}
|
||||
|
||||
type LayerInfo struct {
|
||||
DiffID string
|
||||
CreatedBy string // can be empty
|
||||
}
|
||||
|
||||
func NewArtifact(img types.Image, c cache.ArtifactCache, opt artifact.Option) (artifact.Artifact, error) {
|
||||
// Initialize handlers
|
||||
handlerManager, err := handler.NewManager(opt)
|
||||
@@ -90,11 +95,14 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
|
||||
log.Logger.Debugf("Base Layers: %v", baseDiffIDs)
|
||||
|
||||
// Convert image ID and layer IDs to cache keys
|
||||
imageKey, layerKeys, layerKeyMap, err := a.calcCacheKeys(imageID, diffIDs)
|
||||
imageKey, layerKeys, err := a.calcCacheKeys(imageID, diffIDs)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, err
|
||||
}
|
||||
|
||||
// Parse histories and extract a list of "created_by"
|
||||
layerKeyMap := a.consolidateCreatedBy(diffIDs, layerKeys, configFile)
|
||||
|
||||
missingImage, missingLayers, err := a.cache.MissingBlobs(imageKey, layerKeys)
|
||||
if err != nil {
|
||||
return types.ArtifactReference{}, xerrors.Errorf("unable to get missing layers: %w", err)
|
||||
@@ -130,45 +138,77 @@ func (Artifact) Clean(_ types.ArtifactReference) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a Artifact) calcCacheKeys(imageID string, diffIDs []string) (string, []string, map[string]string, error) {
|
||||
func (a Artifact) calcCacheKeys(imageID string, diffIDs []string) (string, []string, error) {
|
||||
// Pass an empty config scanner option so that the cache key can be the same, even when policies are updated.
|
||||
imageKey, err := cache.CalcKey(imageID, a.analyzer.ImageConfigAnalyzerVersions(), nil, artifact.Option{})
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
layerKeyMap := map[string]string{}
|
||||
hookVersions := a.handlerManager.Versions()
|
||||
var layerKeys []string
|
||||
for _, diffID := range diffIDs {
|
||||
blobKey, err := cache.CalcKey(diffID, a.analyzer.AnalyzerVersions(), hookVersions, a.artifactOption)
|
||||
if err != nil {
|
||||
return "", nil, nil, err
|
||||
return "", nil, err
|
||||
}
|
||||
layerKeys = append(layerKeys, blobKey)
|
||||
layerKeyMap[blobKey] = diffID
|
||||
}
|
||||
return imageKey, layerKeys, layerKeyMap, nil
|
||||
return imageKey, layerKeys, nil
|
||||
}
|
||||
|
||||
func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, baseDiffIDs []string, layerKeyMap map[string]string) error {
|
||||
func (a Artifact) consolidateCreatedBy(diffIDs, layerKeys []string, configFile *v1.ConfigFile) map[string]LayerInfo {
|
||||
// save createdBy fields in order of layers
|
||||
var createdBy []string
|
||||
for _, h := range configFile.History {
|
||||
// skip histories for empty layers
|
||||
if h.EmptyLayer {
|
||||
continue
|
||||
}
|
||||
c := strings.TrimPrefix(h.CreatedBy, "/bin/sh -c ")
|
||||
c = strings.TrimPrefix(c, "#(nop) ")
|
||||
createdBy = append(createdBy, c)
|
||||
}
|
||||
|
||||
// If history detected incorrect - use only diffID
|
||||
// TODO: our current logic may not detect empty layers correctly in rare cases.
|
||||
validCreatedBy := len(diffIDs) == len(createdBy)
|
||||
|
||||
layerKeyMap := map[string]LayerInfo{}
|
||||
for i, diffID := range diffIDs {
|
||||
|
||||
c := ""
|
||||
if validCreatedBy {
|
||||
c = createdBy[i]
|
||||
}
|
||||
|
||||
layerKey := layerKeys[i]
|
||||
layerKeyMap[layerKey] = LayerInfo{
|
||||
DiffID: diffID,
|
||||
CreatedBy: c,
|
||||
}
|
||||
}
|
||||
return layerKeyMap
|
||||
}
|
||||
|
||||
func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, baseDiffIDs []string, layerKeyMap map[string]LayerInfo) error {
|
||||
done := make(chan struct{})
|
||||
errCh := make(chan error)
|
||||
|
||||
var osFound types.OS
|
||||
for _, k := range layerKeys {
|
||||
go func(ctx context.Context, layerKey string) {
|
||||
diffID := layerKeyMap[layerKey]
|
||||
layer := layerKeyMap[layerKey]
|
||||
|
||||
// If it is a base layer, secret scanning should not be performed.
|
||||
var disabledAnalyers []analyzer.Type
|
||||
if slices.Contains(baseDiffIDs, diffID) {
|
||||
if slices.Contains(baseDiffIDs, layer.DiffID) {
|
||||
disabledAnalyers = append(disabledAnalyers, analyzer.TypeSecret)
|
||||
}
|
||||
|
||||
layerInfo, err := a.inspectLayer(ctx, diffID, disabledAnalyers)
|
||||
layerInfo, err := a.inspectLayer(ctx, layer, disabledAnalyers)
|
||||
if err != nil {
|
||||
errCh <- xerrors.Errorf("failed to analyze layer: %s : %w", diffID, err)
|
||||
errCh <- xerrors.Errorf("failed to analyze layer: %s : %w", layerInfo.DiffID, err)
|
||||
return
|
||||
}
|
||||
if err = a.cache.PutBlob(layerKey, layerInfo); err != nil {
|
||||
@@ -202,12 +242,12 @@ func (a Artifact) inspect(ctx context.Context, missingImage string, layerKeys, b
|
||||
|
||||
}
|
||||
|
||||
func (a Artifact) inspectLayer(ctx context.Context, diffID string, disabled []analyzer.Type) (types.BlobInfo, error) {
|
||||
log.Logger.Debugf("Missing diff ID in cache: %s", diffID)
|
||||
func (a Artifact) inspectLayer(ctx context.Context, layerInfo LayerInfo, disabled []analyzer.Type) (types.BlobInfo, error) {
|
||||
log.Logger.Debugf("Missing diff ID in cache: %s", layerInfo.DiffID)
|
||||
|
||||
layerDigest, r, err := a.uncompressedLayer(diffID)
|
||||
layerDigest, r, err := a.uncompressedLayer(layerInfo.DiffID)
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, xerrors.Errorf("unable to get uncompressed layer %s: %w", diffID, err)
|
||||
return types.BlobInfo{}, xerrors.Errorf("unable to get uncompressed layer %s: %w", layerInfo.DiffID, err)
|
||||
}
|
||||
|
||||
// Prepare variables
|
||||
@@ -236,15 +276,16 @@ func (a Artifact) inspectLayer(ctx context.Context, diffID string, disabled []an
|
||||
blobInfo := types.BlobInfo{
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: layerDigest,
|
||||
DiffID: diffID,
|
||||
DiffID: layerInfo.DiffID,
|
||||
CreatedBy: layerInfo.CreatedBy,
|
||||
OpaqueDirs: opqDirs,
|
||||
WhiteoutFiles: whFiles,
|
||||
OS: result.OS,
|
||||
Repository: result.Repository,
|
||||
PackageInfos: result.PackageInfos,
|
||||
Applications: result.Applications,
|
||||
Secrets: result.Secrets,
|
||||
Licenses: result.Licenses,
|
||||
OpaqueDirs: opqDirs,
|
||||
WhiteoutFiles: whFiles,
|
||||
CustomResources: result.CustomResources,
|
||||
|
||||
// For Red Hat
|
||||
|
||||
@@ -65,6 +65,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
|
||||
CreatedBy: "ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ",
|
||||
OS: &types.OS{
|
||||
Family: "alpine",
|
||||
Name: "3.11.5",
|
||||
@@ -275,6 +276,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
CreatedBy: "bazel build ...",
|
||||
OS: &types.OS{
|
||||
Family: "debian",
|
||||
Name: "9.9",
|
||||
@@ -342,6 +344,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
CreatedBy: "bazel build ...",
|
||||
PackageInfos: []types.PackageInfo{
|
||||
{
|
||||
FilePath: "var/lib/dpkg/status.d/libc6",
|
||||
@@ -408,6 +411,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
CreatedBy: "COPY file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ",
|
||||
Applications: []types.Application{
|
||||
{
|
||||
Type: "composer", FilePath: "php-app/composer.lock",
|
||||
@@ -440,6 +444,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566",
|
||||
CreatedBy: "COPY file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ",
|
||||
Applications: []types.Application{
|
||||
{
|
||||
Type: types.Bundler, FilePath: "ruby-app/Gemfile.lock",
|
||||
@@ -625,6 +630,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:932da51564135c98a49a34a193d6cd363d8fa4184d957fde16c9d8527b3f3b02",
|
||||
CreatedBy: "bazel build ...",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -635,6 +641,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:dffd9992ca398466a663c87c92cfea2a2db0ae0cf33fcb99da60eec52addbfc5",
|
||||
CreatedBy: "bazel build ...",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -645,6 +652,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:24df0d4e20c0f42d3703bf1f1db2bdd77346c7956f74f423603d651e8e5ae8a7",
|
||||
CreatedBy: "COPY file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ",
|
||||
OpaqueDirs: []string{"php-app/"},
|
||||
},
|
||||
},
|
||||
@@ -656,6 +664,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:a4595c43a874856bf95f3bfc4fbf78bbaa04c92c726276d4f64193a47ced0566",
|
||||
CreatedBy: "COPY file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ",
|
||||
OpaqueDirs: []string{"ruby-app/"},
|
||||
},
|
||||
},
|
||||
@@ -780,6 +789,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
|
||||
CreatedBy: "ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ",
|
||||
OS: &types.OS{
|
||||
Family: "alpine",
|
||||
Name: "3.11.5",
|
||||
@@ -911,6 +921,7 @@ func TestArtifact_Inspect(t *testing.T) {
|
||||
SchemaVersion: types.BlobJSONSchemaVersion,
|
||||
Digest: "",
|
||||
DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
|
||||
CreatedBy: "ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ",
|
||||
OS: &types.OS{
|
||||
Family: "alpine",
|
||||
Name: "3.11.5",
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
api "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/go-connections/nat"
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/samber/lo"
|
||||
@@ -90,7 +91,7 @@ func ContainerdImage(ctx context.Context, imageName string) (Image, func(), erro
|
||||
_ = os.Remove(f.Name())
|
||||
}
|
||||
|
||||
insp, err := inspect(ctx, img, ref)
|
||||
insp, history, err := inspect(ctx, img, ref)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("inspect error: %w", err)
|
||||
}
|
||||
@@ -98,6 +99,7 @@ func ContainerdImage(ctx context.Context, imageName string) (Image, func(), erro
|
||||
return &image{
|
||||
opener: imageOpener(ctx, ref.String(), f, imageWriter(client, img)),
|
||||
inspect: insp,
|
||||
history: history,
|
||||
}, cleanup, nil
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ func readImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image,
|
||||
}
|
||||
|
||||
// ported from https://github.com/containerd/nerdctl/blob/d110fea18018f13c3f798fa6565e482f3ff03591/pkg/inspecttypes/dockercompat/dockercompat.go#L279-L321
|
||||
func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.ImageInspect, error) {
|
||||
func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.ImageInspect, []v1.History, error) {
|
||||
var tag string
|
||||
if tagged, ok := ref.(refdocker.Tagged); ok {
|
||||
tag = tagged.Tag()
|
||||
@@ -130,7 +132,7 @@ func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.I
|
||||
|
||||
imgConfig, imgConfigDesc, err := readImageConfig(ctx, img)
|
||||
if err != nil {
|
||||
return api.ImageInspect{}, err
|
||||
return api.ImageInspect{}, nil, err
|
||||
}
|
||||
|
||||
var lastHistory ocispec.History
|
||||
@@ -138,6 +140,17 @@ func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.I
|
||||
lastHistory = imgConfig.History[len(imgConfig.History)-1]
|
||||
}
|
||||
|
||||
var history []v1.History
|
||||
for _, h := range imgConfig.History {
|
||||
history = append(history, v1.History{
|
||||
Author: h.Author,
|
||||
Created: v1.Time{Time: *h.Created},
|
||||
CreatedBy: h.CreatedBy,
|
||||
Comment: h.Comment,
|
||||
EmptyLayer: h.EmptyLayer,
|
||||
})
|
||||
}
|
||||
|
||||
portSet := make(nat.PortSet)
|
||||
for k := range imgConfig.Config.ExposedPorts {
|
||||
portSet[nat.Port(k)] = struct{}{}
|
||||
@@ -168,5 +181,5 @@ func inspect(ctx context.Context, img containerd.Image, ref docker.Named) (api.I
|
||||
return d.String()
|
||||
}),
|
||||
},
|
||||
}, nil
|
||||
}, history, nil
|
||||
}
|
||||
|
||||
@@ -56,6 +56,6 @@ func DockerImage(ref name.Reference) (Image, func(), error) {
|
||||
return &image{
|
||||
opener: imageOpener(context.Background(), imageID, f, c.ImageSave),
|
||||
inspect: inspect,
|
||||
history: history,
|
||||
history: configHistory(history),
|
||||
}, cleanup, nil
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ type image struct {
|
||||
v1.Image
|
||||
opener opener
|
||||
inspect types.ImageInspect
|
||||
history []dimage.HistoryResponseItem
|
||||
history []v1.History
|
||||
}
|
||||
|
||||
// populateImage initializes an "image" struct.
|
||||
@@ -112,7 +112,7 @@ func (img *image) ConfigFile() (*v1.ConfigFile, error) {
|
||||
Created: v1.Time{Time: created},
|
||||
DockerVersion: img.inspect.DockerVersion,
|
||||
Config: img.imageConfig(img.inspect.Config),
|
||||
History: img.configHistory(),
|
||||
History: img.history,
|
||||
OS: img.inspect.Os,
|
||||
RootFS: v1.RootFS{
|
||||
Type: img.inspect.RootFS.Type,
|
||||
@@ -143,50 +143,6 @@ func (img *image) RepoDigests() []string {
|
||||
return img.inspect.RepoDigests
|
||||
}
|
||||
|
||||
func (img *image) configHistory() []v1.History {
|
||||
// Fill only required metadata
|
||||
var history []v1.History
|
||||
for i := len(img.history) - 1; i >= 0; i-- {
|
||||
h := img.history[i]
|
||||
history = append(history, v1.History{
|
||||
Created: v1.Time{
|
||||
Time: time.Unix(h.Created, 0).UTC(),
|
||||
},
|
||||
CreatedBy: h.CreatedBy,
|
||||
Comment: h.Comment,
|
||||
EmptyLayer: emptyLayer(h),
|
||||
})
|
||||
}
|
||||
return history
|
||||
}
|
||||
|
||||
func emptyLayer(history dimage.HistoryResponseItem) bool {
|
||||
if history.Size != 0 {
|
||||
return false
|
||||
}
|
||||
createdBy := strings.TrimSpace(strings.TrimLeft(history.CreatedBy, "/bin/sh -c #(nop)"))
|
||||
// This logic is taken from https://github.com/moby/buildkit/blob/2942d13ff489a2a49082c99e6104517e357e53ad/frontend/dockerfile/dockerfile2llb/convert.go
|
||||
if strings.HasPrefix(createdBy, "ENV") ||
|
||||
strings.HasPrefix(createdBy, "MAINTAINER") ||
|
||||
strings.HasPrefix(createdBy, "LABEL") ||
|
||||
strings.HasPrefix(createdBy, "CMD") ||
|
||||
strings.HasPrefix(createdBy, "ENTRYPOINT") ||
|
||||
strings.HasPrefix(createdBy, "HEALTHCHECK") ||
|
||||
strings.HasPrefix(createdBy, "EXPOSE") ||
|
||||
strings.HasPrefix(createdBy, "USER") ||
|
||||
strings.HasPrefix(createdBy, "VOLUME") ||
|
||||
strings.HasPrefix(createdBy, "STOPSIGNAL") ||
|
||||
strings.HasPrefix(createdBy, "SHELL") ||
|
||||
strings.HasPrefix(createdBy, "ARG") ||
|
||||
createdBy == "WORKDIR /" { // only when workdir == "/" then layer is empty
|
||||
return true
|
||||
}
|
||||
// commands here: 'ADD', COPY, RUN and WORKDIR != "/"
|
||||
// Also RUN command may not include 'RUN' prefix
|
||||
// e.g. '/bin/sh -c mkdir test '
|
||||
return false
|
||||
}
|
||||
|
||||
func (img *image) diffIDs() ([]v1.Hash, error) {
|
||||
var diffIDs []v1.Hash
|
||||
for _, l := range img.inspect.RootFS.Layers {
|
||||
@@ -248,3 +204,48 @@ func (img *image) imageConfig(config *container.Config) v1.Config {
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func configHistory(dhistory []dimage.HistoryResponseItem) []v1.History {
|
||||
// Fill only required metadata
|
||||
var history []v1.History
|
||||
|
||||
for i := len(dhistory) - 1; i >= 0; i-- {
|
||||
h := dhistory[i]
|
||||
history = append(history, v1.History{
|
||||
Created: v1.Time{
|
||||
Time: time.Unix(h.Created, 0).UTC(),
|
||||
},
|
||||
CreatedBy: h.CreatedBy,
|
||||
Comment: h.Comment,
|
||||
EmptyLayer: emptyLayer(h),
|
||||
})
|
||||
}
|
||||
return history
|
||||
}
|
||||
|
||||
func emptyLayer(history dimage.HistoryResponseItem) bool {
|
||||
if history.Size != 0 {
|
||||
return false
|
||||
}
|
||||
createdBy := strings.TrimSpace(strings.TrimLeft(history.CreatedBy, "/bin/sh -c #(nop)"))
|
||||
// This logic is taken from https://github.com/moby/buildkit/blob/2942d13ff489a2a49082c99e6104517e357e53ad/frontend/dockerfile/dockerfile2llb/convert.go
|
||||
if strings.HasPrefix(createdBy, "ENV") ||
|
||||
strings.HasPrefix(createdBy, "MAINTAINER") ||
|
||||
strings.HasPrefix(createdBy, "LABEL") ||
|
||||
strings.HasPrefix(createdBy, "CMD") ||
|
||||
strings.HasPrefix(createdBy, "ENTRYPOINT") ||
|
||||
strings.HasPrefix(createdBy, "HEALTHCHECK") ||
|
||||
strings.HasPrefix(createdBy, "EXPOSE") ||
|
||||
strings.HasPrefix(createdBy, "USER") ||
|
||||
strings.HasPrefix(createdBy, "VOLUME") ||
|
||||
strings.HasPrefix(createdBy, "STOPSIGNAL") ||
|
||||
strings.HasPrefix(createdBy, "SHELL") ||
|
||||
strings.HasPrefix(createdBy, "ARG") ||
|
||||
createdBy == "WORKDIR /" { // only when workdir == "/" then layer is empty
|
||||
return true
|
||||
}
|
||||
// commands here: 'ADD', COPY, RUN and WORKDIR != "/"
|
||||
// Also RUN command may not include 'RUN' prefix
|
||||
// e.g. '/bin/sh -c mkdir test '
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -11,11 +11,13 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
api "github.com/docker/docker/api/types"
|
||||
dimage "github.com/docker/docker/api/types/image"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var (
|
||||
inspectURL = "http://podman/images/%s/json"
|
||||
historyURL = "http://podman/images/%s/history"
|
||||
saveURL = "http://podman/images/%s/get"
|
||||
)
|
||||
|
||||
@@ -70,6 +72,29 @@ func (p podmanClient) imageInspect(imageName string) (api.ImageInspect, error) {
|
||||
return inspect, nil
|
||||
}
|
||||
|
||||
func (p podmanClient) imageHistoryInspect(imageName string) ([]dimage.HistoryResponseItem, error) {
|
||||
url := fmt.Sprintf(historyURL, imageName)
|
||||
resp, err := p.c.Get(url)
|
||||
if err != nil {
|
||||
return []dimage.HistoryResponseItem{}, xerrors.Errorf("http error: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
var res errResponse
|
||||
if err = json.NewDecoder(resp.Body).Decode(&res); err != nil {
|
||||
return []dimage.HistoryResponseItem{}, xerrors.Errorf("unknown status code from Podman: %d", resp.StatusCode)
|
||||
}
|
||||
return []dimage.HistoryResponseItem{}, xerrors.New(res.Message)
|
||||
}
|
||||
|
||||
var history []dimage.HistoryResponseItem
|
||||
if err = json.NewDecoder(resp.Body).Decode(&history); err != nil {
|
||||
return []dimage.HistoryResponseItem{}, xerrors.Errorf("unable to decode JSON: %w", err)
|
||||
}
|
||||
return history, nil
|
||||
}
|
||||
|
||||
func (p podmanClient) imageSave(_ context.Context, imageNames []string) (io.ReadCloser, error) {
|
||||
if len(imageNames) < 1 {
|
||||
return nil, xerrors.Errorf("no specified image")
|
||||
@@ -96,6 +121,11 @@ func PodmanImage(ref string) (Image, func(), error) {
|
||||
return nil, cleanup, xerrors.Errorf("unable to inspect the image (%s): %w", ref, err)
|
||||
}
|
||||
|
||||
history, err := c.imageHistoryInspect(ref)
|
||||
if err != nil {
|
||||
return nil, cleanup, xerrors.Errorf("unable to inspect the image (%s): %w", ref, err)
|
||||
}
|
||||
|
||||
f, err := os.CreateTemp("", "fanal-*")
|
||||
if err != nil {
|
||||
return nil, cleanup, xerrors.Errorf("failed to create a temporary file")
|
||||
@@ -109,5 +139,6 @@ func PodmanImage(ref string) (Image, func(), error) {
|
||||
return &image{
|
||||
opener: imageOpener(context.Background(), ref, f, c.imageSave),
|
||||
inspect: inspect,
|
||||
history: configHistory(history),
|
||||
}, cleanup, nil
|
||||
}
|
||||
|
||||
@@ -53,13 +53,18 @@ func TestPodmanImage(t *testing.T) {
|
||||
imageName string
|
||||
fields fields
|
||||
wantConfigName string
|
||||
wantCreateBy []string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
imageName: "alpine:3.11",
|
||||
wantConfigName: "sha256:a187dde48cd289ac374ad8539930628314bc581a481cdb41409c9289419ddb72",
|
||||
wantErr: false,
|
||||
wantCreateBy: []string{
|
||||
"/bin/sh -c #(nop) CMD [\"/bin/sh\"]",
|
||||
"/bin/sh -c #(nop) ADD file:0c4555f363c2672e350001f1293e689875a3760afe7b3f9146886afe67121cba in / ",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "unknown image",
|
||||
@@ -88,6 +93,14 @@ func TestPodmanImage(t *testing.T) {
|
||||
confName, err := img.ConfigName()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.wantConfigName, confName.String())
|
||||
|
||||
confFile, err := img.ConfigFile()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, len(confFile.History), len(tt.wantCreateBy))
|
||||
for _, h := range confFile.History {
|
||||
assert.Contains(t, tt.wantCreateBy, h.CreatedBy)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,17 @@ func TestContainerd_LocalImage(t *testing.T) {
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
},
|
||||
},
|
||||
History: []v1.History{
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2019, 8, 20, 20, 19, 55, 62606894, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ADD file:fe64057fbb83dccb960efabbf1cd8777920ef279a7fa8dbca0a8801c651bdf7c in / ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2019, 8, 20, 20, 19, 55, 211423266, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) CMD [\"/bin/sh\"]",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -201,6 +212,173 @@ func TestContainerd_LocalImage(t *testing.T) {
|
||||
"/docker-entrypoint.sh",
|
||||
},
|
||||
},
|
||||
History: []v1.History{
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 11, 22, 19, 38, 885299940, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ADD file:49f9e47e678d868d5b023482aa8dded71276a241a665c4f8b55ca77269321b34 in / ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 11, 22, 19, 39, 58628442, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) CMD [\"/bin/sh\"]",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 26, 59, 951316015, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV PHPIZE_DEPS=autoconf \t\tdpkg-dev dpkg \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkgconf \t\tre2c",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 1, 470388635, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c apk add --no-cache --virtual .persistent-deps \t\tca-certificates \t\tcurl \t\ttar \t\txz \t\tlibressl",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 2, 432381785, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c set -x \t&& addgroup -g 82 -S www-data \t&& adduser -u 82 -D -S -G www-data www-data",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 2, 715120309, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV PHP_INI_DIR=/usr/local/etc/php",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 3, 655421341, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c mkdir -p $PHP_INI_DIR/conf.d",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 3, 931799562, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 4, 210945499, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 4, 523116501, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV PHP_LDFLAGS=-Wl,-O1 -Wl,--hash-style=both -pie",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 9, 12, 1, 27, 4, 795176159, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV GPG_KEYS=1729F83938DA44E27BA0F4D3DBDB397470D12172 B1B44D8F021E4E2D6021E995DC9FF8D3EE5AF27F",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 18, 415761689, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV PHP_VERSION=7.2.11",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 18, 599097853, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV PHP_URL=https://secure.php.net/get/php-7.2.11.tar.xz/from/this/mirror PHP_ASC_URL=https://secure.php.net/get/php-7.2.11.tar.xz.asc/from/this/mirror",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 18, 782890412, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV PHP_SHA256=da1a705c0bc46410e330fc6baa967666c8cd2985378fb9707c01a8e33b01d985 PHP_MD5=",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 22, 795846753, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c set -xe; \t\tapk add --no-cache --virtual .fetch-deps \t\tgnupg \t\twget \t; \t\tmkdir -p /usr/src; \tcd /usr/src; \t\twget -O php.tar.xz \"$PHP_URL\"; \t\tif [ -n \"$PHP_SHA256\" ]; then \t\techo \"$PHP_SHA256 *php.tar.xz\" | sha256sum -c -; \tfi; \tif [ -n \"$PHP_MD5\" ]; then \t\techo \"$PHP_MD5 *php.tar.xz\" | md5sum -c -; \tfi; \t\tif [ -n \"$PHP_ASC_URL\" ]; then \t\twget -O php.tar.xz.asc \"$PHP_ASC_URL\"; \t\texport GNUPGHOME=\"$(mktemp -d)\"; \t\tfor key in $GPG_KEYS; do \t\t\tgpg --keyserver ha.pool.sks-keyservers.net --recv-keys \"$key\"; \t\tdone; \t\tgpg --batch --verify php.tar.xz.asc php.tar.xz; \t\tcommand -v gpgconf > /dev/null && gpgconf --kill all; \t\trm -rf \"$GNUPGHOME\"; \tfi; \t\tapk del .fetch-deps",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 2, 23, 71406376, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) COPY file:207c686e3fed4f71f8a7b245d8dcae9c9048d276a326d82b553c12a90af0c0ca in /usr/local/bin/ ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 13, 93396680, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c set -xe \t&& apk add --no-cache --virtual .build-deps \t\t$PHPIZE_DEPS \t\tcoreutils \t\tcurl-dev \t\tlibedit-dev \t\tlibressl-dev \t\tlibsodium-dev \t\tlibxml2-dev \t\tsqlite-dev \t\t&& export CFLAGS=\"$PHP_CFLAGS\" \t\tCPPFLAGS=\"$PHP_CPPFLAGS\" \t\tLDFLAGS=\"$PHP_LDFLAGS\" \t&& docker-php-source extract \t&& cd /usr/src/php \t&& gnuArch=\"$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)\" \t&& ./configure \t\t--build=\"$gnuArch\" \t\t--with-config-file-path=\"$PHP_INI_DIR\" \t\t--with-config-file-scan-dir=\"$PHP_INI_DIR/conf.d\" \t\t\t\t--enable-option-checking=fatal \t\t\t\t--with-mhash \t\t\t\t--enable-ftp \t\t--enable-mbstring \t\t--enable-mysqlnd \t\t--with-sodium=shared \t\t\t\t--with-curl \t\t--with-libedit \t\t--with-openssl \t\t--with-zlib \t\t\t\t$(test \"$gnuArch\" = 's390x-linux-gnu' && echo '--without-pcre-jit') \t\t\t\t$PHP_EXTRA_CONFIGURE_ARGS \t&& make -j \"$(nproc)\" \t&& make install \t&& { find /usr/local/bin /usr/local/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; } \t&& make clean \t\t&& cp -v php.ini-* \"$PHP_INI_DIR/\" \t\t&& cd / \t&& docker-php-source delete \t\t&& runDeps=\"$( \t\tscanelf --needed --nobanner --format '%n#p' --recursive /usr/local \t\t\t| tr ',' '\\n' \t\t\t| sort -u \t\t\t| awk 'system(\"[ -e /usr/local/lib/\" $1 \" ]\") == 0 { next } { print \"so:\" $1 }' \t)\" \t&& apk add --no-cache --virtual .php-rundeps $runDeps \t\t&& apk del .build-deps \t\t&& pecl update-channels \t&& rm -rf /tmp/pear ~/.pearrc",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 13, 722586262, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) COPY multi:2cdcedabcf5a3b9ae610fab7848e94bc2f64b4d85710d55fd6f79e44dacf73d8 in /usr/local/bin/ ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 14, 618087104, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c docker-php-ext-enable sodium",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 14, 826981756, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENTRYPOINT [\"docker-php-entrypoint\"]",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 19, 7, 15, 10831572, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) CMD [\"php\" \"-a\"]",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 21, 919735971, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c apk --no-cache add git subversion openssh mercurial tini bash patch",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 22, 611763893, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c echo \"memory_limit=-1\" > \"$PHP_INI_DIR/conf.d/memory-limit.ini\" && echo \"date.timezone=${PHP_TIMEZONE:-UTC}\" > \"$PHP_INI_DIR/conf.d/date_timezone.ini\"",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 50, 224278478, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c apk add --no-cache --virtual .build-deps zlib-dev && docker-php-ext-install zip && runDeps=\"$( scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions | tr ',' '\\n' | sort -u | awk 'system(\"[ -e /usr/local/lib/\" $1 \" ]\") == 0 { next } { print \"so:\" $1 }' )\" && apk add --virtual .composer-phpext-rundeps $runDeps && apk del .build-deps",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 50, 503010161, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV COMPOSER_ALLOW_SUPERUSER=1",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 50, 775378559, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV COMPOSER_HOME=/tmp",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 51, 35012363, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENV COMPOSER_VERSION=1.7.2",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 52, 491402624, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c curl --silent --fail --location --retry 3 --output /tmp/installer.php --url https://raw.githubusercontent.com/composer/getcomposer.org/b107d959a5924af895807021fcef4ffec5a76aa9/web/installer && php -r \" \\$signature = '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061'; \\$hash = hash('SHA384', file_get_contents('/tmp/installer.php')); if (!hash_equals(\\$signature, \\$hash)) { unlink('/tmp/installer.php'); echo 'Integrity check failed, installer is either corrupt or worse.' . PHP_EOL; exit(1); }\" && php /tmp/installer.php --no-ansi --install-dir=/usr/bin --filename=composer --version=${COMPOSER_VERSION} && composer --ansi --version --no-interaction && rm -rf /tmp/* /tmp/.htaccess",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 52, 948859545, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) COPY file:295943a303e8f27de4302b6aa3687bce4b1d1392335efaaab9ecd37bec5ab4c5 in /docker-entrypoint.sh ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 53, 295399872, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) WORKDIR /app",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 53, 582920705, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ENTRYPOINT [\"/bin/sh\" \"/docker-entrypoint.sh\"]",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2018, 10, 15, 21, 28, 53, 798628678, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) CMD [\"composer\"]",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 57, 211142800, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ADD file:842584685f26edb24dc305d76894f51cfda2bad0c24a05e727f9d4905d184a70 in /php-app/composer.lock ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 57, 583779000, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ADD file:c6d0373d380252b91829a5bb3c81d5b1afa574c91cef7752d18170a231c31f6d in /ruby-app/Gemfile.lock ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 57, 921730100, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ADD file:54a1c52556a5ebe98fd124f51c25d071f9e29e2714c72c80d6d3d254b9e83386 in /node-app/package-lock.json ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 58, 311593100, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ADD file:097d32f46acde76c4da9e55f17110d69d02cc6d16c86da907980da335fc0fc5f in /python-app/Pipfile.lock ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{Time: time.Date(2019, 8, 7, 7, 25, 58, 651649800, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ADD file:7f147d85de19bfb905c260a0c175f227a433259022c163017b96d0efacdcd105 in /rust-app/Cargo.lock ",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -320,6 +498,17 @@ func TestContainerd_PullImage(t *testing.T) {
|
||||
},
|
||||
ArgsEscaped: false,
|
||||
},
|
||||
History: []v1.History{
|
||||
{
|
||||
Created: v1.Time{time.Date(2019, 8, 20, 20, 19, 55, 62606894, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) ADD file:fe64057fbb83dccb960efabbf1cd8777920ef279a7fa8dbca0a8801c651bdf7c in / ",
|
||||
},
|
||||
{
|
||||
Created: v1.Time{time.Date(2019, 8, 20, 20, 19, 55, 211423266, time.UTC)},
|
||||
CreatedBy: "/bin/sh -c #(nop) CMD [\"/bin/sh\"]",
|
||||
EmptyLayer: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -18,8 +18,9 @@ type Repository struct {
|
||||
}
|
||||
|
||||
type Layer struct {
|
||||
Digest string `json:",omitempty"`
|
||||
DiffID string `json:",omitempty"`
|
||||
Digest string `json:",omitempty"`
|
||||
DiffID string `json:",omitempty"`
|
||||
CreatedBy string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
@@ -133,9 +134,16 @@ type ArtifactInfo struct {
|
||||
|
||||
// BlobInfo is stored in cache
|
||||
type BlobInfo struct {
|
||||
SchemaVersion int
|
||||
Digest string `json:",omitempty"`
|
||||
DiffID string `json:",omitempty"`
|
||||
SchemaVersion int
|
||||
|
||||
// Layer information
|
||||
Digest string `json:",omitempty"`
|
||||
DiffID string `json:",omitempty"`
|
||||
CreatedBy string `json:",omitempty"`
|
||||
OpaqueDirs []string `json:",omitempty"`
|
||||
WhiteoutFiles []string `json:",omitempty"`
|
||||
|
||||
// Analysis result
|
||||
OS *OS `json:",omitempty"`
|
||||
Repository *Repository `json:",omitempty"`
|
||||
PackageInfos []PackageInfo `json:",omitempty"`
|
||||
@@ -143,8 +151,6 @@ type BlobInfo struct {
|
||||
Misconfigurations []Misconfiguration `json:",omitempty"`
|
||||
Secrets []Secret `json:",omitempty"`
|
||||
Licenses []LicenseFile `json:",omitempty"`
|
||||
OpaqueDirs []string `json:",omitempty"`
|
||||
WhiteoutFiles []string `json:",omitempty"`
|
||||
|
||||
// Red Hat distributions have build info per layer.
|
||||
// This information will be embedded into packages when applying layers.
|
||||
|
||||
@@ -16,6 +16,5 @@ type SecretFinding struct {
|
||||
EndLine int
|
||||
Code Code
|
||||
Match string
|
||||
Deleted bool
|
||||
Layer Layer `json:",omitempty"`
|
||||
}
|
||||
|
||||
@@ -119,12 +119,20 @@ func (r *secretRenderer) renderCode(secret types.SecretFinding) {
|
||||
lineInfo = tml.Sprintf("%s<blue>-%d", lineInfo, secret.EndLine)
|
||||
}
|
||||
}
|
||||
|
||||
var note string
|
||||
if secret.Deleted {
|
||||
note = " (deleted in the intermediate layer)"
|
||||
if c := secret.Layer.CreatedBy; c != "" {
|
||||
if len(c) > 40 {
|
||||
// Too long
|
||||
c = c[:40]
|
||||
}
|
||||
note = fmt.Sprintf(" (added by '%s')", c)
|
||||
} else if secret.Layer.DiffID != "" {
|
||||
note = fmt.Sprintf(" (added in layer '%s')", strings.TrimPrefix(secret.Layer.DiffID, "sha256:")[:12])
|
||||
}
|
||||
r.printf(" <blue>%s%s<magenta>%s\r\n", r.target, lineInfo, note)
|
||||
r.printSingleDivider()
|
||||
|
||||
for i, line := range lines {
|
||||
if line.Truncated {
|
||||
r.printf("<dim>%4s ", strings.Repeat(".", len(fmt.Sprintf("%d", line.Number))))
|
||||
|
||||
@@ -27,6 +27,7 @@ func TestSecretRenderer(t *testing.T) {
|
||||
Category: ftypes.SecretRuleCategory("category"),
|
||||
Title: "this is a title",
|
||||
Severity: "HIGH",
|
||||
Layer: ftypes.Layer{DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203"},
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
Code: ftypes.Code{
|
||||
@@ -52,7 +53,7 @@ HIGH: category (rule-id)
|
||||
════════════════════════════════════════
|
||||
this is a title
|
||||
────────────────────────────────────────
|
||||
my-file:1
|
||||
my-file:1 (added in layer 'beee9f30bc1f')
|
||||
────────────────────────────────────────
|
||||
1 [ password=secret
|
||||
────────────────────────────────────────
|
||||
@@ -64,11 +65,14 @@ this is a title
|
||||
name: "multiple line",
|
||||
input: []ftypes.SecretFinding{
|
||||
{
|
||||
RuleID: "rule-id",
|
||||
Category: ftypes.SecretRuleCategory("category"),
|
||||
Title: "this is a title",
|
||||
Severity: "HIGH",
|
||||
Deleted: true,
|
||||
RuleID: "rule-id",
|
||||
Category: ftypes.SecretRuleCategory("category"),
|
||||
Title: "this is a title",
|
||||
Severity: "HIGH",
|
||||
Layer: ftypes.Layer{
|
||||
DiffID: "sha256:beee9f30bc1f711043e78d4a2be0668955d4b761d587d6f60c2c8dc081efb203",
|
||||
CreatedBy: "COPY my-file my-file",
|
||||
},
|
||||
StartLine: 3,
|
||||
EndLine: 4,
|
||||
Code: ftypes.Code{
|
||||
@@ -115,7 +119,7 @@ HIGH: category (rule-id)
|
||||
════════════════════════════════════════
|
||||
this is a title
|
||||
────────────────────────────────────────
|
||||
my-file:3-4 (deleted in the intermediate layer)
|
||||
my-file:3-4 (added by 'COPY my-file my-file')
|
||||
────────────────────────────────────────
|
||||
1 #!/bin/bash
|
||||
2
|
||||
|
||||
@@ -102,7 +102,6 @@ func ConvertToRPCSecretFindings(findings []ftypes.SecretFinding) []*common.Secre
|
||||
StartLine: int32(f.StartLine),
|
||||
Code: ConvertToRPCCode(f.Code),
|
||||
Match: f.Match,
|
||||
Deleted: f.Deleted,
|
||||
Layer: ConvertToRPCLayer(f.Layer),
|
||||
})
|
||||
}
|
||||
@@ -230,8 +229,9 @@ func ConvertToRPCMisconfs(misconfs []types.DetectedMisconfiguration) []*common.D
|
||||
// ConvertToRPCLayer returns common.Layer
|
||||
func ConvertToRPCLayer(layer ftypes.Layer) *common.Layer {
|
||||
return &common.Layer{
|
||||
Digest: layer.Digest,
|
||||
DiffId: layer.DiffID,
|
||||
Digest: layer.Digest,
|
||||
DiffId: layer.DiffID,
|
||||
CreatedBy: layer.CreatedBy,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,10 +313,10 @@ func ConvertFromRPCSecretFindings(rpcFindings []*common.SecretFinding) []ftypes.
|
||||
EndLine: int(finding.EndLine),
|
||||
Code: ConvertFromRPCCode(finding.Code),
|
||||
Match: finding.Match,
|
||||
Deleted: finding.Deleted,
|
||||
Layer: ftypes.Layer{
|
||||
Digest: finding.Layer.Digest,
|
||||
DiffID: finding.Layer.DiffId,
|
||||
Digest: finding.Layer.Digest,
|
||||
DiffID: finding.Layer.DiffId,
|
||||
CreatedBy: finding.Layer.CreatedBy,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1060,8 +1060,9 @@ type Layer struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Digest string `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"`
|
||||
DiffId string `protobuf:"bytes,2,opt,name=diff_id,json=diffId,proto3" json:"diff_id,omitempty"`
|
||||
Digest string `protobuf:"bytes,1,opt,name=digest,proto3" json:"digest,omitempty"`
|
||||
DiffId string `protobuf:"bytes,2,opt,name=diff_id,json=diffId,proto3" json:"diff_id,omitempty"`
|
||||
CreatedBy string `protobuf:"bytes,3,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Layer) Reset() {
|
||||
@@ -1110,6 +1111,13 @@ func (x *Layer) GetDiffId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Layer) GetCreatedBy() string {
|
||||
if x != nil {
|
||||
return x.CreatedBy
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CVSS struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -1415,7 +1423,6 @@ type SecretFinding struct {
|
||||
EndLine int32 `protobuf:"varint,6,opt,name=end_line,json=endLine,proto3" json:"end_line,omitempty"`
|
||||
Code *Code `protobuf:"bytes,7,opt,name=code,proto3" json:"code,omitempty"`
|
||||
Match string `protobuf:"bytes,8,opt,name=match,proto3" json:"match,omitempty"`
|
||||
Deleted bool `protobuf:"varint,9,opt,name=deleted,proto3" json:"deleted,omitempty"`
|
||||
Layer *Layer `protobuf:"bytes,10,opt,name=layer,proto3" json:"layer,omitempty"`
|
||||
}
|
||||
|
||||
@@ -1507,13 +1514,6 @@ func (x *SecretFinding) GetMatch() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *SecretFinding) GetDeleted() bool {
|
||||
if x != nil {
|
||||
return x.Deleted
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *SecretFinding) GetLayer() *Layer {
|
||||
if x != nil {
|
||||
return x.Layer
|
||||
@@ -1764,80 +1764,80 @@ var file_rpc_common_service_proto_rawDesc = []byte{
|
||||
0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
|
||||
0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x38, 0x0a, 0x05, 0x4c, 0x61, 0x79, 0x65,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x57, 0x0a, 0x05, 0x4c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x69, 0x66,
|
||||
0x66, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x66, 0x66,
|
||||
0x49, 0x64, 0x22, 0x76, 0x0a, 0x04, 0x43, 0x56, 0x53, 0x53, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x32,
|
||||
0x5f, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76,
|
||||
0x32, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x33, 0x5f, 0x76, 0x65,
|
||||
0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x33, 0x56, 0x65,
|
||||
0x63, 0x74, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x32, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x76, 0x32, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12,
|
||||
0x19, 0x0a, 0x08, 0x76, 0x33, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x01, 0x52, 0x07, 0x76, 0x33, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x43,
|
||||
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
|
||||
0x65, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x29,
|
||||
0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e,
|
||||
0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79,
|
||||
0x65, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x04, 0x64, 0x61, 0x74,
|
||||
0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
|
||||
0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xf3, 0x01, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06,
|
||||
0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
|
||||
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
|
||||
0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
|
||||
0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x74,
|
||||
0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
|
||||
0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x67,
|
||||
0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
|
||||
0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66,
|
||||
0x69, 0x72, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x22, 0x30, 0x0a, 0x04, 0x43,
|
||||
0x6f, 0x64, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||
0x6e, 0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0xb3, 0x02,
|
||||
0x0a, 0x0d, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12,
|
||||
0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65,
|
||||
0x67, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65,
|
||||
0x67, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79,
|
||||
0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f,
|
||||
0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72,
|
||||
0x74, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6e,
|
||||
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x4c, 0x69, 0x6e, 0x65,
|
||||
0x12, 0x26, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12,
|
||||
0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6f,
|
||||
0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63,
|
||||
0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x18,
|
||||
0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||
0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x05, 0x6c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x6c, 0x61,
|
||||
0x79, 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a,
|
||||
0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x08, 0x66, 0x69, 0x6c, 0x65, 0x70, 0x61, 0x74, 0x68, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x69, 0x6e,
|
||||
0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72,
|
||||
0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65,
|
||||
0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x73, 0x2a, 0x44, 0x0a, 0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x0b,
|
||||
0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4c,
|
||||
0x4f, 0x57, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x44, 0x49, 0x55, 0x4d, 0x10, 0x02,
|
||||
0x12, 0x08, 0x0a, 0x04, 0x48, 0x49, 0x47, 0x48, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52,
|
||||
0x49, 0x54, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x04, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72,
|
||||
0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x6f, 0x6e, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42,
|
||||
0x79, 0x22, 0x76, 0x0a, 0x04, 0x43, 0x56, 0x53, 0x53, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x32, 0x5f,
|
||||
0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x32,
|
||||
0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x33, 0x5f, 0x76, 0x65, 0x63,
|
||||
0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x33, 0x56, 0x65, 0x63,
|
||||
0x74, 0x6f, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x32, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x76, 0x32, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x19,
|
||||
0x0a, 0x08, 0x76, 0x33, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01,
|
||||
0x52, 0x07, 0x76, 0x33, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x43, 0x75,
|
||||
0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x29, 0x0a,
|
||||
0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74,
|
||||
0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04,
|
||||
0x64, 0x61, 0x74, 0x61, 0x22, 0xf3, 0x01, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a,
|
||||
0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e,
|
||||
0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12,
|
||||
0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x07, 0x69, 0x73, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x6e,
|
||||
0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
|
||||
0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72,
|
||||
0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74,
|
||||
0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x69, 0x67, 0x68,
|
||||
0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x68,
|
||||
0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69,
|
||||
0x72, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||
0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c,
|
||||
0x61, 0x73, 0x74, 0x5f, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||
0x09, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x61, 0x75, 0x73, 0x65, 0x22, 0x30, 0x0a, 0x04, 0x43, 0x6f,
|
||||
0x64, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x12, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||
0x2e, 0x4c, 0x69, 0x6e, 0x65, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x9f, 0x02, 0x0a,
|
||||
0x0d, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x17,
|
||||
0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67,
|
||||
0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x61, 0x74, 0x65, 0x67,
|
||||
0x6f, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||
0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6c,
|
||||
0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74,
|
||||
0x4c, 0x69, 0x6e, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65,
|
||||
0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x4c, 0x69, 0x6e, 0x65, 0x12,
|
||||
0x26, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e,
|
||||
0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x64,
|
||||
0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68,
|
||||
0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x29, 0x0a,
|
||||
0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74,
|
||||
0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4c, 0x61, 0x79, 0x65,
|
||||
0x72, 0x52, 0x05, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0x5d,
|
||||
0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65,
|
||||
0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65,
|
||||
0x70, 0x61, 0x74, 0x68, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73,
|
||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x46, 0x69, 0x6e, 0x64,
|
||||
0x69, 0x6e, 0x67, 0x52, 0x08, 0x66, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2a, 0x44, 0x0a,
|
||||
0x08, 0x53, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b,
|
||||
0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12,
|
||||
0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x44, 0x49, 0x55, 0x4d, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x48,
|
||||
0x49, 0x47, 0x48, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x52, 0x49, 0x54, 0x49, 0x43, 0x41,
|
||||
0x4c, 0x10, 0x04, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74,
|
||||
0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x3b,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -115,8 +115,9 @@ message DataSource {
|
||||
}
|
||||
|
||||
message Layer {
|
||||
string digest = 1;
|
||||
string diff_id = 2;
|
||||
string digest = 1;
|
||||
string diff_id = 2;
|
||||
string created_by = 3;
|
||||
}
|
||||
|
||||
enum Severity {
|
||||
@@ -165,8 +166,9 @@ message SecretFinding {
|
||||
int32 end_line = 6;
|
||||
Code code = 7;
|
||||
string match = 8;
|
||||
bool deleted = 9;
|
||||
Layer layer = 10;
|
||||
|
||||
reserved 9; // deprecated 'deleted'
|
||||
}
|
||||
|
||||
message Secret {
|
||||
|
||||
Reference in New Issue
Block a user