Repository: tenable/terrascan (language: python)

Issue:
Issue on Azure DevOps Agents since 1.3.2 : failed to initialize terrascan
* terrascan version: 1.3.3
* Operating System: Windows Azure DevOps Agent Hosted

### Description

Until 1.3.1, we didn't have any issue, and since 1.3.2 all pipelines failed with warning. The issue still present with 1.3.3.
It seem that the issue is coming with the last fix about downlaod policies on 1.3.2 https://github.com/accurics/terrascan/issues/521

When we add debug log, we can see that Terrascan are unable to init because can't install policies. I think it's because the target folder is write protected, but on Hosted Azure Devops Agent we can't change it.

So, I'm a bit confused if it's a limitation of Azure DevOps and at same time like it's worked until 1.3.1 if last update can break the usage of terrascan on Azure DevOps. Is it really an issue ? BTW in anycase, works perfectly locally on my Windows Computer. Maybe it's just be an improvement that we need for still use in Azure DevOps by using an extra arguments for say where policies need to be downloaded (on a non protected write folder) for workaround, but I didn't find a way to add this extra args.

Thanks for your help/advice, Regards
Alex

### What I Did

```
terrascan.exe scan -t azure -i terraform --iac-version v14 -o json
```

Here the error log that I can have with just a terrascan init on Azure DevOps
```
2021-02-19T19:46:40.347Z	debug	config/global.go:59	global config env variable is not specified
2021-02-19T19:46:40.380Z	debug	initialize/run.go:40	initializing terrascan
2021-02-19T19:46:40.380Z	debug	initialize/run.go:60	downloading policies
2021-02-19T19:46:40.380Z	debug	initialize/run.go:69	cloning terrascan repo at C:\Users\VSSADM~1\AppData\Local\Temp\terrascan-756921911
2021-02-19T19:46:50.958Z	error	cli/init.go:42	failed to initialize terrascan. error : failed to install policies to '/.terrascan'. error: 'rename C:\Users\VSSADM~1\AppData\Local\Temp\terrascan-756921911 /.terrascan: The system cannot move the file to a different disk drive.'
```




Discussion / hints:
Hi @alex-3sr! Thanks for the report. Will follow up soon
Hey @alex-3sr , we're working on a fix for this issue. gonna release with a patch soon.

