-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
⭐️ gitlab terraform discovery (#1755)
This PR adds the ability to the gitlab provider to detect terraform inside of the git repo. ```bash cnquery shell gitlab --group example --project example-gitlab → loaded configuration from /Users/chris/.config/mondoo/mondoo.yml using source default → discover related assets for 1 asset(s) → resolved assets resolved-assets=2 Available assets > 1. example / Example Gitlab (gitlab-project) 2. example / Example Gitlab (terraform-hcl) ```
- Loading branch information
1 parent
fcc2c19
commit 602bef1
Showing
5 changed files
with
172 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ import ( | |
"encoding/hex" | ||
"encoding/json" | ||
"fmt" | ||
|
||
"io/fs" | ||
"os" | ||
"path/filepath" | ||
|
@@ -17,6 +18,7 @@ import ( | |
"github.com/hashicorp/hcl/v2/hclparse" | ||
"github.com/rs/zerolog/log" | ||
"go.mondoo.com/cnquery/motor/providers" | ||
"go.mondoo.com/cnquery/motor/vault" | ||
) | ||
|
||
var ( | ||
|
@@ -44,7 +46,7 @@ func New(tc *providers.Config) (*Provider, error) { | |
var closer func() | ||
path := tc.Options["path"] | ||
if strings.HasPrefix(path, "git+https://") || strings.HasPrefix(path, "git+ssh://") { | ||
path, closer, err = processGitForTerraform(path) | ||
path, closer, err = processGitForTerraform(path, tc.Credentials) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
@@ -239,20 +241,55 @@ func (p *Provider) Plan() (*Plan, error) { | |
|
||
var reGitHttps = regexp.MustCompile(`git\+https://([^/]+)/(.*)`) | ||
|
||
func processGitForTerraform(url string) (string, func(), error) { | ||
// gitCloneUrl returns a git clone url from a git+https url | ||
// If a token is provided, it will be used to clone the repo | ||
// gitlab: git clone https://oauth2:[email protected]/vendor/package.git | ||
func gitCloneUrl(url string, credentials []*vault.Credential) (string, error) { | ||
|
||
user := "" | ||
token := "" | ||
for i := range credentials { | ||
cred := credentials[i] | ||
if cred.Type == vault.CredentialType_password { | ||
user = cred.User | ||
token = string(cred.Secret) | ||
if token == "" && cred.Password != "" { | ||
token = string(cred.Password) | ||
} | ||
} | ||
} | ||
|
||
m := reGitHttps.FindStringSubmatch(url) | ||
if len(m) == 3 { | ||
if strings.Contains(m[1], ":") { | ||
return "", nil, errors.New("url cannot contain a port! (" + m[1] + ")") | ||
return "", errors.New("url cannot contain a port! (" + m[1] + ")") | ||
} | ||
|
||
if user != "" && token != "" { | ||
// e.g. used by GitLab | ||
url = "https://" + user + ":" + token + "@" + m[1] + "/" + m[2] | ||
} else if token != "" { | ||
// e.g. used by GitHub | ||
url = "https://" + token + "@" + m[1] + "/" + m[2] | ||
} else { | ||
url = "git@" + m[1] + ":" + m[2] | ||
} | ||
url = "git@" + m[1] + ":" + m[2] | ||
} | ||
// url = strings.ReplaceAll(url, "git+https://gitlab.com/", "[email protected]:") | ||
url = strings.ReplaceAll(url, "git+ssh://", "") | ||
|
||
if !strings.HasSuffix(url, ".git") { | ||
url += ".git" | ||
} | ||
return url, nil | ||
} | ||
|
||
// processGitForTerraform clones a git repo and returns the path to the clone | ||
func processGitForTerraform(url string, credentials []*vault.Credential) (string, func(), error) { | ||
cloneUrl, err := gitCloneUrl(url, credentials) | ||
if err != nil { | ||
return "", nil, errors.Wrap(err, "failed to parse git clone url "+url) | ||
} | ||
|
||
cloneDir, err := os.MkdirTemp(os.TempDir(), "gitClone") | ||
if err != nil { | ||
|
@@ -269,7 +306,7 @@ func processGitForTerraform(url string) (string, func(), error) { | |
|
||
log.Info().Str("url", url).Str("path", cloneDir).Msg("git clone") | ||
repo, err := git.PlainClone(cloneDir, false, &git.CloneOptions{ | ||
URL: url, | ||
URL: cloneUrl, | ||
Progress: os.Stderr, | ||
Depth: 1, | ||
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
package terraform | ||
|
||
import ( | ||
"go.mondoo.com/cnquery/motor/vault" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
@@ -32,3 +33,17 @@ func TestModuleManifestIssue676(t *testing.T) { | |
require.NotNil(t, p.modulesManifest) | ||
require.Len(t, p.modulesManifest.Records, 3) | ||
} | ||
|
||
func TestGitCloneUrl(t *testing.T) { | ||
cloneUrl, err := gitCloneUrl("git+https://somegitlab.com/vendor/package.git", nil) | ||
require.NoError(t, err) | ||
assert.Equal(t, "[email protected]:vendor/package.git", cloneUrl) | ||
|
||
cloneUrl, err = gitCloneUrl("git+https://somegitlab.com/vendor/package.git", []*vault.Credential{{ | ||
Type: vault.CredentialType_password, | ||
User: "oauth2", | ||
Password: "ACCESS_TOKEN", | ||
}}) | ||
require.NoError(t, err) | ||
assert.Equal(t, "https://oauth2:[email protected]/vendor/package.git", cloneUrl) | ||
} |