@@ -41,6 +41,7 @@ import (
41
41
"github.com/distribution/distribution/v3/configuration"
42
42
"github.com/distribution/distribution/v3/registry/handlers"
43
43
_ "github.com/distribution/distribution/v3/registry/storage/driver/filesystem"
44
+ dockerconfig "github.com/docker/cli/cli/config"
44
45
"github.com/docker/cli/cli/config/configfile"
45
46
"github.com/fatih/color"
46
47
v1 "github.com/google/go-containerregistry/pkg/v1"
@@ -56,7 +57,7 @@ import (
56
57
var ErrNoFallbackImage = errors .New ("no fallback image has been specified" )
57
58
58
59
// DockerConfig represents the Docker configuration file.
59
- type DockerConfig configfile.ConfigFile
60
+ type DockerConfig = configfile.ConfigFile
60
61
61
62
type runtimeDataStore struct {
62
63
// Runtime data.
@@ -1567,8 +1568,8 @@ func maybeDeleteFilesystem(logger log.Func, force bool) error {
1567
1568
}
1568
1569
1569
1570
func fileExists (fs billy.Filesystem , path string ) bool {
1570
- _ , err := fs .Stat (path )
1571
- return err == nil
1571
+ fi , err := fs .Stat (path )
1572
+ return err == nil && ! fi . IsDir ()
1572
1573
}
1573
1574
1574
1575
func readFile (fs billy.Filesystem , name string ) ([]byte , error ) {
@@ -1656,88 +1657,150 @@ func parseMagicImageFile(fs billy.Filesystem, path string, v any) error {
1656
1657
return nil
1657
1658
}
1658
1659
1660
+ const (
1661
+ dockerConfigFile = dockerconfig .ConfigFileName
1662
+ dockerConfigEnvKey = dockerconfig .EnvOverrideConfigDir
1663
+ )
1664
+
1665
+ // initDockerConfigOverride sets the DOCKER_CONFIG environment variable
1666
+ // to a path within the working directory. If a base64 encoded Docker
1667
+ // config is provided, it is written to the path/config.json and the
1668
+ // DOCKER_CONFIG environment variable is set to the path. If no base64
1669
+ // encoded Docker config is provided, the following paths are checked in
1670
+ // order:
1671
+ //
1672
+ // 1. $DOCKER_CONFIG/config.json
1673
+ // 2. $DOCKER_CONFIG
1674
+ // 3. /.envbuilder/config.json
1675
+ //
1676
+ // If a Docker config file is found, its path is set as DOCKER_CONFIG.
1659
1677
func initDockerConfigOverride (bfs billy.Filesystem , logf log.Func , workingDir workingdir.WorkingDir , dockerConfigBase64 string ) (func () error , error ) {
1660
- configFile := "config.json"
1661
- oldDockerConfig := os .Getenv ("DOCKER_CONFIG" )
1662
- newDockerConfig := workingDir .Path ()
1678
+ // If dockerConfigBase64 is set, it will have priority over file
1679
+ // detection.
1680
+ var dockerConfigJSON []byte
1681
+ var err error
1682
+ if dockerConfigBase64 != "" {
1683
+ logf (log .LevelInfo , "Using base64 encoded Docker config" )
1684
+
1685
+ dockerConfigJSON , err = base64 .StdEncoding .DecodeString (dockerConfigBase64 )
1686
+ if err != nil {
1687
+ return nil , fmt .Errorf ("decode docker config: %w" , err )
1688
+ }
1689
+ }
1663
1690
1664
- err := os .Setenv ( "DOCKER_CONFIG" , newDockerConfig )
1665
- if err != nil {
1666
- logf ( log . LevelError , "Failed to set DOCKER_CONFIG: %s" , err )
1667
- return nil , fmt . Errorf ( "set DOCKER_CONFIG: %w" , err )
1691
+ oldDockerConfig := os .Getenv ( dockerConfigEnvKey )
1692
+ var oldDockerConfigFile string
1693
+ if oldDockerConfig != "" {
1694
+ oldDockerConfigFile = filepath . Join ( oldDockerConfig , dockerConfigFile )
1668
1695
}
1669
- logf (log .LevelInfo , "Set DOCKER_CONFIG to %s" , newDockerConfig )
1670
- restoreEnv := onceErrFunc (func () error {
1671
- // Restore the old DOCKER_CONFIG value.
1672
- if err := func () error {
1673
- if oldDockerConfig == "" {
1674
- return os .Unsetenv ("DOCKER_CONFIG" )
1675
- }
1676
- return os .Setenv ("DOCKER_CONFIG" , oldDockerConfig )
1677
- }(); err != nil {
1678
- return fmt .Errorf ("restore DOCKER_CONFIG: %w" , err )
1696
+ for _ , path := range []string {
1697
+ oldDockerConfigFile , // $DOCKER_CONFIG/config.json
1698
+ oldDockerConfig , // $DOCKER_CONFIG
1699
+ workingDir .Join (dockerConfigFile ), // /.envbuilder/config.json
1700
+ } {
1701
+ if path == "" || ! fileExists (bfs , path ) {
1702
+ continue
1679
1703
}
1680
- logf (log .LevelInfo , "Restored DOCKER_CONFIG to %s" , oldDockerConfig )
1681
- return nil
1682
- })
1683
1704
1684
- // If the user hasn't set the BASE64 encoded Docker config, we
1685
- // should respect the DOCKER_CONFIG environment variable.
1686
- oldDockerConfigFile := filepath . Join ( oldDockerConfig , configFile )
1687
- if dockerConfigBase64 == "" && fileExists ( bfs , oldDockerConfigFile ) {
1688
- // It's possible that the target file is mounted and needs to
1689
- // be remounted later, so we should copy the file instead of
1690
- // hoping that the file is still there when we build.
1691
- logf ( log . LevelInfo , "Using DOCKER_CONFIG at %s " , oldDockerConfig )
1692
- b , err := readFile ( bfs , oldDockerConfigFile )
1693
- if err != nil {
1694
- return nil , fmt . Errorf ( "read existing DOCKER_CONFIG: %w " , err )
1705
+ logf ( log . LevelWarn , "Found Docker config at %s, this file will remain after the build" , path )
1706
+
1707
+ if dockerConfigJSON == nil {
1708
+ logf ( log . LevelInfo , "Using Docker config at %s" , path )
1709
+
1710
+ dockerConfigJSON , err = readFile ( bfs , path )
1711
+ if err != nil {
1712
+ return nil , fmt . Errorf ( "read docker config: %w " , err )
1713
+ }
1714
+ } else {
1715
+ logf ( log . LevelWarn , "Ignoring Docker config at %s, using base64 encoded Docker config instead " , path )
1695
1716
}
1696
- // Read into dockerConfigBase64 so we can keep the same logic.
1697
- dockerConfigBase64 = base64 .StdEncoding .EncodeToString (b )
1717
+ break
1698
1718
}
1699
1719
1700
- if dockerConfigBase64 == "" {
1701
- return restoreEnv , nil
1720
+ if dockerConfigJSON == nil {
1721
+ // No user-provided config available.
1722
+ return func () error { return nil }, nil
1702
1723
}
1703
1724
1704
- decoded , err := base64 . StdEncoding . DecodeString ( dockerConfigBase64 )
1725
+ dockerConfigJSON , err = hujson . Standardize ( dockerConfigJSON )
1705
1726
if err != nil {
1706
- return restoreEnv , fmt .Errorf ("decode docker config: %w" , err )
1727
+ return nil , fmt .Errorf ("humanize json for docker config: %w" , err )
1707
1728
}
1708
- decoded , err = hujson . Standardize ( decoded )
1709
- if err != nil {
1710
- return restoreEnv , fmt .Errorf ("humanize json for docker config : %w" , err )
1729
+
1730
+ if err = logDockerAuthConfigs ( logf , dockerConfigJSON ); err != nil {
1731
+ return nil , fmt .Errorf ("log docker auth configs : %w" , err )
1711
1732
}
1712
- var dockerConfig DockerConfig
1713
- err = json .Unmarshal (decoded , & dockerConfig )
1733
+
1734
+ // We're going to set the DOCKER_CONFIG environment variable to a
1735
+ // path within the working directory so that Kaniko can pick it up.
1736
+ // A user should not mount a file directly to this path as we will
1737
+ // write to the file.
1738
+ newDockerConfig := workingDir .Join (".docker" )
1739
+ newDockerConfigFile := filepath .Join (newDockerConfig , dockerConfigFile )
1740
+ err = bfs .MkdirAll (newDockerConfig , 0o700 )
1714
1741
if err != nil {
1715
- return restoreEnv , fmt .Errorf ("parse docker config: %w" , err )
1742
+ return nil , fmt .Errorf ("create docker config dir : %w" , err )
1716
1743
}
1717
- for k := range dockerConfig .AuthConfigs {
1718
- logf (log .LevelInfo , "Docker config contains auth for registry %q" , k )
1744
+
1745
+ if fileExists (bfs , newDockerConfigFile ) {
1746
+ return nil , fmt .Errorf ("unable to write Docker config file, file already exists: %s" , newDockerConfigFile )
1719
1747
}
1720
1748
1721
- newDockerConfigFile := filepath .Join (newDockerConfig , configFile )
1722
- err = writeFile (bfs , newDockerConfigFile , decoded , 0o644 )
1749
+ restoreEnv , err := setAndRestoreEnv (logf , dockerConfigEnvKey , newDockerConfig )
1723
1750
if err != nil {
1724
- return restoreEnv , fmt .Errorf ("write docker config: %w" , err )
1751
+ return nil , fmt .Errorf ("set docker config override: %w" , err )
1752
+ }
1753
+
1754
+ err = writeFile (bfs , newDockerConfigFile , dockerConfigJSON , 0o600 )
1755
+ if err != nil {
1756
+ _ = restoreEnv () // Best effort.
1757
+ return nil , fmt .Errorf ("write docker config: %w" , err )
1725
1758
}
1726
1759
logf (log .LevelInfo , "Wrote Docker config JSON to %s" , newDockerConfigFile )
1727
1760
1728
- cleanup := onceErrFunc (func () error {
1729
- err := restoreEnv ()
1761
+ cleanupFile := onceErrFunc (func () error {
1730
1762
// Remove the Docker config secret file!
1731
- if err2 := os .Remove (newDockerConfigFile ); err2 != nil {
1732
- if ! errors .Is (err2 , fs .ErrNotExist ) {
1733
- err2 = fmt .Errorf ("remove docker config: %w" , err2 )
1734
- }
1735
- logf (log .LevelError , "Failed to remove the Docker config secret file: %s" , err2 )
1736
- err = errors .Join (err , err2 )
1763
+ if err := bfs .Remove (newDockerConfigFile ); err != nil {
1764
+ logf (log .LevelError , "Failed to remove the Docker config secret file: %s" , err )
1765
+ return fmt .Errorf ("remove docker config: %w" , err )
1737
1766
}
1738
- return err
1767
+ return nil
1739
1768
})
1740
- return cleanup , nil
1769
+ return func () error { return errors .Join (cleanupFile (), restoreEnv ()) }, nil
1770
+ }
1771
+
1772
+ func logDockerAuthConfigs (logf log.Func , dockerConfigJSON []byte ) error {
1773
+ dc := new (DockerConfig )
1774
+ err := dc .LoadFromReader (bytes .NewReader (dockerConfigJSON ))
1775
+ if err != nil {
1776
+ return fmt .Errorf ("load docker config: %w" , err )
1777
+ }
1778
+ for k := range dc .AuthConfigs {
1779
+ logf (log .LevelInfo , "Docker config contains auth for registry %q" , k )
1780
+ }
1781
+ return nil
1782
+ }
1783
+
1784
+ func setAndRestoreEnv (logf log.Func , key , value string ) (restore func () error , err error ) {
1785
+ old := os .Getenv (key )
1786
+ err = os .Setenv (key , value )
1787
+ if err != nil {
1788
+ logf (log .LevelError , "Failed to set %s: %s" , key , err )
1789
+ return nil , fmt .Errorf ("set %s: %w" , key , err )
1790
+ }
1791
+ logf (log .LevelInfo , "Set %s to %s" , key , value )
1792
+ return onceErrFunc (func () error {
1793
+ if err := func () error {
1794
+ if old == "" {
1795
+ return os .Unsetenv (key )
1796
+ }
1797
+ return os .Setenv (key , old )
1798
+ }(); err != nil {
1799
+ return fmt .Errorf ("restore %s: %w" , key , err )
1800
+ }
1801
+ logf (log .LevelInfo , "Restored %s to %s" , key , old )
1802
+ return nil
1803
+ }), nil
1741
1804
}
1742
1805
1743
1806
func onceErrFunc (f func () error ) func () error {
0 commit comments