go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/connection/tar_test.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package connection_test
     5  
     6  import (
     7  	"io"
     8  	"net/http"
     9  	"os"
    10  	"regexp"
    11  	"testing"
    12  
    13  	"github.com/google/go-containerregistry/pkg/authn"
    14  	"github.com/google/go-containerregistry/pkg/name"
    15  	"github.com/google/go-containerregistry/pkg/v1/remote"
    16  	"github.com/google/go-containerregistry/pkg/v1/tarball"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  	"go.mondoo.com/cnquery/providers-sdk/v1/inventory"
    20  	"go.mondoo.com/cnquery/providers/os/connection"
    21  	"go.mondoo.com/cnquery/providers/os/connection/tar"
    22  )
    23  
    24  const (
    25  	alpineImage         = "alpine:3.9"
    26  	alpineContainerPath = "./alpine-container.tar"
    27  
    28  	centosImage         = "centos:7"
    29  	centosContainerPath = "./centos-container.tar"
    30  )
    31  
    32  func TestTarCommand(t *testing.T) {
    33  	err := cacheAlpine()
    34  	require.NoError(t, err, "should create tar without error")
    35  
    36  	c, err := connection.NewTarConnection(0, &inventory.Config{
    37  		Type: "tar",
    38  		Options: map[string]string{
    39  			connection.OPTION_FILE: alpineContainerPath,
    40  		},
    41  	}, nil)
    42  	assert.Equal(t, nil, err, "should create tar without error")
    43  
    44  	cmd, err := c.RunCommand("ls /")
    45  	assert.Nil(t, err)
    46  	if assert.NotNil(t, cmd) {
    47  		assert.Equal(t, nil, err, "should execute without error")
    48  		assert.Equal(t, -1, cmd.ExitStatus, "command should not be executed")
    49  		stdoutContent, _ := io.ReadAll(cmd.Stdout)
    50  		assert.Equal(t, "", string(stdoutContent), "output should be correct")
    51  		stderrContent, _ := io.ReadAll(cmd.Stdout)
    52  		assert.Equal(t, "", string(stderrContent), "output should be correct")
    53  	}
    54  }
    55  
    56  func TestPlatformIdentifier(t *testing.T) {
    57  	err := cacheAlpine()
    58  	require.NoError(t, err, "should create tar without error")
    59  
    60  	conn, err := connection.NewTarConnection(0, &inventory.Config{
    61  		Type: "tar",
    62  		Options: map[string]string{
    63  			connection.OPTION_FILE: alpineContainerPath,
    64  		},
    65  	}, nil)
    66  	require.NoError(t, err)
    67  	platformId, err := conn.Identifier()
    68  	require.NoError(t, err)
    69  	assert.True(t, len(platformId) > 0)
    70  }
    71  
    72  func TestTarSymlinkFile(t *testing.T) {
    73  	err := cacheAlpine()
    74  	require.NoError(t, err, "should create tar without error")
    75  
    76  	c, err := connection.NewTarConnection(0, &inventory.Config{
    77  		Type: "tar",
    78  		Options: map[string]string{
    79  			connection.OPTION_FILE: alpineContainerPath,
    80  		},
    81  	}, nil)
    82  	assert.Equal(t, nil, err, "should create tar without error")
    83  
    84  	f, err := c.FileSystem().Open("/bin/cat")
    85  	assert.Nil(t, err)
    86  	if assert.NotNil(t, f) {
    87  		assert.Equal(t, nil, err, "should execute without error")
    88  
    89  		p := f.Name()
    90  		assert.Equal(t, "/bin/cat", p, "path should be correct")
    91  
    92  		stat, err := f.Stat()
    93  		assert.Equal(t, nil, err, "should stat without error")
    94  		assert.Equal(t, int64(796240), stat.Size(), "should read file size")
    95  
    96  		content, err := io.ReadAll(f)
    97  		assert.Equal(t, nil, err, "should execute without error")
    98  		assert.Equal(t, 796240, len(content), "should read the full content")
    99  	}
   100  }
   101  
   102  // deactivate test for now for speedier testing
   103  // in contrast to alpine, the symlink on centos is pointing to a relative target and not an absolute one
   104  func TestTarRelativeSymlinkFileCentos(t *testing.T) {
   105  	err := cacheCentos()
   106  	require.NoError(t, err, "should create tar without error")
   107  
   108  	c, err := connection.NewTarConnection(0, &inventory.Config{
   109  		Type: "tar",
   110  		Options: map[string]string{
   111  			connection.OPTION_FILE: centosContainerPath,
   112  		},
   113  	}, nil)
   114  	assert.Equal(t, nil, err, "should create tar without error")
   115  
   116  	f, err := c.FileSystem().Open("/etc/redhat-release")
   117  	require.NoError(t, err)
   118  
   119  	if assert.NotNil(t, f) {
   120  		assert.Equal(t, nil, err, "should execute without error")
   121  
   122  		p := f.Name()
   123  		assert.Equal(t, "/etc/redhat-release", p, "path should be correct")
   124  
   125  		stat, err := f.Stat()
   126  		assert.Equal(t, nil, err, "should stat without error")
   127  		assert.Equal(t, int64(37), stat.Size(), "should read file size")
   128  
   129  		content, err := io.ReadAll(f)
   130  		assert.Equal(t, nil, err, "should execute without error")
   131  		assert.Equal(t, 37, len(content), "should read the full content")
   132  	}
   133  }
   134  
   135  func TestTarFile(t *testing.T) {
   136  	err := cacheAlpine()
   137  	require.NoError(t, err, "should create tar without error")
   138  
   139  	c, err := connection.NewTarConnection(0, &inventory.Config{
   140  		Type: "tar",
   141  		Options: map[string]string{
   142  			connection.OPTION_FILE: alpineContainerPath,
   143  		},
   144  	}, nil)
   145  	assert.Equal(t, nil, err, "should create tar without error")
   146  
   147  	f, err := c.FileSystem().Open("/etc/alpine-release")
   148  	assert.Nil(t, err)
   149  	if assert.NotNil(t, f) {
   150  		assert.Equal(t, nil, err, "should execute without error")
   151  
   152  		p := f.Name()
   153  		assert.Equal(t, "/etc/alpine-release", p, "path should be correct")
   154  
   155  		stat, err := f.Stat()
   156  		assert.Equal(t, int64(6), stat.Size(), "should read file size")
   157  		assert.Equal(t, nil, err, "should execute without error")
   158  
   159  		content, err := io.ReadAll(f)
   160  		assert.Equal(t, nil, err, "should execute without error")
   161  		assert.Equal(t, 6, len(content), "should read the full content")
   162  	}
   163  }
   164  
   165  func TestFilePermissions(t *testing.T) {
   166  	err := cacheAlpine()
   167  	require.NoError(t, err, "should create tar without error")
   168  
   169  	c, err := connection.NewTarConnection(0, &inventory.Config{
   170  		Type: "tar",
   171  		Options: map[string]string{
   172  			connection.OPTION_FILE: alpineContainerPath,
   173  		},
   174  	}, nil)
   175  	require.NoError(t, err)
   176  
   177  	path := "/etc/alpine-release"
   178  	details, err := c.FileInfo(path)
   179  	require.NoError(t, err)
   180  	assert.Equal(t, int64(0), details.Uid)
   181  	assert.Equal(t, int64(0), details.Gid)
   182  	assert.True(t, details.Size >= 0)
   183  	assert.Equal(t, false, details.Mode.IsDir())
   184  	assert.Equal(t, true, details.Mode.IsRegular())
   185  	assert.Equal(t, "-rw-r--r--", details.Mode.String())
   186  	assert.True(t, details.Mode.UserReadable())
   187  	assert.True(t, details.Mode.UserWriteable())
   188  	assert.False(t, details.Mode.UserExecutable())
   189  	assert.True(t, details.Mode.GroupReadable())
   190  	assert.False(t, details.Mode.GroupWriteable())
   191  	assert.False(t, details.Mode.GroupExecutable())
   192  	assert.True(t, details.Mode.OtherReadable())
   193  	assert.False(t, details.Mode.OtherWriteable())
   194  	assert.False(t, details.Mode.OtherExecutable())
   195  	assert.False(t, details.Mode.Suid())
   196  	assert.False(t, details.Mode.Sgid())
   197  	assert.False(t, details.Mode.Sticky())
   198  
   199  	path = "/etc"
   200  	details, err = c.FileInfo(path)
   201  	require.NoError(t, err)
   202  	assert.Equal(t, int64(0), details.Uid)
   203  	assert.Equal(t, int64(0), details.Gid)
   204  	assert.True(t, details.Size >= 0)
   205  	assert.True(t, details.Mode.IsDir())
   206  	assert.False(t, details.Mode.IsRegular())
   207  	assert.Equal(t, "drwxr-xr-x", details.Mode.String())
   208  	assert.True(t, details.Mode.UserReadable())
   209  	assert.True(t, details.Mode.UserWriteable())
   210  	assert.True(t, details.Mode.UserExecutable())
   211  	assert.True(t, details.Mode.GroupReadable())
   212  	assert.False(t, details.Mode.GroupWriteable())
   213  	assert.True(t, details.Mode.GroupExecutable())
   214  	assert.True(t, details.Mode.OtherReadable())
   215  	assert.False(t, details.Mode.OtherWriteable())
   216  	assert.True(t, details.Mode.OtherExecutable())
   217  	assert.False(t, details.Mode.Suid())
   218  	assert.False(t, details.Mode.Sgid())
   219  	assert.False(t, details.Mode.Sticky())
   220  }
   221  
   222  func TestTarFileFind(t *testing.T) {
   223  	err := cacheAlpine()
   224  	require.NoError(t, err, "should create tar without error")
   225  
   226  	c, err := connection.NewTarConnection(0, &inventory.Config{
   227  		Type: "tar",
   228  		Options: map[string]string{
   229  			connection.OPTION_FILE: alpineContainerPath,
   230  		},
   231  	}, nil)
   232  	assert.Equal(t, nil, err, "should create tar without error")
   233  
   234  	fs := c.FileSystem()
   235  
   236  	fSearch := fs.(*tar.FS)
   237  
   238  	infos, err := fSearch.Find("/", regexp.MustCompile(`alpine-release`), "file")
   239  	require.NoError(t, err)
   240  
   241  	assert.Equal(t, 1, len(infos))
   242  }
   243  
   244  func cacheAlpine() error {
   245  	return cacheImageToTar(alpineImage, alpineContainerPath)
   246  }
   247  
   248  func cacheCentos() error {
   249  	return cacheImageToTar(centosImage, centosContainerPath)
   250  }
   251  
   252  func cacheImageToTar(source string, filename string) error {
   253  	// check if the cache is already there
   254  	_, err := os.Stat(filename)
   255  	if err == nil {
   256  		return nil
   257  	}
   258  
   259  	tag, err := name.NewTag(source, name.WeakValidation)
   260  	if err != nil {
   261  		return err
   262  	}
   263  
   264  	auth, err := authn.DefaultKeychain.Resolve(tag.Registry)
   265  	if err != nil {
   266  		return err
   267  	}
   268  
   269  	img, err := remote.Image(tag, remote.WithAuth(auth), remote.WithTransport(http.DefaultTransport))
   270  	if err != nil {
   271  		return err
   272  	}
   273  
   274  	return tarball.WriteToFile(filename, tag, img)
   275  }