github.com/arthur-befumo/witchcraft-go-server@v1.12.0/integration/config_test.go (about)

     1  // Copyright (c) 2019 Palantir Technologies. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package integration
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"fmt"
    21  	"io/ioutil"
    22  	"os"
    23  	"path/filepath"
    24  	"testing"
    25  
    26  	"github.com/palantir/witchcraft-go-server/config"
    27  	"github.com/palantir/witchcraft-go-server/witchcraft"
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestEncryptedConfig(t *testing.T) {
    33  	var (
    34  		decryptedValue = "hello world"
    35  		encryptionKey  = "AES:T6H7a4WvQS9ITcNIihyUIj30K4SIrD6dB39ENJQ7oAo="
    36  		encryptedValue = "${enc:eyJ0eXBlIjoiQUVTIiwibW9kZSI6IkdDTSIsImNpcGhlcnRleHQiOiJqcGl0bThQRStRekd2YlE9IiwiaXYiOiJrTHlBOEZBNzFnTDVpdkswIiwidGFnIjoicmxpcXY3amYwbWVnaGU1N0pyQ3ZzZz09In0=}"
    37  	)
    38  
    39  	type message struct {
    40  		config.Runtime `yaml:",inline"`
    41  		Message        string `yaml:"message"`
    42  	}
    43  
    44  	type messageInstall struct {
    45  		config.Install `yaml:",inline"`
    46  		Message        string `yaml:"message"`
    47  	}
    48  
    49  	for _, test := range []struct {
    50  		Name          string
    51  		ECVKeyContent string
    52  		InstallConfig string
    53  		RuntimeConfig string
    54  		// Use InitFn to verify config
    55  		Verify    func(info witchcraft.InitInfo) error
    56  		VerifyLog func(t *testing.T, logOutput []byte)
    57  	}{
    58  		{
    59  			Name:          "init function sees decrypted config",
    60  			ECVKeyContent: encryptionKey,
    61  			InstallConfig: fmt.Sprintf("message: %s\nuse-console-log: true\n", encryptedValue),
    62  			RuntimeConfig: fmt.Sprintf("message: %s\nlogging:\n  level: warn\n", encryptedValue),
    63  			Verify: func(info witchcraft.InitInfo) error {
    64  				if msg := info.InstallConfig.(*messageInstall).Message; msg != decryptedValue {
    65  					return fmt.Errorf("expected %q got %q", decryptedValue, msg)
    66  				}
    67  				if msg := info.RuntimeConfig.Current().(*message).Message; msg != decryptedValue {
    68  					return fmt.Errorf("expected %q got %q", decryptedValue, msg)
    69  				}
    70  				return nil
    71  			},
    72  			VerifyLog: func(t *testing.T, logOutput []byte) {
    73  				assert.Equal(t, []string{"abort startup"}, getLogFileMessages(t, logOutput))
    74  			},
    75  		},
    76  		{
    77  			Name:          "no ecv required if no encrypted config",
    78  			ECVKeyContent: "test_invalid_key_material",
    79  			InstallConfig: "message: hello install\nuse-console-log: true\n",
    80  			RuntimeConfig: "message: hello runtime\nlogging:\n  level: warn\n",
    81  			Verify: func(info witchcraft.InitInfo) error {
    82  				if msg := info.InstallConfig.(*messageInstall).Message; msg != "hello install" {
    83  					return fmt.Errorf("expected %q got %q", "hello install", msg)
    84  				}
    85  				if msg := info.RuntimeConfig.Current().(*message).Message; msg != "hello runtime" {
    86  					return fmt.Errorf("expected %q got %q", "hello runtime", msg)
    87  				}
    88  				return nil
    89  			},
    90  			VerifyLog: func(t *testing.T, logOutput []byte) {
    91  				assert.Equal(t, []string{"abort startup"}, getLogFileMessages(t, logOutput))
    92  			},
    93  		},
    94  		{
    95  			Name:          "warning printed if ecv key fails in runtime",
    96  			ECVKeyContent: "test_invalid_key_material",
    97  			InstallConfig: "message: hello install\nuse-console-log: true\n",
    98  			RuntimeConfig: fmt.Sprintf("message: %s\nlogging:\n  level: warn\n", encryptedValue),
    99  			Verify: func(info witchcraft.InitInfo) error {
   100  				if msg := info.InstallConfig.(*messageInstall).Message; msg != "hello install" {
   101  					return fmt.Errorf("expected %q got %q", "hello install", msg)
   102  				}
   103  				if msg := info.RuntimeConfig.Current().(*message).Message; msg != encryptedValue {
   104  					return fmt.Errorf("expected %q got %q", encryptedValue, msg)
   105  				}
   106  				return nil
   107  			},
   108  			VerifyLog: func(t *testing.T, logOutput []byte) {
   109  				assert.Equal(t, []string{"Failed to decrypt encrypted runtime configuration", "abort startup"}, getLogFileMessages(t, logOutput))
   110  			},
   111  		},
   112  	} {
   113  		t.Run(test.Name, func(t *testing.T) {
   114  			tmpDir, err := ioutil.TempDir("", "TestEncryptedConfig_")
   115  			require.NoError(t, err)
   116  			defer func() {
   117  				_ = os.RemoveAll(tmpDir)
   118  			}()
   119  			ecvKeyFile := filepath.Join(tmpDir, "ecv.key")
   120  			err = ioutil.WriteFile(ecvKeyFile, []byte(test.ECVKeyContent), 0600)
   121  			require.NoError(t, err)
   122  			installFile := filepath.Join(tmpDir, "install.yml")
   123  			err = ioutil.WriteFile(installFile, []byte(test.InstallConfig), 0644)
   124  			require.NoError(t, err)
   125  			runtimeFile := filepath.Join(tmpDir, "runtime.yml")
   126  			err = ioutil.WriteFile(runtimeFile, []byte(test.RuntimeConfig), 0644)
   127  			require.NoError(t, err)
   128  
   129  			logOutputBuffer := &bytes.Buffer{}
   130  			server := witchcraft.NewServer().
   131  				WithECVKeyFromFile(ecvKeyFile).
   132  				WithInstallConfigFromFile(installFile).
   133  				WithInstallConfigType(&messageInstall{}).
   134  				WithRuntimeConfigFromFile(runtimeFile).
   135  				WithRuntimeConfigType(&message{}).
   136  				WithLoggerStdoutWriter(logOutputBuffer).
   137  				WithDisableGoRuntimeMetrics().
   138  				WithSelfSignedCertificate().
   139  				WithInitFunc(func(ctx context.Context, info witchcraft.InitInfo) (cleanup func(), rErr error) {
   140  					if err := test.Verify(info); err != nil {
   141  						return nil, err
   142  					}
   143  					return nil, fmt.Errorf("abort startup")
   144  				})
   145  			// Execute server, expecting error
   146  			err = server.Start()
   147  			require.EqualError(t, err, "abort startup")
   148  
   149  			if test.VerifyLog != nil {
   150  				test.VerifyLog(t, logOutputBuffer.Bytes())
   151  			}
   152  		})
   153  	}
   154  }