github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/cli/command/trust/signer_add_test.go (about)

     1  package trust
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"testing"
    10  
    11  	"github.com/khulnasoft/cli/cli/config"
    12  	"github.com/khulnasoft/cli/internal/test"
    13  	notaryfake "github.com/khulnasoft/cli/internal/test/notary"
    14  	"github.com/theupdateframework/notary"
    15  	"gotest.tools/v3/assert"
    16  	is "gotest.tools/v3/assert/cmp"
    17  )
    18  
    19  func TestTrustSignerAddErrors(t *testing.T) {
    20  	testCases := []struct {
    21  		name          string
    22  		args          []string
    23  		expectedError string
    24  	}{
    25  		{
    26  			name:          "not-enough-args",
    27  			expectedError: "requires at least 2 argument",
    28  		},
    29  		{
    30  			name:          "no-key",
    31  			args:          []string{"foo", "bar"},
    32  			expectedError: "path to a public key must be provided using the `--key` flag",
    33  		},
    34  		{
    35  			name:          "reserved-releases-signer-add",
    36  			args:          []string{"releases", "my-image", "--key", "/path/to/key"},
    37  			expectedError: "releases is a reserved keyword, please use a different signer name",
    38  		},
    39  		{
    40  			name:          "disallowed-chars",
    41  			args:          []string{"ali/ce", "my-image", "--key", "/path/to/key"},
    42  			expectedError: "signer name \"ali/ce\" must start with lowercase alphanumeric characters and can include \"-\" or \"_\" after the first character",
    43  		},
    44  		{
    45  			name:          "no-upper-case",
    46  			args:          []string{"Alice", "my-image", "--key", "/path/to/key"},
    47  			expectedError: "signer name \"Alice\" must start with lowercase alphanumeric characters and can include \"-\" or \"_\" after the first character",
    48  		},
    49  		{
    50  			name:          "start-with-letter",
    51  			args:          []string{"_alice", "my-image", "--key", "/path/to/key"},
    52  			expectedError: "signer name \"_alice\" must start with lowercase alphanumeric characters and can include \"-\" or \"_\" after the first character",
    53  		},
    54  	}
    55  	config.SetDir(t.TempDir())
    56  
    57  	for _, tc := range testCases {
    58  		cli := test.NewFakeCli(&fakeClient{})
    59  		cli.SetNotaryClient(notaryfake.GetOfflineNotaryRepository)
    60  		cmd := newSignerAddCommand(cli)
    61  		cmd.SetArgs(tc.args)
    62  		cmd.SetOut(io.Discard)
    63  		assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
    64  	}
    65  }
    66  
    67  func TestSignerAddCommandNoTargetsKey(t *testing.T) {
    68  	config.SetDir(t.TempDir())
    69  
    70  	tmpfile, err := os.CreateTemp("", "pemfile")
    71  	assert.NilError(t, err)
    72  	tmpfile.Close()
    73  	defer os.Remove(tmpfile.Name())
    74  
    75  	cli := test.NewFakeCli(&fakeClient{})
    76  	cli.SetNotaryClient(notaryfake.GetEmptyTargetsNotaryRepository)
    77  	cmd := newSignerAddCommand(cli)
    78  	cmd.SetArgs([]string{"--key", tmpfile.Name(), "alice", "alpine", "linuxkit/alpine"})
    79  
    80  	cmd.SetOut(io.Discard)
    81  	assert.Error(t, cmd.Execute(), fmt.Sprintf("could not parse public key from file: %s: no valid public key found", tmpfile.Name()))
    82  }
    83  
    84  func TestSignerAddCommandBadKeyPath(t *testing.T) {
    85  	config.SetDir(t.TempDir())
    86  
    87  	cli := test.NewFakeCli(&fakeClient{})
    88  	cli.SetNotaryClient(notaryfake.GetEmptyTargetsNotaryRepository)
    89  	cmd := newSignerAddCommand(cli)
    90  	cmd.SetArgs([]string{"--key", "/path/to/key.pem", "alice", "alpine"})
    91  
    92  	cmd.SetOut(io.Discard)
    93  	expectedError := "unable to read public key from file: open /path/to/key.pem: no such file or directory"
    94  	if runtime.GOOS == "windows" {
    95  		expectedError = "unable to read public key from file: open /path/to/key.pem: The system cannot find the path specified."
    96  	}
    97  	assert.Error(t, cmd.Execute(), expectedError)
    98  }
    99  
   100  func TestSignerAddCommandInvalidRepoName(t *testing.T) {
   101  	config.SetDir(t.TempDir())
   102  
   103  	pubKeyDir := t.TempDir()
   104  	pubKeyFilepath := filepath.Join(pubKeyDir, "pubkey.pem")
   105  	assert.NilError(t, os.WriteFile(pubKeyFilepath, pubKeyFixture, notary.PrivNoExecPerms))
   106  
   107  	cli := test.NewFakeCli(&fakeClient{})
   108  	cli.SetNotaryClient(notaryfake.GetUninitializedNotaryRepository)
   109  	cmd := newSignerAddCommand(cli)
   110  	imageName := "870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd"
   111  	cmd.SetArgs([]string{"--key", pubKeyFilepath, "alice", imageName})
   112  
   113  	cmd.SetOut(io.Discard)
   114  	assert.Error(t, cmd.Execute(), "failed to add signer to: 870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd")
   115  	expectedErr := fmt.Sprintf("invalid repository name (%s), cannot specify 64-byte hexadecimal strings\n\n", imageName)
   116  
   117  	assert.Check(t, is.Equal(expectedErr, cli.ErrBuffer().String()))
   118  }
   119  
   120  func TestIngestPublicKeys(t *testing.T) {
   121  	// Call with a bad path
   122  	_, err := ingestPublicKeys([]string{"foo", "bar"})
   123  	expectedError := "unable to read public key from file: open foo: no such file or directory"
   124  	if runtime.GOOS == "windows" {
   125  		expectedError = "unable to read public key from file: open foo: The system cannot find the file specified."
   126  	}
   127  	assert.Error(t, err, expectedError)
   128  	// Call with real file path
   129  	tmpfile, err := os.CreateTemp("", "pemfile")
   130  	assert.NilError(t, err)
   131  	tmpfile.Close()
   132  	defer os.Remove(tmpfile.Name())
   133  	_, err = ingestPublicKeys([]string{tmpfile.Name()})
   134  	assert.Error(t, err, fmt.Sprintf("could not parse public key from file: %s: no valid public key found", tmpfile.Name()))
   135  }