source: trunk/integration/test_sftp.py

Last change on this file was 1cfe843d, checked in by Alexandre Detiste <alexandre.detiste@…>, at 2024-02-22T23:40:25Z

more python2 removal

  • Property mode set to 100644
File size: 4.7 KB
Line 
1"""
2It's possible to create/rename/delete files and directories in Tahoe-LAFS using
3SFTP.
4
5These tests use Paramiko, rather than Twisted's Conch, because:
6
7    1. It's a different implementation, so we're not testing Conch against
8       itself.
9
10    2. Its API is much simpler to use.
11"""
12
13import os.path
14from posixpath import join
15from stat import S_ISDIR
16
17from paramiko import SSHClient
18from paramiko.client import AutoAddPolicy
19from paramiko.sftp_client import SFTPClient
20from paramiko.ssh_exception import AuthenticationException
21from paramiko.rsakey import RSAKey
22
23import pytest
24
25from .util import generate_ssh_key, run_in_thread
26
27
28def connect_sftp(connect_args):
29    """Create an SFTP client."""
30    client = SSHClient()
31    client.set_missing_host_key_policy(AutoAddPolicy)
32    client.connect("localhost", port=8022, look_for_keys=False,
33                   allow_agent=False, **connect_args)
34    sftp = SFTPClient.from_transport(client.get_transport())
35
36    def rmdir(path, delete_root=True):
37        for f in sftp.listdir_attr(path=path):
38            childpath = join(path, f.filename)
39            if S_ISDIR(f.st_mode):
40                rmdir(childpath)
41            else:
42                sftp.remove(childpath)
43        if delete_root:
44            sftp.rmdir(path)
45
46    # Delete any files left over from previous tests :(
47    rmdir("/", delete_root=False)
48
49    return sftp
50
51
52@run_in_thread
53def test_bad_account_password_ssh_key(alice, tmpdir):
54    """
55    Can't login with unknown username, any password, or wrong SSH pub key.
56    """
57    # Any password, wrong username:
58    for u, p in [("alice-key", "wrong"), ("someuser", "password")]:
59        with pytest.raises(AuthenticationException):
60            connect_sftp(connect_args={
61                "username": u, "password": p,
62            })
63
64    another_key = os.path.join(str(tmpdir), "ssh_key")
65    generate_ssh_key(another_key)
66    good_key = RSAKey(filename=os.path.join(alice.process.node_dir, "private", "ssh_client_rsa_key"))
67    bad_key = RSAKey(filename=another_key)
68
69    # Wrong key:
70    with pytest.raises(AuthenticationException):
71        connect_sftp(connect_args={
72            "username": "alice-key", "pkey": bad_key,
73        })
74
75    # Wrong username:
76    with pytest.raises(AuthenticationException):
77        connect_sftp(connect_args={
78            "username": "someoneelse", "pkey": good_key,
79        })
80
81
82def sftp_client_key(client):
83    """
84    :return RSAKey: the RSA client key associated with this grid.Client
85    """
86    # XXX move to Client / grid.py?
87    return RSAKey(
88        filename=os.path.join(client.process.node_dir, "private", "ssh_client_rsa_key"),
89    )
90
91
92@run_in_thread
93def test_ssh_key_auth(alice):
94    """It's possible to login authenticating with SSH public key."""
95    key = sftp_client_key(alice)
96    sftp = connect_sftp(connect_args={
97        "username": "alice-key", "pkey": key
98    })
99    assert sftp.listdir() == []
100
101
102@run_in_thread
103def test_read_write_files(alice):
104    """It's possible to upload and download files."""
105    sftp = connect_sftp(connect_args={
106        "username": "alice-key",
107        "pkey": sftp_client_key(alice),
108    })
109    with sftp.file("myfile", "wb") as f:
110        f.write(b"abc")
111        f.write(b"def")
112
113    with sftp.file("myfile", "rb") as f:
114        assert f.read(4) == b"abcd"
115        assert f.read(2) == b"ef"
116        assert f.read(1) == b""
117
118
119@run_in_thread
120def test_directories(alice):
121    """
122    It's possible to create, list directories, and create and remove files in
123    them.
124    """
125    sftp = connect_sftp(connect_args={
126        "username": "alice-key",
127        "pkey": sftp_client_key(alice),
128    })
129    assert sftp.listdir() == []
130
131    sftp.mkdir("childdir")
132    assert sftp.listdir() == ["childdir"]
133
134    with sftp.file("myfile", "wb") as f:
135        f.write(b"abc")
136    assert sorted(sftp.listdir()) == ["childdir", "myfile"]
137
138    sftp.chdir("childdir")
139    assert sftp.listdir() == []
140
141    with sftp.file("myfile2", "wb") as f:
142        f.write(b"def")
143    assert sftp.listdir() == ["myfile2"]
144
145    sftp.chdir(None)  # root
146    with sftp.file("childdir/myfile2", "rb") as f:
147        assert f.read() == b"def"
148
149    sftp.remove("myfile")
150    assert sftp.listdir() == ["childdir"]
151
152    sftp.rmdir("childdir")
153    assert sftp.listdir() == []
154
155
156@run_in_thread
157def test_rename(alice):
158    """Directories and files can be renamed."""
159    sftp = connect_sftp(connect_args={
160        "username": "alice-key",
161        "pkey": sftp_client_key(alice),
162    })
163    sftp.mkdir("dir")
164
165    filepath = join("dir", "file")
166    with sftp.file(filepath, "wb") as f:
167        f.write(b"abc")
168
169    sftp.rename(filepath, join("dir", "file2"))
170    sftp.rename("dir", "dir2")
171
172    with sftp.file(join("dir2", "file2"), "rb") as f:
173        assert f.read() == b"abc"
Note: See TracBrowser for help on using the repository browser.