-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fef77cb
commit 34c6b1c
Showing
17 changed files
with
3,842 additions
and
245 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,4 +36,9 @@ fmtcheck: | |
|
||
.PHONY: fmt | ||
fmt: | ||
gofumpt -l -w . | ||
gofumpt -l -w . | ||
|
||
mocks: | ||
go install github.com/vektra/mockery/[email protected] | ||
mockery --srcpkg github.com/hashicorp/hcp-sdk-go/clients/cloud-resource-manager/stable/2019-12-10/client/organization_service --name=ClientService | ||
mockery --srcpkg github.com/hashicorp/hcp-sdk-go/clients/cloud-resource-manager/stable/2019-12-10/client/project_service --name=ClientService |
This file was deleted.
Oops, something went wrong.
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 |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package vaulthcplib | ||
|
||
import "github.com/mitchellh/cli" | ||
|
||
func InitHCPCommand(ui cli.Ui) map[string]cli.CommandFactory { | ||
return map[string]cli.CommandFactory{ | ||
"hcp connect": func() (cli.Command, error) { | ||
return &HCPConnectCommand{ | ||
Ui: ui, | ||
}, nil | ||
}, | ||
"hcp disconnect": func() (cli.Command, error) { | ||
return &HCPDisconnectCommand{ | ||
Ui: ui, | ||
}, nil | ||
}, | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package vaulthcplib | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/mitchellh/cli" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_InitHCPCommand(t *testing.T) { | ||
cmdMap := InitHCPCommand(&cli.MockUi{}) | ||
|
||
assert.Contains(t, cmdMap, "hcp connect") | ||
assert.Contains(t, cmdMap, "hcp disconnect") | ||
} |
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 |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package vaulthcplib | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"time" | ||
|
||
"github.com/hashicorp/hcp-sdk-go/config" | ||
) | ||
|
||
const ( | ||
defaultDirectory = ".config/hcp/hvd" | ||
testDirectory = "hcptest" | ||
fileName = "hvd_proxy_config.json" | ||
directoryPermissions = 0755 | ||
|
||
envVarCacheTestMode = "HCP_CACHE_TEST_MODE" | ||
) | ||
|
||
type HCPToken struct { | ||
AccessToken string `json:"access_token,omitempty"` | ||
AccessTokenExpiry time.Time `json:"access_token_expiry,omitempty"` | ||
ProxyAddr string `json:"proxy_addr,omitempty"` | ||
} | ||
|
||
func GetHCPToken() (*HCPToken, error) { | ||
configCache, err := readConfig() | ||
if err != nil { | ||
return nil, err | ||
} | ||
if configCache == nil { | ||
return nil, nil | ||
} | ||
|
||
// this will either get from a cache file or | ||
opts := []config.HCPConfigOption{ | ||
config.WithoutLogging(), | ||
config.WithoutBrowserLogin(), | ||
config.FromEnv(), | ||
} | ||
if configCache.ClientID != "" && configCache.SecretID != "" { | ||
opts = append(opts, config.WithClientCredentials(configCache.ClientID, configCache.SecretID)) | ||
} | ||
hcp, err := config.NewHCPConfig(opts...) | ||
|
||
tk, err := hcp.Token() | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to retrieve the HCP token: %w", err) | ||
} | ||
|
||
return &HCPToken{ | ||
AccessToken: tk.AccessToken, | ||
AccessTokenExpiry: tk.Expiry, | ||
ProxyAddr: configCache.ProxyAddr, | ||
}, nil | ||
} | ||
|
||
type HCPConfigCache struct { | ||
ClientID string | ||
SecretID string | ||
ProxyAddr string | ||
} | ||
|
||
// Write saves HCP auth data in a common location in the home directory. | ||
func writeConfig(addr string, clientID string, secretID string) error { | ||
credentialPath, credentialDirectory, err := getConfigPaths() | ||
if err != nil { | ||
return fmt.Errorf("failed to retrieve credential path and directory: %v", err) | ||
} | ||
|
||
err = os.MkdirAll(credentialDirectory, directoryPermissions) | ||
if err != nil { | ||
return fmt.Errorf("failed to create credential directory: %v", err) | ||
} | ||
|
||
cache := &HCPConfigCache{ | ||
ClientID: clientID, | ||
SecretID: secretID, | ||
ProxyAddr: addr, | ||
} | ||
cacheJSON, err := json.Marshal(cache) | ||
if err != nil { | ||
return fmt.Errorf("failed to marshal the struct to json: %v", err) | ||
} | ||
|
||
err = os.WriteFile(credentialPath, cacheJSON, directoryPermissions) | ||
if err != nil { | ||
return fmt.Errorf("failed to write config to the cache file: %v", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// readConfig opens the saved HCP auth data and returns the token. | ||
func readConfig() (*HCPConfigCache, error) { | ||
configPath, _, err := getConfigPaths() | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to retrieve config path and directory: %v", err) | ||
} | ||
|
||
var cache HCPConfigCache | ||
if _, err = os.Stat(configPath); os.IsNotExist(err) { | ||
return nil, nil | ||
} | ||
|
||
rawJSON, err := os.ReadFile(configPath) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read file from user's config path: %v", err) | ||
} | ||
|
||
err = json.Unmarshal(rawJSON, &cache) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &cache, nil | ||
} | ||
|
||
func eraseConfig() error { | ||
_, credentialDirectory, err := getConfigPaths() | ||
if err != nil { | ||
return fmt.Errorf("failed to retrieve credential path and directory: %v", err) | ||
} | ||
|
||
err = os.RemoveAll(credentialDirectory) | ||
if err != nil { | ||
return fmt.Errorf("failed to remove config directory: %v", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// getCredentialPaths returns the complete credential path and directory. | ||
func getConfigPaths() (configPath string, configDirectory string, err error) { | ||
// Get the user's home directory. | ||
userHome, err := os.UserHomeDir() | ||
if err != nil { | ||
return "", "", fmt.Errorf("failed to retrieve user's home directory path: %v", err) | ||
} | ||
|
||
directoryName := defaultDirectory | ||
// If in test mode, use test directory. | ||
if testMode, ok := os.LookupEnv(envVarCacheTestMode); ok { | ||
if testMode == "true" { | ||
directoryName = testDirectory | ||
} | ||
} | ||
|
||
// Determine absolute path to config file and directory. | ||
configDirectory = filepath.Join(userHome, directoryName) | ||
configPath = filepath.Join(userHome, directoryName, fileName) | ||
|
||
return configPath, configDirectory, nil | ||
} |
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 |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package vaulthcplib | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_GetHCPConfiguration(t *testing.T) { | ||
cases := map[string]struct { | ||
Valid bool | ||
}{ | ||
"valid hcp configuration": { | ||
Valid: true, | ||
}, | ||
"empty hcp configuration": { | ||
Valid: false, | ||
}, | ||
} | ||
|
||
for n, tst := range cases { | ||
t.Run(n, func(t *testing.T) { | ||
CacheSetup(t, tst.Valid) | ||
|
||
tk, err := GetHCPToken() | ||
|
||
assert.NoError(t, err) | ||
|
||
if tst.Valid { | ||
assert.Equal(t, "https://hcp-proxy.addr:8200", tk.ProxyAddr) | ||
assert.Contains(t, tk.AccessToken, "Test.Access.Token") | ||
assert.NotEmpty(t, tk.AccessTokenExpiry) | ||
} else { | ||
assert.Nil(t, tk) | ||
assert.Nil(t, err) | ||
} | ||
|
||
}) | ||
} | ||
} | ||
|
||
func Test_GetHCPConfiguration_EraseConfig(t *testing.T) { | ||
err := os.Setenv(envVarCacheTestMode, "true") | ||
assert.NoError(t, err) | ||
|
||
err = eraseConfig() | ||
assert.NoError(t, err) | ||
|
||
_, err = GetHCPToken() | ||
assert.NoError(t, err) | ||
} |
Oops, something went wrong.