mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
Add relationships for rust audit binary packages (#3500)
* add rust audit binary pkg relationships Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix linting Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
4adb56d2fe
commit
340b5e17f0
@ -5,11 +5,11 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/syft/source/sourceproviders"
|
||||
)
|
||||
|
||||
|
||||
@ -5,11 +5,12 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/wagoodman/go-progress"
|
||||
|
||||
"github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/stereoscope/pkg/filetree"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/internal/windows"
|
||||
"github.com/wagoodman/go-progress"
|
||||
)
|
||||
|
||||
type fileIndexer struct {
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
package fileresolver
|
||||
|
||||
import (
|
||||
"github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/stereoscope/pkg/file"
|
||||
)
|
||||
|
||||
// - Verify that both the parent and the path are indexed
|
||||
|
||||
@ -14,13 +14,14 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
|
||||
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
// Tests for filetree resolver when directory is used for index
|
||||
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||
)
|
||||
|
||||
const cargoAuditBinaryCatalogerName = "cargo-auditable-binary-cataloger"
|
||||
|
||||
// NewCargoLockCataloger returns a new Rust Cargo lock file cataloger object.
|
||||
func NewCargoLockCataloger() pkg.Cataloger {
|
||||
return generic.NewCataloger("rust-cargo-lock-cataloger").
|
||||
@ -18,6 +20,6 @@ func NewCargoLockCataloger() pkg.Cataloger {
|
||||
// NewAuditBinaryCataloger returns a new Rust auditable binary cataloger object that can detect dependencies
|
||||
// in binaries produced with https://github.com/Shnatsel/rust-audit
|
||||
func NewAuditBinaryCataloger() pkg.Cataloger {
|
||||
return generic.NewCataloger("cargo-auditable-binary-cataloger").
|
||||
return generic.NewCataloger(cargoAuditBinaryCatalogerName).
|
||||
WithParserByMimeTypes(parseAuditBinary, mimetype.ExecutableMIMETypeSet.List()...)
|
||||
}
|
||||
|
||||
@ -3,48 +3,270 @@ package rust
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
||||
)
|
||||
|
||||
func TestNewAuditBinaryCataloger(t *testing.T) {
|
||||
locations := file.NewLocationSet(file.NewVirtualLocation("/usr/local/bin/hello_world", "/usr/local/bin/hello_world"))
|
||||
|
||||
argh := pkg.Package{
|
||||
Name: "argh",
|
||||
Version: "0.1.12",
|
||||
PURL: "pkg:cargo/argh@0.1.12",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "argh",
|
||||
Version: "0.1.12",
|
||||
Source: "crates.io",
|
||||
},
|
||||
}
|
||||
|
||||
arghDerive := pkg.Package{
|
||||
Name: "argh_derive",
|
||||
Version: "0.1.12",
|
||||
PURL: "pkg:cargo/argh_derive@0.1.12",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "argh_derive",
|
||||
Version: "0.1.12",
|
||||
Source: "crates.io",
|
||||
},
|
||||
}
|
||||
|
||||
arghShared := pkg.Package{
|
||||
Name: "argh_shared",
|
||||
Version: "0.1.12",
|
||||
PURL: "pkg:cargo/argh_shared@0.1.12",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "argh_shared",
|
||||
Version: "0.1.12",
|
||||
Source: "crates.io",
|
||||
},
|
||||
}
|
||||
|
||||
helloWorld := pkg.Package{
|
||||
Name: "hello_world",
|
||||
Version: "0.1.0",
|
||||
PURL: "pkg:cargo/hello_world@0.1.0",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "hello_world",
|
||||
Version: "0.1.0",
|
||||
Source: "local",
|
||||
},
|
||||
}
|
||||
|
||||
procMacro2 := pkg.Package{
|
||||
Name: "proc-macro2",
|
||||
Version: "1.0.92",
|
||||
PURL: "pkg:cargo/proc-macro2@1.0.92",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "proc-macro2",
|
||||
Version: "1.0.92",
|
||||
Source: "crates.io",
|
||||
},
|
||||
}
|
||||
|
||||
quote := pkg.Package{
|
||||
Name: "quote",
|
||||
Version: "1.0.37",
|
||||
PURL: "pkg:cargo/quote@1.0.37",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "quote",
|
||||
Version: "1.0.37",
|
||||
Source: "crates.io",
|
||||
},
|
||||
}
|
||||
|
||||
serde := pkg.Package{
|
||||
Name: "serde",
|
||||
Version: "1.0.215",
|
||||
PURL: "pkg:cargo/serde@1.0.215",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "serde",
|
||||
Version: "1.0.215",
|
||||
Source: "crates.io",
|
||||
},
|
||||
}
|
||||
|
||||
serdeDerive := pkg.Package{
|
||||
Name: "serde_derive",
|
||||
Version: "1.0.215",
|
||||
PURL: "pkg:cargo/serde_derive@1.0.215",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "serde_derive",
|
||||
Version: "1.0.215",
|
||||
Source: "crates.io",
|
||||
},
|
||||
}
|
||||
|
||||
syn := pkg.Package{
|
||||
Name: "syn",
|
||||
Version: "2.0.90",
|
||||
PURL: "pkg:cargo/syn@2.0.90",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "syn",
|
||||
Version: "2.0.90",
|
||||
Source: "crates.io",
|
||||
},
|
||||
}
|
||||
|
||||
unicodeIdent := pkg.Package{
|
||||
Name: "unicode-ident",
|
||||
Version: "1.0.14",
|
||||
PURL: "pkg:cargo/unicode-ident@1.0.14",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: locations,
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "unicode-ident",
|
||||
Version: "1.0.14",
|
||||
Source: "crates.io",
|
||||
},
|
||||
}
|
||||
|
||||
expectedPkgs := []pkg.Package{
|
||||
argh,
|
||||
arghDerive,
|
||||
arghShared,
|
||||
helloWorld,
|
||||
procMacro2,
|
||||
quote,
|
||||
serde,
|
||||
serdeDerive,
|
||||
syn,
|
||||
unicodeIdent,
|
||||
}
|
||||
|
||||
expectedRelationships := []artifact.Relationship{
|
||||
{
|
||||
Name: "auditable",
|
||||
Version: "0.1.0",
|
||||
PURL: "pkg:cargo/auditable@0.1.0",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")),
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "auditable",
|
||||
Version: "0.1.0",
|
||||
Source: "local",
|
||||
},
|
||||
From: argh,
|
||||
To: helloWorld,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
Name: "hello-auditable",
|
||||
Version: "0.1.0",
|
||||
PURL: "pkg:cargo/hello-auditable@0.1.0",
|
||||
FoundBy: "cargo-auditable-binary-cataloger",
|
||||
Locations: file.NewLocationSet(file.NewVirtualLocation("/hello-auditable", "/hello-auditable")),
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: "hello-auditable",
|
||||
Version: "0.1.0",
|
||||
Source: "local",
|
||||
From: arghDerive,
|
||||
To: argh,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: arghShared,
|
||||
To: argh,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: arghShared,
|
||||
To: arghDerive,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: procMacro2,
|
||||
To: arghDerive,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: procMacro2,
|
||||
To: quote,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: procMacro2,
|
||||
To: serdeDerive,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: procMacro2,
|
||||
To: syn,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: quote,
|
||||
To: arghDerive,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: quote,
|
||||
To: serdeDerive,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: quote,
|
||||
To: syn,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: serde,
|
||||
To: arghShared,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: serdeDerive,
|
||||
To: serde,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: syn,
|
||||
To: arghDerive,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: syn,
|
||||
To: serdeDerive,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: unicodeIdent,
|
||||
To: procMacro2,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
{
|
||||
From: unicodeIdent,
|
||||
To: syn,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
}
|
||||
|
||||
pkgtest.NewCatalogTester().
|
||||
WithImageResolver(t, "image-audit").
|
||||
IgnoreLocationLayer(). // this fixture can be rebuilt, thus the layer ID will change
|
||||
Expects(expectedPkgs, nil).
|
||||
Expects(expectedPkgs, expectedRelationships).
|
||||
TestCataloger(t, NewAuditBinaryCataloger())
|
||||
}
|
||||
|
||||
|
||||
@ -25,19 +25,6 @@ func newPackageFromCargoMetadata(m pkg.RustCargoLockEntry, locations ...file.Loc
|
||||
return p
|
||||
}
|
||||
|
||||
func newPackagesFromAudit(location file.Location, versionInfo rustaudit.VersionInfo) []pkg.Package {
|
||||
var pkgs []pkg.Package
|
||||
|
||||
for _, dep := range versionInfo.Packages {
|
||||
p := newPackageFromAudit(&dep, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
|
||||
if pkg.IsValid(&p) && dep.Kind == rustaudit.Runtime {
|
||||
pkgs = append(pkgs, p)
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs
|
||||
}
|
||||
|
||||
func newPackageFromAudit(dep *rustaudit.Package, locations ...file.Location) pkg.Package {
|
||||
p := pkg.Package{
|
||||
Name: dep.Name,
|
||||
@ -46,6 +33,7 @@ func newPackageFromAudit(dep *rustaudit.Package, locations ...file.Location) pkg
|
||||
Language: pkg.Rust,
|
||||
Type: pkg.RustPkg,
|
||||
Locations: file.NewLocationSet(locations...),
|
||||
FoundBy: cargoAuditBinaryCatalogerName,
|
||||
Metadata: pkg.RustBinaryAuditEntry{
|
||||
Name: dep.Name,
|
||||
Version: dep.Version,
|
||||
|
||||
@ -5,9 +5,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
rustaudit "github.com/microsoft/go-rustaudit"
|
||||
"github.com/microsoft/go-rustaudit"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/internal/relationship"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/internal/unionreader"
|
||||
@ -18,6 +19,7 @@ import (
|
||||
// Catalog identifies executables then attempts to read Rust dependency information from them
|
||||
func parseAuditBinary(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
var pkgs []pkg.Package
|
||||
var relationships []artifact.Relationship
|
||||
|
||||
unionReader, err := unionreader.GetUnionReader(reader.ReadCloser)
|
||||
if err != nil {
|
||||
@ -26,10 +28,12 @@ func parseAuditBinary(_ context.Context, _ file.Resolver, _ *generic.Environment
|
||||
|
||||
infos, err := parseAuditBinaryEntry(unionReader, reader.RealPath)
|
||||
for _, versionInfo := range infos {
|
||||
pkgs = append(pkgs, newPackagesFromAudit(reader.Location, versionInfo)...)
|
||||
auditPkgs, auditRelationships := processAuditVersionInfo(reader.Location, versionInfo)
|
||||
pkgs = append(pkgs, auditPkgs...)
|
||||
relationships = append(relationships, auditRelationships...)
|
||||
}
|
||||
|
||||
return pkgs, nil, err
|
||||
return pkgs, relationships, err
|
||||
}
|
||||
|
||||
// scanFile scans file to try to report the Rust crate dependencies
|
||||
@ -61,3 +65,64 @@ func parseAuditBinaryEntry(reader unionreader.UnionReader, filename string) ([]r
|
||||
|
||||
return versionInfos, nil
|
||||
}
|
||||
|
||||
// auditPkgPair is a helper struct to track the original index of the package in the original audit report + the syft package created for it
|
||||
type auditPkgPair struct {
|
||||
pkg *pkg.Package
|
||||
rustPkg rustaudit.Package
|
||||
index int
|
||||
}
|
||||
|
||||
func processAuditVersionInfo(location file.Location, versionInfo rustaudit.VersionInfo) ([]pkg.Package, []artifact.Relationship) {
|
||||
var pkgs []pkg.Package
|
||||
|
||||
// first pass: create packages for all runtime dependencies (skip dev and invalid dependencies)
|
||||
pairsByOgIndex := make(map[int]auditPkgPair)
|
||||
for idx, dep := range versionInfo.Packages {
|
||||
p := newPackageFromAudit(&dep, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
|
||||
pair := auditPkgPair{
|
||||
rustPkg: dep,
|
||||
index: idx,
|
||||
}
|
||||
if pkg.IsValid(&p) && dep.Kind == rustaudit.Runtime {
|
||||
pkgs = append(pkgs, p)
|
||||
pair.pkg = &pkgs[len(pkgs)-1]
|
||||
}
|
||||
pairsByOgIndex[idx] = pair
|
||||
}
|
||||
|
||||
// second pass: create relationships between any packages created
|
||||
// we have all the original audit package indices + info, but not all audit packages will have syft packages.
|
||||
// we need to be careful to not create relationships for packages that were not created.
|
||||
var rels []artifact.Relationship
|
||||
for _, parentPair := range pairsByOgIndex {
|
||||
// the rust-audit report lists dependencies by index from the original version info object. We need to find
|
||||
// the syft packages created for each listed dependency from that original object.
|
||||
for _, ogPkgIndex := range parentPair.rustPkg.Dependencies {
|
||||
if ogPkgIndex >= uint(len(versionInfo.Packages)) {
|
||||
log.WithFields("pkg", parentPair.pkg).Trace("cargo audit dependency index out of range: %d", ogPkgIndex)
|
||||
continue
|
||||
}
|
||||
depPair, ok := pairsByOgIndex[int(ogPkgIndex)]
|
||||
if !ok {
|
||||
log.WithFields("pkg", parentPair.pkg).Trace("cargo audit dependency not found: %d", ogPkgIndex)
|
||||
continue
|
||||
}
|
||||
|
||||
if depPair.pkg == nil || parentPair.pkg == nil {
|
||||
// skip relationships for syft packages that were not created from the original report (no matter the reason)
|
||||
continue
|
||||
}
|
||||
|
||||
rels = append(rels, artifact.Relationship{
|
||||
From: *depPair.pkg,
|
||||
To: *parentPair.pkg,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
relationship.Sort(rels)
|
||||
|
||||
return pkgs, rels
|
||||
}
|
||||
|
||||
96
syft/pkg/cataloger/rust/test-fixtures/image-audit/Cargo.lock
generated
Normal file
96
syft/pkg/cataloger/rust/test-fixtures/image-audit/Cargo.lock
generated
Normal file
@ -0,0 +1,96 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "argh"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219"
|
||||
dependencies = [
|
||||
"argh_derive",
|
||||
"argh_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh_derive"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a"
|
||||
dependencies = [
|
||||
"argh_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh_shared"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hello_world"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"argh",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "hello_world"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
argh = "0.1"
|
||||
@ -1 +1,14 @@
|
||||
FROM docker.io/tofay/hello-rust-auditable:latest@sha256:1d35d1e007180b3f7500aae5e27560697909132ca9a6d480c4c825534c1c47a9
|
||||
FROM rust:1.74.0 AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN cargo install cargo-auditable --locked
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
COPY src ./src
|
||||
RUN cargo fetch
|
||||
RUN cargo auditable build --release
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=builder /app/target/release/hello_world /usr/local/bin/hello_world
|
||||
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
use argh::FromArgs;
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[argh(description = "A simple Hello World CLI application.")]
|
||||
struct Args {
|
||||
#[argh(option, description = "name to greet")]
|
||||
name: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Args = argh::from_env();
|
||||
println!("Hello, {}!", args.name);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user