github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/storage/bucket/s3/config_test.go (about) 1 package s3 2 3 import ( 4 "encoding/base64" 5 "net/http" 6 "testing" 7 "time" 8 9 "github.com/grafana/dskit/flagext" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "gopkg.in/yaml.v2" 13 14 bucket_http "github.com/grafana/loki/pkg/storage/bucket/http" 15 ) 16 17 // defaultConfig should match the default flag values defined in RegisterFlagsWithPrefix. 18 var defaultConfig = Config{ 19 SignatureVersion: SignatureVersionV4, 20 HTTP: HTTPConfig{ 21 Config: bucket_http.Config{ 22 IdleConnTimeout: 90 * time.Second, 23 ResponseHeaderTimeout: 2 * time.Minute, 24 InsecureSkipVerify: false, 25 TLSHandshakeTimeout: 10 * time.Second, 26 ExpectContinueTimeout: 1 * time.Second, 27 MaxIdleConns: 100, 28 MaxIdleConnsPerHost: 100, 29 MaxConnsPerHost: 0, 30 }, 31 }, 32 } 33 34 func TestConfig(t *testing.T) { 35 t.Parallel() 36 37 tests := map[string]struct { 38 config string 39 expectedConfig Config 40 expectedErr error 41 }{ 42 "default config": { 43 config: "", 44 expectedConfig: defaultConfig, 45 expectedErr: nil, 46 }, 47 "custom config": { 48 config: ` 49 endpoint: test-endpoint 50 region: test-region 51 bucket_name: test-bucket-name 52 secret_access_key: test-secret-access-key 53 access_key_id: test-access-key-id 54 insecure: true 55 signature_version: test-signature-version 56 sse: 57 type: test-type 58 kms_key_id: test-kms-key-id 59 kms_encryption_context: test-kms-encryption-context 60 http: 61 idle_conn_timeout: 2s 62 response_header_timeout: 3s 63 insecure_skip_verify: true 64 tls_handshake_timeout: 4s 65 expect_continue_timeout: 5s 66 max_idle_connections: 6 67 max_idle_connections_per_host: 7 68 max_connections_per_host: 8 69 `, 70 expectedConfig: Config{ 71 Endpoint: "test-endpoint", 72 Region: "test-region", 73 BucketName: "test-bucket-name", 74 SecretAccessKey: flagext.SecretWithValue("test-secret-access-key"), 75 AccessKeyID: "test-access-key-id", 76 Insecure: true, 77 SignatureVersion: "test-signature-version", 78 SSE: SSEConfig{ 79 Type: "test-type", 80 KMSKeyID: "test-kms-key-id", 81 KMSEncryptionContext: "test-kms-encryption-context", 82 }, 83 HTTP: HTTPConfig{ 84 Config: bucket_http.Config{ 85 IdleConnTimeout: 2 * time.Second, 86 ResponseHeaderTimeout: 3 * time.Second, 87 InsecureSkipVerify: true, 88 TLSHandshakeTimeout: 4 * time.Second, 89 ExpectContinueTimeout: 5 * time.Second, 90 MaxIdleConns: 6, 91 MaxIdleConnsPerHost: 7, 92 MaxConnsPerHost: 8, 93 }, 94 }, 95 }, 96 expectedErr: nil, 97 }, 98 "invalid type": { 99 config: `insecure: foo`, 100 expectedConfig: defaultConfig, 101 expectedErr: &yaml.TypeError{Errors: []string{"line 1: cannot unmarshal !!str `foo` into bool"}}, 102 }, 103 } 104 105 for testName, testData := range tests { 106 testData := testData 107 108 t.Run(testName, func(t *testing.T) { 109 cfg := Config{} 110 flagext.DefaultValues(&cfg) 111 112 err := yaml.Unmarshal([]byte(testData.config), &cfg) 113 require.Equal(t, testData.expectedErr, err) 114 require.Equal(t, testData.expectedConfig, cfg) 115 }) 116 } 117 } 118 119 func TestSSEConfig_Validate(t *testing.T) { 120 tests := map[string]struct { 121 setup func() *SSEConfig 122 expected error 123 }{ 124 "should pass with default config": { 125 setup: func() *SSEConfig { 126 cfg := &SSEConfig{} 127 flagext.DefaultValues(cfg) 128 129 return cfg 130 }, 131 }, 132 "should fail on invalid SSE type": { 133 setup: func() *SSEConfig { 134 return &SSEConfig{ 135 Type: "unknown", 136 } 137 }, 138 expected: errUnsupportedSSEType, 139 }, 140 "should fail on invalid SSE KMS encryption context": { 141 setup: func() *SSEConfig { 142 return &SSEConfig{ 143 Type: SSEKMS, 144 KMSEncryptionContext: "!{}!", 145 } 146 }, 147 expected: errInvalidSSEContext, 148 }, 149 "should pass on valid SSE KMS encryption context": { 150 setup: func() *SSEConfig { 151 return &SSEConfig{ 152 Type: SSEKMS, 153 KMSEncryptionContext: `{"department": "10103.0"}`, 154 } 155 }, 156 }, 157 } 158 159 for testName, testData := range tests { 160 t.Run(testName, func(t *testing.T) { 161 assert.Equal(t, testData.expected, testData.setup().Validate()) 162 }) 163 } 164 } 165 166 func TestSSEConfig_BuildMinioConfig(t *testing.T) { 167 tests := map[string]struct { 168 cfg *SSEConfig 169 expectedType string 170 expectedKeyID string 171 expectedContext string 172 }{ 173 "SSE KMS without encryption context": { 174 cfg: &SSEConfig{ 175 Type: SSEKMS, 176 KMSKeyID: "test-key", 177 }, 178 expectedType: "aws:kms", 179 expectedKeyID: "test-key", 180 expectedContext: "", 181 }, 182 "SSE KMS with encryption context": { 183 cfg: &SSEConfig{ 184 Type: SSEKMS, 185 KMSKeyID: "test-key", 186 KMSEncryptionContext: "{\"department\":\"10103.0\"}", 187 }, 188 expectedType: "aws:kms", 189 expectedKeyID: "test-key", 190 expectedContext: "{\"department\":\"10103.0\"}", 191 }, 192 } 193 194 for testName, testData := range tests { 195 t.Run(testName, func(t *testing.T) { 196 sse, err := testData.cfg.BuildMinioConfig() 197 require.NoError(t, err) 198 199 headers := http.Header{} 200 sse.Marshal(headers) 201 202 assert.Equal(t, testData.expectedType, headers.Get("x-amz-server-side-encryption")) 203 assert.Equal(t, testData.expectedKeyID, headers.Get("x-amz-server-side-encryption-aws-kms-key-id")) 204 assert.Equal(t, base64.StdEncoding.EncodeToString([]byte(testData.expectedContext)), headers.Get("x-amz-server-side-encryption-context")) 205 }) 206 } 207 } 208 209 func TestParseKMSEncryptionContext(t *testing.T) { 210 actual, err := parseKMSEncryptionContext("") 211 assert.NoError(t, err) 212 assert.Equal(t, map[string]string(nil), actual) 213 214 expected := map[string]string{ 215 "department": "10103.0", 216 } 217 actual, err = parseKMSEncryptionContext(`{"department": "10103.0"}`) 218 assert.NoError(t, err) 219 assert.Equal(t, expected, actual) 220 }