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  }