88 "io/fs"
99 "net/url"
1010 "os"
11+ "path"
1112 "path/filepath"
1213
1314 "github.com/containers/podman/v5/pkg/machine/define"
@@ -178,46 +179,6 @@ ExecStart=
178179ExecStart=-/usr/sbin/agetty --autologin root --noclear %I $TERM
179180`
180181
181- // This service gets environment variables that are provided
182- // through qemu fw_cfg and then sets them into systemd/system.conf.d,
183- // profile.d and environment.d files
184- //
185- // Currently, it is used for propagating
186- // proxy settings e.g. HTTP_PROXY and others, on a start avoiding
187- // a need of re-creating/re-initiating a VM
188-
189- envset := parser .NewUnitFile ()
190- envset .Add ("Unit" , "Description" , "Environment setter from QEMU FW_CFG" )
191-
192- envset .Add ("Service" , "Type" , "oneshot" )
193- envset .Add ("Service" , "RemainAfterExit" , "yes" )
194- envset .Add ("Service" , "Environment" , "FWCFGRAW=/sys/firmware/qemu_fw_cfg/by_name/opt/com.coreos/environment/raw" )
195- envset .Add ("Service" , "Environment" , "SYSTEMD_CONF=/etc/systemd/system.conf.d/default-env.conf" )
196- envset .Add ("Service" , "Environment" , "ENVD_CONF=/etc/environment.d/default-env.conf" )
197- envset .Add ("Service" , "Environment" , "PROFILE_CONF=/etc/profile.d/default-env.sh" )
198- envset .Add ("Service" , "ExecStart" , `/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} &&\
199- echo "[Manager]\n#Got from QEMU FW_CFG\nDefaultEnvironment=$(/usr/bin/base64 -d ${FWCFGRAW} | sed -e "s+|+ +g")\n" > ${SYSTEMD_CONF} ||\
200- echo "[Manager]\n#Got nothing from QEMU FW_CFG\n#DefaultEnvironment=\n" > ${SYSTEMD_CONF}'` )
201- envset .Add ("Service" , "ExecStart" , `/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} && (\
202- echo "#Got from QEMU FW_CFG"> ${ENVD_CONF};\
203- IFS="|";\
204- for iprxy in $(/usr/bin/base64 -d ${FWCFGRAW}); do\
205- echo "$iprxy" >> ${ENVD_CONF}; done ) || \
206- echo "#Got nothing from QEMU FW_CFG"> ${ENVD_CONF}'` )
207- envset .Add ("Service" , "ExecStart" , `/usr/bin/bash -c '/usr/bin/test -f ${FWCFGRAW} && (\
208- echo "#Got from QEMU FW_CFG"> ${PROFILE_CONF};\
209- IFS="|";\
210- for iprxy in $(/usr/bin/base64 -d ${FWCFGRAW}); do\
211- echo "export $iprxy" >> ${PROFILE_CONF}; done ) || \
212- echo "#Got nothing from QEMU FW_CFG"> ${PROFILE_CONF}'` )
213- envset .Add ("Service" , "ExecStartPost" , "/usr/bin/systemctl daemon-reload" )
214-
215- envset .Add ("Install" , "WantedBy" , "sysinit.target" )
216- envsetFile , err := envset .ToString ()
217- if err != nil {
218- return err
219- }
220-
221182 ignSystemd := Systemd {
222183 Units : []Unit {
223184 {
@@ -261,16 +222,6 @@ ExecStart=-/usr/sbin/agetty --autologin root --noclear %I $TERM
261222 },
262223 }
263224
264- // Only qemu has the qemu firmware environment setting
265- if ign .VMType == define .QemuVirt {
266- qemuUnit := Unit {
267- Enabled : BoolToPtr (true ),
268- Name : "envset-fwcfg.service" ,
269- Contents : & envsetFile ,
270- }
271- ignSystemd .Units = append (ignSystemd .Units , qemuUnit )
272- }
273-
274225 if ign .NetRecover {
275226 contents , err := GetNetRecoveryUnitFile ().ToString ()
276227 if err != nil {
@@ -582,23 +533,29 @@ Delegate=memory pids cpu io
582533 certFiles = getCerts (filepath .Join (userHome , ".config/docker/certs.d" ), true )
583534 files = append (files , certFiles ... )
584535
585- if sslCertFile , ok := os .LookupEnv ("SSL_CERT_FILE" ); ok {
586- if _ , err := os .Stat (sslCertFile ); err == nil {
587- certFiles = getCerts (sslCertFile , false )
536+ sslCertFileName , ok := os .LookupEnv (sslCertFile )
537+ if ok {
538+ if _ , err := os .Stat (sslCertFileName ); err == nil {
539+ certFiles = getCerts (sslCertFileName , false )
588540 files = append (files , certFiles ... )
589541 } else {
590- logrus .Warnf ("Invalid path in SSL_CERT_FILE : %q" , err )
542+ logrus .Warnf ("Invalid path in %s : %q" , sslCertFile , err )
591543 }
592544 }
593545
594- if sslCertDir , ok := os .LookupEnv ("SSL_CERT_DIR" ); ok {
595- if _ , err := os .Stat (sslCertDir ); err == nil {
596- certFiles = getCerts (sslCertDir , true )
546+ sslCertDirName , ok := os .LookupEnv (sslCertDir )
547+ if ok {
548+ if _ , err := os .Stat (sslCertDirName ); err == nil {
549+ certFiles = getCerts (sslCertDirName , true )
597550 files = append (files , certFiles ... )
598551 } else {
599- logrus .Warnf ("Invalid path in SSL_CERT_DIR : %q" , err )
552+ logrus .Warnf ("Invalid path in %s : %q" , sslCertDir , err )
600553 }
601554 }
555+ if sslCertFileName != "" || sslCertDirName != "" {
556+ // If we copied certs via env then also make the to set the env in the VM.
557+ files = append (files , getSSLEnvironmentFiles (sslCertFileName , sslCertDirName )... )
558+ }
602559
603560 files = append (files , File {
604561 Node : Node {
@@ -686,16 +643,18 @@ func getCerts(certsDir string, isDir bool) []File {
686643 return files
687644}
688645
689- func prepareCertFile (path string , name string ) (File , error ) {
690- b , err := os .ReadFile (path )
646+ func prepareCertFile (fpath string , name string ) (File , error ) {
647+ b , err := os .ReadFile (fpath )
691648 if err != nil {
692649 logrus .Warnf ("Unable to read cert file %v" , err )
693650 return File {}, err
694651 }
695652
696- targetPath := filepath .Join (define .UserCertsTargetPath , name )
653+ // Note path is required here as we always create a path for the linux VM
654+ // even when the client run on windows so we cannot use filepath.
655+ targetPath := path .Join (define .UserCertsTargetPath , name )
697656
698- logrus .Debugf ("Copying cert file from '%s' to '%s'." , path , targetPath )
657+ logrus .Debugf ("Copying cert file from '%s' to '%s'." , fpath , targetPath )
699658
700659 file := File {
701660 Node : Node {
@@ -714,6 +673,57 @@ func prepareCertFile(path string, name string) (File, error) {
714673 return file , nil
715674}
716675
676+ const (
677+ systemdSSLConf = "/etc/systemd/system.conf.d/podman-machine-ssl.conf"
678+ envdSSLConf = "/etc/environment.d/podman-machine-ssl.conf"
679+ profileSSLConf = "/etc/profile.d/podman-machine-ssl.sh"
680+ sslCertFile = "SSL_CERT_FILE"
681+ sslCertDir = "SSL_CERT_DIR"
682+ )
683+
684+ func getSSLEnvironmentFiles (sslFileName , sslDirName string ) []File {
685+ systemdFileContent := "[Manager]\n "
686+ envdFileContent := ""
687+ profileFileContent := ""
688+ if sslFileName != "" {
689+ // certs are written to UserCertsTargetPath see prepareCertFile()
690+ // Note the mix of path/filepath is intentional and required, we want to get the name of
691+ // a path on the client (i.e. windows) but then join to linux path that will be used inside the VM.
692+ env := fmt .Sprintf ("%s=%q\n " , sslCertFile , path .Join (define .UserCertsTargetPath , filepath .Base (sslFileName )))
693+ systemdFileContent += "DefaultEnvironment=" + env
694+ envdFileContent += env
695+ profileFileContent += "export " + env
696+ }
697+ if sslDirName != "" {
698+ // certs are written to UserCertsTargetPath see prepareCertFile()
699+ env := fmt .Sprintf ("%s=%q\n " , sslCertDir , define .UserCertsTargetPath )
700+ systemdFileContent += "DefaultEnvironment=" + env
701+ envdFileContent += env
702+ profileFileContent += "export " + env
703+ }
704+ return []File {
705+ getSSLFile (systemdSSLConf , systemdFileContent ),
706+ getSSLFile (envdSSLConf , envdFileContent ),
707+ getSSLFile (profileSSLConf , profileFileContent ),
708+ }
709+ }
710+
711+ func getSSLFile (path , content string ) File {
712+ return File {
713+ Node : Node {
714+ Group : GetNodeGrp ("root" ),
715+ Path : path ,
716+ User : GetNodeUsr ("root" ),
717+ },
718+ FileEmbedded1 : FileEmbedded1 {
719+ Contents : Resource {
720+ Source : EncodeDataURLPtr (content ),
721+ },
722+ Mode : IntToPtr (0644 ),
723+ },
724+ }
725+ }
726+
717727func getLinks (usrName string ) []Link {
718728 return []Link {{
719729 Node : Node {
0 commit comments