Skip to content

Commit

Permalink
⭐️ github terraform discovery (#4109)
Browse files Browse the repository at this point in the history
* ⭐️ github terraform discovery

Signed-off-by: Ivan Milchev <[email protected]>

* use github search api when looking for terraform files

Signed-off-by: Ivan Milchev <[email protected]>

---------

Signed-off-by: Ivan Milchev <[email protected]>
  • Loading branch information
imilchev authored May 27, 2024
1 parent 98bd4ad commit 981a931
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
2 changes: 1 addition & 1 deletion providers/github/connection/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const (
DiscoveryRepository = "repository" // deprecated: use repos
DiscoveryUser = "user" // deprecated: use users
DiscoveryOrganization = "organization"
DiscoveryTerraform = "terraform"
)

var (
Expand Down Expand Up @@ -62,7 +63,6 @@ func (c *GithubConnection) PlatformInfo() (*inventory.Platform, error) {
}

if userId := conf.Options["user"]; userId != "" {

return NewGithubUserPlatform(userId), nil
}

Expand Down
62 changes: 62 additions & 0 deletions providers/github/resources/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@
package resources

import (
"context"
"strings"

"github.com/gobwas/glob"
"github.com/google/go-github/v61/github"
"github.com/rs/zerolog/log"
"go.mondoo.com/cnquery/v11/llx"
"go.mondoo.com/cnquery/v11/providers-sdk/v1/inventory"
"go.mondoo.com/cnquery/v11/providers-sdk/v1/plugin"
"go.mondoo.com/cnquery/v11/providers-sdk/v1/vault"
"go.mondoo.com/cnquery/v11/providers/github/connection"
"go.mondoo.com/cnquery/v11/utils/stringx"
"google.golang.org/protobuf/proto"
)

func Discover(runtime *plugin.Runtime, opts map[string]string) (*inventory.Inventory, error) {
Expand Down Expand Up @@ -116,6 +120,14 @@ func org(runtime *plugin.Runtime, orgName string, conn *connection.GithubConnect
Labels: make(map[string]string),
Connections: []*inventory.Config{cfg},
})

if stringx.ContainsAnyOf(targets, connection.DiscoveryAll, connection.DiscoveryTerraform) {
terraformAssets, err := discoverTerraform(conn, repo)
if err != nil {
return nil, err
}
assetList = append(assetList, terraformAssets...)
}
}
}
if stringx.ContainsAnyOf(targets, connection.DiscoveryUsers, connection.DiscoveryUser) {
Expand Down Expand Up @@ -165,6 +177,14 @@ func repo(runtime *plugin.Runtime, repoName string, owner string, conn *connecti
Connections: []*inventory.Config{cfg},
})

if stringx.ContainsAnyOf(targets, connection.DiscoveryAll, connection.DiscoveryTerraform) {
terraformAssets, err := discoverTerraform(conn, repo)
if err != nil {
return nil, err
}
assetList = append(assetList, terraformAssets...)
}

return assetList, nil
}

Expand Down Expand Up @@ -257,3 +277,45 @@ func (f *ReposFilter) skipRepo(namespace string) bool {

return false
}

func discoverTerraform(conn *connection.GithubConnection, repo *mqlGithubRepository) ([]*inventory.Asset, error) {
// For git clone we need to set the user to oauth2 to be usable with the token.
conf := conn.Asset().Connections[0]
creds := make([]*vault.Credential, len(conf.Credentials))
for i := range conf.Credentials {
cred := conf.Credentials[i]
cc := proto.Clone(cred).(*vault.Credential)
if cc.User == "" {
cc.User = "oauth2"
}
creds[i] = cc
}

var res []*inventory.Asset
hasTf, err := hasTerraformHcl(conn.Client(), repo)
if err != nil {
log.Error().Err(err).Str("project", repo.FullName.Data).Msg("failed to discover terraform repo in gitlab")
} else if hasTf {
res = append(res, &inventory.Asset{
Connections: []*inventory.Config{{
Type: "terraform-hcl-git",
Options: map[string]string{
"ssh-url": repo.SshUrl.Data,
"http-url": repo.CloneUrl.Data,
},
Credentials: creds,
}},
})
}
return res, nil
}

// hasTerraformHcl will check if the repository contains terraform files
func hasTerraformHcl(client *github.Client, repo *mqlGithubRepository) (bool, error) {
query := "repo:" + repo.FullName.Data + " extension:tf"
res, _, err := client.Search.Code(context.Background(), query, &github.SearchOptions{})
if err != nil {
return false, err
}
return res.GetTotal() > 0, nil
}

0 comments on commit 981a931

Please sign in to comment.