1package awsat
2
3import (
4	"io/ioutil"
5	"os"
6	"path/filepath"
7	"testing"
8
9	"github.com/aws/aws-sdk-go/service/iam"
10	"github.com/wallix/awless/aws/config"
11	"github.com/wallix/awless/aws/spec"
12	"github.com/wallix/awless/cloud/properties"
13	"github.com/wallix/awless/graph"
14	"github.com/wallix/awless/graph/resourcetest"
15)
16
17func TestAccesskey(t *testing.T) {
18	t.Run("create", func(t *testing.T) {
19		defer redirectStdErrToDevNull()()
20
21		t.Run("no-prompt", func(t *testing.T) {
22
23			Template("create accesskey user=jdoe no-prompt=true").
24				Mock(&iamMock{
25					CreateAccessKeyFunc: func(*iam.CreateAccessKeyInput) (*iam.CreateAccessKeyOutput, error) {
26						return &iam.CreateAccessKeyOutput{AccessKey: &iam.AccessKey{AccessKeyId: String("new-keypair-id")}}, nil
27					},
28				}).ExpectInput("CreateAccessKey", &iam.CreateAccessKeyInput{UserName: String("jdoe")}).
29				ExpectCommandResult("new-keypair-id").ExpectCalls("CreateAccessKey").Run(t)
30		})
31
32		t.Run("save credentials", func(t *testing.T) {
33			awsFolder, err := ioutil.TempDir("", "")
34			if err != nil {
35				t.Fatal(err)
36			}
37			defer os.RemoveAll(awsFolder)
38			awsconfig.AWSHomeDir = func() string {
39				return awsFolder
40			}
41			awsspec.AWSCredFilepath = filepath.Join(awsFolder, "credentials")
42			Template("create accesskey user=jdoe save=true").
43				Mock(&iamMock{
44					CreateAccessKeyFunc: func(*iam.CreateAccessKeyInput) (*iam.CreateAccessKeyOutput, error) {
45						return &iam.CreateAccessKeyOutput{AccessKey: &iam.AccessKey{AccessKeyId: String("0123456EXAMPLE0123456EXAMPLE"), SecretAccessKey: String("MYSECRETKEYMYSECRETKEYMYSECRETKEYMYSECRETKEY")}}, nil
46					},
47				}).ExpectInput("CreateAccessKey", &iam.CreateAccessKeyInput{UserName: String("jdoe")}).
48				ExpectCommandResult("0123456EXAMPLE0123456EXAMPLE").ExpectCalls("CreateAccessKey").Run(t)
49			cred, err := ioutil.ReadFile(awsspec.AWSCredFilepath)
50			if err != nil {
51				t.Fatal(err)
52			}
53			expected := `
54[jdoe]
55aws_access_key_id = 0123456EXAMPLE0123456EXAMPLE
56aws_secret_access_key = MYSECRETKEYMYSECRETKEYMYSECRETKEYMYSECRETKEY
57`
58			if got, want := string(cred), expected; got != want {
59				t.Fatalf("got %s, want %s", got, want)
60			}
61		})
62	})
63
64	t.Run("delete", func(t *testing.T) {
65		t.Run("with user", func(t *testing.T) {
66			Template("delete accesskey id=ACCESSKEYID user=jdoe").
67				Mock(&iamMock{
68					DeleteAccessKeyFunc: func(param0 *iam.DeleteAccessKeyInput) (*iam.DeleteAccessKeyOutput, error) {
69						return nil, nil
70					},
71				}).ExpectInput("DeleteAccessKey", &iam.DeleteAccessKeyInput{
72				UserName:    String("jdoe"),
73				AccessKeyId: String("ACCESSKEYID"),
74			}).ExpectCalls("DeleteAccessKey").Run(t)
75		})
76		t.Run("without user and id in local graph", func(t *testing.T) {
77			g := graph.NewGraph()
78			g.AddResource(resourcetest.AccessKey("ACCESSKEYID").Prop(properties.Username, "myusername").Build())
79			g.AddResource(resourcetest.AccessKey("OTHERACCESSKEYID").Prop(properties.Username, "notthis").Build())
80			Template("delete accesskey id=ACCESSKEYID").
81				Mock(&iamMock{
82					DeleteAccessKeyFunc: func(param0 *iam.DeleteAccessKeyInput) (*iam.DeleteAccessKeyOutput, error) {
83						return nil, nil
84					},
85				}).Graph(g).ExpectInput("DeleteAccessKey", &iam.DeleteAccessKeyInput{
86				UserName:    String("myusername"),
87				AccessKeyId: String("ACCESSKEYID"),
88			}).ExpectCalls("DeleteAccessKey").Run(t)
89		})
90		t.Run("without user and id not in local graph", func(t *testing.T) {
91			Template("delete accesskey id=ACCESSKEYID").
92				Mock(&iamMock{
93					DeleteAccessKeyFunc: func(param0 *iam.DeleteAccessKeyInput) (*iam.DeleteAccessKeyOutput, error) {
94						return nil, nil
95					},
96				}).ExpectInput("DeleteAccessKey", &iam.DeleteAccessKeyInput{
97				AccessKeyId: String("ACCESSKEYID"),
98			}).ExpectCalls("DeleteAccessKey").Run(t)
99		})
100		t.Run("with user without id", func(t *testing.T) {
101			Template("delete accesskey user=myusername").
102				Mock(&iamMock{
103					DeleteAccessKeyFunc: func(param0 *iam.DeleteAccessKeyInput) (*iam.DeleteAccessKeyOutput, error) {
104						return nil, nil
105					},
106					ListAccessKeysFunc: func(param0 *iam.ListAccessKeysInput) (*iam.ListAccessKeysOutput, error) {
107						return &iam.ListAccessKeysOutput{AccessKeyMetadata: []*iam.AccessKeyMetadata{{AccessKeyId: String("ACCESSKEYID")}}}, nil
108					},
109				}).ExpectInput("DeleteAccessKey", &iam.DeleteAccessKeyInput{
110				UserName:    String("myusername"),
111				AccessKeyId: String("ACCESSKEYID"),
112			}).ExpectInput("ListAccessKeys", &iam.ListAccessKeysInput{
113				UserName: String("myusername"),
114			}).ExpectCalls("ListAccessKeys", "DeleteAccessKey").Run(t)
115		})
116	})
117}
118
119func redirectStdErrToDevNull() func() {
120	originalStdErr := os.Stderr
121	toDefer := func() {
122		os.Stderr = originalStdErr
123	}
124	devNull, err := os.OpenFile(os.DevNull, os.O_RDWR, 0777)
125	if err != nil {
126		panic(err)
127	}
128	os.Stderr = devNull
129	return toDefer
130}
131