From 4e32ba675075ea5292a85ce90dc9ddf5860d66f1 Mon Sep 17 00:00:00 2001 From: Christoph Hartmann Date: Fri, 15 Mar 2024 07:10:15 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B9=20make=20ansible=20inventory=20par?= =?UTF-8?q?ser=20more=20restrict=20(#3572)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- explorer/scan/discovery.go | 2 +- .../inventory/ansibleinventory/inventory.go | 14 +++++--- .../ansibleinventory/inventory_test.go | 35 +++++++++++++++++++ providers-sdk/v1/inventory/inventory.go | 17 ++++++--- 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/explorer/scan/discovery.go b/explorer/scan/discovery.go index 200afdf2ab..3501aa5fce 100644 --- a/explorer/scan/discovery.go +++ b/explorer/scan/discovery.go @@ -74,7 +74,7 @@ func (d *DiscoveredAssets) GetAssetsByPlatformID(platformID string) []*AssetWith func DiscoverAssets(ctx context.Context, inv *inventory.Inventory, upstream *upstream.UpstreamConfig, recording llx.Recording) (*DiscoveredAssets, error) { im, err := manager.NewManager(manager.WithInventory(inv, providers.DefaultRuntime())) if err != nil { - return nil, errors.New("failed to resolve inventory for connection") + return nil, errors.New("failed to resolve inventory for connection: " + err.Error()) } invAssets := im.GetAssets() if len(invAssets) == 0 { diff --git a/providers-sdk/v1/inventory/ansibleinventory/inventory.go b/providers-sdk/v1/inventory/ansibleinventory/inventory.go index 7a851fe296..759463f7c7 100644 --- a/providers-sdk/v1/inventory/ansibleinventory/inventory.go +++ b/providers-sdk/v1/inventory/ansibleinventory/inventory.go @@ -30,6 +30,10 @@ type All struct { } func Parse(data []byte) (*Inventory, error) { + if !IsInventory(data) { + return nil, errors.New("unsupported ansible inventory, use `ansible-inventory -i {inventory} --list` to convert it first") + } + inventory := Inventory{} err := inventory.Decode(data) if err != nil { @@ -52,13 +56,15 @@ func IsInventory(data []byte) bool { return false } - // if the all key is there, its a ansible yaml + // if the all key is there, its a ansible format // NOTE: as this point we only support fully resolved ansible config _, ok := raw["all"] - if ok { - return true + if !ok { + return false } - return false + + _, ok = raw["_meta"] + return ok } func (i *Inventory) Decode(data []byte) error { diff --git a/providers-sdk/v1/inventory/ansibleinventory/inventory_test.go b/providers-sdk/v1/inventory/ansibleinventory/inventory_test.go index b451315ee9..4d04200938 100644 --- a/providers-sdk/v1/inventory/ansibleinventory/inventory_test.go +++ b/providers-sdk/v1/inventory/ansibleinventory/inventory_test.go @@ -43,6 +43,41 @@ func TestValidInventory(t *testing.T) { ] } } +` + assert.False(t, ansibleinventory.IsInventory([]byte(jsonFile))) + + jsonFile = ` +all: + hosts: + ub2204: + ansible_host: 34.69.247.108 + ansible_user: chris + ansible_ssh_private_key_file: ~/.ssh/id_ed25519 +` + assert.False(t, ansibleinventory.IsInventory([]byte(jsonFile))) + + jsonFile = ` +{ + "_meta": { + "hostvars": { + "ub2204": { + "ansible_host": "34.69.247.108", + "ansible_ssh_private_key_file": "~/.ssh/id_ed25519", + "ansible_user": "chris" + } + } + }, + "all": { + "children": [ + "ungrouped" + ] + }, + "ungrouped": { + "hosts": [ + "ub2204" + ] + } +} ` assert.True(t, ansibleinventory.IsInventory([]byte(jsonFile))) } diff --git a/providers-sdk/v1/inventory/inventory.go b/providers-sdk/v1/inventory/inventory.go index b676cc63de..b555275cfa 100644 --- a/providers-sdk/v1/inventory/inventory.go +++ b/providers-sdk/v1/inventory/inventory.go @@ -5,6 +5,7 @@ package inventory import ( "os" + "os/user" "path/filepath" "strings" @@ -172,10 +173,18 @@ func (p *Inventory) PreProcess() error { if cred.PrivateKeyPath != "" { path := cred.PrivateKeyPath - // special handling for relative filenames, instead of loading - // private keys from relative to the work directory, we want to - // load the files relative to the source inventory - if !filepath.IsAbs(cred.PrivateKeyPath) { + if strings.HasPrefix(path, "~/") { + // special handling for ~ + usr, err := user.Current() + if err != nil { + return err + } + path = filepath.Join(usr.HomeDir, path[2:]) + } else if !filepath.IsAbs(cred.PrivateKeyPath) { + // special handling for relative filenames, instead of loading + // private keys from relative to the work directory, we want to + // load the files relative to the source inventory + // we handle credentials relative to the inventory file fileLoc, ok := p.Metadata.Labels[InventoryFilePath] if ok {