occystrap 0.4.0__py3-none-any.whl → 0.4.1__py3-none-any.whl

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.
Files changed (38) hide show
  1. occystrap/_version.py +34 -0
  2. occystrap/filters/__init__.py +10 -0
  3. occystrap/filters/base.py +67 -0
  4. occystrap/filters/exclude.py +136 -0
  5. occystrap/filters/inspect.py +179 -0
  6. occystrap/filters/normalize_timestamps.py +123 -0
  7. occystrap/filters/search.py +177 -0
  8. occystrap/inputs/__init__.py +1 -0
  9. occystrap/inputs/base.py +40 -0
  10. occystrap/inputs/docker.py +171 -0
  11. occystrap/{docker_registry.py → inputs/registry.py} +112 -50
  12. occystrap/inputs/tarfile.py +88 -0
  13. occystrap/main.py +330 -31
  14. occystrap/outputs/__init__.py +1 -0
  15. occystrap/outputs/base.py +46 -0
  16. occystrap/{output_directory.py → outputs/directory.py} +10 -9
  17. occystrap/outputs/docker.py +137 -0
  18. occystrap/{output_mounts.py → outputs/mounts.py} +2 -1
  19. occystrap/{output_ocibundle.py → outputs/ocibundle.py} +1 -1
  20. occystrap/outputs/registry.py +240 -0
  21. occystrap/{output_tarfile.py → outputs/tarfile.py} +18 -2
  22. occystrap/pipeline.py +297 -0
  23. occystrap/tarformat.py +122 -0
  24. occystrap/tests/test_inspect.py +355 -0
  25. occystrap/tests/test_tarformat.py +199 -0
  26. occystrap/uri.py +231 -0
  27. occystrap/util.py +67 -38
  28. occystrap-0.4.1.dist-info/METADATA +444 -0
  29. occystrap-0.4.1.dist-info/RECORD +38 -0
  30. {occystrap-0.4.0.dist-info → occystrap-0.4.1.dist-info}/WHEEL +1 -1
  31. {occystrap-0.4.0.dist-info → occystrap-0.4.1.dist-info}/entry_points.txt +0 -1
  32. occystrap/docker_extract.py +0 -36
  33. occystrap-0.4.0.dist-info/METADATA +0 -131
  34. occystrap-0.4.0.dist-info/RECORD +0 -20
  35. occystrap-0.4.0.dist-info/pbr.json +0 -1
  36. {occystrap-0.4.0.dist-info → occystrap-0.4.1.dist-info/licenses}/AUTHORS +0 -0
  37. {occystrap-0.4.0.dist-info → occystrap-0.4.1.dist-info/licenses}/LICENSE +0 -0
  38. {occystrap-0.4.0.dist-info → occystrap-0.4.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,444 @@
1
+ Metadata-Version: 2.4
2
+ Name: occystrap
3
+ Version: 0.4.1
4
+ Summary: occystrap: docker and OCI container tools
5
+ Author-email: Michael Still <mikal@stillhq.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/shakenfist/occystrap
8
+ Project-URL: Bug Tracker, https://github.com/shakenfist/occystrap/issues
9
+ Classifier: Intended Audience :: Information Technology
10
+ Classifier: Intended Audience :: System Administrators
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: >=3.7
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ License-File: AUTHORS
18
+ Requires-Dist: click>=7.1.1
19
+ Requires-Dist: requests
20
+ Requires-Dist: requests-unixsocket
21
+ Requires-Dist: prettytable
22
+ Requires-Dist: oslo.concurrency
23
+ Requires-Dist: shakenfist-utilities
24
+ Provides-Extra: test
25
+ Requires-Dist: coverage; extra == "test"
26
+ Requires-Dist: testtools; extra == "test"
27
+ Requires-Dist: mock; extra == "test"
28
+ Requires-Dist: stestr; extra == "test"
29
+ Requires-Dist: flake8; extra == "test"
30
+ Dynamic: license-file
31
+
32
+ # Occy Strap
33
+
34
+ Occy Strap is a simple set of Docker and OCI container tools, which can be used
35
+ either for container forensics or for implementing an OCI orchestrator,
36
+ depending on your needs. This is a very early implementation, so be braced for
37
+ impact.
38
+
39
+ ## Quick Start with URI-Style Commands
40
+
41
+ The recommended way to use Occy Strap is with the new URI-style `process` and
42
+ `search` commands:
43
+
44
+ ```
45
+ # Download from registry to tarball
46
+ occystrap process registry://docker.io/library/busybox:latest tar://busybox.tar
47
+
48
+ # Download from registry to directory
49
+ occystrap process registry://docker.io/library/centos:7 dir://centos7
50
+
51
+ # Export from local Docker to tarball with timestamp normalization
52
+ occystrap process docker://myimage:v1 tar://output.tar -f normalize-timestamps
53
+
54
+ # Search for files in an image
55
+ occystrap search registry://docker.io/library/busybox:latest "bin/*sh"
56
+ ```
57
+
58
+ ## The `process` Command
59
+
60
+ The `process` command takes a source URI, a destination URI, and optional
61
+ filters:
62
+
63
+ ```
64
+ occystrap process SOURCE DESTINATION [-f FILTER]...
65
+ ```
66
+
67
+ ### Input URI Schemes
68
+
69
+ - `registry://HOST/IMAGE:TAG` - Docker/OCI registry
70
+ - `docker://IMAGE:TAG` - Local Docker daemon
71
+ - `tar:///path/to/file.tar` - Docker-save format tarball
72
+
73
+ ### Output URI Schemes
74
+
75
+ - `tar:///path/to/output.tar` - Create tarball
76
+ - `dir:///path/to/directory` - Extract to directory
77
+ - `oci:///path/to/bundle` - Create OCI runtime bundle
78
+ - `mounts:///path/to/directory` - Create overlay mounts
79
+ - `docker://IMAGE:TAG` - Load into local Docker daemon
80
+ - `registry://HOST/IMAGE:TAG` - Push to Docker/OCI registry
81
+
82
+ ### URI Options
83
+
84
+ Options can be passed as query parameters:
85
+
86
+ ```
87
+ # Extract with unique names and expansion
88
+ occystrap process registry://docker.io/library/busybox:latest \
89
+ "dir://merged?unique_names=true&expand=true"
90
+
91
+ # Use custom Docker socket
92
+ occystrap process "docker://myimage:v1?socket=/run/podman/podman.sock" \
93
+ tar://output.tar
94
+ ```
95
+
96
+ ### Filters
97
+
98
+ Filters transform or inspect image elements as they pass through the pipeline:
99
+
100
+ ```
101
+ # Normalize timestamps for reproducible builds
102
+ occystrap process registry://docker.io/library/busybox:latest \
103
+ tar://busybox.tar -f normalize-timestamps
104
+
105
+ # Normalize with custom timestamp
106
+ occystrap process registry://docker.io/library/busybox:latest \
107
+ tar://busybox.tar -f "normalize-timestamps:ts=1609459200"
108
+
109
+ # Search while creating output (prints matches AND creates tarball)
110
+ occystrap process registry://docker.io/library/busybox:latest \
111
+ tar://busybox.tar -f "search:pattern=*.conf"
112
+
113
+ # Chain multiple filters
114
+ occystrap process registry://docker.io/library/busybox:latest \
115
+ tar://busybox.tar -f normalize-timestamps -f "search:pattern=bin/*"
116
+
117
+ # Record layer metadata to a JSONL file (inspect filter)
118
+ occystrap process docker://myimage:v1 registry://myregistry/myimage:v1 \
119
+ -f "inspect:file=layers-before.jsonl" \
120
+ -f normalize-timestamps \
121
+ -f "inspect:file=layers-after.jsonl"
122
+
123
+ # Exclude files matching glob patterns from layers
124
+ occystrap process registry://docker.io/library/python:3.11 \
125
+ tar://python.tar -f "exclude:pattern=**/.git/**"
126
+
127
+ # Exclude multiple patterns (comma-separated)
128
+ occystrap process registry://docker.io/library/python:3.11 \
129
+ tar://python.tar -f "exclude:pattern=**/.git/**,**/__pycache__/**,**/*.pyc"
130
+
131
+ # Load image directly into local Docker daemon
132
+ occystrap process registry://docker.io/library/busybox:latest \
133
+ docker://busybox:latest
134
+
135
+ # Load into Podman
136
+ occystrap process registry://docker.io/library/busybox:latest \
137
+ "docker://busybox:latest?socket=/run/podman/podman.sock"
138
+
139
+ # Push image to a registry
140
+ occystrap process docker://myimage:v1 \
141
+ registry://myregistry.example.com/myuser/myimage:v1
142
+
143
+ # Push to registry with authentication
144
+ occystrap --username myuser --password mytoken \
145
+ process tar://image.tar registry://ghcr.io/myorg/myimage:latest
146
+ ```
147
+
148
+ ## The `search` Command
149
+
150
+ Search for files in container image layers:
151
+
152
+ ```
153
+ occystrap search SOURCE PATTERN [--regex] [--script-friendly]
154
+ ```
155
+
156
+ Examples:
157
+
158
+ ```
159
+ # Search registry image
160
+ occystrap search registry://docker.io/library/busybox:latest "bin/*sh"
161
+
162
+ # Search local Docker image
163
+ occystrap search docker://myimage:v1 "*.conf"
164
+
165
+ # Search tarball with regex
166
+ occystrap search --regex tar://image.tar ".*\.py$"
167
+
168
+ # Machine-parseable output
169
+ occystrap search --script-friendly registry://docker.io/library/busybox:latest "*sh"
170
+ ```
171
+
172
+ ## Legacy Commands (Deprecated)
173
+
174
+ The following commands are deprecated but still work for backwards
175
+ compatibility. They will be removed in a future version.
176
+
177
+ ### Downloading an image from a repository and storing as a tarball
178
+
179
+ Let's say we want to download an image from a repository and store it as a
180
+ local tarball. This is a common thing to want to do in airgapped environments
181
+ for example. You could do this with docker with a `docker pull; docker save`.
182
+ The Occy Strap equivalent is:
183
+
184
+ ```
185
+ occystrap fetch-to-tarfile registry-1.docker.io library/busybox latest busybox.tar
186
+ ```
187
+
188
+ **New equivalent:**
189
+ ```
190
+ occystrap process registry://registry-1.docker.io/library/busybox:latest tar://busybox.tar
191
+ ```
192
+
193
+ In this example we're pulling from the Docker Hub (registry-1.docker.io), and
194
+ are downloading busybox's latest version into a tarball named `busybox.tar`.
195
+ This tarball can be loaded with `docker load -i busybox.tar` on an airgapped
196
+ Docker environment.
197
+
198
+ ### Repeatable builds with normalized timestamps
199
+
200
+ To make builds more repeatable, you can normalize file access and modification
201
+ times in the image layers. This is useful when you want to ensure that the
202
+ same image content produces the same tarball hash, regardless of when the
203
+ files were originally created:
204
+
205
+ ```
206
+ occystrap fetch-to-tarfile --normalize-timestamps registry-1.docker.io library/busybox latest busybox.tar
207
+ ```
208
+
209
+ **New equivalent:**
210
+ ```
211
+ occystrap process registry://registry-1.docker.io/library/busybox:latest tar://busybox.tar -f normalize-timestamps
212
+ ```
213
+
214
+ This will set all timestamps in the layer tarballs to 0 (Unix epoch: January
215
+ 1, 1970). You can also specify a custom timestamp:
216
+
217
+ ```
218
+ occystrap fetch-to-tarfile --normalize-timestamps --timestamp 1609459200 registry-1.docker.io library/busybox latest busybox.tar
219
+ ```
220
+
221
+ **New equivalent:**
222
+ ```
223
+ occystrap process registry://registry-1.docker.io/library/busybox:latest tar://busybox.tar -f "normalize-timestamps:ts=1609459200"
224
+ ```
225
+
226
+ When timestamps are normalized, the layer SHAs are recalculated and the
227
+ manifest is updated to reflect the new hashes. This ensures the tarball
228
+ structure remains consistent and valid.
229
+
230
+ ### Downloading an image from a repository and storing as an extracted tarball
231
+
232
+ The format of the tarball in the previous example is two JSON configuration
233
+ files and a series of image layers as tarballs inside the main tarball. You
234
+ can write these elements to a directory instead of to a tarball if you'd like
235
+ to inspect them:
236
+
237
+ ```
238
+ occystrap fetch-to-extracted registry-1.docker.io library/centos 7 centos7
239
+ ```
240
+
241
+ **New equivalent:**
242
+ ```
243
+ occystrap process registry://registry-1.docker.io/library/centos:7 dir://centos7
244
+ ```
245
+
246
+ ### Downloading an image to a merged directory
247
+
248
+ In scenarios where image layers are likely to be reused between images, you
249
+ can save disk space by downloading images to a directory which contains more
250
+ than one image:
251
+
252
+ ```
253
+ occystrap fetch-to-extracted --use-unique-names registry-1.docker.io \
254
+ homeassistant/home-assistant latest merged_images
255
+ ```
256
+
257
+ **New equivalent:**
258
+ ```
259
+ occystrap process registry://registry-1.docker.io/homeassistant/home-assistant:latest \
260
+ "dir://merged_images?unique_names=true"
261
+ ```
262
+
263
+ ### Storing an image tarfile in a merged directory
264
+
265
+ Sometimes you have image tarfiles instead of images in a registry:
266
+
267
+ ```
268
+ occystrap tarfile-to-extracted --use-unique-names file.tar merged_images
269
+ ```
270
+
271
+ **New equivalent:**
272
+ ```
273
+ occystrap process tar://file.tar "dir://merged_images?unique_names=true"
274
+ ```
275
+
276
+ ### Exploring the contents of layers and overwritten files
277
+
278
+ If you'd like the layers to be expanded from their tarballs to the filesystem:
279
+
280
+ ```
281
+ occystrap fetch-to-extracted --expand quay.io \
282
+ ukhomeofficedigital/centos-base latest ukhomeoffice-centos
283
+ ```
284
+
285
+ **New equivalent:**
286
+ ```
287
+ occystrap process registry://quay.io/ukhomeofficedigital/centos-base:latest \
288
+ "dir://ukhomeoffice-centos?expand=true"
289
+ ```
290
+
291
+ ### Generating an OCI runtime bundle
292
+
293
+ ```
294
+ occystrap fetch-to-oci registry-1.docker.io library/hello-world latest bar
295
+ ```
296
+
297
+ **New equivalent:**
298
+ ```
299
+ occystrap process registry://registry-1.docker.io/library/hello-world:latest oci://bar
300
+ ```
301
+
302
+ ### Searching image layers for files
303
+
304
+ ```
305
+ occystrap search-layers registry-1.docker.io library/busybox latest "bin/*sh"
306
+ ```
307
+
308
+ **New equivalent:**
309
+ ```
310
+ occystrap search registry://registry-1.docker.io/library/busybox:latest "bin/*sh"
311
+ ```
312
+
313
+ ### Working with local Docker or Podman daemon
314
+
315
+ ```
316
+ occystrap docker-to-tarfile library/busybox latest busybox.tar
317
+ ```
318
+
319
+ **New equivalent:**
320
+ ```
321
+ occystrap process docker://library/busybox:latest tar://busybox.tar
322
+ ```
323
+
324
+ For Podman:
325
+ ```
326
+ occystrap process "docker://myimage:latest?socket=/run/podman/podman.sock" tar://output.tar
327
+ ```
328
+
329
+ Note: Podman doesn't run a daemon by default. You need to start the socket
330
+ service first:
331
+
332
+ ```
333
+ # For rootless Podman
334
+ systemctl --user start podman.socket
335
+
336
+ # For rootful Podman
337
+ sudo systemctl start podman.socket
338
+ ```
339
+
340
+ ## Authenticating with private registries
341
+
342
+ To fetch images from private registries (such as GitLab Container Registry,
343
+ AWS ECR, or private Docker Hub repositories), use the `--username` and
344
+ `--password` global options:
345
+
346
+ ```
347
+ occystrap --username myuser --password mytoken \
348
+ process registry://registry.gitlab.com/mygroup/myimage:latest tar://output.tar
349
+ ```
350
+
351
+ You can also use environment variables to avoid putting credentials on the
352
+ command line:
353
+
354
+ ```
355
+ export OCCYSTRAP_USERNAME=myuser
356
+ export OCCYSTRAP_PASSWORD=mytoken
357
+ occystrap process registry://registry.gitlab.com/mygroup/myimage:latest tar://output.tar
358
+ ```
359
+
360
+ For GitLab Container Registry, the username is typically your GitLab username
361
+ and the password is a personal access token with `read_registry` scope.
362
+
363
+ ## Supporting non-default architectures
364
+
365
+ Docker image repositories can store multiple versions of a single image, with
366
+ each image corresponding to a different (operating system, cpu architecture,
367
+ cpu variant) tuple. Occy Strap supports letting you specify which to use with
368
+ global command line flags. Occy Strap defaults to linux amd64 if you don't
369
+ specify something different:
370
+
371
+ ```
372
+ occystrap --os linux --architecture arm64 --variant v8 \
373
+ process registry://registry-1.docker.io/library/busybox:latest dir://busybox
374
+ ```
375
+
376
+ Or via URI query parameters:
377
+
378
+ ```
379
+ occystrap process "registry://registry-1.docker.io/library/busybox:latest?os=linux&arch=arm64&variant=v8" \
380
+ dir://busybox
381
+ ```
382
+
383
+ ## Development
384
+
385
+ ### Install for Development
386
+
387
+ ```
388
+ pip install -e ".[test]"
389
+ ```
390
+
391
+ ### Pre-commit Hooks
392
+
393
+ This project uses pre-commit hooks to validate code before commits. Install them
394
+ with:
395
+
396
+ ```
397
+ pip install pre-commit
398
+ pre-commit install
399
+ ```
400
+
401
+ The hooks run:
402
+ - `actionlint` - GitHub Actions workflow validation
403
+ - `shellcheck` - Shell script linting
404
+ - `tox -eflake8` - Python code style checks
405
+ - `tox -epy3` - Unit tests
406
+
407
+ To run the hooks manually:
408
+
409
+ ```
410
+ pre-commit run --all-files
411
+ ```
412
+
413
+ ### Running Tests
414
+
415
+ Unit tests are in `occystrap/tests/` and can be run with:
416
+
417
+ ```
418
+ tox -epy3
419
+ ```
420
+
421
+ Functional tests are in `deploy/occystrap_ci/tests/` and are run in CI.
422
+
423
+ ### Releasing
424
+
425
+ Releases are automated via GitHub Actions. Push a version tag to trigger the
426
+ pipeline:
427
+
428
+ ```
429
+ git tag -s v0.5.0 -m "Release v0.5.0"
430
+ git push origin v0.5.0
431
+ ```
432
+
433
+ The workflow builds the package, signs the tag with Sigstore, publishes to
434
+ PyPI, and creates a GitHub Release. See [RELEASE-SETUP.md](RELEASE-SETUP.md)
435
+ for one-time configuration steps.
436
+
437
+ ## Documentation
438
+
439
+ For more detailed documentation, see the [docs/](docs/) directory:
440
+
441
+ - [Installation](docs/installation.md) - Getting started guide
442
+ - [Command Reference](docs/command-reference.md) - Complete CLI reference
443
+ - [Pipeline Architecture](docs/pipeline.md) - How the pipeline works
444
+ - [Use Cases](docs/use-cases.md) - Common scenarios and examples
@@ -0,0 +1,38 @@
1
+ occystrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ occystrap/_version.py,sha256=k7cu0JKra64gmMNU_UfA5sw2eNc_GRvf3QmesiYAy8g,704
3
+ occystrap/common.py,sha256=Zm4hHpn8RgSXp0W86HhZzpyXq19QIsLJgp9SxK_1QQg,1300
4
+ occystrap/constants.py,sha256=kmOt-12settGbDTW1efpT3UENRQouG9f0ZjgOqWdrIA,4399
5
+ occystrap/main.py,sha256=bo87uuAJYCZq0YL-EnjpNUsbiaySyvpYPgi-SQF2uaE,15521
6
+ occystrap/pipeline.py,sha256=oiWXB6Wrjl32jC0MI0HksATjxcUQ7o5ntKm864BZxnA,10849
7
+ occystrap/tarformat.py,sha256=Fw5GPntymn7mNzDNiCQr55iNtDQ2GYqes9yBYT1XtJE,4113
8
+ occystrap/uri.py,sha256=uKwy2hb0i1Pjf2QpwSBTobgcH2ve1WNsYSK0n2GpkK8,6858
9
+ occystrap/util.py,sha256=eYZOkamk6hWyFuN4W8NoimR23A_FG1cMl_AfT7vJbEw,3987
10
+ occystrap/filters/__init__.py,sha256=ZT9J7QX4tuEeEJEnty-pGcQQPxv_7lj6ymELleMR_wU,383
11
+ occystrap/filters/base.py,sha256=D1Li3mgNFzrn6BBL7pz35IUGUVWcqwWBfHYXqfQQ1-8,2375
12
+ occystrap/filters/exclude.py,sha256=RrISggbuSMIWOEi1SPKpnorTa6cJVKlIBwAPHxI99D0,4749
13
+ occystrap/filters/inspect.py,sha256=saxsO5vCcZ1-7exkboTa4bkzmglFXY9Fi6U9Q66iV8g,6101
14
+ occystrap/filters/normalize_timestamps.py,sha256=-oM05xtwuf8qjiAZ2jUJDqRLdom10H5KE9_QlPJOQUk,4663
15
+ occystrap/filters/search.py,sha256=ftxTTsHS44L0BvxgFb09hFKC1t0znIj8zEDCK6-5lbo,6782
16
+ occystrap/inputs/__init__.py,sha256=mbLK9EG2LauQqSJ-hqCyW0P2VCZNeG68mqT14FI8jmA,66
17
+ occystrap/inputs/base.py,sha256=xLXp19fSO1Ks8eXETvOQkI3gUu42rI1OdhM_yuIJSts,1271
18
+ occystrap/inputs/docker.py,sha256=QRGJ_LGLbuSaNN-HsgRembHrIAoP3JbyQwH7hF470vI,6420
19
+ occystrap/inputs/registry.py,sha256=hQaqQ09sruuhkZl0KcZdCNIES2dZgJVWt8i20kIyDHk,10572
20
+ occystrap/inputs/tarfile.py,sha256=7OHT4TYckI6zyAMwpUr-8B3Mg8T4M9qTVTHCJ_pFlDI,2898
21
+ occystrap/outputs/__init__.py,sha256=E_-OfS5WtQi-yWMQTSviAlC8enO6IH88ZcOYCY_IjCw,38
22
+ occystrap/outputs/base.py,sha256=TiucjT_XB_f8-QjWOFhhwSFyrS66mK6T8W8GYT1uKYI,1471
23
+ occystrap/outputs/directory.py,sha256=MGZVIDqc3sNk5p3rd1wMgEO3u9_yvfLgE_y5_8Bu81w,11496
24
+ occystrap/outputs/docker.py,sha256=AxCpYotlMnaBci5NObzKLEsHbXNYP3TuzPMffBxHQw0,4585
25
+ occystrap/outputs/mounts.py,sha256=-rMNbetDW_rZO5gkLFtTYtuPTDhuzyhYg9CZXeuq_TQ,6433
26
+ occystrap/outputs/ocibundle.py,sha256=tK09wZ7bCjeVnqoGsz6MF38Ma36hI9OofHEzG5HBtI4,2155
27
+ occystrap/outputs/registry.py,sha256=qlhSaa4y7G_zC31MqItEtkWz3Ks83a_g4JlBj8RHleI,8633
28
+ occystrap/outputs/tarfile.py,sha256=AHY6UvBo2WPG7nj5FHE7GRzouuxpFnQkwZEHz_KCLRY,2310
29
+ occystrap/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ occystrap/tests/test_inspect.py,sha256=HA1ogCLyy5SCFWpesyVkhp6mL95k2XhGuCcAPQ5kMSc,11209
31
+ occystrap/tests/test_tarformat.py,sha256=6q3tG7UtLpX274rjngvgQ8HCUk7lN17TMiXXjxdN2OA,7156
32
+ occystrap-0.4.1.dist-info/licenses/AUTHORS,sha256=toKLUaf9c-NkNow00B_akwMGcGtm-S_ihcC_eql9qWc,34
33
+ occystrap-0.4.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
34
+ occystrap-0.4.1.dist-info/METADATA,sha256=HDKdBAasvpNlirXiQUt4qXOuQRBvaLSNl4DG-yovdRw,13194
35
+ occystrap-0.4.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
36
+ occystrap-0.4.1.dist-info/entry_points.txt,sha256=Uba7wHWknje_I2ZN1sGOpmP4twuQ1XEsOa5o28bvc2Y,49
37
+ occystrap-0.4.1.dist-info/top_level.txt,sha256=06nN7FHq2z_Jpp2PZNm3rGOGUA1cIGlUr6MEZrqgOlc,10
38
+ occystrap-0.4.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.34.2)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  occystrap = occystrap.main:cli
3
-
@@ -1,36 +0,0 @@
1
- #!/usr/bin/python3
2
-
3
- # Call me like this:
4
- # docker-image-extract tarfile.tar extracted
5
-
6
- import tarfile
7
- import json
8
- import os
9
- import sys
10
-
11
- image_path = sys.argv[1]
12
- extracted_path = sys.argv[2]
13
-
14
- with tarfile.open(image_path) as image:
15
- manifest = json.loads(image.extractfile('manifest.json').read())
16
- print('Manifest: %s' % manifest)
17
-
18
- config = json.loads(image.extractfile(manifest[0]['Config']).read())
19
- print('Config: %s' % config)
20
-
21
- for layer in manifest[0]['Layers']:
22
- print('Found layer: %s' % layer)
23
- layer_tar = tarfile.open(fileobj=image.extractfile(layer))
24
-
25
- for tarinfo in layer_tar:
26
- print(' ... %s' % tarinfo.name)
27
- if tarinfo.isdev():
28
- print(' --> skip device files')
29
- continue
30
-
31
- dest = os.path.join(extracted_path, tarinfo.name)
32
- if not tarinfo.isdir() and os.path.exists(dest):
33
- print(' --> remove old version of file')
34
- os.unlink(dest)
35
-
36
- layer_tar.extract(tarinfo, path=extracted_path)
@@ -1,131 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: occystrap
3
- Version: 0.4.0
4
- Summary: occystrap: docker and OCI container tools
5
- Home-page: https://github.com/shakenfist/occystrap
6
- Author: Michael Still
7
- Author-email: mikal@stillhq.com
8
- License: Apache2
9
- Platform: UNKNOWN
10
- Classifier: Intended Audience :: Information Technology
11
- Classifier: Intended Audience :: System Administrators
12
- Classifier: License :: OSI Approved :: Apache Software License
13
- Classifier: Operating System :: POSIX :: Linux
14
- Classifier: Programming Language :: Python
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.7
17
- Description-Content-Type: text/markdown
18
- Requires-Dist: click (>=7.1.1)
19
- Requires-Dist: oslo.concurrency
20
- Requires-Dist: pbr
21
- Requires-Dist: prettytable
22
- Requires-Dist: requests
23
- Requires-Dist: shakenfist-utilities
24
-
25
- # Occy Strap
26
-
27
- Occy Strap is a simple set of Docker and OCI container tools, which can be used either for container forensics or for implementing an OCI orchestrator, depending on your needs. This is a very early implementation, so be braced for impact.
28
-
29
- ## Downloading an image from a repository and storing as a tarball
30
-
31
- Let's say we want to download an image from a repository and store it as a local tarball. This is a common thing to want to do in airgapped environments for example. You could do this with docker with a `docker pull; docker save`. The Occy Strap equivalent is:
32
-
33
- ```
34
- occystrap fetch-to-tarfile registry-1.docker.io library/busybox latest busybox.tar
35
- ```
36
-
37
- In this example we're pulling from the Docker Hub (registry-1.docker.io), and are downloading busybox's latest version into a tarball named `busybox-occy.tar`. This tarball can be loaded with `docker load -i busybox.tar` on an airgapped Docker environment.
38
-
39
- ## Downloading an image from a repository and storing as an extracted tarball
40
-
41
- The format of the tarball in the previous example is two JSON configuration files and a series of image layers as tarballs inside the main tarball. You can write these elements to a directory instead of to a tarball if you'd like to inspect them. For example:
42
-
43
- ```
44
- occystrap fetch-to-extracted registry-1.docker.io library/centos 7 centos7
45
- ```
46
-
47
- This example will pull from the Docker Hub the Centos image with the label "7", and write the content to a directory in the current working directory called "centos7". If you tarred centos7 like this, you'd end up with a tarball equivalent to what `fetch-to-tarfile` produces, which could therefore be loaded with `docker load`:
48
-
49
- ```
50
- cd centos7; tar -cf ../centos7.tar *
51
- ```
52
-
53
- ## Downloading an image from a repository and storing it in a merged directory
54
-
55
- In scenarios where image layers are likely to be reused between images (for example many images which share a common base layer), you can save disk space by downloading images to a directory which contains more than one image. To make this work, you need to instruct Occy Strap to use unique names for the JSON elements within the image file:
56
-
57
- ```
58
- occystrap fetch-to-extracted --use-unique-names registry-1.docker.io \
59
- homeassistant/home-assistant latest merged_images
60
- occystrap fetch-to-extracted --use-unique-names registry-1.docker.io \
61
- homeassistant/home-assistant stable merged_images
62
- occystrap fetch-to-extracted --use-unique-names registry-1.docker.io \
63
- homeassistant/home-assistant 2021.3.0.dev20210219 merged_images
64
- ```
65
-
66
- Each of these images include 21 layers, but the merged_images directory at the time of writing this there are 25 unique layers in the directory. You end up with a layout like this:
67
-
68
- ```
69
- 0465ae924726adc52c0216e78eda5ce2a68c42bf688da3f540b16f541fd3018c
70
- 10556f40181a651a72148d6c643ac9b176501d4947190a8732ec48f2bf1ac4fb
71
- ...
72
- catalog.json
73
- cd8d37c8075e8a0195ae12f1b5c96fe4e8fe378664fc8943f2748336a7d2f2f3
74
- d1862a2c28ec9e23d88c8703096d106e0fe89bc01eae4c461acde9519d97b062
75
- d1ac3982d662e038e06cc7e1136c6a84c295465c9f5fd382112a6d199c364d20.json
76
- ...
77
- d81f69adf6d8aeddbaa1421cff10ba47869b19cdc721a2ebe16ede57679850f0.json
78
- ...
79
- manifest-homeassistant_home-assistant-2021.3.0.dev20210219.json
80
- manifest-homeassistant_home-assistant-latest.json
81
- manifest-homeassistant_home-assistant-stable.json
82
- ```
83
-
84
- `catalog.json` is an Occy Strap specific artefact which maps which layers are used by which image. Each of the manifest files for the various images have been converted to have a unique name instead of `manifest.json` as well.
85
-
86
- To extract a single image from such a shared directory, use the `recreate-image` command:
87
-
88
- ```
89
- occystrap recreate-image merged_images homeassistant/home-assistant latest ha-latest.tar
90
- ```
91
-
92
- ## Exploring the contents of layers and overwritten files
93
-
94
- Similarly, if you'd like the layers to be expanded from their tarballs to the filesystem, you can pass the `--expand` argument to `fetch-to-extracted` to have them extracted. This will also create a filesystem at the name of the manifest which is the final state of the image (the layers applied sequential). For example:
95
-
96
- ```
97
- occystrap fetch-to-extracted --expand quay.io \
98
- ukhomeofficedigital/centos-base latest ukhomeoffice-centos
99
- ```
100
-
101
- Note that layers delete files from previous layers with files named ".wh.$previousfilename". These files are _not_ processed in the expanded layers, so that they are visible to the user. They are however processed in the merged layer named for the manifest file.
102
-
103
- ## Generating an OCI runtime bundle
104
-
105
- This isn't fully supported yet, but you can extract an image to an OCI image bundle
106
- with the following command:
107
-
108
- ```
109
- occystrap fetch-to-oci registry-1.docker.io library/hello-world latest bar
110
- ```
111
-
112
- You should then be able to run that container by doing something like:
113
-
114
- ```
115
- cd bar
116
- sudo apt-get install runc
117
- sudo runc run id-0001
118
- ```
119
-
120
- ## Supporting non-default architectures
121
-
122
- Docker image repositories can store multiple versions of a single image, with each image corresponding to a different (operating system, cpu architecture, cpu variant) tuple. Occy Strap supports letting you specify which to use with global command line flags. Occy Strap defaults to linux amd64 if you don't specify something different. For example, to fetch the linux arm64 v8 image for busybox, you would run:
123
-
124
- ```
125
- occystrap --os linux --architecture arm64 --variant v8 \
126
- fetch-to-extracted registry-1.docker.io library/busybox \
127
- latest busybox
128
- ```
129
-
130
-
131
-
@@ -1,20 +0,0 @@
1
- occystrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- occystrap/common.py,sha256=Zm4hHpn8RgSXp0W86HhZzpyXq19QIsLJgp9SxK_1QQg,1300
3
- occystrap/constants.py,sha256=kmOt-12settGbDTW1efpT3UENRQouG9f0ZjgOqWdrIA,4399
4
- occystrap/docker_extract.py,sha256=j2GSIOShZZh0c5gckXeu-SO7201p4S1EJg3fi7WPQHk,1055
5
- occystrap/docker_registry.py,sha256=GRpBj1SCxRV_0wOuLIMjMyTRU3Uxinyofzfa2pnwXpo,7936
6
- occystrap/main.py,sha256=sevQkqAqgnZRrt61DMUPz9xzoE4AIcWYx2_ZurO_Lls,4059
7
- occystrap/output_directory.py,sha256=S-uL8NSHyHsVKeWsvPRT63E7wE1pWaluGHOFVsS09Xg,11408
8
- occystrap/output_mounts.py,sha256=AH4vouBF9PmhQ5oGfsSZyN1FhatWbs_20IDlI9psn_k,6381
9
- occystrap/output_ocibundle.py,sha256=lsVW66ltL2Y-Mxh5Hp2KSCdh9bvsME1142CJ_Uh99oo,2154
10
- occystrap/output_tarfile.py,sha256=Di8N_2TSo-gQz490D3XOsKCYiv5T_bxZzTRFbd4WGBA,1620
11
- occystrap/util.py,sha256=nrKfAxDUjb_v9ERDXTmMSSNdJSuLgjdtwOMWk46n0a0,2720
12
- occystrap/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- occystrap-0.4.0.dist-info/AUTHORS,sha256=toKLUaf9c-NkNow00B_akwMGcGtm-S_ihcC_eql9qWc,34
14
- occystrap-0.4.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
15
- occystrap-0.4.0.dist-info/METADATA,sha256=mpNFr7zm2FZcmHXnNTZYcsbiA-BqU0mrWQPLKDYYRX4,6308
16
- occystrap-0.4.0.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
17
- occystrap-0.4.0.dist-info/entry_points.txt,sha256=51kLRjAxFtC6GWCbTFGezSYMNk5t6xrBmS8Pf7gehiU,50
18
- occystrap-0.4.0.dist-info/pbr.json,sha256=BKNfUPL0QseayDX9_Ko6PtOTlIdH1276JChGUVbKXk0,46
19
- occystrap-0.4.0.dist-info/top_level.txt,sha256=06nN7FHq2z_Jpp2PZNm3rGOGUA1cIGlUr6MEZrqgOlc,10
20
- occystrap-0.4.0.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- {"git_version": "c1cb09a", "is_release": true}