github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/cmd/serve/proxy/proxy_test.go (about)

     1  package proxy
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/rsa"
     6  	"crypto/sha256"
     7  	"encoding/base64"
     8  	"log"
     9  	"strings"
    10  	"testing"
    11  
    12  	_ "github.com/rclone/rclone/backend/local"
    13  	"github.com/rclone/rclone/fs/config/configmap"
    14  	"github.com/rclone/rclone/fs/config/obscure"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  	"golang.org/x/crypto/ssh"
    18  )
    19  
    20  func TestRun(t *testing.T) {
    21  	opt := DefaultOpt
    22  	cmd := "go run proxy_code.go"
    23  	opt.AuthProxy = cmd
    24  	p := New(&opt)
    25  
    26  	t.Run("Normal", func(t *testing.T) {
    27  		config, err := p.run(map[string]string{
    28  			"type": "ftp",
    29  			"user": "me",
    30  			"pass": "pass",
    31  			"host": "127.0.0.1",
    32  		})
    33  		require.NoError(t, err)
    34  		assert.Equal(t, configmap.Simple{
    35  			"type":  "ftp",
    36  			"user":  "me-test",
    37  			"pass":  "pass",
    38  			"host":  "127.0.0.1",
    39  			"_root": "",
    40  		}, config)
    41  	})
    42  
    43  	t.Run("Error", func(t *testing.T) {
    44  		config, err := p.run(map[string]string{
    45  			"error": "potato",
    46  		})
    47  		assert.Nil(t, config)
    48  		require.Error(t, err)
    49  		require.Contains(t, err.Error(), "potato")
    50  	})
    51  
    52  	t.Run("Obscure", func(t *testing.T) {
    53  		config, err := p.run(map[string]string{
    54  			"type":     "ftp",
    55  			"user":     "me",
    56  			"pass":     "pass",
    57  			"host":     "127.0.0.1",
    58  			"_obscure": "pass,user",
    59  		})
    60  		require.NoError(t, err)
    61  		config["user"] = obscure.MustReveal(config["user"])
    62  		config["pass"] = obscure.MustReveal(config["pass"])
    63  		assert.Equal(t, configmap.Simple{
    64  			"type":     "ftp",
    65  			"user":     "me-test",
    66  			"pass":     "pass",
    67  			"host":     "127.0.0.1",
    68  			"_obscure": "pass,user",
    69  			"_root":    "",
    70  		}, config)
    71  	})
    72  
    73  	const testUser = "testUser"
    74  	const testPass = "testPass"
    75  
    76  	t.Run("call w/Password", func(t *testing.T) {
    77  		// check cache empty
    78  		assert.Equal(t, 0, p.vfsCache.Entries())
    79  		defer p.vfsCache.Clear()
    80  
    81  		passwordBytes := []byte(testPass)
    82  		value, err := p.call(testUser, testPass, false)
    83  		require.NoError(t, err)
    84  		entry, ok := value.(cacheEntry)
    85  		require.True(t, ok)
    86  
    87  		// check hash is correct in entry
    88  		assert.Equal(t, entry.pwHash, sha256.Sum256(passwordBytes))
    89  		require.NotNil(t, entry.vfs)
    90  		f := entry.vfs.Fs()
    91  		require.NotNil(t, f)
    92  		assert.Equal(t, "proxy-"+testUser, f.Name())
    93  		assert.True(t, strings.HasPrefix(f.String(), "Local file system"))
    94  
    95  		// check it is in the cache
    96  		assert.Equal(t, 1, p.vfsCache.Entries())
    97  		cacheValue, ok := p.vfsCache.GetMaybe(testUser)
    98  		assert.True(t, ok)
    99  		assert.Equal(t, value, cacheValue)
   100  	})
   101  
   102  	t.Run("Call w/Password", func(t *testing.T) {
   103  		// check cache empty
   104  		assert.Equal(t, 0, p.vfsCache.Entries())
   105  		defer p.vfsCache.Clear()
   106  
   107  		vfs, vfsKey, err := p.Call(testUser, testPass, false)
   108  		require.NoError(t, err)
   109  		require.NotNil(t, vfs)
   110  		assert.Equal(t, "proxy-"+testUser, vfs.Fs().Name())
   111  		assert.Equal(t, testUser, vfsKey)
   112  
   113  		// check it is in the cache
   114  		assert.Equal(t, 1, p.vfsCache.Entries())
   115  		cacheValue, ok := p.vfsCache.GetMaybe(testUser)
   116  		assert.True(t, ok)
   117  		cacheEntry, ok := cacheValue.(cacheEntry)
   118  		assert.True(t, ok)
   119  		assert.Equal(t, vfs, cacheEntry.vfs)
   120  
   121  		// Test Get works while we have something in the cache
   122  		t.Run("Get", func(t *testing.T) {
   123  			assert.Equal(t, vfs, p.Get(testUser))
   124  			assert.Nil(t, p.Get("unknown"))
   125  		})
   126  
   127  		// now try again from the cache
   128  		vfs, vfsKey, err = p.Call(testUser, testPass, false)
   129  		require.NoError(t, err)
   130  		require.NotNil(t, vfs)
   131  		assert.Equal(t, "proxy-"+testUser, vfs.Fs().Name())
   132  		assert.Equal(t, testUser, vfsKey)
   133  
   134  		// check cache is at the same level
   135  		assert.Equal(t, 1, p.vfsCache.Entries())
   136  
   137  		// now try again from the cache but with wrong password
   138  		vfs, vfsKey, err = p.Call(testUser, testPass+"wrong", false)
   139  		require.Error(t, err)
   140  		require.Contains(t, err.Error(), "incorrect password")
   141  		require.Nil(t, vfs)
   142  		require.Equal(t, "", vfsKey)
   143  
   144  		// check cache is at the same level
   145  		assert.Equal(t, 1, p.vfsCache.Entries())
   146  
   147  	})
   148  
   149  	privateKey, privateKeyErr := rsa.GenerateKey(rand.Reader, 2048)
   150  	if privateKeyErr != nil {
   151  		log.Fatal("error generating test private key " + privateKeyErr.Error())
   152  	}
   153  	publicKey, publicKeyError := ssh.NewPublicKey(&privateKey.PublicKey)
   154  	if privateKeyErr != nil {
   155  		log.Fatal("error generating test public key " + publicKeyError.Error())
   156  	}
   157  
   158  	publicKeyString := base64.StdEncoding.EncodeToString(publicKey.Marshal())
   159  
   160  	t.Run("Call w/PublicKey", func(t *testing.T) {
   161  		// check cache empty
   162  		assert.Equal(t, 0, p.vfsCache.Entries())
   163  		defer p.vfsCache.Clear()
   164  
   165  		value, err := p.call(testUser, publicKeyString, true)
   166  		require.NoError(t, err)
   167  		entry, ok := value.(cacheEntry)
   168  		require.True(t, ok)
   169  
   170  		// check publicKey is correct in entry
   171  		require.NoError(t, err)
   172  		require.NotNil(t, entry.vfs)
   173  		f := entry.vfs.Fs()
   174  		require.NotNil(t, f)
   175  		assert.Equal(t, "proxy-"+testUser, f.Name())
   176  		assert.True(t, strings.HasPrefix(f.String(), "Local file system"))
   177  
   178  		// check it is in the cache
   179  		assert.Equal(t, 1, p.vfsCache.Entries())
   180  		cacheValue, ok := p.vfsCache.GetMaybe(testUser)
   181  		assert.True(t, ok)
   182  		assert.Equal(t, value, cacheValue)
   183  	})
   184  
   185  	t.Run("call w/PublicKey", func(t *testing.T) {
   186  		// check cache empty
   187  		assert.Equal(t, 0, p.vfsCache.Entries())
   188  		defer p.vfsCache.Clear()
   189  
   190  		vfs, vfsKey, err := p.Call(
   191  			testUser,
   192  			publicKeyString,
   193  			true,
   194  		)
   195  		require.NoError(t, err)
   196  		require.NotNil(t, vfs)
   197  		assert.Equal(t, "proxy-"+testUser, vfs.Fs().Name())
   198  		assert.Equal(t, testUser, vfsKey)
   199  
   200  		// check it is in the cache
   201  		assert.Equal(t, 1, p.vfsCache.Entries())
   202  		cacheValue, ok := p.vfsCache.GetMaybe(testUser)
   203  		assert.True(t, ok)
   204  		cacheEntry, ok := cacheValue.(cacheEntry)
   205  		assert.True(t, ok)
   206  		assert.Equal(t, vfs, cacheEntry.vfs)
   207  
   208  		// Test Get works while we have something in the cache
   209  		t.Run("Get", func(t *testing.T) {
   210  			assert.Equal(t, vfs, p.Get(testUser))
   211  			assert.Nil(t, p.Get("unknown"))
   212  		})
   213  
   214  		// now try again from the cache
   215  		vfs, vfsKey, err = p.Call(testUser, publicKeyString, true)
   216  		require.NoError(t, err)
   217  		require.NotNil(t, vfs)
   218  		assert.Equal(t, "proxy-"+testUser, vfs.Fs().Name())
   219  		assert.Equal(t, testUser, vfsKey)
   220  
   221  		// check cache is at the same level
   222  		assert.Equal(t, 1, p.vfsCache.Entries())
   223  
   224  		// now try again from the cache but with wrong public key
   225  		vfs, vfsKey, err = p.Call(testUser, publicKeyString+"wrong", true)
   226  		require.Error(t, err)
   227  		require.Contains(t, err.Error(), "incorrect public key")
   228  		require.Nil(t, vfs)
   229  		require.Equal(t, "", vfsKey)
   230  
   231  		// check cache is at the same level
   232  		assert.Equal(t, 1, p.vfsCache.Entries())
   233  	})
   234  }