get.porter.sh/porter@v1.3.0/pkg/storage/sanitizer_test.go (about)

     1  package storage_test
     2  
     3  import (
     4  	"context"
     5  	"path/filepath"
     6  	"reflect"
     7  	"sort"
     8  	"testing"
     9  
    10  	"get.porter.sh/porter/pkg/cnab"
    11  	"get.porter.sh/porter/pkg/porter"
    12  	"get.porter.sh/porter/pkg/portercontext"
    13  	"get.porter.sh/porter/pkg/secrets"
    14  	"get.porter.sh/porter/pkg/storage"
    15  	"github.com/cnabio/cnab-go/secrets/host"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestSanitizer_Parameters(t *testing.T) {
    20  	c := portercontext.New()
    21  	bun, err := cnab.LoadBundle(c, filepath.Join("../porter/testdata/bundle.json"))
    22  	require.NoError(t, err)
    23  
    24  	ctx := context.Background()
    25  	r := porter.NewTestPorter(t)
    26  	defer r.Close()
    27  
    28  	recordID := "01FZVC5AVP8Z7A78CSCP1EJ604"
    29  	sensitiveParamName := "my-second-param"
    30  	sensitiveParamKey := recordID + "-" + sensitiveParamName
    31  	expected := []secrets.SourceMap{
    32  		{Name: "my-first-param", Source: secrets.Source{Strategy: host.SourceValue, Hint: "1"}, ResolvedValue: "1"},
    33  		{Name: sensitiveParamName, Source: secrets.Source{Strategy: secrets.SourceSecret, Hint: sensitiveParamKey}, ResolvedValue: "2"},
    34  	}
    35  	sort.SliceStable(expected, func(i, j int) bool {
    36  		return expected[i].Name < expected[j].Name
    37  	})
    38  
    39  	// parameters that are hard coded values should be sanitized, while those mapped from secrets or env vars should be left alone by the sanitizer
    40  	rawParams := map[string]interface{}{
    41  		"my-first-param":   1,
    42  		sensitiveParamName: "2",
    43  	}
    44  	result, err := r.TestSanitizer.CleanRawParameters(ctx, rawParams, bun, recordID)
    45  	require.NoError(t, err)
    46  	require.Equal(t, len(expected), len(result))
    47  	sort.SliceStable(result, func(i, j int) bool {
    48  		return result[i].Name < result[j].Name
    49  	})
    50  
    51  	require.Truef(t, reflect.DeepEqual(result, expected), "expected: %v, got: %v", expected, result)
    52  
    53  	pset := storage.NewParameterSet("", "dev", result...)
    54  	resolved, err := r.TestSanitizer.RestoreParameterSet(ctx, pset, bun)
    55  	require.NoError(t, err)
    56  
    57  	require.Equal(t, len(rawParams), len(resolved))
    58  	for name, value := range resolved {
    59  		require.Equal(t, rawParams[name], value)
    60  	}
    61  }
    62  
    63  func TestSanitizer_CleanParameters(t *testing.T) {
    64  	testcases := []struct {
    65  		name       string
    66  		paramName  string
    67  		sourceKey  string
    68  		wantSource secrets.Source
    69  	}{
    70  		{ // Should be switched to a secret
    71  			name:       "hardcoded sensitive value",
    72  			paramName:  "my-second-param",
    73  			sourceKey:  host.SourceValue,
    74  			wantSource: secrets.Source{Strategy: secrets.SourceSecret, Hint: "INSTALLATION_ID-my-second-param"},
    75  		},
    76  		{ // Should be left alone
    77  			name:       "hardcoded insensitive value",
    78  			paramName:  "my-first-param",
    79  			sourceKey:  host.SourceValue,
    80  			wantSource: secrets.Source{Strategy: host.SourceValue, Hint: "myvalue"},
    81  		},
    82  		{ // Should be left alone
    83  			name:       "secret",
    84  			paramName:  "my-first-param",
    85  			sourceKey:  secrets.SourceSecret,
    86  			wantSource: secrets.Source{Strategy: secrets.SourceSecret, Hint: "myvalue"},
    87  		},
    88  		{ // Should be left alone
    89  			name:       "env var",
    90  			paramName:  "my-second-param",
    91  			sourceKey:  host.SourceEnv,
    92  			wantSource: secrets.Source{Strategy: host.SourceEnv, Hint: "myvalue"},
    93  		},
    94  	}
    95  
    96  	for _, tc := range testcases {
    97  		tc := tc
    98  		t.Run(tc.name, func(t *testing.T) {
    99  
   100  			c := portercontext.New()
   101  			bun, err := cnab.LoadBundle(c, filepath.Join("../porter/testdata/bundle.json"))
   102  			require.NoError(t, err)
   103  
   104  			ctx := context.Background()
   105  			r := porter.NewTestPorter(t)
   106  			defer r.Close()
   107  
   108  			inst := storage.NewInstallation("", "mybuns")
   109  			inst.ID = "INSTALLATION_ID" // Standardize for easy comparisons later
   110  			inst.Parameters.Parameters = []secrets.SourceMap{
   111  				{Name: tc.paramName, Source: secrets.Source{Strategy: tc.sourceKey, Hint: "myvalue"}},
   112  			}
   113  			gotParams, err := r.Sanitizer.CleanParameters(ctx, inst.Parameters.Parameters, bun, inst.ID)
   114  			require.NoError(t, err, "CleanParameters failed")
   115  
   116  			wantParms := []secrets.SourceMap{{Name: tc.paramName, Source: tc.wantSource}}
   117  			require.Equal(t, wantParms, gotParams, "unexpected value returned from CleanParameters")
   118  		})
   119  	}
   120  }
   121  
   122  func TestSanitizer_Output(t *testing.T) {
   123  	c := portercontext.New()
   124  	bun, err := cnab.LoadBundle(c, filepath.Join("../porter/testdata/bundle.json"))
   125  	require.NoError(t, err)
   126  
   127  	ctx := context.Background()
   128  	r := porter.NewTestPorter(t)
   129  	defer r.Close()
   130  
   131  	recordID := "01FZVC5AVP8Z7A78CSCP1EJ604"
   132  	sensitiveOutputName := "my-first-output"
   133  	sensitiveOutput := storage.Output{
   134  		Name:  sensitiveOutputName,
   135  		Key:   "",
   136  		Value: []byte("this is secret output"),
   137  		RunID: recordID,
   138  	}
   139  
   140  	expectedSensitiveOutput := storage.Output{
   141  		Name:  sensitiveOutputName,
   142  		Key:   recordID + "-" + sensitiveOutputName,
   143  		Value: nil,
   144  		RunID: recordID,
   145  	}
   146  
   147  	plainOutput := storage.Output{
   148  		Name:  "my-second-output",
   149  		Key:   "",
   150  		Value: []byte("true"),
   151  		RunID: recordID,
   152  	}
   153  
   154  	plainResult, err := r.TestSanitizer.CleanOutput(ctx, plainOutput, bun)
   155  	require.NoError(t, err)
   156  	require.Equal(t, plainOutput, plainResult)
   157  
   158  	sensitiveResult, err := r.TestSanitizer.CleanOutput(ctx, sensitiveOutput, bun)
   159  	require.NoError(t, err)
   160  	require.Equal(t, expectedSensitiveOutput, sensitiveResult)
   161  
   162  	expectedOutputs := storage.NewOutputs([]storage.Output{
   163  		plainOutput,
   164  		{Name: sensitiveOutputName, Key: expectedSensitiveOutput.Key, Value: sensitiveOutput.Value, RunID: recordID},
   165  	})
   166  	resolved, err := r.TestSanitizer.RestoreOutputs(ctx, storage.NewOutputs([]storage.Output{sensitiveResult, plainOutput}))
   167  	require.NoError(t, err)
   168  	sort.Sort(resolved)
   169  	sort.Sort(expectedOutputs)
   170  	require.Truef(t, reflect.DeepEqual(expectedOutputs, resolved), "expected outputs: %v, got outputs: %v", expectedOutputs, resolved)
   171  
   172  }