go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/discovery/docker_engine/container.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package docker_engine
     5  
     6  import (
     7  	"context"
     8  	"strings"
     9  
    10  	"github.com/docker/docker/api/types"
    11  	"github.com/rs/zerolog/log"
    12  	"go.mondoo.com/cnquery/providers-sdk/v1/inventory"
    13  	"go.mondoo.com/cnquery/providers/os/id/containerid"
    14  )
    15  
    16  func (e *dockerEngineDiscovery) containerList() ([]types.Container, error) {
    17  	dc, err := e.client()
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  
    22  	return dc.ContainerList(context.Background(), types.ContainerListOptions{})
    23  }
    24  
    25  func (e *dockerEngineDiscovery) ListContainerShas() ([]string, error) {
    26  	containers, err := e.containerList()
    27  	if err != nil {
    28  		return []string{}, err
    29  	}
    30  
    31  	containerShas := []string{}
    32  	for i := range containers {
    33  		containerShas = append(containerShas, containers[i].ID)
    34  	}
    35  
    36  	return containerShas, nil
    37  }
    38  
    39  type ContainerInfo struct {
    40  	ID         string
    41  	Name       string
    42  	PlatformID string
    43  	Running    bool
    44  	Labels     map[string]string
    45  	Arch       string
    46  }
    47  
    48  // will resolve name and id to a container id
    49  func (e *dockerEngineDiscovery) ContainerInfo(name string) (ContainerInfo, error) {
    50  	ci := ContainerInfo{}
    51  	dc, err := e.client()
    52  	if err != nil {
    53  		return ci, err
    54  	}
    55  
    56  	cdata, err := dc.ContainerInspect(context.Background(), name)
    57  	if err != nil {
    58  		return ci, err
    59  	}
    60  
    61  	cName := cdata.Name
    62  	cName = strings.TrimPrefix(cName, "/")
    63  	if len(cName) == 0 {
    64  		cName = containerid.ShortContainerID(cdata.ID)
    65  	}
    66  
    67  	ci.ID = cdata.ID
    68  	ci.Name = cName
    69  	ci.PlatformID = containerid.MondooContainerID(ci.ID)
    70  	ci.Running = cdata.State.Running
    71  
    72  	// fetch docker specific metadata
    73  	labels := map[string]string{}
    74  	labels["docker.io/container-id"] = cdata.ID
    75  	labels["docker.io/image-name"] = cdata.Image
    76  	labels["docker.io/names"] = cName
    77  
    78  	ci.Labels = labels
    79  
    80  	return ci, nil
    81  }
    82  
    83  type ImageInfo struct {
    84  	ID         string
    85  	Name       string
    86  	PlatformID string
    87  	Labels     map[string]string
    88  	Arch       string
    89  	// Size in megabytes
    90  	Size int64
    91  }
    92  
    93  func (e *dockerEngineDiscovery) ImageInfo(name string) (ImageInfo, error) {
    94  	ii := ImageInfo{}
    95  	dc, err := e.client()
    96  	if err != nil {
    97  		return ii, err
    98  	}
    99  
   100  	res, _, err := dc.ImageInspectWithRaw(context.Background(), name)
   101  	if err != nil {
   102  		return ii, err
   103  	}
   104  
   105  	switch res.Architecture {
   106  	case "amd64":
   107  		ii.Arch = "x86_64"
   108  	}
   109  
   110  	ii.Size = res.Size / 1024 / 1024
   111  
   112  	labels := map[string]string{}
   113  	labels["mondoo.com/image-id"] = res.ID
   114  	labels["docker.io/tags"] = strings.Join(res.RepoTags, ",")
   115  	labels["docker.io/digests"] = strings.Join(res.RepoDigests, ",")
   116  
   117  	if len(res.RepoTags) > 0 {
   118  		ii.Name = res.RepoTags[0] + "@"
   119  	}
   120  	ii.Name = ii.Name + containerid.ShortContainerImageID(res.ID)
   121  	ii.ID = res.ID
   122  	ii.Labels = labels
   123  	ii.PlatformID = containerid.MondooContainerImageID(res.ID)
   124  	return ii, nil
   125  }
   126  
   127  func (e *dockerEngineDiscovery) ListContainer() ([]*inventory.Asset, error) {
   128  	dContainers, err := e.containerList()
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  
   133  	container := make([]*inventory.Asset, len(dContainers))
   134  	for i, dContainer := range dContainers {
   135  		asset := &inventory.Asset{
   136  			Connections: []*inventory.Config{
   137  				{
   138  					Type: "docker-container",
   139  					Host: dContainer.ID,
   140  				},
   141  			},
   142  		}
   143  		log.Debug().Str("container", dContainer.ID).Msg("discovered container")
   144  
   145  		container[i] = asset
   146  	}
   147  	return container, nil
   148  }
   149  
   150  func mapContainerState(state string) inventory.State {
   151  	switch state {
   152  	case "running":
   153  		return inventory.State_STATE_RUNNING
   154  	case "created":
   155  		return inventory.State_STATE_PENDING
   156  	case "paused":
   157  		return inventory.State_STATE_STOPPED
   158  	case "exited":
   159  		return inventory.State_STATE_TERMINATED
   160  	case "restarting":
   161  		return inventory.State_STATE_PENDING
   162  	case "dead":
   163  		return inventory.State_STATE_ERROR
   164  	default:
   165  		log.Warn().Str("state", state).Msg("unknown container state")
   166  		return inventory.State_STATE_UNKNOWN
   167  	}
   168  }
   169  
   170  // DockerDisplayNames removes the leading slash of the internal docker name
   171  // @see  https://github.com/moby/moby/issues/6705
   172  func DockerDisplayNames(names []string) []string {
   173  	if names == nil {
   174  		return nil
   175  	}
   176  
   177  	displayNames := make([]string, len(names))
   178  	for i := range names {
   179  		displayNames[i] = strings.TrimLeft(names[i], "/")
   180  	}
   181  
   182  	return displayNames
   183  }