github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/fanal/test/integration/docker/docker.go (about) 1 package docker 2 3 import ( 4 "context" 5 "encoding/base64" 6 "encoding/json" 7 "fmt" 8 "io" 9 "net/url" 10 "os" 11 "os/exec" 12 13 "github.com/docker/docker/client" 14 15 "github.com/docker/docker/api/types" 16 ) 17 18 type RegistryConfig struct { 19 URL *url.URL 20 Username string 21 Password string 22 } 23 24 func (c RegistryConfig) GetAuthConfig() types.AuthConfig { 25 return types.AuthConfig{ 26 Username: c.Username, 27 Password: c.Password, 28 ServerAddress: c.URL.Host, 29 } 30 } 31 32 func (c RegistryConfig) GetRegistryAuth() (string, error) { 33 authConfig := types.AuthConfig{ 34 Username: c.Username, 35 Password: c.Password, 36 } 37 encodedJSON, err := json.Marshal(authConfig) 38 if err != nil { 39 return "", err 40 } 41 return base64.URLEncoding.EncodeToString(encodedJSON), nil 42 } 43 44 func (c RegistryConfig) GetBasicAuthorization() string { 45 return fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", c.Username, c.Password)))) 46 } 47 48 type Docker struct { 49 cli *client.Client 50 } 51 52 func New() (Docker, error) { 53 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) 54 if err != nil { 55 return Docker{}, err 56 } 57 return Docker{ 58 cli: cli, 59 }, nil 60 } 61 62 func (d Docker) Login(conf RegistryConfig) error { 63 auth := conf.GetAuthConfig() 64 return exec.Command("docker", "login", "-u", auth.Username, "-p", auth.Password, auth.ServerAddress).Run() 65 } 66 67 func (d Docker) Logout(conf RegistryConfig) error { 68 auth := conf.GetAuthConfig() 69 return exec.Command("docker", "logout", auth.ServerAddress).Run() 70 } 71 72 // ReplicateImage tags the given imagePath and pushes it to the given dest registry. 73 func (d Docker) ReplicateImage(ctx context.Context, imageRef, imagePath string, dest RegistryConfig) error { 74 // remove existing Image if any 75 _, _ = d.cli.ImageRemove(ctx, imageRef, types.ImageRemoveOptions{ 76 Force: true, 77 PruneChildren: true, 78 }) 79 80 testfile, err := os.Open(imagePath) 81 if err != nil { 82 return err 83 } 84 85 // load image into docker engine 86 resp, err := d.cli.ImageLoad(ctx, testfile, true) 87 if err != nil { 88 return err 89 } 90 if _, err := io.Copy(io.Discard, resp.Body); err != nil { 91 return err 92 } 93 defer resp.Body.Close() 94 95 targetImageRef := fmt.Sprintf("%s/%s", dest.URL.Host, imageRef) 96 97 if err = d.cli.ImageTag(ctx, imageRef, targetImageRef); err != nil { 98 return err 99 } 100 defer func() { 101 _, _ = d.cli.ImageRemove(ctx, imageRef, types.ImageRemoveOptions{ 102 Force: true, 103 PruneChildren: true, 104 }) 105 _, _ = d.cli.ImageRemove(ctx, targetImageRef, types.ImageRemoveOptions{ 106 Force: true, 107 PruneChildren: true, 108 }) 109 }() 110 111 auth, err := dest.GetRegistryAuth() 112 if err != nil { 113 return err 114 } 115 116 pushOut, err := d.cli.ImagePush(ctx, targetImageRef, types.ImagePushOptions{RegistryAuth: auth}) 117 if err != nil { 118 return err 119 } 120 defer pushOut.Close() 121 122 if _, err = io.Copy(io.Discard, pushOut); err != nil { 123 return err 124 } 125 return nil 126 }