go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers-sdk/v1/inventory/ansibleinventory/inventory_test.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package ansibleinventory_test
     5  
     6  import (
     7  	"os"
     8  	"sort"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"go.mondoo.com/cnquery/providers-sdk/v1/inventory"
    13  	"go.mondoo.com/cnquery/providers-sdk/v1/inventory/ansibleinventory"
    14  	"go.mondoo.com/cnquery/providers-sdk/v1/vault"
    15  )
    16  
    17  func TestValidInventory(t *testing.T) {
    18  	assert.False(t, ansibleinventory.IsInventory([]byte{}))
    19  
    20  	iniFile := `
    21  [win]
    22  172.16.2.5 
    23  172.16.2.6 
    24  	`
    25  	assert.False(t, ansibleinventory.IsInventory([]byte(iniFile)))
    26  
    27  	jsonFile := `
    28  {
    29  	"_meta": {
    30  					"hostvars": {}
    31  	},
    32  	"ungrouped": {}
    33  }
    34  `
    35  	assert.False(t, ansibleinventory.IsInventory([]byte(jsonFile)))
    36  
    37  	jsonFile = `
    38  {
    39  	"all": {
    40  		"children": [
    41  				"local", 
    42  				"ungrouped"
    43  		]
    44  	}
    45  }
    46  `
    47  	assert.True(t, ansibleinventory.IsInventory([]byte(jsonFile)))
    48  }
    49  
    50  func TestParseInventory(t *testing.T) {
    51  	input, err := os.ReadFile("./testdata/empty.json")
    52  	assert.Nil(t, err)
    53  	assert.True(t, ansibleinventory.IsInventory(input))
    54  
    55  	inventory := ansibleinventory.Inventory{}
    56  	err = inventory.Decode(input)
    57  	assert.Nil(t, err)
    58  	assert.Equal(t, inventory.All.Children, []string{"ungrouped"})
    59  }
    60  
    61  func TestParseInventoryUngrouped(t *testing.T) {
    62  	input, err := os.ReadFile("./testdata/ungrouped.json")
    63  	assert.Nil(t, err)
    64  	assert.True(t, ansibleinventory.IsInventory(input))
    65  
    66  	inventory := ansibleinventory.Inventory{}
    67  	err = inventory.Decode(input)
    68  	assert.Nil(t, err)
    69  
    70  	assert.Equal(t, []string{"ungrouped", "workers"}, inventory.All.Children)
    71  	assert.Equal(t, ansibleinventory.Group{Hosts: []string{"34.244.38.44"}}, inventory.Groups["ungrouped"])
    72  }
    73  
    74  func TestFullInventory(t *testing.T) {
    75  	input, err := os.ReadFile("./testdata/inventory.json")
    76  	assert.Nil(t, err)
    77  	assert.True(t, ansibleinventory.IsInventory(input))
    78  
    79  	inventory := ansibleinventory.Inventory{}
    80  	err = inventory.Decode(input)
    81  	assert.Nil(t, err)
    82  
    83  	assert.Equal(t, []string{
    84  		"api",
    85  		"aws_ec2",
    86  		"payment",
    87  		"ungrouped",
    88  		"web",
    89  		"webservers",
    90  	}, inventory.All.Children)
    91  
    92  	assert.Equal(t, []string{"192.168.2.1", "192.168.2.2"}, inventory.Groups["api"].Hosts)
    93  	assert.Equal(t, []string{"ec2-34-242-192-191.eu-west-1.compute.amazonaws.com"}, inventory.Groups["aws_ec2"].Hosts)
    94  }
    95  
    96  func sortHosts(hosts []*ansibleinventory.Host) {
    97  	sort.SliceStable(hosts, func(i, j int) bool {
    98  		return hosts[i].Alias < hosts[j].Alias
    99  	})
   100  }
   101  
   102  func TestHostExtraction(t *testing.T) {
   103  	input, err := os.ReadFile("./testdata/ungrouped.json")
   104  	assert.Nil(t, err)
   105  	assert.True(t, ansibleinventory.IsInventory(input))
   106  
   107  	inventory := ansibleinventory.Inventory{}
   108  	err = inventory.Decode(input)
   109  	assert.Nil(t, err)
   110  
   111  	hosts := inventory.List()
   112  	assert.Equal(t, 3, len(hosts))
   113  
   114  	hosts = inventory.List("ungrouped")
   115  	assert.Equal(t, 1, len(hosts))
   116  
   117  	assert.Equal(t, []*ansibleinventory.Host{{
   118  		Alias:      "34.244.38.44",
   119  		Host:       "34.244.38.44",
   120  		Port:       "2222",
   121  		Connection: "ssh",
   122  	}}, hosts)
   123  
   124  	hosts = inventory.List("workers")
   125  	assert.Equal(t, 2, len(hosts))
   126  
   127  	// ensure order for equality check
   128  	sortHosts(hosts)
   129  
   130  	assert.Equal(t, []*ansibleinventory.Host{{
   131  		Alias:      "34.244.38.46",
   132  		Host:       "34.244.38.46",
   133  		User:       "ec2-user",
   134  		Port:       "22",
   135  		Connection: "ssh",
   136  	}, {
   137  		Alias:      "34.255.178.16",
   138  		Host:       "34.255.178.16",
   139  		User:       "ec2-user",
   140  		Identity:   "/Users/chartmann/.ssh/id_rsa",
   141  		Connection: "ssh",
   142  	}}, hosts)
   143  }
   144  
   145  // convert the ini via
   146  // ansible-inventory -i integrations/ansibleinventory/testdata/local.ini --list > integrations/ansibleinventory/testdata/local.json
   147  func TestHostConnectionLocal(t *testing.T) {
   148  	input, err := os.ReadFile("./testdata/local.json")
   149  	assert.Nil(t, err)
   150  	assert.True(t, ansibleinventory.IsInventory(input))
   151  
   152  	inventory := ansibleinventory.Inventory{}
   153  	err = inventory.Decode(input)
   154  	assert.Nil(t, err)
   155  
   156  	hosts := inventory.List()
   157  	assert.Equal(t, 1, len(hosts))
   158  
   159  	hosts = inventory.List("local")
   160  	assert.Equal(t, 1, len(hosts))
   161  
   162  	assert.Equal(t, []*ansibleinventory.Host{{
   163  		Alias:      "127.0.0.1",
   164  		Host:       "127.0.0.1",
   165  		Connection: "local",
   166  	}}, hosts)
   167  }
   168  
   169  // yq -y . integrations/ansibleinventory/testdata/local.json
   170  func TestHostConnectionLocalYaml(t *testing.T) {
   171  	input, err := os.ReadFile("./testdata/local.yaml")
   172  	assert.Nil(t, err)
   173  	assert.True(t, ansibleinventory.IsInventory(input))
   174  
   175  	inventory := ansibleinventory.Inventory{}
   176  	err = inventory.Decode(input)
   177  	assert.Nil(t, err)
   178  
   179  	hosts := inventory.List()
   180  	assert.Equal(t, 1, len(hosts))
   181  
   182  	hosts = inventory.List("local")
   183  	assert.Equal(t, 1, len(hosts))
   184  
   185  	assert.Equal(t, []*ansibleinventory.Host{{
   186  		Alias:      "127.0.0.1",
   187  		Host:       "127.0.0.1",
   188  		Connection: "local",
   189  	}}, hosts)
   190  }
   191  
   192  // convert winrm.ini via
   193  // ansible-inventory -i integrations/ansibleinventory/testdata/windows.ini --list > integrations/ansibleinventory/testdata/windows.json
   194  func TestHostConnectionWinrm(t *testing.T) {
   195  	input, err := os.ReadFile("./testdata/winrm.json")
   196  	assert.Nil(t, err)
   197  	assert.True(t, ansibleinventory.IsInventory(input))
   198  
   199  	inventory := ansibleinventory.Inventory{}
   200  	err = inventory.Decode(input)
   201  	assert.Nil(t, err)
   202  
   203  	hosts := inventory.List()
   204  	assert.Equal(t, 2, len(hosts))
   205  
   206  	hosts = inventory.List("win")
   207  	assert.Equal(t, 2, len(hosts))
   208  
   209  	// ensure order for equality check
   210  	sortHosts(hosts)
   211  
   212  	assert.Equal(t, []*ansibleinventory.Host{{
   213  		Alias:      "172.16.2.5",
   214  		Host:       "172.16.2.5",
   215  		User:       "vagrant",
   216  		Password:   "password",
   217  		Connection: "winrm",
   218  	}, {
   219  		Alias:      "172.16.2.6",
   220  		Host:       "172.16.2.6",
   221  		User:       "vagrant",
   222  		Password:   "password",
   223  		Connection: "winrm",
   224  	}}, hosts)
   225  }
   226  
   227  func TestHostSSHPrivateKey(t *testing.T) {
   228  	input, err := os.ReadFile("./testdata/ssh_private_key.json")
   229  	assert.Nil(t, err)
   230  	assert.True(t, ansibleinventory.IsInventory(input))
   231  
   232  	inventory := ansibleinventory.Inventory{}
   233  	err = inventory.Decode(input)
   234  	assert.Nil(t, err)
   235  
   236  	hosts := inventory.List()
   237  	assert.Equal(t, 1, len(hosts))
   238  
   239  	assert.Equal(t, []*ansibleinventory.Host{{
   240  		Alias:      "instance1",
   241  		Host:       "192.168.178.11",
   242  		User:       "custom-user",
   243  		Identity:   "/home/custom-user/.ssh/id_rsa",
   244  		Connection: "ssh",
   245  	}}, hosts)
   246  }
   247  
   248  func TestInventoryConversion(t *testing.T) {
   249  	input, err := os.ReadFile("./testdata/inventory.json")
   250  	assert.Nil(t, err)
   251  	assert.True(t, ansibleinventory.IsInventory(input))
   252  
   253  	ansibleInventory := ansibleinventory.Inventory{}
   254  	err = ansibleInventory.Decode(input)
   255  	assert.Nil(t, err)
   256  
   257  	v1Inventory := ansibleInventory.ToV1Inventory()
   258  
   259  	assert.Equal(t, 8, len(v1Inventory.Spec.Assets))
   260  }
   261  
   262  func TestInventoryWithUsernameConversion(t *testing.T) {
   263  	input, err := os.ReadFile("./testdata/hosts.json")
   264  	assert.Nil(t, err)
   265  	assert.True(t, ansibleinventory.IsInventory(input))
   266  
   267  	ansibleInventory := ansibleinventory.Inventory{}
   268  	err = ansibleInventory.Decode(input)
   269  	assert.Nil(t, err)
   270  
   271  	v1Inventory := ansibleInventory.ToV1Inventory()
   272  	assert.Equal(t, 2, len(v1Inventory.Spec.Assets))
   273  
   274  	a := findAsset(v1Inventory.Spec.Assets, "instance1")
   275  	assert.NotNil(t, a)
   276  	assert.Equal(t, "104.154.55.51", a.Connections[0].Host)
   277  	secretId := a.Connections[0].Credentials[0].SecretId
   278  	cred := v1Inventory.Spec.Credentials[secretId]
   279  	assert.Equal(t, "chris", cred.User)
   280  	assert.Equal(t, vault.CredentialType_ssh_agent, cred.Type)
   281  
   282  	a = findAsset(v1Inventory.Spec.Assets, "34.133.130.53")
   283  	assert.NotNil(t, a)
   284  	assert.Equal(t, "34.133.130.53", a.Connections[0].Host)
   285  	secretId = a.Connections[0].Credentials[0].SecretId
   286  	cred = v1Inventory.Spec.Credentials[secretId]
   287  	assert.Equal(t, "chris", cred.User)
   288  	assert.Equal(t, vault.CredentialType_ssh_agent, cred.Type)
   289  }
   290  
   291  func TestTagsAndGroups(t *testing.T) {
   292  	input, err := os.ReadFile("./testdata/tags_groups.json")
   293  	assert.Nil(t, err)
   294  	assert.True(t, ansibleinventory.IsInventory(input))
   295  
   296  	ansibleInventory := ansibleinventory.Inventory{}
   297  	err = ansibleInventory.Decode(input)
   298  	assert.Nil(t, err)
   299  
   300  	hosts := ansibleInventory.List()
   301  	assert.Equal(t, 1, len(hosts))
   302  
   303  	assert.Equal(t, []*ansibleinventory.Host{{
   304  		Alias:      "instance1",
   305  		Host:       "192.168.178.11",
   306  		User:       "custom-user",
   307  		Identity:   "/home/custom-user/.ssh/id_rsa",
   308  		Connection: "ssh",
   309  		Labels:     []string{"ansible_host", "mondoo_agent"},
   310  	}}, hosts)
   311  
   312  	// convert to mondoo inventory
   313  	v1Inventory := ansibleInventory.ToV1Inventory()
   314  	assert.Equal(t, 1, len(v1Inventory.Spec.Assets))
   315  
   316  	a := findAsset(v1Inventory.Spec.Assets, "instance1")
   317  	assert.NotNil(t, a)
   318  	assert.Equal(t, "192.168.178.11", a.Connections[0].Host)
   319  	secretId := a.Connections[0].Credentials[0].SecretId
   320  	cred := v1Inventory.Spec.Credentials[secretId]
   321  	assert.Equal(t, "custom-user", cred.User)
   322  	assert.Equal(t, vault.CredentialType_private_key, cred.Type)
   323  	assert.Equal(t, "/home/custom-user/.ssh/id_rsa", cred.PrivateKeyPath)
   324  }
   325  
   326  func findAsset(assetList []*inventory.Asset, name string) *inventory.Asset {
   327  	for i := range assetList {
   328  		if assetList[i].Name == name {
   329  			return assetList[i]
   330  		}
   331  	}
   332  	return nil
   333  }