Skip to content

Commit

Permalink
aws/credentials: Add tests for credential_process
Browse files Browse the repository at this point in the history
  • Loading branch information
YakDriver committed Oct 22, 2018
1 parent 6bb8b4c commit f356986
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 98 deletions.
4 changes: 0 additions & 4 deletions aws/credentials/example.ini
Expand Up @@ -2,7 +2,6 @@
aws_access_key_id = accessKey
aws_secret_access_key = secret
aws_session_token = token
credential_process = /bin/echo {"Version": 1, "AccessKeyId": "accessKey", "SecretAccessKey": "secret", "SessionToken": "tokenDefault", "Expiration": "2000-01-01T00:00:00-00:00"}

[no_token]
aws_access_key_id = accessKey
Expand All @@ -11,6 +10,3 @@ aws_secret_access_key = secret
[with_colon]
aws_access_key_id: accessKey
aws_secret_access_key: secret

[profile process]
credential_process = /bin/echo {"Version": 1, "AccessKeyId": "accessKey", "SecretAccessKey": "secret", "SessionToken": "tokenProcess", "Expiration": "2000-01-01T00:00:00-00:00"}
5 changes: 5 additions & 0 deletions aws/credentials/processcreds/example.ini
@@ -0,0 +1,5 @@
[default]
credential_process = echo {\"Version\": 1, \"AccessKeyId\": \"accessKey\", \"SecretAccessKey\": \"secret\", \"SessionToken\": \"tokenDefault\", \"Expiration\": \"2000-01-01T00:00:00-00:00\"}

[profile non_expire]
credential_process = echo {\"Version\": 1, \"AccessKeyId\": \"accessKey\", \"SecretAccessKey\": \"secret\", \"SessionToken\": \"nonDefaultToken\"}
5 changes: 5 additions & 0 deletions aws/credentials/processcreds/example_win.ini
@@ -0,0 +1,5 @@
[default]
credential_process = echo {"Version": 1, "AccessKeyId": "accessKey", "SecretAccessKey": "secret", "SessionToken": "tokenDefault", "Expiration": "2000-01-01T00:00:00-00:00"}

[profile non_expire]
credential_process = echo {"Version": 1, "AccessKeyId": "accessKey", "SecretAccessKey": "secret", "SessionToken": "nonDefaultToken"}
267 changes: 173 additions & 94 deletions aws/credentials/processcreds/provider_test.go
@@ -1,133 +1,192 @@
package processcreds
package processcreds_test

import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/processcreds"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/awstesting"
)

func TestProcessProvider(t *testing.T) {
os.Clearenv()

p := ProcessProvider{Filename: "example.ini", Profile: "process", executionFunc: executeCredentialProcess}
creds, err := p.Retrieve()
assert.Nil(t, err, "Expect no error")
func TestProcessProviderFromSession(t *testing.T) {
oldEnv := preserveImportantStashEnv()
defer awstesting.PopEnv(oldEnv)

assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
assert.Equal(t, "tokenProcess", creds.SessionToken, "Expect session token to match")
}
if runtime.GOOS == "windows" {
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "example_win.ini")
} else {
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "example.ini")
}

func fakeExectuteCredsExpired(process string) ([]byte, error) {
return []byte(`{"Version": 1, "AccessKeyId": "accessKey", "SecretAccessKey": "secret", "SessionToken": "tokenDefault", "Expiration": "2000-01-01T00:00:00-00:00"}`), nil
}
sess, err := session.NewSession(&aws.Config{
Region: aws.String("region")},
)

func TestProcessProviderIsExpired(t *testing.T) {
os.Clearenv()
if err != nil {
t.Errorf("error getting session: %v", err)
}

p := ProcessProvider{Filename: "example.ini", Profile: "process", executionFunc: fakeExectuteCredsExpired}
creds, err := sess.Config.Credentials.Get()
if err != nil {
t.Errorf("error getting credentials: %v", err)
}

assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve")
}
if e, a := "accessKey", creds.AccessKeyID; e != a {
t.Errorf("expected %v, got %v", e, a)
}

func TestProcessProviderWithAWS_CONFIG_FILE(t *testing.T) {
os.Clearenv()
os.Setenv("AWS_CONFIG_FILE", "example.ini")
os.Setenv("AWS_DEFAULT_PROFILE", "process")
p := ProcessProvider{Filename: "", Profile: "", executionFunc: executeCredentialProcess}
creds, err := p.Retrieve()
if e, a := "secret", creds.SecretAccessKey; e != a {
t.Errorf("expected %v, got %v", e, a)
}

assert.Nil(t, err, "Expect no error")
if e, a := "tokenDefault", creds.SessionToken; e != a {
t.Errorf("expected %v, got %v", e, a)
}

assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
assert.Equal(t, "tokenProcess", creds.SessionToken, "Expect session token to match")
}

