deps: update images to v0.24.0

Update the images dependency to v0.24.0

Includes the addition of the new FDO option
'di_mfg_string_type_mac_iface'.
This commit is contained in:
Achilleas Koutsou 2023-12-12 20:10:54 +01:00
parent c6aa7d88d2
commit 6d57e01506
69 changed files with 765 additions and 261 deletions

View file

@ -45,8 +45,9 @@ type FDOCustomization struct {
DiunPubKeyInsecure string `json:"diun_pub_key_insecure,omitempty" toml:"diun_pub_key_insecure,omitempty"`
// This is the output of:
// echo "sha256:$(openssl x509 -fingerprint -sha256 -noout -in diun_cert.pem | cut -d"=" -f2 | sed 's/://g')"
DiunPubKeyHash string `json:"diun_pub_key_hash,omitempty" toml:"diun_pub_key_hash,omitempty"`
DiunPubKeyRootCerts string `json:"diun_pub_key_root_certs,omitempty" toml:"diun_pub_key_root_certs,omitempty"`
DiunPubKeyHash string `json:"diun_pub_key_hash,omitempty" toml:"diun_pub_key_hash,omitempty"`
DiunPubKeyRootCerts string `json:"diun_pub_key_root_certs,omitempty" toml:"diun_pub_key_root_certs,omitempty"`
DiMfgStringTypeMacIface string `json:"di_mfg_string_type_mac_iface,omitempty" toml:"di_mfg_string_type_mac_iface,omitempty"`
}
type KernelCustomization struct {

View file

@ -11,8 +11,8 @@ import (
"strings"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/pathpolicy"
"github.com/osbuild/images/pkg/customizations/fsnode"
)
// validateModeString checks that the given string is a valid mode octal number

View file

@ -7,23 +7,24 @@ import (
"strings"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/rpmmd"
)
type RepositoryCustomization struct {
Id string `json:"id" toml:"id"`
BaseURLs []string `json:"baseurls,omitempty" toml:"baseurls,omitempty"`
GPGKeys []string `json:"gpgkeys,omitempty" toml:"gpgkeys,omitempty"`
Metalink string `json:"metalink,omitempty" toml:"metalink,omitempty"`
Mirrorlist string `json:"mirrorlist,omitempty" toml:"mirrorlist,omitempty"`
Name string `json:"name,omitempty" toml:"name,omitempty"`
Priority *int `json:"priority,omitempty" toml:"priority,omitempty"`
Enabled *bool `json:"enabled,omitempty" toml:"enabled,omitempty"`
GPGCheck *bool `json:"gpgcheck,omitempty" toml:"gpgcheck,omitempty"`
RepoGPGCheck *bool `json:"repo_gpgcheck,omitempty" toml:"repo_gpgcheck,omitempty"`
SSLVerify *bool `json:"sslverify,omitempty" toml:"sslverify,omitempty"`
Filename string `json:"filename,omitempty" toml:"filename,omitempty"`
Id string `json:"id" toml:"id"`
BaseURLs []string `json:"baseurls,omitempty" toml:"baseurls,omitempty"`
GPGKeys []string `json:"gpgkeys,omitempty" toml:"gpgkeys,omitempty"`
Metalink string `json:"metalink,omitempty" toml:"metalink,omitempty"`
Mirrorlist string `json:"mirrorlist,omitempty" toml:"mirrorlist,omitempty"`
Name string `json:"name,omitempty" toml:"name,omitempty"`
Priority *int `json:"priority,omitempty" toml:"priority,omitempty"`
Enabled *bool `json:"enabled,omitempty" toml:"enabled,omitempty"`
GPGCheck *bool `json:"gpgcheck,omitempty" toml:"gpgcheck,omitempty"`
RepoGPGCheck *bool `json:"repo_gpgcheck,omitempty" toml:"repo_gpgcheck,omitempty"`
SSLVerify *bool `json:"sslverify,omitempty" toml:"sslverify,omitempty"`
ModuleHotfixes *bool `json:"module_hotfixes,omitempty" toml:"module_hotfixes,omitempty"`
Filename string `json:"filename,omitempty" toml:"filename,omitempty"`
}
const repoFilenameRegex = "^[\\w.-]{1,250}\\.repo$"
@ -117,16 +118,17 @@ func (repo RepositoryCustomization) customRepoToRepoConfig() rpmmd.RepoConfig {
copy(keys, repo.GPGKeys)
repoConfig := rpmmd.RepoConfig{
Id: repo.Id,
BaseURLs: urls,
GPGKeys: keys,
Name: repo.Name,
Metalink: repo.Metalink,
MirrorList: repo.Mirrorlist,
CheckGPG: repo.GPGCheck,
CheckRepoGPG: repo.RepoGPGCheck,
Priority: repo.Priority,
Enabled: repo.Enabled,
Id: repo.Id,
BaseURLs: urls,
GPGKeys: keys,
Name: repo.Name,
Metalink: repo.Metalink,
MirrorList: repo.Mirrorlist,
CheckGPG: repo.GPGCheck,
CheckRepoGPG: repo.RepoGPGCheck,
Priority: repo.Priority,
ModuleHotfixes: repo.ModuleHotfixes,
Enabled: repo.Enabled,
}
if repo.SSLVerify != nil {

View file

@ -0,0 +1,16 @@
package fdo
import "github.com/osbuild/images/pkg/blueprint"
type Options struct {
ManufacturingServerURL string
DiunPubKeyInsecure string
DiunPubKeyHash string
DiunPubKeyRootCerts string
DiMfgStringTypeMacIface string
}
func FromBP(bpFDO blueprint.FDOCustomization) *Options {
fdo := Options(bpFDO)
return &fdo
}

View file

@ -0,0 +1,34 @@
package fsnode
import "os"
type Directory struct {
baseFsNode
ensureParentDirs bool
}
func (d *Directory) IsDir() bool {
return true
}
func (d *Directory) EnsureParentDirs() bool {
if d == nil {
return false
}
return d.ensureParentDirs
}
// NewDirectory creates a new directory with the given path, mode, user and group.
// user and group can be either a string (user name/group name), an int64 (UID/GID) or nil.
func NewDirectory(path string, mode *os.FileMode, user interface{}, group interface{}, ensureParentDirs bool) (*Directory, error) {
baseNode, err := newBaseFsNode(path, mode, user, group)
if err != nil {
return nil, err
}
return &Directory{
baseFsNode: *baseNode,
ensureParentDirs: ensureParentDirs,
}, nil
}

View file

@ -0,0 +1,36 @@
package fsnode
import (
"os"
)
type File struct {
baseFsNode
data []byte
}
func (f *File) IsDir() bool {
return false
}
func (f *File) Data() []byte {
if f == nil {
return nil
}
return f.data
}
// NewFile creates a new file with the given path, data, mode, user and group.
// user and group can be either a string (user name/group name), an int64 (UID/GID) or nil.
func NewFile(path string, mode *os.FileMode, user interface{}, group interface{}, data []byte) (*File, error) {
baseNode, err := newBaseFsNode(path, mode, user, group)
if err != nil {
return nil, err
}
return &File{
baseFsNode: *baseNode,
data: data,
}, nil
}

View file

@ -0,0 +1,133 @@
package fsnode
import (
"fmt"
"os"
"path"
"regexp"
)
const usernameRegex = `^[A-Za-z0-9_.][A-Za-z0-9_.-]{0,31}$`
const groupnameRegex = `^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$`
type FsNode interface {
Path() string
Mode() *os.FileMode
// User can return either a string (user name/group name), an int64 (UID/GID) or nil
User() interface{}
// Group can return either a string (user name/group name), an int64 (UID/GID) or nil
Group() interface{}
IsDir() bool
}
type baseFsNode struct {
path string
mode *os.FileMode
user interface{}
group interface{}
}
func (f *baseFsNode) Path() string {
if f == nil {
return ""
}
return f.path
}
func (f *baseFsNode) Mode() *os.FileMode {
if f == nil {
return nil
}
return f.mode
}
// User can return either a string (user name) or an int64 (UID)
func (f *baseFsNode) User() interface{} {
if f == nil {
return nil
}
return f.user
}
// Group can return either a string (group name) or an int64 (GID)
func (f *baseFsNode) Group() interface{} {
if f == nil {
return nil
}
return f.group
}
func newBaseFsNode(path string, mode *os.FileMode, user interface{}, group interface{}) (*baseFsNode, error) {
node := &baseFsNode{
path: path,
mode: mode,
user: user,
group: group,
}
err := node.validate()
if err != nil {
return nil, err
}
return node, nil
}
func (f *baseFsNode) validate() error {
// Check that the path is valid
if f.path == "" {
return fmt.Errorf("path must not be empty")
}
if f.path[0] != '/' {
return fmt.Errorf("path must be absolute")
}
if f.path[len(f.path)-1] == '/' {
return fmt.Errorf("path must not end with a slash")
}
if f.path != path.Clean(f.path) {
return fmt.Errorf("path must be canonical")
}
// Check that the mode is valid
if f.mode != nil && *f.mode&os.ModeType != 0 {
return fmt.Errorf("mode must not contain file type bits")
}
// Check that the user and group are valid
switch user := f.user.(type) {
case string:
nameRegex := regexp.MustCompile(usernameRegex)
if !nameRegex.MatchString(user) {
return fmt.Errorf("user name %q doesn't conform to validating regex (%s)", user, nameRegex.String())
}
case int64:
if user < 0 {
return fmt.Errorf("user ID must be non-negative")
}
case nil:
// user is not set
default:
return fmt.Errorf("user must be either a string or an int64, got %T", user)
}
switch group := f.group.(type) {
case string:
nameRegex := regexp.MustCompile(groupnameRegex)
if !nameRegex.MatchString(group) {
return fmt.Errorf("group name %q doesn't conform to validating regex (%s)", group, nameRegex.String())
}
case int64:
if group < 0 {
return fmt.Errorf("group ID must be non-negative")
}
case nil:
// group is not set
default:
return fmt.Errorf("group must be either a string or an int64, got %T", group)
}
return nil
}
func (f *baseFsNode) IsDir() bool {
panic("IsDir() called on baseFsNode")
}

View file

@ -0,0 +1,31 @@
package ignition
import (
"encoding/base64"
"errors"
"github.com/osbuild/images/pkg/blueprint"
)
type FirstBootOptions struct {
ProvisioningURL string
}
func FirstbootOptionsFromBP(bpIgnitionFirstboot blueprint.FirstBootIgnitionCustomization) *FirstBootOptions {
ignition := FirstBootOptions(bpIgnitionFirstboot)
return &ignition
}
type EmbeddedOptions struct {
Config string
}
func EmbeddedOptionsFromBP(bpIgnitionEmbedded blueprint.EmbeddedIgnitionCustomization) (*EmbeddedOptions, error) {
decodedConfig, err := base64.StdEncoding.DecodeString(bpIgnitionEmbedded.Config)
if err != nil {
return nil, errors.New("can't decode Ignition config")
}
return &EmbeddedOptions{
Config: string(decodedConfig),
}, nil
}

View file

@ -0,0 +1,91 @@
package oscap
import (
"fmt"
"path/filepath"
"strings"
"github.com/osbuild/images/pkg/customizations/fsnode"
)
type Profile string
func (p Profile) String() string {
return string(p)
}
const (
AnssiBp28Enhanced Profile = "xccdf_org.ssgproject.content_profile_anssi_bp28_enhanced"
AnssiBp28High Profile = "xccdf_org.ssgproject.content_profile_anssi_bp28_high"
AnssiBp28Intermediary Profile = "xccdf_org.ssgproject.content_profile_anssi_bp28_intermediary"
AnssiBp28Minimal Profile = "xccdf_org.ssgproject.content_profile_anssi_bp28_minimal"
Cis Profile = "xccdf_org.ssgproject.content_profile_cis"
CisServerL1 Profile = "xccdf_org.ssgproject.content_profile_cis_server_l1"
CisWorkstationL1 Profile = "xccdf_org.ssgproject.content_profile_cis_workstation_l1"
CisWorkstationL2 Profile = "xccdf_org.ssgproject.content_profile_cis_workstation_l2"
Cui Profile = "xccdf_org.ssgproject.content_profile_cui"
E8 Profile = "xccdf_org.ssgproject.content_profile_e8"
Hippa Profile = "xccdf_org.ssgproject.content_profile_hipaa"
IsmO Profile = "xccdf_org.ssgproject.content_profile_ism_o"
Ospp Profile = "xccdf_org.ssgproject.content_profile_ospp"
PciDss Profile = "xccdf_org.ssgproject.content_profile_pci-dss"
Standard Profile = "xccdf_org.ssgproject.content_profile_standard"
Stig Profile = "xccdf_org.ssgproject.content_profile_stig"
StigGui Profile = "xccdf_org.ssgproject.content_profile_stig_gui"
// datastream fallbacks
defaultFedoraDatastream string = "/usr/share/xml/scap/ssg/content/ssg-fedora-ds.xml"
defaultCentos8Datastream string = "/usr/share/xml/scap/ssg/content/ssg-centos8-ds.xml"
defaultCentos9Datastream string = "/usr/share/xml/scap/ssg/content/ssg-cs9-ds.xml"
defaultRHEL8Datastream string = "/usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml"
defaultRHEL9Datastream string = "/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml"
// tailoring directory path
tailoringDirPath string = "/usr/share/xml/osbuild-openscap-data"
)
func DefaultFedoraDatastream() string {
return defaultFedoraDatastream
}
func DefaultRHEL8Datastream(isRHEL bool) string {
if isRHEL {
return defaultRHEL8Datastream
}
return defaultCentos8Datastream
}
func DefaultRHEL9Datastream(isRHEL bool) string {
if isRHEL {
return defaultRHEL9Datastream
}
return defaultCentos9Datastream
}
func IsProfileAllowed(profile string, allowlist []Profile) bool {
for _, a := range allowlist {
if a.String() == profile {
return true
}
// this enables a user to specify
// the full profile or the short
// profile id
if strings.HasSuffix(a.String(), profile) {
return true
}
}
return false
}
func GetTailoringFile(profile string) (string, string, *fsnode.Directory, error) {
newProfile := fmt.Sprintf("%s_osbuild_tailoring", profile)
path := filepath.Join(tailoringDirPath, "tailoring.xml")
tailoringDir, err := fsnode.NewDirectory(tailoringDirPath, nil, nil, nil, true)
if err != nil {
return "", "", nil, err
}
return newProfile, path, tailoringDir, nil
}

View file

@ -0,0 +1,11 @@
package shell
type EnvironmentVariable struct {
Key string
Value string
}
type InitFile struct {
Filename string
Variables []EnvironmentVariable
}

View file

@ -0,0 +1,40 @@
package users
import "github.com/osbuild/images/pkg/blueprint"
type User struct {
Name string
Description *string
Password *string
Key *string
Home *string
Shell *string
Groups []string
UID *int
GID *int
}
type Group struct {
Name string
GID *int
}
func UsersFromBP(userCustomizations []blueprint.UserCustomization) []User {
users := make([]User, len(userCustomizations))
for idx := range userCustomizations {
// currently, they have the same structure, so we convert directly
// this will fail to compile as soon as one of the two changes
users[idx] = User(userCustomizations[idx])
}
return users
}
func GroupsFromBP(groupCustomizations []blueprint.GroupCustomization) []Group {
groups := make([]Group, len(groupCustomizations))
for idx := range groupCustomizations {
// currently, they have the same structure, so we convert directly
// this will fail to compile as soon as one of the two changes
groups[idx] = Group(groupCustomizations[idx])
}
return groups
}

View file

@ -5,6 +5,8 @@ import (
"math/rand"
"github.com/google/uuid"
"github.com/osbuild/images/internal/common"
)
type Argon2id struct {
@ -96,5 +98,5 @@ func (lc *LUKSContainer) MetadataSize() uint64 {
}
// 16 MiB is the default size for the LUKS2 header
return 16 * 1024 * 1024
return 16 * common.MiB
}

View file

@ -138,7 +138,7 @@ func (vg *LVMVolumeGroup) MetadataSize() uint64 {
// of the metadata and its location and thus the start of the physical
// extent. For now we assume the default which results in a start of
// the physical extent 1 MiB
return 1024 * 1024
return 1 * common.MiB
}
type LVMLogicalVolume struct {

View file

@ -7,6 +7,7 @@ import (
"github.com/google/uuid"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/blueprint"
)
@ -630,7 +631,7 @@ func (pt *PartitionTable) ensureLVM() error {
// we need a /boot partition to boot LVM, ensure one exists
bootPath := entityPath(pt, "/boot")
if bootPath == nil {
_, err := pt.CreateMountpoint("/boot", 512*1024*1024)
_, err := pt.CreateMountpoint("/boot", 512*common.MiB)
if err != nil {
return err

View file

@ -8,9 +8,9 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/oscap"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/platform"
@ -38,6 +38,9 @@ const (
// Added kernel command line options for ami, qcow2, openstack, vhd and vmdk types
cloudKernelOptions = "ro no_timer_check console=ttyS0,115200n8 biosdevname=0 net.ifnames=0"
// location for saving openscap remediation data
oscapDataDir = "/oscap_data"
)
var (

View file

@ -5,14 +5,14 @@ import (
"math/rand"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/fdo"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/ignition"
"github.com/osbuild/images/internal/oscap"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fdo"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/ignition"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/image"
"github.com/osbuild/images/pkg/manifest"
@ -165,14 +165,25 @@ func osCustomizations(
if t.rpmOstree {
panic("unexpected oscap options for ostree image type")
}
// although the osbuild stage will create this directory,
// it's probably better to ensure that it is created here
dataDirNode, err := fsnode.NewDirectory(oscapDataDir, nil, nil, nil, true)
if err != nil {
panic("unexpected error creating OpenSCAP data directory")
}
osc.Directories = append(osc.Directories, dataDirNode)
var datastream = oscapConfig.DataStream
if datastream == "" {
datastream = oscap.DefaultFedoraDatastream()
}
oscapStageOptions := osbuild.OscapConfig{
Datastream: datastream,
ProfileID: oscapConfig.ProfileID,
Datastream: datastream,
ProfileID: oscapConfig.ProfileID,
Compression: true,
}
if oscapConfig.Tailoring != nil {
@ -182,14 +193,15 @@ func osCustomizations(
}
tailoringOptions := osbuild.OscapAutotailorConfig{
NewProfile: newProfile,
Datastream: datastream,
ProfileID: oscapConfig.ProfileID,
Selected: oscapConfig.Tailoring.Selected,
Unselected: oscapConfig.Tailoring.Unselected,
NewProfile: newProfile,
}
osc.OpenSCAPTailorConfig = osbuild.NewOscapAutotailorStageOptions(
tailoringFilepath,
oscapStageOptions,
tailoringOptions,
)
@ -201,7 +213,7 @@ func osCustomizations(
osc.Directories = append(osc.Directories, tailoringDir)
}
osc.OpenSCAPConfig = osbuild.NewOscapRemediationStageOptions(oscapStageOptions)
osc.OpenSCAPConfig = osbuild.NewOscapRemediationStageOptions(oscapDataDir, oscapStageOptions)
}
osc.ShellInit = imageConfig.ShellInit

View file

@ -7,11 +7,11 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/internal/oscap"
"github.com/osbuild/images/internal/pathpolicy"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/image"

View file

@ -4,8 +4,8 @@ import (
"fmt"
"reflect"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/shell"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/shell"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/subscription"
)

View file

@ -22,6 +22,9 @@ const (
// blueprint package set name
blueprintPkgsKey = "blueprint"
// location for saving openscap remediation data
oscapDataDir = "/oscap_data"
)
// RHEL-based OS image configuration defaults

View file

@ -5,11 +5,11 @@ import (
"math/rand"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/image"
"github.com/osbuild/images/pkg/manifest"
@ -131,9 +131,11 @@ func osCustomizations(
if oscapConfig := c.GetOpenSCAP(); oscapConfig != nil {
osc.OpenSCAPConfig = osbuild.NewOscapRemediationStageOptions(
oscapDataDir,
osbuild.OscapConfig{
Datastream: oscapConfig.DataStream,
ProfileID: oscapConfig.ProfileID,
Datastream: oscapConfig.DataStream,
ProfileID: oscapConfig.ProfileID,
Compression: true,
},
)
}

View file

@ -2,8 +2,8 @@ package rhel8
import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/shell"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/customizations/shell"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/osbuild"

View file

@ -7,8 +7,8 @@ import (
"strings"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/oscap"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/platform"

View file

@ -4,8 +4,8 @@ import (
"fmt"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/rpmmd"
)

View file

@ -4,15 +4,15 @@ import (
"fmt"
"math/rand"
"github.com/osbuild/images/internal/fdo"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/ignition"
"github.com/osbuild/images/internal/oscap"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fdo"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/ignition"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/image"
"github.com/osbuild/images/pkg/manifest"
@ -186,14 +186,25 @@ func osCustomizations(
if t.rpmOstree {
panic("unexpected oscap options for ostree image type")
}
// although the osbuild stage will create this directory,
// it's probably better to ensure that it is created here
dataDirNode, err := fsnode.NewDirectory(oscapDataDir, nil, nil, nil, true)
if err != nil {
panic("unexpected error creating OpenSCAP data directory")
}
osc.Directories = append(osc.Directories, dataDirNode)
var datastream = oscapConfig.DataStream
if datastream == "" {
datastream = oscap.DefaultRHEL8Datastream(t.arch.distro.isRHEL())
}
oscapStageOptions := osbuild.OscapConfig{
Datastream: datastream,
ProfileID: oscapConfig.ProfileID,
Datastream: datastream,
ProfileID: oscapConfig.ProfileID,
Compression: true,
}
if oscapConfig.Tailoring != nil {
@ -203,14 +214,15 @@ func osCustomizations(
}
tailoringOptions := osbuild.OscapAutotailorConfig{
NewProfile: newProfile,
Datastream: datastream,
ProfileID: oscapConfig.ProfileID,
Selected: oscapConfig.Tailoring.Selected,
Unselected: oscapConfig.Tailoring.Unselected,
NewProfile: newProfile,
}
osc.OpenSCAPTailorConfig = osbuild.NewOscapAutotailorStageOptions(
tailoringFilepath,
oscapStageOptions,
tailoringOptions,
)
@ -222,7 +234,7 @@ func osCustomizations(
osc.Directories = append(osc.Directories, tailoringDir)
}
osc.OpenSCAPConfig = osbuild.NewOscapRemediationStageOptions(oscapStageOptions)
osc.OpenSCAPConfig = osbuild.NewOscapRemediationStageOptions(oscapDataDir, oscapStageOptions)
}
osc.ShellInit = imageConfig.ShellInit

View file

@ -10,11 +10,11 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/internal/oscap"
"github.com/osbuild/images/internal/pathpolicy"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/image"
@ -37,6 +37,9 @@ const (
// blueprint package set name
blueprintPkgsKey = "blueprint"
// location for saving openscap remediation data
oscapDataDir = "/oscap_data"
)
type imageFunc func(workload workload.Workload, t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, packageSets map[string]rpmmd.PackageSet, containers []container.SourceSpec, rng *rand.Rand) (image.ImageKind, error)

View file

@ -7,8 +7,8 @@ import (
"strings"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/oscap"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/platform"

View file

@ -5,8 +5,8 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/osbuild"
@ -400,7 +400,7 @@ func edgeBasePartitionTables(t *imageType) (disk.PartitionTable, bool) {
Description: "built with lvm2 and osbuild",
LogicalVolumes: []disk.LVMLogicalVolume{
{
Size: 9 * 1024 * 1024 * 1024, // 9 GB
Size: 9 * common.GiB, // 9 GiB
Name: "rootlv",
Payload: &disk.Filesystem{
Type: "xfs",
@ -471,7 +471,7 @@ func edgeBasePartitionTables(t *imageType) (disk.PartitionTable, bool) {
Description: "built with lvm2 and osbuild",
LogicalVolumes: []disk.LVMLogicalVolume{
{
Size: 9 * 1024 * 1024 * 1024, // 9 GB
Size: 9 * common.GiB, // 9 GiB
Name: "rootlv",
Payload: &disk.Filesystem{
Type: "xfs",

View file

@ -5,14 +5,14 @@ import (
"math/rand"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/fdo"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/ignition"
"github.com/osbuild/images/internal/oscap"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fdo"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/ignition"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/image"
"github.com/osbuild/images/pkg/manifest"
@ -183,14 +183,25 @@ func osCustomizations(
if t.rpmOstree {
panic("unexpected oscap options for ostree image type")
}
// although the osbuild stage will create this directory,
// it's probably better to ensure that it is created here
dataDirNode, err := fsnode.NewDirectory(oscapDataDir, nil, nil, nil, true)
if err != nil {
panic("unexpected error creating OpenSCAP data directory")
}
osc.Directories = append(osc.Directories, dataDirNode)
var datastream = oscapConfig.DataStream
if datastream == "" {
datastream = oscap.DefaultRHEL9Datastream(t.arch.distro.isRHEL())
}
oscapStageOptions := osbuild.OscapConfig{
Datastream: datastream,
ProfileID: oscapConfig.ProfileID,
Datastream: datastream,
ProfileID: oscapConfig.ProfileID,
Compression: true,
}
if oscapConfig.Tailoring != nil {
@ -200,14 +211,15 @@ func osCustomizations(
}
tailoringOptions := osbuild.OscapAutotailorConfig{
NewProfile: newProfile,
Datastream: datastream,
ProfileID: oscapConfig.ProfileID,
Selected: oscapConfig.Tailoring.Selected,
Unselected: oscapConfig.Tailoring.Unselected,
NewProfile: newProfile,
}
osc.OpenSCAPTailorConfig = osbuild.NewOscapAutotailorStageOptions(
tailoringFilepath,
oscapStageOptions,
tailoringOptions,
)
@ -219,7 +231,7 @@ func osCustomizations(
osc.Directories = append(osc.Directories, tailoringDir)
}
osc.OpenSCAPConfig = osbuild.NewOscapRemediationStageOptions(oscapStageOptions)
osc.OpenSCAPConfig = osbuild.NewOscapRemediationStageOptions(oscapDataDir, oscapStageOptions)
}
osc.ShellInit = imageConfig.ShellInit

View file

@ -10,11 +10,11 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/internal/oscap"
"github.com/osbuild/images/internal/pathpolicy"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/oscap"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/image"
@ -40,6 +40,9 @@ const (
// blueprint package set name
blueprintPkgsKey = "blueprint"
// location for saving openscap remediation data
oscapDataDir = "/oscap_data"
)
type imageFunc func(workload workload.Workload, t *imageType, customizations *blueprint.Customizations, options distro.ImageOptions, packageSets map[string]rpmmd.PackageSet, containers []container.SourceSpec, rng *rand.Rand) (image.ImageKind, error)

View file

@ -46,7 +46,7 @@ func (img *AnacondaLiveInstaller) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifest.NewBuild(m, runner, repos, nil)
buildPipeline.Checkpoint()
livePipeline := manifest.NewAnacondaInstaller(m,

View file

@ -5,9 +5,9 @@ import (
"math/rand"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/artifact"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/ostree"
@ -53,7 +53,7 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifest.NewBuild(m, runner, repos, nil)
buildPipeline.Checkpoint()
anacondaPipeline := manifest.NewAnacondaInstaller(m,

View file

@ -7,10 +7,10 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/artifact"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/platform"
@ -63,7 +63,7 @@ func (img *AnacondaTarInstaller) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifest.NewBuild(m, runner, repos, nil)
buildPipeline.Checkpoint()
anacondaPipeline := manifest.NewAnacondaInstaller(m,

View file

@ -31,7 +31,7 @@ func (img *Archive) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifest.NewBuild(m, runner, repos, nil)
buildPipeline.Checkpoint()
osPipeline := manifest.NewOS(m, buildPipeline, img.Platform, repos)

View file

@ -31,7 +31,7 @@ func (img *BaseContainer) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifest.NewBuild(m, runner, repos, nil)
buildPipeline.Checkpoint()
osPipeline := manifest.NewOS(m, buildPipeline, img.Platform, repos)

View file

@ -49,7 +49,7 @@ func (img *DiskImage) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifest.NewBuild(m, runner, repos, nil)
buildPipeline.Checkpoint()
osPipeline := manifest.NewOS(m, buildPipeline, img.Platform, repos)

View file

@ -47,7 +47,7 @@ func (img *OSTreeArchive) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifest.NewBuild(m, runner, repos, nil)
buildPipeline.Checkpoint()
osPipeline := manifest.NewOS(m, buildPipeline, img.Platform, repos)

View file

@ -44,7 +44,7 @@ func (img *OSTreeContainer) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifest.NewBuild(m, runner, repos, nil)
buildPipeline.Checkpoint()
osPipeline := manifest.NewOS(m, buildPipeline, img.Platform, repos)

View file

@ -4,11 +4,11 @@ import (
"fmt"
"math/rand"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/artifact"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/ostree"
@ -53,6 +53,10 @@ type OSTreeDiskImage struct {
// Lock the root account in the deployment unless the user defined root
// user options in the build configuration.
LockRoot bool
// Container buildable tweaks the buildroot to be container friendly,
// i.e. to not rely on an installed osbuild-selinux
ContainerBuildable bool
}
func NewOSTreeDiskImageFromCommit(commit ostree.SourceSpec) *OSTreeDiskImage {
@ -102,11 +106,14 @@ func baseRawOstreeImage(img *OSTreeDiskImage, m *manifest.Manifest, buildPipelin
return manifest.NewRawOStreeImage(buildPipeline, osPipeline, img.Platform)
}
// replaced in testing
var manifestNewBuild = manifest.NewBuild
func (img *OSTreeDiskImage) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifestNewBuild(m, runner, repos, &manifest.BuildOptions{ContainerBuildable: img.ContainerBuildable})
buildPipeline.Checkpoint()
// don't support compressing non-raw images

View file

@ -6,11 +6,11 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/internal/fdo"
"github.com/osbuild/images/internal/ignition"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/artifact"
"github.com/osbuild/images/pkg/customizations/fdo"
"github.com/osbuild/images/pkg/customizations/ignition"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/platform"
@ -73,7 +73,7 @@ func (img *OSTreeSimplifiedInstaller) InstantiateManifest(m *manifest.Manifest,
repos []rpmmd.RepoConfig,
runner runner.Runner,
rng *rand.Rand) (*artifact.Artifact, error) {
buildPipeline := manifest.NewBuild(m, runner, repos)
buildPipeline := manifest.NewBuild(m, runner, repos, nil)
buildPipeline.Checkpoint()
imageFilename := "image.raw.xz"
@ -127,6 +127,9 @@ func (img *OSTreeSimplifiedInstaller) InstantiateManifest(m *manifest.Manifest,
if img.FDO.DiunPubKeyRootCerts != "" {
kernelOpts = append(kernelOpts, "fdo.diun_pub_key_root_certs=/fdo_diun_pub_key_root_certs.pem")
}
if img.FDO.DiMfgStringTypeMacIface != "" {
kernelOpts = append(kernelOpts, "fdo.di_mfg_string_type_mac_iface="+img.FDO.DiMfgStringTypeMacIface)
}
}
bootTreePipeline.KernelOpts = kernelOpts

View file

@ -4,10 +4,10 @@ import (
"fmt"
"os"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/platform"
@ -309,14 +309,11 @@ func (p *AnacondaInstaller) serialize() osbuild.Pipeline {
if p.Type == AnacondaInstallerTypePayload {
if p.InteractiveDefaults != nil {
kickstartOptions, err := osbuild.NewKickstartStageOptions(
kickstartOptions, err := osbuild.NewKickstartStageOptionsWithLiveIMG(
"/usr/share/anaconda/interactive-defaults.ks",
p.InteractiveDefaults.TarPath,
p.Users,
p.Groups,
"",
"",
"",
p.InteractiveDefaults.TarPath,
)
if err != nil {

View file

@ -4,8 +4,8 @@ import (
"fmt"
"path"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
@ -272,7 +272,13 @@ func (p *AnacondaInstallerISOTree) serialize() osbuild.Pipeline {
))
// Configure the kickstart file with the payload and any user options
kickstartOptions, err := osbuild.NewKickstartStageOptions(p.KSPath, "", p.Users, p.Groups, makeISORootPath(p.PayloadPath), p.ostreeCommitSpec.Ref, p.OSName)
kickstartOptions, err := osbuild.NewKickstartStageOptionsWithOSTreeCommit(
p.KSPath,
p.Users,
p.Groups,
makeISORootPath(p.PayloadPath),
p.ostreeCommitSpec.Ref,
p.OSName)
if err != nil {
panic("failed to create kickstartstage options")
@ -288,7 +294,12 @@ func (p *AnacondaInstallerISOTree) serialize() osbuild.Pipeline {
// If the KSPath is set, we need to add the kickstart stage to this (bootiso-tree) pipeline.
// If it's not specified here, it should have been added to the InteractiveDefaults in the anaconda-tree.
if p.KSPath != "" {
kickstartOptions, err := osbuild.NewKickstartStageOptions(p.KSPath, makeISORootPath(p.PayloadPath), p.Users, p.Groups, "", "", p.OSName)
kickstartOptions, err := osbuild.NewKickstartStageOptionsWithLiveIMG(
p.KSPath,
p.Users,
p.Groups,
makeISORootPath(p.PayloadPath))
if err != nil {
panic("failed to create kickstartstage options")
}

View file

@ -22,17 +22,31 @@ type Build struct {
dependents []Pipeline
repos []rpmmd.RepoConfig
packageSpecs []rpmmd.PackageSpec
containerBuildable bool
}
type BuildOptions struct {
// ContainerBuildable tweaks the buildroot to be container friendly,
// i.e. to not rely on an installed osbuild-selinux
ContainerBuildable bool
}
// NewBuild creates a new build pipeline from the repositories in repos
// and the specified packages.
func NewBuild(m *Manifest, runner runner.Runner, repos []rpmmd.RepoConfig) *Build {
func NewBuild(m *Manifest, runner runner.Runner, repos []rpmmd.RepoConfig, opts *BuildOptions) *Build {
if opts == nil {
opts = &BuildOptions{}
}
name := "build"
pipeline := &Build{
Base: NewBase(m, name, nil),
runner: runner,
dependents: make([]Pipeline, 0),
repos: filterRepos(repos, name),
containerBuildable: opts.ContainerBuildable,
}
m.addPipeline(pipeline)
return pipeline
@ -109,6 +123,10 @@ func (p *Build) getSELinuxLabels() map[string]string {
switch pkg.Name {
case "coreutils":
labels["/usr/bin/cp"] = "system_u:object_r:install_exec_t:s0"
if p.containerBuildable {
labels["/usr/bin/mount"] = "system_u:object_r:install_exec_t:s0"
labels["/usr/bin/umount"] = "system_u:object_r:install_exec_t:s0"
}
case "tar":
labels["/usr/bin/tar"] = "system_u:object_r:install_exec_t:s0"
}

View file

@ -4,7 +4,7 @@ import (
"crypto/sha256"
"fmt"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/osbuild"
)

View file

@ -3,10 +3,10 @@ package manifest
import (
"fmt"
"github.com/osbuild/images/internal/fdo"
"github.com/osbuild/images/internal/ignition"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fdo"
"github.com/osbuild/images/pkg/customizations/ignition"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/platform"

View file

@ -7,12 +7,12 @@ import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/environment"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/shell"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/internal/workload"
"github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/shell"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
@ -220,7 +220,7 @@ func (p *OS) getPackageSetChain(Distro) []rpmmd.PackageSet {
}
if p.OpenSCAPConfig != nil {
packages = append(packages, "openscap-scanner", "scap-security-guide")
packages = append(packages, "openscap-scanner", "scap-security-guide", "xz")
}
// Make sure the right packages are included for subscriptions

View file

@ -6,9 +6,9 @@ import (
"strings"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"

View file

@ -4,7 +4,7 @@ import (
"os"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/disk"
)

View file

@ -4,7 +4,7 @@ import (
"crypto/sha256"
"fmt"
"github.com/osbuild/images/internal/fsnode"
"github.com/osbuild/images/pkg/customizations/fsnode"
)
// GenFileNodesStages generates the stages for a list of file nodes.

View file

@ -1,7 +1,7 @@
package osbuild
import (
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/pkg/customizations/users"
)
type GroupsStageOptions struct {

View file

@ -1,31 +1,40 @@
package osbuild
import "github.com/osbuild/images/internal/users"
import "github.com/osbuild/images/pkg/customizations/users"
type KickstartStageOptions struct {
// Where to place the kickstart file
Path string `json:"path"`
OSTree *OSTreeOptions `json:"ostree,omitempty"`
OSTreeCommit *OSTreeCommitOptions `json:"ostree,omitempty"`
OSTreeContainer *OSTreeContainerOptions `json:"ostreecontainer,omitempty"`
LiveIMG *LiveIMG `json:"liveimg,omitempty"`
LiveIMG *LiveIMGOptions `json:"liveimg,omitempty"`
Users map[string]UsersStageOptionsUser `json:"users,omitempty"`
Groups map[string]GroupsStageOptionsGroup `json:"groups,omitempty"`
}
type LiveIMG struct {
type LiveIMGOptions struct {
URL string `json:"url"`
}
type OSTreeOptions struct {
type OSTreeCommitOptions struct {
OSName string `json:"osname"`
URL string `json:"url"`
Ref string `json:"ref"`
GPG bool `json:"gpg"`
}
type OSTreeContainerOptions struct {
StateRoot string `json:"stateroot"`
URL string `json:"url"`
Transport string `json:"transport"`
Remote string `json:"remote"`
SignatureVerification bool `json:"signatureverification"`
}
func (KickstartStageOptions) isStageOptions() {}
// Creates an Anaconda kickstart file
@ -38,12 +47,8 @@ func NewKickstartStage(options *KickstartStageOptions) *Stage {
func NewKickstartStageOptions(
path string,
imageURL string,
userCustomizations []users.User,
groupCustomizations []users.Group,
ostreeURL string,
ostreeRef string,
osName string) (*KickstartStageOptions, error) {
groupCustomizations []users.Group) (*KickstartStageOptions, error) {
var users map[string]UsersStageOptionsUser
if usersOptions, err := NewUsersStageOptions(userCustomizations, false); err != nil {
@ -57,27 +62,91 @@ func NewKickstartStageOptions(
groups = groupsOptions.Groups
}
var ostreeOptions *OSTreeOptions
return &KickstartStageOptions{
Path: path,
OSTreeCommit: nil,
LiveIMG: nil,
Users: users,
Groups: groups,
}, nil
}
func NewKickstartStageOptionsWithOSTreeCommit(
path string,
userCustomizations []users.User,
groupCustomizations []users.Group,
ostreeURL string,
ostreeRef string,
osName string) (*KickstartStageOptions, error) {
options, err := NewKickstartStageOptions(path, userCustomizations, groupCustomizations)
if err != nil {
return nil, err
}
if ostreeURL != "" {
ostreeOptions = &OSTreeOptions{
ostreeCommitOptions := &OSTreeCommitOptions{
OSName: osName,
URL: ostreeURL,
Ref: ostreeRef,
GPG: false,
}
options.OSTreeCommit = ostreeCommitOptions
}
return options, nil
}
func NewKickstartStageOptionsWithOSTreeContainer(
path string,
userCustomizations []users.User,
groupCustomizations []users.Group,
containerURL string,
containerTransport string,
containerRemote string,
containerStateRoot string) (*KickstartStageOptions, error) {
options, err := NewKickstartStageOptions(path, userCustomizations, groupCustomizations)
if err != nil {
return nil, err
}
if containerURL != "" {
ostreeContainerOptions := &OSTreeContainerOptions{
StateRoot: containerStateRoot,
URL: containerURL,
Remote: containerRemote,
Transport: containerTransport,
SignatureVerification: false,
}
options.OSTreeContainer = ostreeContainerOptions
}
return options, nil
}
func NewKickstartStageOptionsWithLiveIMG(
path string,
userCustomizations []users.User,
groupCustomizations []users.Group,
imageURL string) (*KickstartStageOptions, error) {
options, err := NewKickstartStageOptions(path, userCustomizations, groupCustomizations)
if err != nil {
return nil, err
}
var liveImg *LiveIMG
if imageURL != "" {
liveImg = &LiveIMG{
liveImg := &LiveIMGOptions{
URL: imageURL,
}
options.LiveIMG = liveImg
}
return &KickstartStageOptions{
Path: path,
OSTree: ostreeOptions,
LiveIMG: liveImg,
Users: users,
Groups: groups,
}, nil
return options, nil
}

View file

@ -6,9 +6,11 @@ type OscapAutotailorStageOptions struct {
Filepath string `json:"filepath"`
Config OscapAutotailorConfig `json:"config"`
}
type OscapAutotailorConfig struct {
OscapConfig
NewProfile string `json:"new_profile"`
Datastream string `json:"datastream" toml:"datastream"`
ProfileID string `json:"profile_id" toml:"profile_id"`
Selected []string `json:"selected,omitempty"`
Unselected []string `json:"unselected,omitempty"`
}
@ -16,11 +18,16 @@ type OscapAutotailorConfig struct {
func (OscapAutotailorStageOptions) isStageOptions() {}
func (c OscapAutotailorConfig) validate() error {
if c.Datastream == "" {
return fmt.Errorf("'datastream' must be specified")
}
if c.ProfileID == "" {
return fmt.Errorf("'profile_id' must be specified")
}
if c.NewProfile == "" {
return fmt.Errorf("'new_profile' must be specified")
}
// reuse the oscap validation
return c.OscapConfig.validate()
return nil
}
func NewOscapAutotailorStage(options *OscapAutotailorStageOptions) *Stage {
@ -34,14 +41,15 @@ func NewOscapAutotailorStage(options *OscapAutotailorStageOptions) *Stage {
}
}
func NewOscapAutotailorStageOptions(filepath string, oscapOptions OscapConfig, autotailorOptions OscapAutotailorConfig) *OscapAutotailorStageOptions {
func NewOscapAutotailorStageOptions(filepath string, autotailorOptions OscapAutotailorConfig) *OscapAutotailorStageOptions {
return &OscapAutotailorStageOptions{
Filepath: filepath,
Config: OscapAutotailorConfig{
OscapConfig: oscapOptions,
NewProfile: autotailorOptions.NewProfile,
Selected: autotailorOptions.Selected,
Unselected: autotailorOptions.Unselected,
NewProfile: autotailorOptions.NewProfile,
Datastream: autotailorOptions.Datastream,
ProfileID: autotailorOptions.ProfileID,
Selected: autotailorOptions.Selected,
Unselected: autotailorOptions.Unselected,
},
}
}

View file

@ -15,6 +15,7 @@ type OscapRemediationStageOptions struct {
DataDir string `json:"data_dir,omitempty"`
Config OscapConfig `json:"config"`
}
type OscapConfig struct {
Datastream string `json:"datastream" toml:"datastream"`
ProfileID string `json:"profile_id" toml:"profile_id"`
@ -23,10 +24,11 @@ type OscapConfig struct {
BenchmarkID string `json:"benchmark_id,omitempty" toml:"benchmark_id,omitempty"`
Tailoring string `json:"tailoring,omitempty" toml:"tailoring,omitempty"`
TailoringID string `json:"tailoring_id,omitempty" toml:"tailoring_id,omitempty"`
ArfResult string `json:"arf_result,omitempty" toml:"arf_result,omitempty"`
ArfResult string `json:"arf_results,omitempty" toml:"arf_results,omitempty"`
HtmlReport string `json:"html_report,omitempty" toml:"html_report,omitempty"`
VerboseLog string `json:"verbose_log,omitempty" toml:"verbose_log,omitempty"`
VerboseLevel OscapVerbosityLevel `json:"verbose_level,omitempty" toml:"verbose_level,omitempty"`
Compression bool `json:"compress_results,omitempty" toml:"compress_results,omitempty"`
}
func (OscapRemediationStageOptions) isStageOptions() {}
@ -70,8 +72,9 @@ func NewOscapRemediationStage(options *OscapRemediationStageOptions) *Stage {
}
}
func NewOscapRemediationStageOptions(options OscapConfig) *OscapRemediationStageOptions {
func NewOscapRemediationStageOptions(dataDir string, options OscapConfig) *OscapRemediationStageOptions {
return &OscapRemediationStageOptions{
DataDir: dataDir,
Config: OscapConfig{
ProfileID: options.ProfileID,
Datastream: options.Datastream,
@ -83,6 +86,7 @@ func NewOscapRemediationStageOptions(options OscapConfig) *OscapRemediationStage
HtmlReport: options.HtmlReport,
VerboseLog: options.VerboseLog,
VerboseLevel: options.VerboseLevel,
Compression: options.Compression,
},
}
}

View file

@ -4,7 +4,7 @@ import (
"fmt"
"regexp"
"github.com/osbuild/images/internal/shell"
"github.com/osbuild/images/pkg/customizations/shell"
)
const filenameRegex = "^[a-zA-Z0-9\\.\\-_]{1,250}$"

View file

@ -39,13 +39,12 @@ func NewSkopeoSourceItem(name, digest string, tlsVerify *bool) SkopeoSourceItem
}
func (item SkopeoSourceItem) validate() error {
if item.Image.Name == "" {
return fmt.Errorf("source item has empty name")
return fmt.Errorf("source item %#v has empty name", item)
}
if !skopeoDigestPattern.MatchString(item.Image.Digest) {
return fmt.Errorf("source item has invalid digest")
return fmt.Errorf("source item %#v has invalid digest", item)
}
return nil
@ -63,7 +62,7 @@ func NewSkopeoSource() *SkopeoSource {
func (source *SkopeoSource) AddItem(name, digest, image string, tlsVerify *bool) {
item := NewSkopeoSourceItem(name, digest, tlsVerify)
if !skopeoDigestPattern.MatchString(image) {
panic("item has invalid image id")
panic(fmt.Errorf("item %#v has invalid image id", image))
}
source.Items[image] = item
}

View file

@ -1,8 +1,8 @@
package osbuild
import (
"github.com/osbuild/images/internal/users"
"github.com/osbuild/images/pkg/crypt"
"github.com/osbuild/images/pkg/customizations/users"
)
type UsersStageOptions struct {

View file

@ -99,17 +99,18 @@ func repoConfigToYumRepository(repo rpmmd.RepoConfig) YumRepository {
}
yumRepo := YumRepository{
Id: repo.Id,
Name: repo.Name,
Mirrorlist: repo.MirrorList,
Metalink: repo.Metalink,
BaseURLs: urls,
GPGKey: keys,
GPGCheck: repo.CheckGPG,
RepoGPGCheck: repo.CheckRepoGPG,
Enabled: repo.Enabled,
Priority: repo.Priority,
SSLVerify: sslVerify,
Id: repo.Id,
Name: repo.Name,
Mirrorlist: repo.MirrorList,
Metalink: repo.Metalink,
BaseURLs: urls,
GPGKey: keys,
GPGCheck: repo.CheckGPG,
RepoGPGCheck: repo.CheckRepoGPG,
Enabled: repo.Enabled,
Priority: repo.Priority,
SSLVerify: sslVerify,
ModuleHotfixes: repo.ModuleHotfixes,
}
return yumRepo

View file

@ -23,6 +23,7 @@ type repository struct {
CheckGPG bool `json:"check_gpg,omitempty"`
IgnoreSSL bool `json:"ignore_ssl,omitempty"`
RHSM bool `json:"rhsm,omitempty"`
ModuleHotfixes *bool `json:"module_hotfixes,omitempty"`
MetadataExpire string `json:"metadata_expire,omitempty"`
ImageTypeTags []string `json:"image_type_tags,omitempty"`
}
@ -42,6 +43,7 @@ type RepoConfig struct {
Priority *int `json:"priority,omitempty"`
IgnoreSSL *bool `json:"ignore_ssl,omitempty"`
MetadataExpire string `json:"metadata_expire,omitempty"`
ModuleHotfixes *bool `json:"module_hotfixes,omitempty"`
RHSM bool `json:"rhsm,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
ImageTypeTags []string `json:"image_type_tags,omitempty"`
@ -58,6 +60,12 @@ func (r *RepoConfig) Hash() string {
bpts := func(b *bool) string {
return fmt.Sprintf("%T", b)
}
bptsIgnoreNil := func(b *bool) string {
if b == nil {
return ""
}
return bts(*b)
}
ats := func(s []string) string {
return strings.Join(s, "")
}
@ -69,7 +77,8 @@ func (r *RepoConfig) Hash() string {
bpts(r.CheckRepoGPG)+
bpts(r.IgnoreSSL)+
r.MetadataExpire+
bts(r.RHSM))))
bts(r.RHSM)+
bptsIgnoreNil(r.ModuleHotfixes))))
}
type DistrosRepoConfigs map[string]map[string][]RepoConfig
@ -245,6 +254,7 @@ func loadRepositoriesFromFile(filename string) (map[string][]RepoConfig, error)
CheckGPG: &repo.CheckGPG,
RHSM: repo.RHSM,
MetadataExpire: repo.MetadataExpire,
ModuleHotfixes: repo.ModuleHotfixes,
ImageTypeTags: repo.ImageTypeTags,
}