mirror of
https://github.com/anchore/syft.git
synced 2026-07-04 18:18:26 +02:00
detect Ubuntu Pro/ESM extended support
Mirrors the existing RHEL `ExtendedSupport` detector for Ubuntu so grype can auto-enable its ESM distro channel on Pro/ESM-enabled scans. `findUbuntuFeatures` sets `linux.Release.ExtendedSupport` when the scanned OS is Ubuntu and any of these hold: - an uncommented apt source (classic `.list` or DEB822 `.sources`, or the ubuntu-advantage auth entry) referencing `esm.ubuntu.com` - an enabled `esm-infra`/`esm-apps` service in the ubuntu-advantage `status.json` cache - an installed dpkg package whose version carries an `[~+]esm` pocket suffix (the usual in-image signal, since containers are rarely Pro-attached) The package fallback reads `s.Artifacts.Packages` from the `DetectFeatures` SBOM callback, which runs after package cataloging, so no new plumbing was needed. Conservative by design: plain Ubuntu and disabled/commented ESM evidence stay false. Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
656a4d46d7
commit
ba661e83a7
@ -2,6 +2,8 @@ package os
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
@ -10,6 +12,7 @@ import (
|
||||
"github.com/anchore/syft/internal/sbomsync"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
@ -19,8 +22,11 @@ func DetectFeatures(_ context.Context, resolver file.Resolver, builder sbomsync.
|
||||
return
|
||||
}
|
||||
|
||||
err := findRhelFeatures(resolver, s.Artifacts.LinuxDistribution)
|
||||
if err != nil {
|
||||
if err := findRhelFeatures(resolver, s.Artifacts.LinuxDistribution); err != nil {
|
||||
log.WithFields("error", err, "release", s.Artifacts.LinuxDistribution).Trace("error searching for extended support")
|
||||
}
|
||||
|
||||
if err := findUbuntuFeatures(resolver, s.Artifacts.LinuxDistribution, s.Artifacts.Packages); err != nil {
|
||||
log.WithFields("error", err, "release", s.Artifacts.LinuxDistribution).Trace("error searching for extended support")
|
||||
}
|
||||
})
|
||||
@ -28,6 +34,9 @@ func DetectFeatures(_ context.Context, resolver file.Resolver, builder sbomsync.
|
||||
return nil
|
||||
}
|
||||
|
||||
// rhelEUSPatterns match a RHEL content manifest referencing an extended-update-support (EUS) repo.
|
||||
var rhelEUSPatterns = []*regexp.Regexp{regexp.MustCompile(`baseos-eus`), regexp.MustCompile(`baseos-eus|appstream-eus`)}
|
||||
|
||||
func findRhelFeatures(resolver file.Resolver, release *linux.Release) error {
|
||||
if release == nil || release.ID != "rhel" {
|
||||
return nil
|
||||
@ -37,9 +46,9 @@ func findRhelFeatures(resolver file.Resolver, release *linux.Release) error {
|
||||
return fmt.Errorf("unable to find content manifests: %w", err)
|
||||
}
|
||||
for _, contentManifestFile := range contentManifestFiles {
|
||||
found, err := hasRhelExtendedSupportInContentManifest(resolver, contentManifestFile)
|
||||
found, err := fileMatchesAny(resolver, contentManifestFile, rhelEUSPatterns...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read content manifest from %s: %w", contentManifestFile.String(), err)
|
||||
return fmt.Errorf("unable to read content manifest from %s: %w", contentManifestFile.RealPath, err)
|
||||
}
|
||||
if found {
|
||||
release.ExtendedSupport = true
|
||||
@ -49,13 +58,152 @@ func findRhelFeatures(resolver file.Resolver, release *linux.Release) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func hasRhelExtendedSupportInContentManifest(resolver file.Resolver, contentManifestFile file.Location) (bool, error) {
|
||||
contents, err := resolver.FileContentsByLocation(contentManifestFile)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to read content manifest from %s: %w", contentManifestFile.String(), err)
|
||||
}
|
||||
defer internal.CloseAndLogError(contents, "content-manifest")
|
||||
// Ubuntu Pro (formerly Ubuntu Advantage) is Canonical's subscription that unlocks Expanded Security
|
||||
// Maintenance (ESM): security fixes past a package's standard support window. we detect the two base ESM
|
||||
// streams, esm-infra (the `main` repo) and esm-apps (`universe`), and collapse them into one ExtendedSupport
|
||||
// signal; the infra-vs-apps split is disambiguated by the downstream consumer, not by this boolean.
|
||||
//
|
||||
// the other Pro streams on the same host (esm.ubuntu.com/fips, /fips-updates, /realtime) are deliberately
|
||||
// excluded: they are separate compliance products with their own downstream channels, and a host can run
|
||||
// them with base ESM disabled, so folding them in would be unsound.
|
||||
//
|
||||
// detection is deliberately forgiving: apt/status evidence disappears when ESM is disabled, but an installed
|
||||
// +esmN package is durable proof ESM content is on disk. so ExtendedSupport means "ESM was or is in effect
|
||||
// for this host or its content", not "currently entitled" (mere eligibility, without evidence, is not enough).
|
||||
|
||||
patterns := []*regexp.Regexp{regexp.MustCompile(`baseos-eus`), regexp.MustCompile(`baseos-eus|appstream-eus`)}
|
||||
// esmAptSourcePattern matches an uncommented apt source (classic or DEB822) or auth entry pointing at the
|
||||
// plain ESM streams esm.ubuntu.com/infra or /apps. it deliberately scopes to /(infra|apps) so the other
|
||||
// Pro streams served from the same host (/fips, /fips-updates, /realtime) are never folded into the base
|
||||
// esm channel. the [^#\n]* before the host ensures a leading `#` (comment) can never satisfy the match.
|
||||
var esmAptSourcePattern = regexp.MustCompile(`(?m)^[^#\n]*esm\.ubuntu\.com/(infra|apps)`)
|
||||
|
||||
// esmVersionPattern matches a dpkg version carrying a numbered ESM pocket suffix, e.g. `...+esm1` or
|
||||
// `...~esm2`. the trailing \d scopes this to the ESM pocket and excludes other Pro pockets (e.g. +fips).
|
||||
var esmVersionPattern = regexp.MustCompile(`[~+]esm\d`)
|
||||
|
||||
func findUbuntuFeatures(resolver file.Resolver, release *linux.Release, packages *pkg.Collection) error {
|
||||
if release == nil || release.ID != "ubuntu" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// an uncommented esm.ubuntu.com apt source or an active pro esm service both prove Pro/ESM was enabled.
|
||||
// these are the durable, file-based signals present on attached hosts. a read error in one signal must
|
||||
// not suppress the others, so errors are collected and detection continues to the next signal.
|
||||
var errs error
|
||||
for _, check := range []func() (bool, error){
|
||||
func() (bool, error) { return hasUbuntuESMAptEvidence(resolver) },
|
||||
func() (bool, error) { return hasActiveUbuntuESMService(resolver) },
|
||||
} {
|
||||
found, err := check()
|
||||
if err != nil {
|
||||
errs = errors.Join(errs, err)
|
||||
continue
|
||||
}
|
||||
if found {
|
||||
release.ExtendedSupport = true
|
||||
return errs
|
||||
}
|
||||
}
|
||||
|
||||
// fallback for images (typically not pro-attached): an installed package whose version carries an
|
||||
// +esm/~esm suffix was pulled from an ESM pocket, so ESM was in effect when it was installed.
|
||||
if hasInstalledESMPackage(packages) {
|
||||
release.ExtendedSupport = true
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// hasUbuntuESMAptEvidence reports whether any apt source (classic .list or DEB822 .sources) or auth entry
|
||||
// references esm.ubuntu.com via an uncommented line.
|
||||
func hasUbuntuESMAptEvidence(resolver file.Resolver) (bool, error) {
|
||||
// apt source files live in a directory (classic .list or DEB822 .sources), the credentials file is a fixed path.
|
||||
sourceLocations, err := resolver.FilesByGlob("/etc/apt/sources.list.d/*")
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to find apt esm sources: %w", err)
|
||||
}
|
||||
authLocations, err := resolver.FilesByPath("/etc/apt/auth.conf.d/90ubuntu-advantage")
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to find apt esm auth: %w", err)
|
||||
}
|
||||
|
||||
// ponytail: a DEB822 source with `Enabled: no` would still match; the pro client removes/comments the
|
||||
// file on disable rather than toggling that key, so this is an accepted false-positive ceiling. the
|
||||
// auth.conf.d entry is deleted by the pro client on disable, so it is a durable positive-only signal.
|
||||
for _, location := range append(sourceLocations, authLocations...) {
|
||||
match, err := fileMatchesAny(resolver, location, esmAptSourcePattern)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if match {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// hasActiveUbuntuESMService reports whether the ubuntu-advantage/pro status cache shows an enabled esm service.
|
||||
func hasActiveUbuntuESMService(resolver file.Resolver) (bool, error) {
|
||||
locations, err := resolver.FilesByPath("/var/lib/ubuntu-advantage/status.json")
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to find ubuntu-advantage status: %w", err)
|
||||
}
|
||||
for _, location := range locations {
|
||||
enabled, err := hasEnabledESMServiceInStatus(resolver, location)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if enabled {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func hasEnabledESMServiceInStatus(resolver file.Resolver, location file.Location) (bool, error) {
|
||||
contents, err := resolver.FileContentsByLocation(location)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to read ubuntu-advantage status from %s: %w", location.RealPath, err)
|
||||
}
|
||||
defer internal.CloseAndLogError(contents, location.RealPath)
|
||||
|
||||
var status struct {
|
||||
Services []struct {
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
} `json:"services"`
|
||||
}
|
||||
if err := json.NewDecoder(contents).Decode(&status); err != nil {
|
||||
return false, fmt.Errorf("unable to parse ubuntu-advantage status from %s: %w", location.RealPath, err)
|
||||
}
|
||||
|
||||
// pro status values are enabled/disabled/n-a/warning/—; only "enabled" proves the stream is active.
|
||||
// warning/expired states are intentionally excluded here and left to the apt-source and installed-package signals.
|
||||
for _, svc := range status.Services {
|
||||
if (svc.Name == "esm-infra" || svc.Name == "esm-apps") && svc.Status == "enabled" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// hasInstalledESMPackage reports whether any installed dpkg package version carries an ESM pocket suffix.
|
||||
func hasInstalledESMPackage(packages *pkg.Collection) bool {
|
||||
if packages == nil {
|
||||
return false
|
||||
}
|
||||
for p := range packages.Enumerate(pkg.DebPkg) {
|
||||
if esmVersionPattern.MatchString(p.Version) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func fileMatchesAny(resolver file.Resolver, location file.Location, patterns ...*regexp.Regexp) (bool, error) {
|
||||
contents, err := resolver.FileContentsByLocation(location)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unable to read %s: %w", location.RealPath, err)
|
||||
}
|
||||
defer internal.CloseAndLogError(contents, location.RealPath)
|
||||
return internal.MatchAnyFromReader(contents, patterns...)
|
||||
}
|
||||
|
||||
@ -2,6 +2,11 @@ package os_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
stdos "os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -11,7 +16,9 @@ import (
|
||||
"github.com/anchore/syft/internal/sbomsync"
|
||||
"github.com/anchore/syft/internal/task"
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
@ -99,3 +106,210 @@ func Test_EnvironmentTask(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_findUbuntuFeatures(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
dir string
|
||||
releaseID string
|
||||
packages []pkg.Package
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "esm apt source present",
|
||||
dir: "testdata/ubuntu_esm_apt",
|
||||
releaseID: "ubuntu",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "esm apt source in DEB822 .sources format",
|
||||
dir: "testdata/ubuntu_esm_deb822",
|
||||
releaseID: "ubuntu",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "esm evidence in apt auth.conf.d",
|
||||
dir: "testdata/ubuntu_esm_authconf",
|
||||
releaseID: "ubuntu",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "active esm service in ubuntu-advantage status",
|
||||
dir: "testdata/ubuntu_esm_status",
|
||||
releaseID: "ubuntu",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "only esm-infra enabled (esm-apps disabled)",
|
||||
dir: "testdata/ubuntu_esm_infra_only",
|
||||
releaseID: "ubuntu",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "malformed status.json does not panic or match",
|
||||
dir: "testdata/ubuntu_esm_malformed",
|
||||
releaseID: "ubuntu",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "installed +esm package version",
|
||||
dir: "testdata/ubuntu_plain",
|
||||
releaseID: "ubuntu",
|
||||
packages: []pkg.Package{
|
||||
{Name: "openssl", Version: "1.1.1f-1ubuntu2.19+esm1", Type: pkg.DebPkg},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "installed ~esm package version",
|
||||
dir: "testdata/ubuntu_plain",
|
||||
releaseID: "ubuntu",
|
||||
packages: []pkg.Package{
|
||||
{Name: "libcap2", Version: "1:2.32-1ubuntu0.1~esm1", Type: pkg.DebPkg},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "plain ubuntu with no esm evidence",
|
||||
dir: "testdata/ubuntu_plain",
|
||||
releaseID: "ubuntu",
|
||||
packages: []pkg.Package{
|
||||
{Name: "openssl", Version: "1.1.1f-1ubuntu2.19", Type: pkg.DebPkg},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "commented esm source and disabled esm service",
|
||||
dir: "testdata/ubuntu_esm_disabled",
|
||||
releaseID: "ubuntu",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "esm disabled but +esm package remains installed",
|
||||
dir: "testdata/ubuntu_esm_disabled",
|
||||
releaseID: "ubuntu",
|
||||
packages: []pkg.Package{
|
||||
{Name: "openssl", Version: "1.1.1f-1ubuntu2.19+esm1", Type: pkg.DebPkg},
|
||||
},
|
||||
expected: true, // durable proof: ESM content is on disk even though the channel is now off
|
||||
},
|
||||
{
|
||||
name: "fips-only pro host is not plain esm",
|
||||
dir: "testdata/ubuntu_fips_only",
|
||||
releaseID: "ubuntu",
|
||||
expected: false, // esm.ubuntu.com/fips must not be folded into the base esm channel
|
||||
},
|
||||
{
|
||||
name: "non-ubuntu is unaffected by esm evidence",
|
||||
dir: "testdata/ubuntu_esm_apt",
|
||||
releaseID: "debian",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "non-ubuntu is unaffected by esm package version",
|
||||
dir: "testdata/ubuntu_plain",
|
||||
releaseID: "debian",
|
||||
packages: []pkg.Package{
|
||||
{Name: "openssl", Version: "1.1.1f-1ubuntu2.19+esm1", Type: pkg.DebPkg},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
resolver := fixtureResolverForDir(t, test.dir)
|
||||
|
||||
s := sbom.SBOM{}
|
||||
s.Artifacts.LinuxDistribution = &linux.Release{ID: test.releaseID}
|
||||
s.Artifacts.Packages = pkg.NewCollection(test.packages...)
|
||||
|
||||
err := os.DetectFeatures(context.Background(), resolver, sbomsync.NewBuilder(&s))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, test.expected, s.Artifacts.LinuxDistribution.ExtendedSupport)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// a read error in the apt-source signal must not suppress the ubuntu-advantage status signal; the three
|
||||
// signals are meant to be independent fallbacks.
|
||||
func Test_findUbuntuFeatures_signalErrorDoesNotSuppressOthers(t *testing.T) {
|
||||
resolver := errOnGlobResolver{
|
||||
fixtureResolver: fixtureResolverForDir(t, "testdata/ubuntu_esm_status").(fixtureResolver),
|
||||
errOnGlob: "/etc/apt/sources.list.d/*",
|
||||
}
|
||||
|
||||
s := sbom.SBOM{}
|
||||
s.Artifacts.LinuxDistribution = &linux.Release{ID: "ubuntu"}
|
||||
s.Artifacts.Packages = pkg.NewCollection()
|
||||
|
||||
require.NoError(t, os.DetectFeatures(context.Background(), resolver, sbomsync.NewBuilder(&s)))
|
||||
|
||||
// the apt glob errors, but the status.json signal (esm-infra enabled) should still be consulted
|
||||
require.True(t, s.Artifacts.LinuxDistribution.ExtendedSupport)
|
||||
}
|
||||
|
||||
// errOnGlobResolver injects a failure for a specific glob to simulate an unreadable apt directory.
|
||||
type errOnGlobResolver struct {
|
||||
fixtureResolver
|
||||
errOnGlob string
|
||||
}
|
||||
|
||||
func (r errOnGlobResolver) FilesByGlob(patterns ...string) ([]file.Location, error) {
|
||||
if slices.Contains(patterns, r.errOnGlob) {
|
||||
return nil, stdos.ErrPermission
|
||||
}
|
||||
return r.fixtureResolver.FilesByGlob(patterns...)
|
||||
}
|
||||
|
||||
// fixtureResolver maps in-image logical paths to on-disk fixture files so DetectFeatures can be driven
|
||||
// without building a container image.
|
||||
type fixtureResolver struct {
|
||||
file.Resolver // unused methods; nil is fine since only the three below are called
|
||||
files map[string]string
|
||||
}
|
||||
|
||||
func (r fixtureResolver) FilesByGlob(patterns ...string) ([]file.Location, error) {
|
||||
var out []file.Location
|
||||
for logical := range r.files {
|
||||
for _, p := range patterns {
|
||||
if ok, _ := path.Match(p, logical); ok {
|
||||
out = append(out, file.NewLocation(logical))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (r fixtureResolver) FilesByPath(paths ...string) ([]file.Location, error) {
|
||||
var out []file.Location
|
||||
for _, p := range paths {
|
||||
if _, ok := r.files[p]; ok {
|
||||
out = append(out, file.NewLocation(p))
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (r fixtureResolver) FileContentsByLocation(l file.Location) (io.ReadCloser, error) {
|
||||
return stdos.Open(r.files[l.RealPath])
|
||||
}
|
||||
|
||||
func fixtureResolverForDir(t *testing.T, dir string) file.Resolver {
|
||||
t.Helper()
|
||||
files := map[string]string{}
|
||||
require.NoError(t, filepath.WalkDir(dir, func(p string, d stdos.DirEntry, err error) error {
|
||||
if err != nil || d.IsDir() {
|
||||
return err
|
||||
}
|
||||
rel, err := filepath.Rel(dir, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
files["/"+filepath.ToSlash(rel)] = p
|
||||
return nil
|
||||
}))
|
||||
return fixtureResolver{files: files}
|
||||
}
|
||||
|
||||
6
internal/os/testdata/ubuntu_esm_apt/etc/apt/sources.list.d/ubuntu-esm-infra.list
vendored
Normal file
6
internal/os/testdata/ubuntu_esm_apt/etc/apt/sources.list.d/ubuntu-esm-infra.list
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# Written by ubuntu-advantage-tools
|
||||
deb https://esm.ubuntu.com/infra/ubuntu focal-infra-security main
|
||||
# deb-src https://esm.ubuntu.com/infra/ubuntu focal-infra-security main
|
||||
|
||||
deb https://esm.ubuntu.com/infra/ubuntu focal-infra-updates main
|
||||
# deb-src https://esm.ubuntu.com/infra/ubuntu focal-infra-updates main
|
||||
2
internal/os/testdata/ubuntu_esm_authconf/etc/apt/auth.conf.d/90ubuntu-advantage
vendored
Normal file
2
internal/os/testdata/ubuntu_esm_authconf/etc/apt/auth.conf.d/90ubuntu-advantage
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
machine esm.ubuntu.com/infra/ubuntu/ login bearer password DUMMYTOKENREDACTED # ubuntu-pro-client
|
||||
machine esm.ubuntu.com/apps/ubuntu/ login bearer password DUMMYTOKENREDACTED # ubuntu-pro-client
|
||||
5
internal/os/testdata/ubuntu_esm_deb822/etc/apt/sources.list.d/ubuntu-esm-infra.sources
vendored
Normal file
5
internal/os/testdata/ubuntu_esm_deb822/etc/apt/sources.list.d/ubuntu-esm-infra.sources
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
Types: deb
|
||||
URIs: https://esm.ubuntu.com/infra/ubuntu
|
||||
Suites: noble-infra-security noble-infra-updates
|
||||
Components: main
|
||||
Signed-By: /usr/share/keyrings/ubuntu-pro-esm-infra-keyring.gpg
|
||||
3
internal/os/testdata/ubuntu_esm_disabled/etc/apt/sources.list.d/ubuntu-esm-infra.list
vendored
Normal file
3
internal/os/testdata/ubuntu_esm_disabled/etc/apt/sources.list.d/ubuntu-esm-infra.list
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Written by ubuntu-advantage-tools
|
||||
# deb https://esm.ubuntu.com/infra/ubuntu focal-infra-security main
|
||||
# deb-src https://esm.ubuntu.com/infra/ubuntu focal-infra-security main
|
||||
18
internal/os/testdata/ubuntu_esm_disabled/var/lib/ubuntu-advantage/status.json
vendored
Normal file
18
internal/os/testdata/ubuntu_esm_disabled/var/lib/ubuntu-advantage/status.json
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"_schema_version": "0.1",
|
||||
"attached": true,
|
||||
"services": [
|
||||
{
|
||||
"name": "esm-apps",
|
||||
"available": "yes",
|
||||
"entitled": "yes",
|
||||
"status": "disabled"
|
||||
},
|
||||
{
|
||||
"name": "esm-infra",
|
||||
"available": "yes",
|
||||
"entitled": "yes",
|
||||
"status": "disabled"
|
||||
}
|
||||
]
|
||||
}
|
||||
21
internal/os/testdata/ubuntu_esm_infra_only/var/lib/ubuntu-advantage/status.json
vendored
Normal file
21
internal/os/testdata/ubuntu_esm_infra_only/var/lib/ubuntu-advantage/status.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"_schema_version": "0.1",
|
||||
"attached": true,
|
||||
"execution_status": "success",
|
||||
"services": [
|
||||
{
|
||||
"name": "esm-apps",
|
||||
"description": "Expanded Security Maintenance for Applications",
|
||||
"available": "yes",
|
||||
"entitled": "yes",
|
||||
"status": "disabled"
|
||||
},
|
||||
{
|
||||
"name": "esm-infra",
|
||||
"description": "Expanded Security Maintenance for Infrastructure",
|
||||
"available": "yes",
|
||||
"entitled": "yes",
|
||||
"status": "enabled"
|
||||
}
|
||||
]
|
||||
}
|
||||
1
internal/os/testdata/ubuntu_esm_malformed/var/lib/ubuntu-advantage/status.json
vendored
Normal file
1
internal/os/testdata/ubuntu_esm_malformed/var/lib/ubuntu-advantage/status.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ this is not valid json
|
||||
28
internal/os/testdata/ubuntu_esm_status/var/lib/ubuntu-advantage/status.json
vendored
Normal file
28
internal/os/testdata/ubuntu_esm_status/var/lib/ubuntu-advantage/status.json
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"_doc": "Content provided in json response is currently considered Experimental and may change",
|
||||
"_schema_version": "0.1",
|
||||
"attached": true,
|
||||
"services": [
|
||||
{
|
||||
"name": "esm-apps",
|
||||
"description": "Expanded Security Maintenance for Applications",
|
||||
"available": "yes",
|
||||
"entitled": "yes",
|
||||
"status": "enabled"
|
||||
},
|
||||
{
|
||||
"name": "esm-infra",
|
||||
"description": "Expanded Security Maintenance for Infrastructure",
|
||||
"available": "yes",
|
||||
"entitled": "yes",
|
||||
"status": "enabled"
|
||||
},
|
||||
{
|
||||
"name": "fips",
|
||||
"description": "NIST-certified FIPS crypto packages",
|
||||
"available": "no",
|
||||
"entitled": "no",
|
||||
"status": "n/a"
|
||||
}
|
||||
]
|
||||
}
|
||||
3
internal/os/testdata/ubuntu_fips_only/etc/apt/sources.list.d/ubuntu-fips.list
vendored
Normal file
3
internal/os/testdata/ubuntu_fips_only/etc/apt/sources.list.d/ubuntu-fips.list
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Written by ubuntu-pro-client
|
||||
deb https://esm.ubuntu.com/fips/ubuntu focal main
|
||||
# deb-src https://esm.ubuntu.com/fips/ubuntu focal main
|
||||
28
internal/os/testdata/ubuntu_fips_only/var/lib/ubuntu-advantage/status.json
vendored
Normal file
28
internal/os/testdata/ubuntu_fips_only/var/lib/ubuntu-advantage/status.json
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"_schema_version": "0.1",
|
||||
"attached": true,
|
||||
"execution_status": "success",
|
||||
"services": [
|
||||
{
|
||||
"name": "esm-apps",
|
||||
"description": "Expanded Security Maintenance for Applications",
|
||||
"available": "yes",
|
||||
"entitled": "yes",
|
||||
"status": "disabled"
|
||||
},
|
||||
{
|
||||
"name": "esm-infra",
|
||||
"description": "Expanded Security Maintenance for Infrastructure",
|
||||
"available": "yes",
|
||||
"entitled": "yes",
|
||||
"status": "disabled"
|
||||
},
|
||||
{
|
||||
"name": "fips",
|
||||
"description": "NIST-certified FIPS crypto packages",
|
||||
"available": "yes",
|
||||
"entitled": "yes",
|
||||
"status": "enabled"
|
||||
}
|
||||
]
|
||||
}
|
||||
5
internal/os/testdata/ubuntu_plain/etc/apt/sources.list.d/ubuntu.sources
vendored
Normal file
5
internal/os/testdata/ubuntu_plain/etc/apt/sources.list.d/ubuntu.sources
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
Types: deb
|
||||
URIs: http://archive.ubuntu.com/ubuntu/
|
||||
Suites: noble noble-updates noble-backports
|
||||
Components: main restricted universe multiverse
|
||||
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
|
||||
Loading…
x
Reference in New Issue
Block a user