meanwhile, could you try specifying the policy path in the [config file](https://docs.accurics.com/projects/accurics-terrascan/en/latest/getting-started/usage/#config-file) for now? let us know if that works for you.

Also, could you let us know if there's any HOME environment variable set on the host machine?

Fix patch:
diff --git a/go.mod b/go.mod
index e51644c75..c76b2a77c 100644
--- a/go.mod
+++ b/go.mod
@@ -19,6 +19,7 @@ require (
 	github.com/hashicorp/terraform v0.14.4
 	github.com/iancoleman/strcase v0.1.3
 	github.com/mattn/go-isatty v0.0.12
+	github.com/mitchellh/go-homedir v1.1.0
 	github.com/onsi/ginkgo v1.12.1
 	github.com/onsi/gomega v1.10.5
 	github.com/open-policy-agent/opa v0.22.0
diff --git a/pkg/config/global.go b/pkg/config/global.go
index 0073631d8..91bcc5c7e 100644
--- a/pkg/config/global.go
+++ b/pkg/config/global.go
@@ -18,7 +18,9 @@ package config
 
 import (
 	"os"
+	"path/filepath"
 
+	"github.com/accurics/terrascan/pkg/utils"
 	"go.uber.org/zap"
 )
 
@@ -30,8 +32,8 @@ const (
 )
 
 var (
-	policyRepoPath = os.Getenv("HOME") + "/.terrascan"
-	policyBasePath = policyRepoPath + "/pkg/policies/opa/rego"
+	policyRepoPath = filepath.Join(utils.GetHomeDir(), ".terrascan")
+	policyBasePath = filepath.Join(policyRepoPath, "pkg", "policies", "opa", "rego")
 )
 
 func init() {
diff --git a/pkg/utils/dir.go b/pkg/utils/dir.go
new file mode 100644
index 000000000..62c17ed5e
--- /dev/null
+++ b/pkg/utils/dir.go
@@ -0,0 +1,19 @@
+package utils
+
+import (
+	"github.com/mitchellh/go-homedir"
+	"go.uber.org/zap"
+)
+
+// GetHomeDir returns the home directory path
+func GetHomeDir() (terrascanDir string) {
+	zap.S().Debug("looking up for the home directory path")
+
+	terrascanDir, err := homedir.Dir()
+
+	if err != nil {
+		zap.S().Warnf("unable to determine the home directory: %v\n", err)
+	}
+
+	return
+}
diff --git a/pkg/utils/path.go b/pkg/utils/path.go
index b5fa3ea8e..9f37d54da 100644
--- a/pkg/utils/path.go
+++ b/pkg/utils/path.go
@@ -34,7 +34,7 @@ func GetAbsPath(path string) (string, error) {
 
 	// Only shell resolves `~` to home so handle it specially
 	if strings.HasPrefix(path, "~") {
-		homeDir := os.Getenv("HOME")
+		homeDir := GetHomeDir()
 		if len(path) > 1 {
 			path = filepath.Join(homeDir, path[1:])
 		} else {


Test patch:
diff --git a/pkg/cli/run_test.go b/pkg/cli/run_test.go
index 8d75366f4..ec47877dd 100644
--- a/pkg/cli/run_test.go
+++ b/pkg/cli/run_test.go
@@ -45,7 +45,7 @@ func setup() {
 
 func shutdown() {
 	// remove the downloaded policies
-	os.RemoveAll(os.Getenv("HOME") + "/.terrascan")
+	os.RemoveAll(filepath.Join(utils.GetHomeDir(), ".terrascan"))
 }
 
 func TestRun(t *testing.T) {
@@ -55,9 +55,9 @@ func TestRun(t *testing.T) {
 	}
 
 	testDirPath := "testdata/run-test"
-	kustomizeTestDirPath := testDirPath + "/kustomize-test"
-	testTerraformFilePath := testDirPath + "/config-only.tf"
-	testRemoteModuleFilePath := testDirPath + "/remote-modules.tf"
+	kustomizeTestDirPath := filepath.Join(testDirPath, "kustomize-test")
+	testTerraformFilePath := filepath.Join(testDirPath, "config-only.tf")
+	testRemoteModuleFilePath := filepath.Join(testDirPath, "remote-modules.tf")
 
 	ruleSlice := []string{"AWS.ECR.DataSecurity.High.0579", "AWS.SecurityGroup.NetworkPortsSecurity.Low.0561"}
 
diff --git a/pkg/utils/path_test.go b/pkg/utils/path_test.go
index 2344c50e7..cd30a2d6c 100644
--- a/pkg/utils/path_test.go
+++ b/pkg/utils/path_test.go
@@ -18,6 +18,7 @@ package utils
 
 import (
 	"os"
+	"path/filepath"
 	"reflect"
 	"testing"
 )
@@ -39,19 +40,19 @@ func TestGetAbsPath(t *testing.T) {
 		{
 			name:    "user HOME dir",
 			path:    "~",
-			want:    os.Getenv("HOME"),
+			want:    GetHomeDir(),
 			wantErr: nil,
 		},
 		{
 			name:    "dir in HOME dir",
 			path:    "~/somedir",
-			want:    os.Getenv("HOME") + "/somedir",
+			want:    filepath.Join(GetHomeDir(), "somedir"),
 			wantErr: nil,
 		},
 		{
 			name:    "testdata dir",
 			path:    "./testdata",
-			want:    os.Getenv("PWD") + "/testdata",
+			want:    filepath.Join(os.Getenv("PWD"), "testdata"),
 			wantErr: nil,
 		},
 	}
diff --git a/test/e2e/init/init_test.go b/test/e2e/init/init_test.go
index 818d34655..749409c64 100644
--- a/test/e2e/init/init_test.go
+++ b/test/e2e/init/init_test.go
@@ -6,6 +6,7 @@ import (
 	"path/filepath"
 	"time"
 
+	"github.com/accurics/terrascan/pkg/utils"
 	initUtil "github.com/accurics/terrascan/test/e2e/init"
 	"github.com/accurics/terrascan/test/helper"
 	. "github.com/onsi/ginkgo"
@@ -17,7 +18,7 @@ import (
 
 var (
 	initCommand            string = "init"
-	defaultPolicyRepoPath  string = os.Getenv("HOME") + "/.terrascan"
+	defaultPolicyRepoPath  string = filepath.Join(utils.GetHomeDir(), ".terrascan")
 	terrascanGitURL        string = "https://github.com/accurics/terrascan.git"
 	terrascanDefaultBranch string = "master"
 	terrascanConfigEnvName string = "TERRASCAN_CONFIG"