awsmount 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- awsmount-1.0.0/LICENSE +21 -0
- awsmount-1.0.0/PKG-INFO +624 -0
- awsmount-1.0.0/README.md +584 -0
- awsmount-1.0.0/pyproject.toml +68 -0
- awsmount-1.0.0/setup.cfg +4 -0
- awsmount-1.0.0/src/awsmount/__init__.py +9 -0
- awsmount-1.0.0/src/awsmount/__main__.py +8 -0
- awsmount-1.0.0/src/awsmount/adapters/__init__.py +10 -0
- awsmount-1.0.0/src/awsmount/adapters/export.py +303 -0
- awsmount-1.0.0/src/awsmount/adapters/fuse/__init__.py +30 -0
- awsmount-1.0.0/src/awsmount/adapters/fuse/mount.py +163 -0
- awsmount-1.0.0/src/awsmount/adapters/fuse/operations.py +359 -0
- awsmount-1.0.0/src/awsmount/adapters/shell/__init__.py +13 -0
- awsmount-1.0.0/src/awsmount/adapters/shell/commands.py +966 -0
- awsmount-1.0.0/src/awsmount/adapters/shell/completer.py +177 -0
- awsmount-1.0.0/src/awsmount/adapters/shell/formatting.py +182 -0
- awsmount-1.0.0/src/awsmount/adapters/shell/jsonpath.py +98 -0
- awsmount-1.0.0/src/awsmount/adapters/shell/pipes.py +97 -0
- awsmount-1.0.0/src/awsmount/adapters/shell/repl.py +103 -0
- awsmount-1.0.0/src/awsmount/adapters/webdav/__init__.py +26 -0
- awsmount-1.0.0/src/awsmount/adapters/webdav/auth.py +76 -0
- awsmount-1.0.0/src/awsmount/adapters/webdav/macos.py +367 -0
- awsmount-1.0.0/src/awsmount/adapters/webdav/provider.py +297 -0
- awsmount-1.0.0/src/awsmount/adapters/webdav/server.py +376 -0
- awsmount-1.0.0/src/awsmount/cli.py +644 -0
- awsmount-1.0.0/src/awsmount/config.py +115 -0
- awsmount-1.0.0/src/awsmount/doctor.py +279 -0
- awsmount-1.0.0/src/awsmount/errors.py +117 -0
- awsmount-1.0.0/src/awsmount/platform.py +186 -0
- awsmount-1.0.0/src/awsmount/providers/__init__.py +292 -0
- awsmount-1.0.0/src/awsmount/providers/acm.py +112 -0
- awsmount-1.0.0/src/awsmount/providers/apigateway.py +126 -0
- awsmount-1.0.0/src/awsmount/providers/autoscaling.py +109 -0
- awsmount-1.0.0/src/awsmount/providers/base.py +177 -0
- awsmount-1.0.0/src/awsmount/providers/cfn_types.py +45 -0
- awsmount-1.0.0/src/awsmount/providers/cloudformation.py +148 -0
- awsmount-1.0.0/src/awsmount/providers/cloudfront.py +160 -0
- awsmount-1.0.0/src/awsmount/providers/cloudwatch.py +98 -0
- awsmount-1.0.0/src/awsmount/providers/common.py +168 -0
- awsmount-1.0.0/src/awsmount/providers/dynamodb.py +126 -0
- awsmount-1.0.0/src/awsmount/providers/ec2.py +418 -0
- awsmount-1.0.0/src/awsmount/providers/ecr.py +102 -0
- awsmount-1.0.0/src/awsmount/providers/ecs.py +244 -0
- awsmount-1.0.0/src/awsmount/providers/eks.py +272 -0
- awsmount-1.0.0/src/awsmount/providers/elbv2.py +367 -0
- awsmount-1.0.0/src/awsmount/providers/eventbridge.py +130 -0
- awsmount-1.0.0/src/awsmount/providers/iam.py +488 -0
- awsmount-1.0.0/src/awsmount/providers/kms.py +184 -0
- awsmount-1.0.0/src/awsmount/providers/lambda_.py +162 -0
- awsmount-1.0.0/src/awsmount/providers/logs.py +131 -0
- awsmount-1.0.0/src/awsmount/providers/organizations.py +141 -0
- awsmount-1.0.0/src/awsmount/providers/rds.py +201 -0
- awsmount-1.0.0/src/awsmount/providers/redshift.py +88 -0
- awsmount-1.0.0/src/awsmount/providers/refs.py +137 -0
- awsmount-1.0.0/src/awsmount/providers/route53.py +157 -0
- awsmount-1.0.0/src/awsmount/providers/s3.py +257 -0
- awsmount-1.0.0/src/awsmount/providers/secretsmanager.py +105 -0
- awsmount-1.0.0/src/awsmount/providers/sns.py +114 -0
- awsmount-1.0.0/src/awsmount/providers/sqs.py +129 -0
- awsmount-1.0.0/src/awsmount/providers/ssm.py +104 -0
- awsmount-1.0.0/src/awsmount/providers/stepfunctions.py +145 -0
- awsmount-1.0.0/src/awsmount/providers/vpc.py +573 -0
- awsmount-1.0.0/src/awsmount/secrets/__init__.py +5 -0
- awsmount-1.0.0/src/awsmount/secrets/cli.py +235 -0
- awsmount-1.0.0/src/awsmount/secrets/session.py +168 -0
- awsmount-1.0.0/src/awsmount/secrets/store.py +179 -0
- awsmount-1.0.0/src/awsmount/secrets/tree.py +382 -0
- awsmount-1.0.0/src/awsmount/session/__init__.py +3 -0
- awsmount-1.0.0/src/awsmount/session/accounts.py +245 -0
- awsmount-1.0.0/src/awsmount/session/budget.py +96 -0
- awsmount-1.0.0/src/awsmount/session/cache.py +188 -0
- awsmount-1.0.0/src/awsmount/session/clients.py +206 -0
- awsmount-1.0.0/src/awsmount/session/context.py +220 -0
- awsmount-1.0.0/src/awsmount/session/errorlog.py +229 -0
- awsmount-1.0.0/src/awsmount/session/limiter.py +59 -0
- awsmount-1.0.0/src/awsmount/session/progress.py +106 -0
- awsmount-1.0.0/src/awsmount/session/redact.py +259 -0
- awsmount-1.0.0/src/awsmount/tree/__init__.py +7 -0
- awsmount-1.0.0/src/awsmount/tree/collection.py +418 -0
- awsmount-1.0.0/src/awsmount/tree/links.py +187 -0
- awsmount-1.0.0/src/awsmount/tree/root.py +199 -0
- awsmount-1.0.0/src/awsmount/tree/tags.py +98 -0
- awsmount-1.0.0/src/awsmount/vfs/__init__.py +28 -0
- awsmount-1.0.0/src/awsmount/vfs/node.py +287 -0
- awsmount-1.0.0/src/awsmount/vfs/path.py +148 -0
- awsmount-1.0.0/src/awsmount/vfs/render.py +149 -0
- awsmount-1.0.0/src/awsmount/vfs/resolver.py +157 -0
- awsmount-1.0.0/src/awsmount/vfs/stat.py +107 -0
- awsmount-1.0.0/src/awsmount/vfs/walk.py +161 -0
- awsmount-1.0.0/src/awsmount.egg-info/PKG-INFO +624 -0
- awsmount-1.0.0/src/awsmount.egg-info/SOURCES.txt +93 -0
- awsmount-1.0.0/src/awsmount.egg-info/dependency_links.txt +1 -0
- awsmount-1.0.0/src/awsmount.egg-info/entry_points.txt +2 -0
- awsmount-1.0.0/src/awsmount.egg-info/requires.txt +12 -0
- awsmount-1.0.0/src/awsmount.egg-info/top_level.txt +1 -0
awsmount-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 KloudSec
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
awsmount-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: awsmount
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Mount any AWS account as a read-only filesystem (shell, WebDAV, FUSE).
|
|
5
|
+
Author-email: Tarek CHEIKH <tarek@kloudsec.io>
|
|
6
|
+
Maintainer-email: Tarek CHEIKH <tarek@kloudsec.io>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/kloudsec-io/awsmount
|
|
9
|
+
Project-URL: Repository, https://github.com/kloudsec-io/awsmount
|
|
10
|
+
Project-URL: Issues, https://github.com/kloudsec-io/awsmount/issues
|
|
11
|
+
Project-URL: Documentation, https://github.com/kloudsec-io/awsmount#readme
|
|
12
|
+
Keywords: aws,filesystem,fuse,webdav,boto3,read-only
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: System Administrators
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: System :: Filesystems
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: boto3>=1.34
|
|
29
|
+
Requires-Dist: click>=8.1
|
|
30
|
+
Requires-Dist: prompt_toolkit>=3.0.40
|
|
31
|
+
Requires-Dist: wsgidav>=4.3
|
|
32
|
+
Requires-Dist: cheroot>=10
|
|
33
|
+
Requires-Dist: mfusepy>=1.0
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-timeout>=2; extra == "dev"
|
|
37
|
+
Requires-Dist: moto[all,server]>=5; extra == "dev"
|
|
38
|
+
Requires-Dist: flake8>=6; extra == "dev"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
<img src="https://raw.githubusercontent.com/kloudsec-io/awsmount/main/assets/awsmount-logo.png" alt="awsmount logo" width="140">
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
<h1 align="center">awsmount</h1>
|
|
46
|
+
|
|
47
|
+
<p align="center">
|
|
48
|
+
<b>Mount any AWS account as a read-only filesystem.</b>
|
|
49
|
+
</p>
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<a href="https://pypi.org/project/awsmount/"><img src="https://img.shields.io/pypi/v/awsmount" alt="PyPI version"></a>
|
|
53
|
+
<a href="https://pypi.org/project/awsmount/"><img src="https://img.shields.io/pypi/pyversions/awsmount" alt="Python versions"></a>
|
|
54
|
+
<a href="https://github.com/kloudsec-io/awsmount/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT license"></a>
|
|
55
|
+
</p>
|
|
56
|
+
|
|
57
|
+
<p align="center">
|
|
58
|
+
<img src="https://raw.githubusercontent.com/kloudsec-io/awsmount/main/assets/awsmount-in-action.png" alt="awsmount mounts an AWS account as a read-only folder: ls, grep -r and cat work on it, secrets are hidden and writes are refused" width="820">
|
|
59
|
+
</p>
|
|
60
|
+
|
|
61
|
+
**awsmount turns your AWS account into a folder** that you can browse with the
|
|
62
|
+
tools you already know: `ls`, `cd`, `cat`, `grep -r`, `find`, `tree`,
|
|
63
|
+
`diff -r`, `jq` and `git`. Every resource (an EC2 instance, a security group,
|
|
64
|
+
a Lambda function, an IAM role...) is a directory, and every API response is
|
|
65
|
+
a readable `describe.json` file. It is **read-only**: nothing in AWS can be
|
|
66
|
+
changed through it.
|
|
67
|
+
|
|
68
|
+
It is for engineers who want to look around an account without clicking
|
|
69
|
+
through the console or remembering `aws ... describe-*` commands, and for AI
|
|
70
|
+
coding agents, which already know how to use a filesystem.
|
|
71
|
+
|
|
72
|
+
## Why use it
|
|
73
|
+
|
|
74
|
+
- **Familiar tools.** `grep -rl '0.0.0.0/0' vpc/security-groups` finds every
|
|
75
|
+
rule open to the world. `cd` follows a resource to its VPC through relative
|
|
76
|
+
symlinks. `diff -r` compares two snapshots of an account.
|
|
77
|
+
- **Read-only.** Only `Describe*`, `List*` and `Get*` calls are allowed, and
|
|
78
|
+
that is enforced before any request is sent. Writes fail with "Read-only
|
|
79
|
+
file system".
|
|
80
|
+
- **Secrets hidden.** Lambda and ECS environment values, EC2 user data and
|
|
81
|
+
secret-looking CloudFormation values show as `<hidden>`. S3 object
|
|
82
|
+
contents and secret values are never fetched. (The separate command
|
|
83
|
+
[`awsmount secrets`](docs/secrets.md) is the only way to read secret
|
|
84
|
+
values, on purpose.)
|
|
85
|
+
- **Light on the API.** Nothing is fetched until you look at it, and an
|
|
86
|
+
optional call budget (`--max-api-calls`) can stop a runaway `grep -r`.
|
|
87
|
+
|
|
88
|
+
## Install
|
|
89
|
+
|
|
90
|
+
awsmount needs **Python 3.11 or newer**, and AWS credentials set up the way
|
|
91
|
+
the AWS CLI expects (a named profile or environment variables).
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
pipx install awsmount # recommended
|
|
95
|
+
# or: python3 -m pip install awsmount
|
|
96
|
+
# or, from source: pipx install git+https://github.com/kloudsec-io/awsmount
|
|
97
|
+
awsmount doctor
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`awsmount doctor` checks what works on your machine and ends with a summary
|
|
101
|
+
line such as:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
shell: OK · webdav-serve: OK · webdav-mount: OK · fuse: optional (not needed, WebDAV mount works)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
- **macOS:** nothing else to install. Mounting uses the WebDAV client that is
|
|
108
|
+
built into macOS, with no administrator password.
|
|
109
|
+
- **Linux:** the interactive shell needs nothing. Mounting needs FUSE:
|
|
110
|
+
`sudo apt install fuse3` (Debian, Ubuntu) or `sudo dnf install fuse3`
|
|
111
|
+
(Fedora).
|
|
112
|
+
- **From a checkout:** `python3 -m pip install -e .`
|
|
113
|
+
|
|
114
|
+
## Getting started
|
|
115
|
+
|
|
116
|
+
Five minutes, from nothing to your first real answer. Replace `myprofile`
|
|
117
|
+
with your AWS profile (leave out `-p myprofile` to use your default
|
|
118
|
+
credentials) and `us-east-1` with the region you want to look at.
|
|
119
|
+
|
|
120
|
+
### 1. Check that it works
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
awsmount doctor --check-credentials -p myprofile
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The last lines show the AWS account and user it found. If a line says
|
|
127
|
+
`FAIL`, fix that first.
|
|
128
|
+
|
|
129
|
+
### 2. Look around in the interactive shell
|
|
130
|
+
|
|
131
|
+
No mounting needed:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
awsmount -p myprofile -r us-east-1 shell
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
You get `ls`, `cd`, `cat`, `grep`, `find`, `tree` and more (type `help`).
|
|
138
|
+
Below are commands you type in the shell and the output awsmount really
|
|
139
|
+
printed, captured from a throwaway test account. The account id and region
|
|
140
|
+
are shortened to `ACCT` and `REGION`, and the long `grep` result is cut
|
|
141
|
+
short (`...`):
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
awsmount:/$ ls /
|
|
145
|
+
ACCT
|
|
146
|
+
awsmount:/$ ls /ACCT/REGION
|
|
147
|
+
acm
|
|
148
|
+
apigateway
|
|
149
|
+
autoscaling
|
|
150
|
+
cloudformation
|
|
151
|
+
cloudwatch
|
|
152
|
+
dynamodb
|
|
153
|
+
ec2
|
|
154
|
+
ecr
|
|
155
|
+
ecs
|
|
156
|
+
eks
|
|
157
|
+
elbv2
|
|
158
|
+
eventbridge
|
|
159
|
+
kms
|
|
160
|
+
lambda
|
|
161
|
+
logs
|
|
162
|
+
rds
|
|
163
|
+
redshift
|
|
164
|
+
s3
|
|
165
|
+
secretsmanager
|
|
166
|
+
sns
|
|
167
|
+
sqs
|
|
168
|
+
ssm
|
|
169
|
+
stepfunctions
|
|
170
|
+
vpc
|
|
171
|
+
awsmount:/$ ls /ACCT/REGION/ec2/instances/i-7960944c02c99b353
|
|
172
|
+
arn
|
|
173
|
+
describe.json
|
|
174
|
+
instance-type
|
|
175
|
+
links
|
|
176
|
+
name
|
|
177
|
+
private-ip
|
|
178
|
+
state
|
|
179
|
+
tags
|
|
180
|
+
tags.json
|
|
181
|
+
user-data
|
|
182
|
+
awsmount:/$ cat /ACCT/REGION/ec2/instances/i-7960944c02c99b353/user-data
|
|
183
|
+
<hidden>
|
|
184
|
+
awsmount:/$ grep -rl 0.0.0.0/0 /ACCT/REGION/vpc/security-groups
|
|
185
|
+
/ACCT/REGION/vpc/security-groups/sg-029ffec0a78d92776/describe.json
|
|
186
|
+
/ACCT/REGION/vpc/security-groups/sg-029ffec0a78d92776/rules.json
|
|
187
|
+
/ACCT/REGION/vpc/security-groups/sg-4f6d07da8cf2aaa65/describe.json
|
|
188
|
+
/ACCT/REGION/vpc/security-groups/sg-4f6d07da8cf2aaa65/rules.json
|
|
189
|
+
...
|
|
190
|
+
awsmount:/$ cat /ACCT/REGION/cloudformation/stacks/leaktest/outputs.json
|
|
191
|
+
[
|
|
192
|
+
{
|
|
193
|
+
"OutputKey": "SecretKey",
|
|
194
|
+
"OutputValue": "<hidden>"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"OutputKey": "DbPass",
|
|
198
|
+
"OutputValue": "<hidden>"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"OutputKey": "QueueName",
|
|
202
|
+
"OutputValue": "ok-to-show"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The first level is the account (its alias, or its id), then the region, then
|
|
208
|
+
the service, then the kind of resource, then one directory per resource.
|
|
209
|
+
Note `user-data` showing `<hidden>`: awsmount hides secrets by default.
|
|
210
|
+
|
|
211
|
+
### 3. Mount your account as a folder
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
mkdir -p ~/aws
|
|
215
|
+
awsmount -p myprofile -r us-east-1 mount ~/aws
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Leave that terminal running. In a second terminal, use any tool you like:
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
ls ~/aws # your account (alias or id)
|
|
222
|
+
cd ~/aws/<account>/us-east-1
|
|
223
|
+
ls # one folder per service
|
|
224
|
+
ls ec2/instances # one folder per instance
|
|
225
|
+
cat ec2/instances/i-0123456789abcdef0/name
|
|
226
|
+
grep -rl '0.0.0.0/0' vpc/security-groups # every rule open to the world
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Trying to change anything fails, on purpose:
|
|
230
|
+
`touch ~/aws/x` gives "Read-only file system".
|
|
231
|
+
|
|
232
|
+
### 4. Unmount
|
|
233
|
+
|
|
234
|
+
Press Ctrl-C in the terminal that runs `awsmount mount`, or from anywhere:
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
awsmount umount ~/aws
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### 5. Where next
|
|
241
|
+
|
|
242
|
+
- Copy a [recipe](#recipes): find open security groups, see what uses a
|
|
243
|
+
resource, diff two snapshots, track an account in git, or hand the folder
|
|
244
|
+
to an AI coding agent.
|
|
245
|
+
- Read [what you will see](#what-you-will-see) to learn the layout.
|
|
246
|
+
- Check [Coverage](#coverage) for the services that are supported.
|
|
247
|
+
|
|
248
|
+
## What you will see
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
/<account-alias-or-id>/ one directory per profile/account
|
|
252
|
+
<region>/<service>/<collection>/<resource>/
|
|
253
|
+
global/{iam,route53,cloudfront,organizations}/...
|
|
254
|
+
_meta/account.json identity.json errors.log stats.json
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
One resource looks like this (example names and IDs, not real output):
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
/acme-prod/eu-west-1/vpc/security-groups/sg-0a1b2c3d4e5f60718/
|
|
261
|
+
describe.json arn name group-name vpc-id rules.json tags.json tags/
|
|
262
|
+
links/vpc -> ../../../vpcs/vpc-0abc1234def567890
|
|
263
|
+
referenced-by/ec2-instances-i-0123456789abcdef0
|
|
264
|
+
-> ../../../../ec2/instances/i-0123456789abcdef0
|
|
265
|
+
referenced-by/lambda-functions-orders-api
|
|
266
|
+
-> ../../../../lambda/functions/orders-api
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
- Every resource directory has `describe.json`: the raw API data with
|
|
270
|
+
`ResponseMetadata` removed, ISO-8601 datetimes, sorted keys, indent 2.
|
|
271
|
+
- It also has `arn`, `name`, `tags.json` and `tags/<Key>` when they apply,
|
|
272
|
+
plus small files such as `state` or `runtime`, `links/` and, for security
|
|
273
|
+
groups, `referenced-by/`.
|
|
274
|
+
- Names containing `/`, `%`, control characters or a leading `.` are
|
|
275
|
+
`%XX`-escaped (`/aws/lambda/fn` becomes `%2Faws%2Flambda%2Ffn`).
|
|
276
|
+
Case-insensitive name collisions get a `~<id>` suffix.
|
|
277
|
+
- Several profiles (`-p a -p b`) give several top-level directories.
|
|
278
|
+
`--region all` mounts every region enabled for the account.
|
|
279
|
+
|
|
280
|
+
## Recipes
|
|
281
|
+
|
|
282
|
+
> The account name `acme-prod`, region and resource IDs in the recipes below are **examples** to adapt, not captured output.
|
|
283
|
+
|
|
284
|
+
The examples assume a mount at `~/aws` with an account directory
|
|
285
|
+
`acme-prod`. Inside `awsmount shell` the same paths start at `/`.
|
|
286
|
+
|
|
287
|
+
### Find security groups open to the world
|
|
288
|
+
|
|
289
|
+
`rules.json` is derived from the security group listing, so reading it costs
|
|
290
|
+
no extra API call. Each rule is one JSON object, one key per line:
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
cd ~/aws/acme-prod/eu-west-1/vpc/security-groups
|
|
294
|
+
grep -l '"cidr": "0.0.0.0/0"' */rules.json # any direction
|
|
295
|
+
for f in */rules.json; do
|
|
296
|
+
jq -e 'any(.[]; .direction == "ingress"
|
|
297
|
+
and (.cidr == "0.0.0.0/0" or .cidr == "::/0"))' \
|
|
298
|
+
"$f" >/dev/null && echo "${f%/rules.json} $(cat "${f%/rules.json}/group-name")"
|
|
299
|
+
done
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Without a mount:
|
|
303
|
+
|
|
304
|
+
```
|
|
305
|
+
awsmount -p prod -r eu-west-1 grep -r -l '"cidr": "0.0.0.0/0"' \
|
|
306
|
+
/acme-prod/eu-west-1/vpc/security-groups
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### What uses this security group?
|
|
310
|
+
|
|
311
|
+
`referenced-by/` lists symlinks to every network interface, EC2 instance,
|
|
312
|
+
security group rule, load balancer, Lambda function, RDS instance and VPC
|
|
313
|
+
endpoint in the same account and region that uses the group:
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
$ ls ~/aws/acme-prod/eu-west-1/vpc/security-groups/sg-0a1b2c3d4e5f60718/referenced-by
|
|
317
|
+
ec2-instances-i-0123456789abcdef0
|
|
318
|
+
ec2-network-interfaces-eni-0fedcba9876543210
|
|
319
|
+
lambda-functions-orders-api
|
|
320
|
+
vpc-security-groups-sg-0f9e8d7c6b5a49382
|
|
321
|
+
$ cat ~/aws/acme-prod/eu-west-1/vpc/security-groups/sg-0a1b2c3d4e5f60718/referenced-by/*/name
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
On FUSE, `readlink` shows the targets. On a macOS WebDAV mount each entry is
|
|
325
|
+
a text file that contains the relative target, so `cat` the entry to see it.
|
|
326
|
+
Building the index costs one cached list call per source collection.
|
|
327
|
+
|
|
328
|
+
### Diff two snapshots of an account
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
awsmount -p prod -r eu-west-1 export /acme-prod/eu-west-1 ~/snap/monday
|
|
332
|
+
# ... later ...
|
|
333
|
+
awsmount -p prod -r eu-west-1 export /acme-prod/eu-west-1 ~/snap/tuesday
|
|
334
|
+
diff -r -x .awsmount-export ~/snap/monday ~/snap/tuesday
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
By default `export` writes each symlink as a small text file holding its
|
|
338
|
+
target (`--links file`), so `diff -r` and `grep -R` work. With
|
|
339
|
+
`--links keep` the export contains real symlinks, and the links between
|
|
340
|
+
resources form cycles that make macOS `diff -r` report "Directory loop
|
|
341
|
+
detected".
|
|
342
|
+
|
|
343
|
+
Every export writes a `.awsmount-export` marker with the export time, so
|
|
344
|
+
exclude it from the diff. If you export a whole account directory, also
|
|
345
|
+
exclude `_meta` (`-x _meta`), because `stats.json` and `errors.log` change
|
|
346
|
+
from run to run. Export reads every file, lazy ones included, so it makes
|
|
347
|
+
many API calls: narrow it with `--services`.
|
|
348
|
+
|
|
349
|
+
### Track an account in git
|
|
350
|
+
|
|
351
|
+
`--clean` deletes everything in the destination before writing (it requires
|
|
352
|
+
the marker of a previous export, or an empty or missing directory). Point it
|
|
353
|
+
at a subdirectory of the repository, never at the repository root, or it
|
|
354
|
+
would delete `.git`:
|
|
355
|
+
|
|
356
|
+
```
|
|
357
|
+
mkdir -p ~/aws-history && cd ~/aws-history && git init
|
|
358
|
+
awsmount -p prod -r eu-west-1 --services vpc,ec2,elbv2,iam \
|
|
359
|
+
export /acme-prod ~/aws-history/acme-prod --clean
|
|
360
|
+
git add -A && git commit -m "acme-prod snapshot $(date -u +%F)"
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Run the last two lines on a schedule; `git log -p` then shows how the
|
|
364
|
+
account changed. Content is deterministic: AWS returns some lists in a
|
|
365
|
+
different order from one call to the next (tags, route table associations,
|
|
366
|
+
security group lists, IP permissions), so awsmount sorts exactly those, and
|
|
367
|
+
leaves every other list in API order. Masking stays on unless you pass
|
|
368
|
+
`--reveal`.
|
|
369
|
+
|
|
370
|
+
### Use it with AI coding agents
|
|
371
|
+
|
|
372
|
+
Agents already know `ls`, `cat`, `grep`, `find` and `jq`. Give them a mount,
|
|
373
|
+
or let them run one-shot commands:
|
|
374
|
+
|
|
375
|
+
```
|
|
376
|
+
awsmount -p prod -r eu-west-1 --max-api-calls 1000 mount ~/aws
|
|
377
|
+
# then, in the agent's instructions:
|
|
378
|
+
# "The AWS account is mounted read-only at ~/aws. Each resource is a
|
|
379
|
+
# directory with describe.json. Follow links/ and referenced-by/.
|
|
380
|
+
# Check ~/aws/<account>/_meta/errors.log for anything you could not read."
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
```
|
|
384
|
+
awsmount -p prod -r eu-west-1 shell -c "grep -r -l orders-api /acme-prod/eu-west-1/lambda"
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Why this is reasonably safe: no operation can modify AWS; secret values,
|
|
388
|
+
object bodies and log events are never fetched by `awsmount mount`, `shell`
|
|
389
|
+
and `serve`; secrets in metadata are
|
|
390
|
+
hidden; the budget stops runaway exploration; GNU `grep -r` and `find` do
|
|
391
|
+
not follow symlinks, and WebDAV mounts serve links as files, so recursive
|
|
392
|
+
tools cannot loop. Do **not** combine agents with `--reveal`: any local
|
|
393
|
+
process, the agent included, can read everything that is revealed.
|
|
394
|
+
|
|
395
|
+
## Secret values: `awsmount secrets`
|
|
396
|
+
|
|
397
|
+
To read the **values** of Secrets Manager secrets and Parameter Store
|
|
398
|
+
parameters as files, there is one separate command. It is the only place
|
|
399
|
+
where awsmount reads a secret value:
|
|
400
|
+
|
|
401
|
+
```
|
|
402
|
+
awsmount secrets mount ~/secrets -p prod -r eu-west-1
|
|
403
|
+
cat ~/secrets/secretsmanager/team%2Fapi/value # the secret, exactly
|
|
404
|
+
cat ~/secrets/ssm/app/db/password # decrypted SecureString
|
|
405
|
+
awsmount secrets umount ~/secrets
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Listing never reads a value; a value is fetched when its file is read, kept
|
|
409
|
+
in memory for 5 minutes (`--ttl`) and overwritten when it expires. One
|
|
410
|
+
profile and one region per mount. `awsmount mount`, `shell`, `serve` and
|
|
411
|
+
`export` still cannot read a value, even with `--reveal`.
|
|
412
|
+
|
|
413
|
+
Two limits you should know: overwriting memory is best effort, and on macOS
|
|
414
|
+
the system's WebDAV client keeps a temporary copy of each file it reads in
|
|
415
|
+
`/private/tmp` until you unmount (keep FileVault on). Read
|
|
416
|
+
[docs/secrets.md](docs/secrets.md) before using it.
|
|
417
|
+
|
|
418
|
+
## Mounting on each OS
|
|
419
|
+
|
|
420
|
+
| | Interactive shell | Real mount | Serve over WebDAV |
|
|
421
|
+
|---|---|---|---|
|
|
422
|
+
| macOS | `awsmount shell` | `awsmount mount DIR`: WebDAV through the built-in `/sbin/mount_webdav` (zero install, no admin rights); FUSE only with `--method fuse` | `awsmount serve` |
|
|
423
|
+
| Linux | `awsmount shell` | `awsmount mount DIR`: FUSE through mfusepy and libfuse 2/3 | `awsmount serve` (mount it yourself, e.g. davfs2) |
|
|
424
|
+
|
|
425
|
+
`--method auto` (the default) picks FUSE on Linux and WebDAV on macOS, even
|
|
426
|
+
when FUSE-T or macFUSE happens to be installed.
|
|
427
|
+
|
|
428
|
+
- **macOS (WebDAV).** awsmount starts a WebDAV server on `127.0.0.1` only,
|
|
429
|
+
with a fresh random password per session, and mounts it read-only with the
|
|
430
|
+
system's own `mount_webdav`. WebDAV has no symlinks, so each link is served
|
|
431
|
+
as a small text file holding its target. Details, including how the
|
|
432
|
+
password is passed and why Spotlight is switched off for the mount:
|
|
433
|
+
[docs/mounting-macos.md](docs/mounting-macos.md).
|
|
434
|
+
- **Linux (FUSE).** The mount is read-only, never uses `allow_other` (only
|
|
435
|
+
your user can read it) and has real symlinks. Details:
|
|
436
|
+
[docs/mounting-linux.md](docs/mounting-linux.md).
|
|
437
|
+
|
|
438
|
+
## Safety
|
|
439
|
+
|
|
440
|
+
- **Read-only.** Each boto3 client has a `before-call` hook that refuses any
|
|
441
|
+
operation that is not on the allow-list derived from the providers (each
|
|
442
|
+
operation is allowed only for the client whose provider declared it),
|
|
443
|
+
does not start with `Describe`/`List`/`Get`/`Search`/`Lookup`, or is on
|
|
444
|
+
the deny-list. The deny-list holds data-plane and credential operations:
|
|
445
|
+
`GetSecretValue`, `GetParameter*`, `GetObject`, `Decrypt`, `GetFunction`,
|
|
446
|
+
`GetLogEvents`, `GetPasswordData`, `ExportCertificate` and others. Only
|
|
447
|
+
`awsmount secrets` runs a separate session that may call `GetSecretValue`
|
|
448
|
+
and `GetParameter`, and nothing else. FUSE write operations return
|
|
449
|
+
`EROFS`. WebDAV write methods return 403.
|
|
450
|
+
- **Masking.** It is applied at render time, to every JSON file, and also
|
|
451
|
+
to exports. EC2 `user-data` and CloudFormation `template` are not even
|
|
452
|
+
fetched unless you pass `--reveal`. Tag values are not hidden.
|
|
453
|
+
- **`--reveal` risk.** `--reveal` turns masking off and prints a warning.
|
|
454
|
+
Mounted files are readable by any process running as your user, including
|
|
455
|
+
AI agents, editors, indexers and backup tools. Use it only for a
|
|
456
|
+
short-lived, targeted session.
|
|
457
|
+
- **Other local users.** The FUSE mount has no `allow_other`. The WebDAV
|
|
458
|
+
server binds to 127.0.0.1 only, checks the `Host` header (DNS-rebinding
|
|
459
|
+
defence), and requires HTTP auth on every request. The per-session URL
|
|
460
|
+
token is not a secret (on macOS it is visible in `ps` and `mount`
|
|
461
|
+
output); the password is the secret. The credentials are generated per
|
|
462
|
+
session and never written to disk. awsmount warns when another user could
|
|
463
|
+
modify the mountpoint's parent directory, or reach it from outside your
|
|
464
|
+
home directory.
|
|
465
|
+
|
|
466
|
+
Details: [docs/security.md](docs/security.md).
|
|
467
|
+
|
|
468
|
+
## Coverage
|
|
469
|
+
|
|
470
|
+
Coverage today: 28 services, 63 resource types. awsmount does not cover
|
|
471
|
+
every AWS service. This table is the output of `awsmount services --short`:
|
|
472
|
+
|
|
473
|
+
| Service | Scope | Resource types |
|
|
474
|
+
|---|---|---|
|
|
475
|
+
| ec2 | region | instances, volumes, snapshots, key-pairs, elastic-ips, network-interfaces, amis, launch-templates |
|
|
476
|
+
| vpc | region | vpcs, subnets, security-groups, route-tables, internet-gateways, nat-gateways, network-acls, endpoints, peering-connections, dhcp-options, transit-gateways, flow-logs |
|
|
477
|
+
| elbv2 | region | load-balancers, load-balancers/listeners, load-balancers/listeners/rules, target-groups |
|
|
478
|
+
| lambda | region | functions |
|
|
479
|
+
| rds | region | instances, clusters, clusters/members |
|
|
480
|
+
| ecs | region | clusters, clusters/services, task-definitions |
|
|
481
|
+
| eks | region | clusters, clusters/nodegroups, clusters/addons |
|
|
482
|
+
| autoscaling | region | groups |
|
|
483
|
+
| s3 | region | buckets |
|
|
484
|
+
| dynamodb | region | tables |
|
|
485
|
+
| sqs | region | queues |
|
|
486
|
+
| sns | region | topics |
|
|
487
|
+
| kms | region | keys, aliases |
|
|
488
|
+
| logs | region | log-groups |
|
|
489
|
+
| cloudwatch | region | alarms |
|
|
490
|
+
| ecr | region | repositories |
|
|
491
|
+
| stepfunctions | region | state-machines |
|
|
492
|
+
| redshift | region | clusters |
|
|
493
|
+
| eventbridge | region | event-buses, event-buses/rules |
|
|
494
|
+
| cloudformation | region | stacks, stacks/resources |
|
|
495
|
+
| secretsmanager | region | secrets |
|
|
496
|
+
| ssm | region | parameters |
|
|
497
|
+
| acm | region | certificates |
|
|
498
|
+
| route53 | global | hosted-zones |
|
|
499
|
+
| iam | global | users, roles, groups, policies |
|
|
500
|
+
| cloudfront | global | distributions |
|
|
501
|
+
| apigateway | region | rest-apis |
|
|
502
|
+
| organizations | global | accounts, roots, policies |
|
|
503
|
+
|
|
504
|
+
`awsmount services` (without `--short`) also lists the files and links
|
|
505
|
+
inside each resource directory, so you can find a path without reading the
|
|
506
|
+
docs. `awsmount services --markdown` regenerates
|
|
507
|
+
[docs/coverage.md](docs/coverage.md), which has that list as a table, and
|
|
508
|
+
`--json` gives machine-readable output.
|
|
509
|
+
|
|
510
|
+
## Verification status
|
|
511
|
+
|
|
512
|
+
- **Automated tests** run against the moto AWS emulator: every provider, the
|
|
513
|
+
read-only guard, masking, caching, the shell, the WebDAV server and the
|
|
514
|
+
FUSE operations.
|
|
515
|
+
- **Real mounts** are tested by scripts: `tests/e2e/macos_webdav.sh` (macOS's
|
|
516
|
+
built-in WebDAV client) and `tests/e2e/linux_fuse.sh` (kernel FUSE in
|
|
517
|
+
Docker), plus `tests/e2e/secrets_macos_webdav.sh` and
|
|
518
|
+
`tests/e2e/secrets_linux_fuse.sh` for `awsmount secrets`.
|
|
519
|
+
- **Real AWS:** checked on a sandbox account, from a Mac and from an Amazon
|
|
520
|
+
Linux 2023 instance, against the AWS API. This includes `awsmount secrets`.
|
|
521
|
+
- **Not tested on real AWS:** CloudFront, Organizations data, cross-account
|
|
522
|
+
trust, an account with thousands of resources (throttling, long
|
|
523
|
+
pagination) and most non-admin permission sets. moto also lacks several of
|
|
524
|
+
these APIs, so those paths are covered by unit tests only. Treat 1.0.0 as
|
|
525
|
+
ready for evaluation on non-production accounts.
|
|
526
|
+
- **Not covered:** Windows, and mounting the macOS tree through FUSE-T or
|
|
527
|
+
macFUSE (the code path exists but has not been run, and awsmount does not
|
|
528
|
+
recommend it; see [docs/mounting-macos.md](docs/mounting-macos.md)).
|
|
529
|
+
|
|
530
|
+
## Limits
|
|
531
|
+
|
|
532
|
+
- 28 services and 63 resource types; everything else is absent. EC2
|
|
533
|
+
snapshots and AMIs are limited to those you own, and ECS task definitions
|
|
534
|
+
to ACTIVE ones.
|
|
535
|
+
- Data is cached for `--ttl` seconds (60 by default). File mtimes are fetch
|
|
536
|
+
times. The shell's `refresh` command drops the cache; a mounted tree
|
|
537
|
+
refreshes when the TTL expires.
|
|
538
|
+
- Lazy files (policies, tags and similar) are fetched when read. In
|
|
539
|
+
`awsmount shell`, `ls -l` renders them to show real sizes (a few API calls
|
|
540
|
+
per directory, cached for the TTL). The FUSE mount (default `--lazy-size
|
|
541
|
+
zero`) and the macOS WebDAV mount report a size of 0 until the file is
|
|
542
|
+
read, so `ls -l` makes no API calls there; the content is still complete.
|
|
543
|
+
Use `--lazy-size render` on FUSE for real sizes. Collection directories
|
|
544
|
+
only contain directories, so listing them is cheap.
|
|
545
|
+
- Walking a whole account (`find`, `tree`, `du`) lists every directory, and
|
|
546
|
+
some directory names come from AWS: each IAM role's `tags/`,
|
|
547
|
+
`inline-policies/` and `links/`, log group and KMS key tags, S3 bucket
|
|
548
|
+
locations, ECS task definitions. On a small account that is a few hundred
|
|
549
|
+
calls; with hundreds of IAM roles it is thousands, one after another.
|
|
550
|
+
Narrow the walk (`find ~/aws/prod/us-east-1/vpc ...`) or mount fewer
|
|
551
|
+
services (`--services vpc,ec2,s3`).
|
|
552
|
+
- `grep -r` over a whole account reads every lazy file, which can take a
|
|
553
|
+
long time. There is no call limit by default (AWS only throttles per API
|
|
554
|
+
and boto3 backs off). Narrow the search with `--services` or `--region`, or
|
|
555
|
+
set `--max-api-calls N` for a hard stop: uncached reads then fail with
|
|
556
|
+
`EIO` and "API call budget exhausted", and cached data is still served.
|
|
557
|
+
- On macOS WebDAV mounts symlinks are text files by default.
|
|
558
|
+
`--webdav-links follow` serves them as their targets, but recursive tools
|
|
559
|
+
may then loop.
|
|
560
|
+
- Linux has no automated WebDAV mount; use FUSE, or `awsmount serve` with
|
|
561
|
+
your own WebDAV client.
|
|
562
|
+
- The region directory lists only that region's buckets; use `--region all`
|
|
563
|
+
to list all of them.
|
|
564
|
+
- S3 object keys are listed only with `--s3-objects N`, and then only the
|
|
565
|
+
first N keys per bucket. Object bodies, secret values, SSM parameter
|
|
566
|
+
values, log events and Lambda code are never available, even with
|
|
567
|
+
`--reveal`. (Secret and parameter values are available only through
|
|
568
|
+
`awsmount secrets`.)
|
|
569
|
+
- Tag values are never hidden.
|
|
570
|
+
- `referenced-by/` exists for security groups only. Its sources are EC2
|
|
571
|
+
instances, network interfaces, other security groups' rules, load
|
|
572
|
+
balancers, Lambda functions, RDS instances and VPC endpoints, in the same
|
|
573
|
+
account and region. ECS services and EKS clusters are not sources: EKS
|
|
574
|
+
lists only cluster names, so finding their security groups would cost one
|
|
575
|
+
extra call per cluster.
|
|
576
|
+
- Not covered inside the services above: EC2 launch template versions
|
|
577
|
+
(they hold user data), ECR images, Step Functions executions, EventBridge
|
|
578
|
+
events and connections, Redshift Serverless, and legacy Auto Scaling
|
|
579
|
+
launch configurations.
|
|
580
|
+
- Names that contain `/` are shown percent-encoded, so the CloudWatch log
|
|
581
|
+
group `/aws/lambda/fn` is the directory `%2Faws%2Flambda%2Ffn`.
|
|
582
|
+
- Resources AWS still reports in a terminal state (terminated EC2
|
|
583
|
+
instances, deleted NAT gateways, Transit Gateways, VPC endpoints and
|
|
584
|
+
peering connections) are not listed.
|
|
585
|
+
- The shell's built-in `grep` uses Python regular expressions.
|
|
586
|
+
- Organizations data appears only in an account allowed to read it, usually
|
|
587
|
+
the management account. Elsewhere the directory is empty and an entry
|
|
588
|
+
goes to `_meta/errors.log`.
|
|
589
|
+
- AccessDenied on a service gives an empty directory plus an `errors.log`
|
|
590
|
+
entry; AccessDenied on a lazy file gives `EACCES` ("Permission denied")
|
|
591
|
+
on both FUSE and the macOS mount, and the cause is a line in
|
|
592
|
+
`_meta/errors.log`. "Operation not permitted" (`EPERM`) is reserved for
|
|
593
|
+
the read-only guard refusing a call, which is a bug. With
|
|
594
|
+
`awsmount serve` a WebDAV client sees HTTP 403 for both. Gaps in moto,
|
|
595
|
+
localemu or other endpoints show up the same way.
|
|
596
|
+
- macOS and Linux only. Windows is not supported. On Windows you can try
|
|
597
|
+
WSL 2 (a Linux distribution such as Ubuntu) and follow the Linux
|
|
598
|
+
instructions; this has not been tested.
|
|
599
|
+
|
|
600
|
+
## Documentation
|
|
601
|
+
|
|
602
|
+
- [docs/usage.md](docs/usage.md): commands, options, layout, recipes
|
|
603
|
+
- [docs/security.md](docs/security.md): read-only model, masking,
|
|
604
|
+
`--reveal`, authentication
|
|
605
|
+
- [docs/secrets.md](docs/secrets.md): `awsmount secrets`, the only command
|
|
606
|
+
that reads secret values
|
|
607
|
+
- [docs/mounting-macos.md](docs/mounting-macos.md): WebDAV, FUSE-T/macFUSE,
|
|
608
|
+
Spotlight
|
|
609
|
+
- [docs/mounting-linux.md](docs/mounting-linux.md): fuse3, fusermount,
|
|
610
|
+
Docker
|
|
611
|
+
- [docs/providers.md](docs/providers.md): how to write a provider
|
|
612
|
+
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md): how the code is built (layers,
|
|
613
|
+
the read-only guard, how directories are made, the adapters)
|
|
614
|
+
- [docs/coverage.md](docs/coverage.md): generated coverage table, with the
|
|
615
|
+
files and links of every resource type
|
|
616
|
+
- [SECURITY.md](SECURITY.md): how to report a vulnerability
|
|
617
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md): how to report a problem or send a
|
|
618
|
+
change
|
|
619
|
+
|
|
620
|
+
## License
|
|
621
|
+
|
|
622
|
+
MIT
|
|
623
|
+
|
|
624
|
+
Maintained by [KloudSec](https://kloudsec.io).
|