func TestProcessProviderWithAWS_CONFIG_FILEAbsPath(t *testing.T) {
os.Clearenv()
wd, err := os.Getwd()
assert.NoError(t, err)
os.Setenv("AWS_CONFIG_FILE", filepath.Join(wd, "example.ini"))
p := ProcessProvider{executionFunc: executeCredentialProcess}
creds, err := p.Retrieve()
assert.Nil(t, err, "Expect no error")

assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
assert.Equal(t, "tokenDefault", creds.SessionToken, "Expect session token to match")
}
func TestProcessProviderFromSessionWithProfile(t *testing.T) {
oldEnv := preserveImportantStashEnv()
defer awstesting.PopEnv(oldEnv)

func fakeExectuteCredsSuccess(process string) ([]byte, error) {
return []byte(`{"Version": 1, "AccessKeyId": "accessKey", "SecretAccessKey": "secret", "SessionToken": "tokenFake", "Expiration": "2000-01-01T00:00:00-00:00"}`), nil
}
if runtime.GOOS == "windows" {
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "example_win.ini")
} else {
os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "example.ini")
}
os.Setenv("AWS_PROFILE", "non_expire")

func TestProcessProviderWithAWS_PROFILE(t *testing.T) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "process")
sess, err := session.NewSession(&aws.Config{
Region: aws.String("region")},
)

p := ProcessProvider{Filename: "example.ini", Profile: "", executionFunc: fakeExectuteCredsSuccess}
creds, err := p.Retrieve()
assert.Nil(t, err, "Expect no error")
if err != nil {
t.Errorf("error getting session: %v", err)
}

assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
assert.Equal(t, "tokenFake", creds.SessionToken, "Expect token to match")
}
creds, err := sess.Config.Credentials.Get()
if err != nil {
t.Errorf("error getting credentials: %v", err)
}

if e, a := "nonDefaultToken", creds.SessionToken; e != a {
t.Errorf("expected %v, got %v", e, a)
}

func fakeExectuteCredsFailMalformed(process string) ([]byte, error) {
return []byte(`{"Version": 1, "AccessKeyId": "accessKey", "SecretAccessKey": "secret", "SessionToken": "tokenDefault", "Expiration": `), nil
}

func TestProcessProviderMalformed(t *testing.T) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "process")
func TestProcessProviderExpectErrors(t *testing.T) {
oldEnv := preserveImportantStashEnv()
defer awstesting.PopEnv(oldEnv)

p := ProcessProvider{Filename: "example.ini", Profile: "", executionFunc: fakeExectuteCredsFailMalformed}
_, err := p.Retrieve()
assert.NotNil(t, err, "Expect an error")
}
creds := credentials.NewCredentials(&processcreds.ProcessProvider{
Process: "/bad/process",
})
_, err := creds.Get()

func fakeExectuteCredsNoToken(process string) ([]byte, error) {
return []byte(`{"Version": 1, "AccessKeyId": "accessKey", "SecretAccessKey": "secret"}`), nil
}
if err.(awserr.Error).Code() != processcreds.ErrCodeProcessProviderExecution {
t.Errorf("expected %v, got %v", processcreds.ErrCodeProcessProviderExecution, err)
}

func TestProcessProviderNoToken(t *testing.T) {
os.Clearenv()
process := fixForOS("echo {\\\"Version\\\": 1")
p := &processcreds.ProcessProvider{
Process: process,
}
_, err = p.Retrieve()
if err.(awserr.Error).Code() != processcreds.ErrCodeProcessProviderParse {
t.Errorf("expected %v, got %v", processcreds.ErrCodeProcessProviderParse, err)
}

p := ProcessProvider{Filename: "example.ini", Profile: "process", executionFunc: fakeExectuteCredsNoToken}
creds, err := p.Retrieve()
assert.Nil(t, err, "Expect no error")
assert.Empty(t, creds.SessionToken, "Expect no token")
}
process = fixForOS("echo {\\\"Version\\\": 2}")
p = &processcreds.ProcessProvider{
Process: process,
}
_, err = p.Retrieve()
if err.(awserr.Error).Code() != processcreds.ErrCodeProcessProviderVersion {
t.Errorf("expected %v, got %v", processcreds.ErrCodeProcessProviderVersion, err)
}

func fakeExectuteCredsFailVersion(process string) ([]byte, error) {
return []byte(`{"Version": 2, "AccessKeyId": "accessKey", "SecretAccessKey": "secret", "SessionToken": "tokenDefault"}`), nil
}
process = fixForOS("echo {\\\"Version\\\": 1, \\\"AccessKeyId\\\": \\\"accesskey\\\"}")
p = &processcreds.ProcessProvider{
Process: process,
}
_, err = p.Retrieve()
if err.(awserr.Error).Code() != processcreds.ErrCodeProcessProviderRequired {
t.Errorf("expected %v, got %v", processcreds.ErrCodeProcessProviderRequired, err)
}

