...

Source file src/edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/plugins/clustersecrets/breakglass/breakglass_test.go

Documentation: edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/plugins/clustersecrets/breakglass

     1  package breakglass
     2  
     3  import (
     4  	"context"
     5  	_ "embed"
     6  	"os"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  	"gotest.tools/v3/fs"
    12  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    13  
    14  	corev1 "k8s.io/api/core/v1"
    15  
    16  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    17  
    18  	kruntime "k8s.io/apimachinery/pkg/runtime"
    19  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    20  	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    21  
    22  	"edge-infra.dev/pkg/sds"
    23  	"edge-infra.dev/pkg/sds/clustersecrets/breakglass"
    24  	cc "edge-infra.dev/pkg/sds/clustersecrets/common"
    25  	"edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/config"
    26  
    27  	v1ien "edge-infra.dev/pkg/sds/ien/k8s/apis/v1"
    28  )
    29  
    30  var p = Plugin{}
    31  
    32  //go:embed testdata/shadow
    33  var contents []byte
    34  
    35  type testCase struct {
    36  	secret *corev1.Secret
    37  }
    38  
    39  var testSuite = []testCase{
    40  	{
    41  		toSecret(
    42  			"724e77776b37516a695951514848707376646670514467512e364c58624f50534a416e777849357438786d7a4264516839432e577553414c6b463578756633564a6347673449666c4b5141646c58754e67784a536a2e",
    43  			"4f54764c3033645a357557386b79394b",
    44  			"eH8DAQEGU2VjcmV0Af+AAAEIAQlQcmluY2lwYWwBDAABCkl0ZXJhdGlvbnMBBAABBFNhbHQBDAABBEhhc2gBDAABCEZ1bmN0aW9uAQwAAQhIYXNoVHlwZQEMAAEKR2VuZXJhdGlvbgEEAAEIUm90YXRpb24BAgAAAP/w/4ABCHp5bGV2ZWwwAiA0ZjU0NzY0YzMwMzM2NDVhMzU3NTU3Mzg2Yjc5Mzk0YgH/rDcyNGU3Nzc3NmIzNzUxNmE2OTU5NTE1MTQ4NDg3MDczNzY2NDY2NzA1MTQ0Njc1MTJlMzY0YzU4NjI0ZjUwNTM0YTQxNmU3Nzc4NDkzNTc0Mzg3ODZkN2E0MjY0NTE2ODM5NDMyZTU3NzU1MzQxNGM2YjQ2MzU3ODc1NjYzMzU2NGE2MzQ3NjczNDQ5NjY2YzRiNTE0MTY0NmM1ODc1NGU2Nzc4NGE1MzZhMmUBBnNoYTUxMgEGc2hhNTEyAQIA",
    45  		),
    46  	},
    47  }
    48  
    49  var nodeHostname = "node-1"
    50  
    51  func TestMain(_ *testing.M) {
    52  	os.Setenv("HOSTNAME", nodeHostname)
    53  }
    54  
    55  func TestBreakGlassApply(t *testing.T) {
    56  	cleanup := setupFilesystem(t)
    57  	defer cleanup()
    58  
    59  	for _, test := range testSuite {
    60  		c := fake.NewClientBuilder().WithScheme(createScheme()).WithObjects(test.secret).Build()
    61  
    62  		ctx := context.Background()
    63  		_, err := p.Reconcile(ctx, &v1ien.IENode{}, config.Data{Client: c})
    64  		require.NoError(t, err)
    65  
    66  		secret, err := breakglass.FromSecret(test.secret)
    67  		require.NoError(t, err)
    68  
    69  		expectedEntry := secret.String()
    70  
    71  		actualContents, err := os.ReadFile(shadowFilePath)
    72  		require.NoError(t, err)
    73  
    74  		entryFound := false
    75  		for _, line := range strings.Split(string(actualContents), "\n") {
    76  			if strings.Contains(line, breakglass.Username) {
    77  				entryFound = true
    78  				require.Equal(t, line, expectedEntry)
    79  			}
    80  		}
    81  		require.True(t, entryFound)
    82  	}
    83  }
    84  
    85  func setupFilesystem(t *testing.T) func() {
    86  	readOnlyTmpDir := fs.NewDir(t, readOnlyShadowFilePath)
    87  	shadowFileTmpDir := fs.NewDir(t, shadowFilePath)
    88  
    89  	cleanupFunc := func() {
    90  		shadowFileTmpDir.Remove()
    91  		readOnlyTmpDir.Remove()
    92  	}
    93  
    94  	shadowFileName := "/shadow"
    95  	readOnlyShadowFilePath = readOnlyTmpDir.Path() + shadowFileName
    96  	shadowFilePath = shadowFileTmpDir.Path() + shadowFileName
    97  
    98  	// write the current shadow file to tmp fs
    99  	err := os.WriteFile(readOnlyShadowFilePath, contents, 0600)
   100  	require.NoError(t, err)
   101  	return cleanupFunc
   102  }
   103  
   104  func toSecret(hash, salt, serialised string) *corev1.Secret {
   105  	return &corev1.Secret{
   106  		ObjectMeta: metav1.ObjectMeta{
   107  			Name:      breakglass.HashedSecretName,
   108  			Namespace: sds.Namespace,
   109  		},
   110  		Data: map[string][]byte{
   111  			breakglass.SecretKey: []byte(serialised),
   112  			cc.PrincipalKey:      []byte(breakglass.Username),
   113  			cc.HashFunctionKey:   []byte("sha512"),
   114  			cc.HashTypeKey:       []byte("sha512"),
   115  			cc.SaltKey:           []byte(salt),
   116  			cc.HashKey:           []byte(hash),
   117  			cc.SecretVersionKey:  []byte("2"),
   118  		},
   119  	}
   120  }
   121  
   122  func createScheme() *kruntime.Scheme {
   123  	scheme := kruntime.NewScheme()
   124  	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
   125  	utilruntime.Must(v1ien.AddToScheme(scheme))
   126  	return scheme
   127  }
   128  

View as plain text