Add Initial Mariner OS Modifier (EMU) Files (#6824)
This commit is contained in:
Родитель
eebc0beedc
Коммит
a6a19b4da0
|
@ -43,6 +43,7 @@ go_tool_list = \
|
||||||
imager \
|
imager \
|
||||||
isomaker \
|
isomaker \
|
||||||
liveinstaller \
|
liveinstaller \
|
||||||
|
osmodifier \
|
||||||
pkgworker \
|
pkgworker \
|
||||||
precacher \
|
precacher \
|
||||||
repoquerywrapper \
|
repoquerywrapper \
|
||||||
|
|
|
@ -1336,7 +1336,7 @@ func createUserWithPassword(installChroot *safechroot.Chroot, user configuration
|
||||||
|
|
||||||
// chage works in the same way as invoking "chage -M passwordExpirationInDays username"
|
// chage works in the same way as invoking "chage -M passwordExpirationInDays username"
|
||||||
// i.e. it sets the maximum password expiration date.
|
// i.e. it sets the maximum password expiration date.
|
||||||
func Chage(installChroot *safechroot.Chroot, passwordExpirationInDays int64, username string) (err error) {
|
func Chage(installChroot safechroot.ChrootInterface, passwordExpirationInDays int64, username string) (err error) {
|
||||||
var (
|
var (
|
||||||
shadow []string
|
shadow []string
|
||||||
usernameWithColon = fmt.Sprintf("%s:", username)
|
usernameWithColon = fmt.Sprintf("%s:", username)
|
||||||
|
@ -1422,7 +1422,7 @@ func Chage(installChroot *safechroot.Chroot, passwordExpirationInDays int64, use
|
||||||
return fmt.Errorf(`user "%s" not found when trying to change the password expiration date`, username)
|
return fmt.Errorf(`user "%s" not found when trying to change the password expiration date`, username)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConfigureUserGroupMembership(installChroot *safechroot.Chroot, username string, primaryGroup string,
|
func ConfigureUserGroupMembership(installChroot safechroot.ChrootInterface, username string, primaryGroup string,
|
||||||
secondaryGroups []string,
|
secondaryGroups []string,
|
||||||
) (err error) {
|
) (err error) {
|
||||||
const squashErrors = false
|
const squashErrors = false
|
||||||
|
@ -1453,7 +1453,7 @@ func ConfigureUserGroupMembership(installChroot *safechroot.Chroot, username str
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConfigureUserStartupCommand(installChroot *safechroot.Chroot, username string, startupCommand string) (err error) {
|
func ConfigureUserStartupCommand(installChroot safechroot.ChrootInterface, username string, startupCommand string) (err error) {
|
||||||
const (
|
const (
|
||||||
passwdFilePath = "etc/passwd"
|
passwdFilePath = "etc/passwd"
|
||||||
sedDelimiter = "|"
|
sedDelimiter = "|"
|
||||||
|
@ -1477,7 +1477,7 @@ func ConfigureUserStartupCommand(installChroot *safechroot.Chroot, username stri
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvisionUserSSHCerts(installChroot *safechroot.Chroot, username string, sshPubKeyPaths []string) (err error) {
|
func ProvisionUserSSHCerts(installChroot safechroot.ChrootInterface, username string, sshPubKeyPaths []string) (err error) {
|
||||||
var (
|
var (
|
||||||
pubKeyData []string
|
pubKeyData []string
|
||||||
exists bool
|
exists bool
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
package safechroot
|
||||||
|
|
||||||
|
type ChrootInterface interface {
|
||||||
|
RootDir() string
|
||||||
|
Run(toRun func() error) error
|
||||||
|
UnsafeRun(toRun func() error) error
|
||||||
|
AddFiles(filesToCopy ...FileToCopy) error
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
package safechroot
|
||||||
|
|
||||||
|
// DummyChroot is a placeholder that implements ChrootInterface.
|
||||||
|
type DummyChroot struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DummyChroot) RootDir() string {
|
||||||
|
return "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DummyChroot) Run(toRun func() error) (err error) {
|
||||||
|
// Only execute the function, no chroot operations
|
||||||
|
return toRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DummyChroot) UnsafeRun(toRun func() error) (err error) {
|
||||||
|
return toRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DummyChroot) AddFiles(filesToCopy ...FileToCopy) (err error) {
|
||||||
|
return addFilesToDestination(d.RootDir(), filesToCopy...)
|
||||||
|
}
|
|
@ -284,10 +284,15 @@ func (c *Chroot) Initialize(tarPath string, extraDirectories []string, extraMoun
|
||||||
|
|
||||||
// AddFiles copies each file 'Src' to the relative path chrootRootDir/'Dest' in the chroot.
|
// AddFiles copies each file 'Src' to the relative path chrootRootDir/'Dest' in the chroot.
|
||||||
func (c *Chroot) AddFiles(filesToCopy ...FileToCopy) (err error) {
|
func (c *Chroot) AddFiles(filesToCopy ...FileToCopy) (err error) {
|
||||||
|
return addFilesToDestination(c.rootDir, filesToCopy...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addFilesToDestination(destDir string, filesToCopy ...FileToCopy) error {
|
||||||
for _, f := range filesToCopy {
|
for _, f := range filesToCopy {
|
||||||
dest := filepath.Join(c.rootDir, f.Dest)
|
dest := filepath.Join(destDir, f.Dest)
|
||||||
logger.Log.Debugf("Copying '%s' to worker '%s'", f.Src, dest)
|
logger.Log.Debugf("Copying '%s' to worker '%s'", f.Src, dest)
|
||||||
|
|
||||||
|
var err error
|
||||||
if f.Permissions != nil {
|
if f.Permissions != nil {
|
||||||
err = file.CopyAndChangeMode(f.Src, dest, os.ModePerm, *f.Permissions)
|
err = file.CopyAndChangeMode(f.Src, dest, os.ModePerm, *f.Permissions)
|
||||||
} else {
|
} else {
|
||||||
|
@ -296,10 +301,10 @@ func (c *Chroot) AddFiles(filesToCopy ...FileToCopy) (err error) {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Errorf("Error provisioning worker with '%s'", f.Src)
|
logger.Log.Errorf("Error provisioning worker with '%s'", f.Src)
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyOutFile copies file 'srcPath' in the chroot to the host at 'destPath'
|
// CopyOutFile copies file 'srcPath' in the chroot to the host at 'destPath'
|
||||||
|
|
|
@ -47,7 +47,7 @@ func HashPassword(password string) (string, error) {
|
||||||
return hashedPassword, nil
|
return hashedPassword, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UserExists(username string, installChroot *safechroot.Chroot) (bool, error) {
|
func UserExists(username string, installChroot safechroot.ChrootInterface) (bool, error) {
|
||||||
var userExists bool
|
var userExists bool
|
||||||
err := installChroot.UnsafeRun(func() error {
|
err := installChroot.UnsafeRun(func() error {
|
||||||
_, stderr, err := shell.Execute("id", "-u", username)
|
_, stderr, err := shell.Execute("id", "-u", username)
|
||||||
|
@ -70,7 +70,7 @@ func UserExists(username string, installChroot *safechroot.Chroot) (bool, error)
|
||||||
return userExists, nil
|
return userExists, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddUser(username string, hashedPassword string, uid string, installChroot *safechroot.Chroot) error {
|
func AddUser(username string, hashedPassword string, uid string, installChroot safechroot.ChrootInterface) error {
|
||||||
var args = []string{username, "-m"}
|
var args = []string{username, "-m"}
|
||||||
if hashedPassword != "" {
|
if hashedPassword != "" {
|
||||||
args = append(args, "-p", hashedPassword)
|
args = append(args, "-p", hashedPassword)
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/microsoft/CBL-Mariner/toolkit/tools/internal/exe"
|
||||||
|
"github.com/microsoft/CBL-Mariner/toolkit/tools/internal/logger"
|
||||||
|
"github.com/microsoft/CBL-Mariner/toolkit/tools/internal/timestamp"
|
||||||
|
"github.com/microsoft/CBL-Mariner/toolkit/tools/pkg/osmodifierlib"
|
||||||
|
"github.com/microsoft/CBL-Mariner/toolkit/tools/pkg/profile"
|
||||||
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
app = kingpin.New("osmodifier", "Used to modify os")
|
||||||
|
|
||||||
|
configFile = app.Flag("config-file", "Path of the os modification config file.").Required().String()
|
||||||
|
logFile = exe.LogFileFlag(app)
|
||||||
|
logLevel = exe.LogLevelFlag(app)
|
||||||
|
profFlags = exe.SetupProfileFlags(app)
|
||||||
|
timestampFile = app.Flag("timestamp-file", "File that stores timestamps for this program.").String()
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||||
|
|
||||||
|
logger.InitBestEffort(*logFile, *logLevel)
|
||||||
|
|
||||||
|
prof, err := profile.StartProfiling(profFlags)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log.Warnf("Could not start profiling: %s", err)
|
||||||
|
}
|
||||||
|
defer prof.StopProfiler()
|
||||||
|
|
||||||
|
timestamp.BeginTiming("osmodifier", *timestampFile)
|
||||||
|
defer timestamp.CompleteTiming()
|
||||||
|
|
||||||
|
err = modifyImage()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("os modification failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func modifyImage() error {
|
||||||
|
err := osmodifierlib.ModifyOSWithConfigFile(*configFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -57,7 +57,7 @@ func doCustomizations(buildDir string, baseConfigPath string, config *imagecusto
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = addOrUpdateUsers(config.SystemConfig.Users, baseConfigPath, imageChroot)
|
err = AddOrUpdateUsers(config.SystemConfig.Users, baseConfigPath, imageChroot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ func runScripts(baseConfigPath string, scripts []imagecustomizerapi.Script, imag
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addOrUpdateUsers(users []imagecustomizerapi.User, baseConfigPath string, imageChroot *safechroot.Chroot) error {
|
func AddOrUpdateUsers(users []imagecustomizerapi.User, baseConfigPath string, imageChroot safechroot.ChrootInterface) error {
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
err := addOrUpdateUser(user, baseConfigPath, imageChroot)
|
err := addOrUpdateUser(user, baseConfigPath, imageChroot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -218,7 +218,7 @@ func addOrUpdateUsers(users []imagecustomizerapi.User, baseConfigPath string, im
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addOrUpdateUser(user imagecustomizerapi.User, baseConfigPath string, imageChroot *safechroot.Chroot) error {
|
func addOrUpdateUser(user imagecustomizerapi.User, baseConfigPath string, imageChroot safechroot.ChrootInterface) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
logger.Log.Infof("Adding/updating user (%s)", user.Name)
|
logger.Log.Infof("Adding/updating user (%s)", user.Name)
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
package osmodifierlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/microsoft/CBL-Mariner/toolkit/tools/imagecustomizerapi"
|
||||||
|
"github.com/microsoft/CBL-Mariner/toolkit/tools/internal/safechroot"
|
||||||
|
"github.com/microsoft/CBL-Mariner/toolkit/tools/pkg/imagecustomizerlib"
|
||||||
|
)
|
||||||
|
|
||||||
|
func doModifications(baseConfigPath string, systemConfig *imagecustomizerapi.SystemConfig) error {
|
||||||
|
var dummyChroot safechroot.ChrootInterface = &safechroot.DummyChroot{}
|
||||||
|
err := imagecustomizerlib.AddOrUpdateUsers(systemConfig.Users, baseConfigPath, dummyChroot)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
package osmodifierlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/microsoft/CBL-Mariner/toolkit/tools/imagecustomizerapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ModifyOSWithConfigFile(configFile string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
var systemConfig imagecustomizerapi.SystemConfig
|
||||||
|
err = imagecustomizerapi.UnmarshalYamlFile(configFile, &systemConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
baseConfigPath, _ := filepath.Split(configFile)
|
||||||
|
|
||||||
|
absBaseConfigPath, err := filepath.Abs(baseConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get absolute path of config file directory:\n%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ModifyOS(absBaseConfigPath, &systemConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ModifyOS(baseConfigPath string, systemConfig *imagecustomizerapi.SystemConfig) error {
|
||||||
|
err := doModifications(baseConfigPath, systemConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
Users:
|
||||||
|
- Name: root
|
||||||
|
Password: password
|
||||||
|
|
||||||
|
- Name: test
|
||||||
|
Password: $6$aEzRqlIsXn8I$uvdD6RgzdAao5qUxap/Edc/ABW2Qfvqe4ZK7AjoguwS1rX2Q5l72/4L4OW5lqOdY5pIIahBco3hdR32NAuZ/O1
|
||||||
|
PasswordHashed: true
|
||||||
|
SecondaryGroups:
|
||||||
|
- sudo
|
Загрузка…
Ссылка в новой задаче