func TestProcessProviderWrongVersion(t *testing.T) {
os.Clearenv()
p := ProcessProvider{Filename: "example.ini", Profile: "process", executionFunc: fakeExectuteCredsFailVersion}
_, err := p.Retrieve()
assert.NotNil(t, err, "Expect an error")
process = fixForOS("echo {\\\"Version\\\": 1, \\\"SecretAccessKey\\\": \\\"secretkey\\\"}")
p = &processcreds.ProcessProvider{
Process: process,
}
_, err = p.Retrieve()
if err.(awserr.Error).Code() != processcreds.ErrCodeProcessProviderRequired {
t.Errorf("expected %v, got %v", processcreds.ErrCodeProcessProviderRequired, err)
}
}

func fakeExectuteCredsFailExpiration(process string) ([]byte, error) {
return []byte(`{"Version": 1, "AccessKeyId": "accessKey", "SecretAccessKey": "secret", "SessionToken": "tokenDefault", "Expiration": "20222"}`), nil
}
func TestProcessProviderBadExpiry(t *testing.T) {
os.Clearenv()
p := ProcessProvider{Filename: "example.ini", Profile: "process", executionFunc: fakeExectuteCredsFailExpiration}
func TestProcessProviderExpiration(t *testing.T) {
oldEnv := preserveImportantStashEnv()
defer awstesting.PopEnv(oldEnv)

// static creds
process := fixForOS("echo {\\\"Version\\\": 1, \\\"SecretAccessKey\\\": \\\"secretkey\\\", \\\"AccessKeyId\\\": \\\"accesskey\\\"}")
p := &processcreds.ProcessProvider{
Process: process,
}
_, err := p.Retrieve()
assert.NotNil(t, err, "Expect an error")
if err != nil {
t.Errorf("expected %v, got %v", "no error", err)
}
if p.IsExpired() {
t.Errorf("expected %v, got %v", "static credentials/not expired", "expired")
}

// not expired creds
future := time.Now().Add(1 * time.Hour).UTC().Format(time.RFC3339)
process = fixForOS(fmt.Sprintf("echo {\\\"Version\\\": 1, \\\"SecretAccessKey\\\": \\\"secretkey\\\", \\\"AccessKeyId\\\": \\\"accesskey\\\", \\\"Expiration\\\": \\\"%v\\\"}", future))
p = &processcreds.ProcessProvider{
Process: process,
}
_, err = p.Retrieve()
if err != nil {
t.Errorf("expected %v, got %v", "no error", err)
}
if p.IsExpired() {
t.Errorf("expected %v, got %v", "not expired", "expired")
}

// expired creds
past := time.Now().Add(-1 * time.Hour).UTC().Format(time.RFC3339)
process = fixForOS(fmt.Sprintf("echo {\\\"Version\\\": 1, \\\"SecretAccessKey\\\": \\\"secretkey\\\", \\\"AccessKeyId\\\": \\\"accesskey\\\", \\\"Expiration\\\": \\\"%v\\\"}", past))
p = &processcreds.ProcessProvider{
Process: process,
}
_, err = p.Retrieve()
if err != nil {
t.Errorf("expected %v, got %v", "no error", err)
}
if !p.IsExpired() {
t.Errorf("expected %v, got %v", "expired", "not expired")
}
}

func BenchmarkProcessProvider(b *testing.B) {
os.Clearenv()
oldEnv := preserveImportantStashEnv()
defer awstesting.PopEnv(oldEnv)

p := ProcessProvider{Filename: "example.ini", Profile: "process", executionFunc: executeCredentialProcess}
process := fixForOS("echo {\\\"Version\\\": 1, \\\"SecretAccessKey\\\": \\\"secretkey\\\", \\\"AccessKeyId\\\": \\\"accesskey\\\"}")
p := &processcreds.ProcessProvider{
Process: process,
}
_, err := p.Retrieve()
if err != nil {
b.Fatal(err)
Expand All @@ -141,3 +200,23 @@ func BenchmarkProcessProvider(b *testing.B) {
}
}
}

func preserveImportantStashEnv() []string {
var comspec string
if len(os.Getenv("ComSpec")) != 0 {
comspec = os.Getenv("ComSpec")
}

oldEnv := awstesting.StashEnv() //clear env

os.Setenv("ComSpec", comspec)
return oldEnv
}

func fixForOS(in string) string {
if runtime.GOOS == "windows" {
return strings.Replace(in, "\\", "", -1)
}

return in
}

0 comments on commit f356986

Please sign in to comment.