Fossil SCM
Post-sleep edit pass on the new material in §3.2 of the containers doc.
Commit
d21fb2678a02b56074fe46fadc90bfe9fca858159ecb0f7bbc3699b1a0eb92a3
Parent
64f141fce02f834…
1 file changed
+21
-24
+21
-24
| --- www/containers.md | ||
| +++ www/containers.md | ||
| @@ -269,20 +269,19 @@ | ||
| 269 | 269 | stage, since it’s written for the case where everything is in `/bin`. |
| 270 | 270 | |
| 271 | 271 | Another useful case to consider is that you’ve installed a [server |
| 272 | 272 | extension](./serverext.wiki) and you need an interpreter for that |
| 273 | 273 | script. The first option above won’t work except in the unlikely case that |
| 274 | -it’s written in one of the bare-bones script interpreters that BusyBox | |
| 274 | +it’s written for one of the bare-bones script interpreters that BusyBox | |
| 275 | 275 | ships.(^BusyBox’s `/bin/sh` is based on the old 4.4BSD Lite Almquist |
| 276 | 276 | shell, implementing little more than what POSIX specified in 1989, plus |
| 277 | 277 | equally stripped-down versions of AWK and `sed`.) |
| 278 | 278 | |
| 279 | 279 | Let’s say the extension is written in Python. While you could handle it |
| 280 | -the same way we do with Tcl, because Python is more popular, we have | |
| 281 | -more options. Let’s inject that into the stock container via a suitable | |
| 282 | -“[distroless]” image instead. Because this will conflict with the | |
| 283 | -bare-bones “`os`” layer we create, the method is more complicated: | |
| 280 | +the same way we do with the Tcl example above, because Python is more | |
| 281 | +popular, we have more options. Let’s inject a Python environment into | |
| 282 | +the stock Fossil container via a suitable “[distroless]” image instead: | |
| 284 | 283 | |
| 285 | 284 | ``` |
| 286 | 285 | ## --------------------------------------------------------------------- |
| 287 | 286 | ## STAGE 2: Pare that back to the bare essentials, plus Python. |
| 288 | 287 | ## --------------------------------------------------------------------- |
| @@ -305,33 +304,31 @@ | ||
| 305 | 304 | $ make container-run && |
| 306 | 305 | docker exec -i $(make container-version) python --version |
| 307 | 306 | 3.11.2 |
| 308 | 307 | ``` |
| 309 | 308 | |
| 310 | -Relative to the Tcl example, the change from “`alpine`” to Chainguard’s | |
| 311 | -Python image means we have no BusyBox environment to execute the `RUN` | |
| 312 | -command with, so we have to copy the `busybox.static` binary in from | |
| 313 | -STAGE 1 and install it in this new STAGE 2 for the same reason the stock | |
| 314 | -container does.(^This is the main reason we change `USER` temporarily to | |
| 315 | -`root` here.) The compensating bonus is huge: we don’t leave a package | |
| 316 | -manager sitting around inside the image, waiting to be abused. | |
| 317 | - | |
| 318 | -Beware that there’s a limit to how much the über-jail nature of | |
| 319 | -containers can save you when you go and provide a more capable OS layer | |
| 320 | -like this. For instance, you might have enabled Fossil’s [risky TH1 docs | |
| 321 | -feature][th1docrisk] along with the Tcl integration feature, which | |
| 322 | -effectively gives anyone with check-in rights on your repo the ability | |
| 323 | -to run arbitrary Tcl code on the host when that document is rendered. | |
| 324 | -The container layer should stop that script from accessing any files out | |
| 325 | -on the host that you haven’t explicitly mounted into the container’s | |
| 326 | -namespace, but it *can* still make network connections, modify the repo | |
| 327 | -DB inside the container, and who knows what else. | |
| 309 | +Relative to the Tcl example, the change from “`alpine`” to [Chainguard’s | |
| 310 | +Python image][cgimgs] means we have no BusyBox environment to execute | |
| 311 | +the `RUN` command with, so we have to copy the `busybox.static` binary | |
| 312 | +in from STAGE 1 and install it in this new STAGE 2 for the same reason | |
| 313 | +the stock container does.(^This is the main reason we change `USER` | |
| 314 | +temporarily to `root` here.) There are a few other steps required to | |
| 315 | +avoid causing a conflict between our previously bare-bones “OS” layer | |
| 316 | +and what the Chainguard image provides. The compensation for this hassle | |
| 317 | +is huge: we no longer leave a package manager sitting around inside the | |
| 318 | +container, waiting for some malefactor to figure out how to abuse it. | |
| 319 | + | |
| 320 | +Beware that there’s a limit to this über-jail’s ability to save you when | |
| 321 | +you go and provide a more capable OS layer like this. The container | |
| 322 | +layer should stop an attacker from accessing any files out on the host | |
| 323 | +that you haven’t explicitly mounted into the container’s namespace, but | |
| 324 | +it can’t stop them from making outbound network connections or modifying | |
| 325 | +the repo DB inside the container. | |
| 328 | 326 | |
| 329 | 327 | [cgimgs]: https://github.com/chainguard-images/images/tree/main/images |
| 330 | 328 | [distroless]: https://www.chainguard.dev/unchained/minimal-container-images-towards-a-more-secure-future |
| 331 | 329 | [MTA]: https://en.wikipedia.org/wiki/Message_transfer_agent |
| 332 | -[th1docrisk]: https://fossil-scm.org/forum/forumpost/42e0c16544 | |
| 333 | 330 | |
| 334 | 331 | |
| 335 | 332 | ### 3.3 <a id="caps"></a>Dropping Unnecessary Capabilities |
| 336 | 333 | |
| 337 | 334 | The example commands above create the container with [a default set of |
| 338 | 335 |
| --- www/containers.md | |
| +++ www/containers.md | |
| @@ -269,20 +269,19 @@ | |
| 269 | stage, since it’s written for the case where everything is in `/bin`. |
| 270 | |
| 271 | Another useful case to consider is that you’ve installed a [server |
| 272 | extension](./serverext.wiki) and you need an interpreter for that |
| 273 | script. The first option above won’t work except in the unlikely case that |
| 274 | it’s written in one of the bare-bones script interpreters that BusyBox |
| 275 | ships.(^BusyBox’s `/bin/sh` is based on the old 4.4BSD Lite Almquist |
| 276 | shell, implementing little more than what POSIX specified in 1989, plus |
| 277 | equally stripped-down versions of AWK and `sed`.) |
| 278 | |
| 279 | Let’s say the extension is written in Python. While you could handle it |
| 280 | the same way we do with Tcl, because Python is more popular, we have |
| 281 | more options. Let’s inject that into the stock container via a suitable |
| 282 | “[distroless]” image instead. Because this will conflict with the |
| 283 | bare-bones “`os`” layer we create, the method is more complicated: |
| 284 | |
| 285 | ``` |
| 286 | ## --------------------------------------------------------------------- |
| 287 | ## STAGE 2: Pare that back to the bare essentials, plus Python. |
| 288 | ## --------------------------------------------------------------------- |
| @@ -305,33 +304,31 @@ | |
| 305 | $ make container-run && |
| 306 | docker exec -i $(make container-version) python --version |
| 307 | 3.11.2 |
| 308 | ``` |
| 309 | |
| 310 | Relative to the Tcl example, the change from “`alpine`” to Chainguard’s |
| 311 | Python image means we have no BusyBox environment to execute the `RUN` |
| 312 | command with, so we have to copy the `busybox.static` binary in from |
| 313 | STAGE 1 and install it in this new STAGE 2 for the same reason the stock |
| 314 | container does.(^This is the main reason we change `USER` temporarily to |
| 315 | `root` here.) The compensating bonus is huge: we don’t leave a package |
| 316 | manager sitting around inside the image, waiting to be abused. |
| 317 | |
| 318 | Beware that there’s a limit to how much the über-jail nature of |
| 319 | containers can save you when you go and provide a more capable OS layer |
| 320 | like this. For instance, you might have enabled Fossil’s [risky TH1 docs |
| 321 | feature][th1docrisk] along with the Tcl integration feature, which |
| 322 | effectively gives anyone with check-in rights on your repo the ability |
| 323 | to run arbitrary Tcl code on the host when that document is rendered. |
| 324 | The container layer should stop that script from accessing any files out |
| 325 | on the host that you haven’t explicitly mounted into the container’s |
| 326 | namespace, but it *can* still make network connections, modify the repo |
| 327 | DB inside the container, and who knows what else. |
| 328 | |
| 329 | [cgimgs]: https://github.com/chainguard-images/images/tree/main/images |
| 330 | [distroless]: https://www.chainguard.dev/unchained/minimal-container-images-towards-a-more-secure-future |
| 331 | [MTA]: https://en.wikipedia.org/wiki/Message_transfer_agent |
| 332 | [th1docrisk]: https://fossil-scm.org/forum/forumpost/42e0c16544 |
| 333 | |
| 334 | |
| 335 | ### 3.3 <a id="caps"></a>Dropping Unnecessary Capabilities |
| 336 | |
| 337 | The example commands above create the container with [a default set of |
| 338 |
| --- www/containers.md | |
| +++ www/containers.md | |
| @@ -269,20 +269,19 @@ | |
| 269 | stage, since it’s written for the case where everything is in `/bin`. |
| 270 | |
| 271 | Another useful case to consider is that you’ve installed a [server |
| 272 | extension](./serverext.wiki) and you need an interpreter for that |
| 273 | script. The first option above won’t work except in the unlikely case that |
| 274 | it’s written for one of the bare-bones script interpreters that BusyBox |
| 275 | ships.(^BusyBox’s `/bin/sh` is based on the old 4.4BSD Lite Almquist |
| 276 | shell, implementing little more than what POSIX specified in 1989, plus |
| 277 | equally stripped-down versions of AWK and `sed`.) |
| 278 | |
| 279 | Let’s say the extension is written in Python. While you could handle it |
| 280 | the same way we do with the Tcl example above, because Python is more |
| 281 | popular, we have more options. Let’s inject a Python environment into |
| 282 | the stock Fossil container via a suitable “[distroless]” image instead: |
| 283 | |
| 284 | ``` |
| 285 | ## --------------------------------------------------------------------- |
| 286 | ## STAGE 2: Pare that back to the bare essentials, plus Python. |
| 287 | ## --------------------------------------------------------------------- |
| @@ -305,33 +304,31 @@ | |
| 304 | $ make container-run && |
| 305 | docker exec -i $(make container-version) python --version |
| 306 | 3.11.2 |
| 307 | ``` |
| 308 | |
| 309 | Relative to the Tcl example, the change from “`alpine`” to [Chainguard’s |
| 310 | Python image][cgimgs] means we have no BusyBox environment to execute |
| 311 | the `RUN` command with, so we have to copy the `busybox.static` binary |
| 312 | in from STAGE 1 and install it in this new STAGE 2 for the same reason |
| 313 | the stock container does.(^This is the main reason we change `USER` |
| 314 | temporarily to `root` here.) There are a few other steps required to |
| 315 | avoid causing a conflict between our previously bare-bones “OS” layer |
| 316 | and what the Chainguard image provides. The compensation for this hassle |
| 317 | is huge: we no longer leave a package manager sitting around inside the |
| 318 | container, waiting for some malefactor to figure out how to abuse it. |
| 319 | |
| 320 | Beware that there’s a limit to this über-jail’s ability to save you when |
| 321 | you go and provide a more capable OS layer like this. The container |
| 322 | layer should stop an attacker from accessing any files out on the host |
| 323 | that you haven’t explicitly mounted into the container’s namespace, but |
| 324 | it can’t stop them from making outbound network connections or modifying |
| 325 | the repo DB inside the container. |
| 326 | |
| 327 | [cgimgs]: https://github.com/chainguard-images/images/tree/main/images |
| 328 | [distroless]: https://www.chainguard.dev/unchained/minimal-container-images-towards-a-more-secure-future |
| 329 | [MTA]: https://en.wikipedia.org/wiki/Message_transfer_agent |
| 330 | |
| 331 | |
| 332 | ### 3.3 <a id="caps"></a>Dropping Unnecessary Capabilities |
| 333 | |
| 334 | The example commands above create the container with [a default set of |
| 335 |