1// Copyright (c) 2015-2021 MinIO, Inc.
2//
3// This file is part of MinIO Object Storage stack
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Affero General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU Affero General Public License for more details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18package cmd
19
20import (
21	"reflect"
22	"testing"
23
24	"github.com/minio/minio-go/v7/pkg/encrypt"
25)
26
27func TestParseEncryptionKeys(t *testing.T) {
28	sseKey1, err := encrypt.NewSSEC([]byte("32byteslongsecretkeymustbegiven2"))
29	if err != nil {
30		t.Fatal(err)
31	}
32	sseKey2, err := encrypt.NewSSEC([]byte("32byteslongsecretkeymustbegiven1"))
33	if err != nil {
34		t.Fatal(err)
35	}
36	sseSpaceKey1, err := encrypt.NewSSEC([]byte("32byteslongsecret   mustbegiven1"))
37	if err != nil {
38		t.Fatal(err)
39	}
40	sseCommaKey1, err := encrypt.NewSSEC([]byte("32byteslongsecretkey,ustbegiven1"))
41	if err != nil {
42		t.Fatal(err)
43	}
44	testCases := []struct {
45		encryptionKey  string
46		expectedEncMap map[string][]prefixSSEPair
47		success        bool
48	}{
49		{
50			encryptionKey: "myminio1/test2=32byteslongsecretkeymustbegiven2",
51			expectedEncMap: map[string][]prefixSSEPair{"myminio1": {{
52				Prefix: "myminio1/test2",
53				SSE:    sseKey1,
54			}}},
55			success: true,
56		},
57		{
58			encryptionKey:  "myminio1/test2=32byteslongsecretkeymustbegiven",
59			expectedEncMap: nil,
60			success:        false,
61		},
62		{
63			encryptionKey: "myminio1/test2=32byteslongsecretkey,ustbegiven1",
64			expectedEncMap: map[string][]prefixSSEPair{"myminio1": {{
65				Prefix: "myminio1/test2",
66				SSE:    sseCommaKey1,
67			}}},
68			success: true,
69		},
70		{
71			encryptionKey: "myminio1/test2=32byteslongsecret   mustbegiven1",
72			expectedEncMap: map[string][]prefixSSEPair{"myminio1": {{
73				Prefix: "myminio1/test2",
74				SSE:    sseSpaceKey1,
75			}}},
76			success: true,
77		},
78		{
79			encryptionKey: "myminio1/test2=32byteslongsecretkeymustbegiven2,myminio1/test1/a=32byteslongsecretkeymustbegiven1",
80			expectedEncMap: map[string][]prefixSSEPair{"myminio1": {{
81				Prefix: "myminio1/test1/a",
82				SSE:    sseKey2,
83			}, {
84				Prefix: "myminio1/test2",
85				SSE:    sseKey1,
86			}}},
87			success: true,
88		},
89	}
90	for i, testCase := range testCases {
91		encMap, err := parseEncryptionKeys(testCase.encryptionKey)
92		if err != nil && testCase.success {
93			t.Fatalf("Test %d: Expected success, got %s", i+1, err)
94		}
95		if err == nil && !testCase.success {
96			t.Fatalf("Test %d: Expected error, got success", i+1)
97		}
98		if testCase.success && !reflect.DeepEqual(encMap, testCase.expectedEncMap) {
99			t.Errorf("Test %d: Expected %s, got %s", i+1, testCase.expectedEncMap, encMap)
100		}
101	}
102}
103
104func TestParseAttribute(t *testing.T) {
105	metaDataCases := []struct {
106		input  string
107		output map[string]string
108		err    error
109		status bool
110	}{
111		// // When blank value is passed.
112		{"", map[string]string{}, ErrInvalidFileSystemAttribute, false},
113		//  When space is passed.
114		{"  ", map[string]string{}, ErrInvalidFileSystemAttribute, false},
115		// When / is passed.
116		{"/", map[string]string{}, ErrInvalidFileSystemAttribute, false},
117		// When "atime:" is passed.
118		{"atime:/", map[string]string{"atime": ""}, ErrInvalidFileSystemAttribute, false},
119		// When "atime:" is passed.
120		{"atime", map[string]string{"atime": ""}, nil, true},
121		//  When "atime:" is passed.
122		{"atime:", map[string]string{"atime": ""}, nil, true},
123		// Passing a valid value
124		{"atime:1/gid:1/gname:a/md:/mode:3/mtime:1/uid:1/uname:a",
125			map[string]string{
126				"atime": "1",
127				"gid":   "1",
128				"gname": "a",
129				"md":    "",
130				"mode":  "3",
131				"mtime": "1",
132				"uid":   "1",
133				"uname": "a",
134			}, nil, true},
135	}
136
137	for idx, testCase := range metaDataCases {
138		meta, err := parseAttribute(map[string]string{
139			metadataKey: testCase.input,
140		})
141		if testCase.status == true {
142			if err != nil {
143				t.Fatalf("Test %d: generated error not matching, expected = `%s`, found = `%s`", idx+1, testCase.err, err)
144			}
145			if !reflect.DeepEqual(meta, testCase.output) {
146				t.Fatalf("Test %d: generated Map not matching, expected = `%s`, found = `%s`", idx+1, testCase.input, meta)
147			}
148		}
149		if testCase.status == false {
150			if !reflect.DeepEqual(meta, testCase.output) {
151				t.Fatalf("Test %d: generated Map not matching, expected = `%s`, found = `%s`", idx+1, testCase.input, meta)
152			}
153			if err != testCase.err {
154				t.Fatalf("Test %d: generated error not matching, expected = `%s`, found = `%s`", idx+1, testCase.err, err)
155			}
156		}
157
158	}
159}
160