finish network, OCI images

This commit is contained in:
Maciej Lebiest 2025-01-01 18:49:53 +01:00
parent a4b860ebb5
commit 5ab3e21513
2 changed files with 142 additions and 5 deletions

145
README.md
View file

@ -259,7 +259,7 @@ Mounting podman volume as read-only is done by specifying `ro` mount option
after `:` separator, for example `--tmpfs /test:ro`, `-v /host/path:/container/path:ro` after `:` separator, for example `--tmpfs /test:ro`, `-v /host/path:/container/path:ro`
On Kubernetes to set base filesystem of a container to read-only, there is On Kubernetes to set base filesystem of a container to read-only, there is
`readOnlyRootFilesystem: true` attribute in container security context, and to `readOnlyRootFilesystem: true` attribute in container security context. To
mount any volume as read-only, there is attribute `readOnly: true` in mount mount any volume as read-only, there is attribute `readOnly: true` in mount
section. section.
@ -320,7 +320,8 @@ you can set the limit using `--cpus` flag. For example `--cpus=2` will limit
cpu time to 2/X of total cpu time current host have. In case of cpu with 16 cpu time to 2/X of total cpu time current host have. In case of cpu with 16
threads this means that container can use up to 12.5% of whole cpu power. This threads this means that container can use up to 12.5% of whole cpu power. This
does not mean assigning the cpu time to specific physical threads, therefore does not mean assigning the cpu time to specific physical threads, therefore
high load in that container will be loadbalanced on all physical threads. high load in that container will be loadbalanced on all physical threads,
without allowing to utilize too much of time.
In case of Kubernetes this works the same, limits are specified per container: In case of Kubernetes this works the same, limits are specified per container:
@ -385,7 +386,7 @@ For such tools there could be few rules that should increase security:
- Don't disable isolation. Isolation makes access harder for remote attacker, - Don't disable isolation. Isolation makes access harder for remote attacker,
even if he can access any port on the container host machine. even if he can access any port on the container host machine.
- when opening ports to access the app from outside, set binding to the least - When opening ports to access the app from outside, set binding to the least
accessible but sufficient interface/address. For example If you expect only accessible but sufficient interface/address. For example If you expect only
to access the app locally over localhost, you could bind to localhost in to access the app locally over localhost, you could bind to localhost in
Podman using flag: `-p 127.0.0.1:8080:8080` to open the port 8080 Podman using flag: `-p 127.0.0.1:8080:8080` to open the port 8080
@ -397,10 +398,146 @@ Kubernetes gives much greater possibilities for both ingress and egress.
Primary tools for that are Network Polcicies, which are implemented via plugins Primary tools for that are Network Polcicies, which are implemented via plugins
(therefore they might be not available on some k8s clusters). (therefore they might be not available on some k8s clusters).
## 8. Images Network Policies allow for very accurate limitation of network traffic,
thanks to their possibilities:
- Using labels to select the pods to which the network policy
applies. This allows you to target specific groups of pods based on their labels.
- Applying network policies across namespaces by selecting
namespaces based on their labels.
- Defining rules based on specific protocols (TCP, UDP) and ports to allow or deny traffic.
- Support for arbitrary CIDR-formatted network addresses ranges.
Example network policy definition:
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: app1
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: app
ports:
- protocol: TCP
port: 123
- protocol: TCP
port: 456
- from:
- ipBlock:
cidr: 10.43.0.0/16
- ipBlock:
cidr: fe80::8cb6:aff8:8dc9:f511/64
ports:
- protocol: TCP
port: 443
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: db
ports:
- protocol: TCP
port: 5432
```
## 8. OCI Images
Containers technically don't require images, the base filesystem can be
provided in different way, but OCI images become standard in the industry.
Images are another important element of (in)security in contenerization.
It is crucial to understand basics of that format, as it can for example leak
secrets to the public, if used incorrectly.
## 8.1 Building ## 8.1 Building
It is obvious that one should not hardcode secrets into an image. Unfortunately
less users is aware how not to do that. When building an image, any instruction
that can modify filesystem of the built image, will be saved separately as a
layer. By default each layer is kept in the image, even, when in the end all
contents of some of those layers was removed.
Example of **insecure** Containerfile:
```Dockerfile
FROM registry.fedoraproject.org/fedora-minimal
# Copy secret into the image (bad practice)
COPY secret.txt ./secret.txt
# Use and delete secret (but it's still in a previous layer)
RUN cat secret.txt && rm secret.txt
```
There is a way to modify image-to-be filesystem in much more secure manner,
which also brings other benefits. It is called multi-stage build and, as the
name suggests, contains multiple stages, where only layers of the latest will
be saved in the resulting image.
The Containerfile can look like that:
```dockerfile
# Stage 1: Use secret during the build
FROM registry.fedoraproject.org/fedora-minimal AS builder
WORKDIR /app
# Copy application files
COPY app/ /app/
# Copy the secret into the build stage
COPY secret.txt /app/secret.txt
# Use the secret securely (e.g., configure app)
RUN cat /app/secret.txt && echo "Configuring app with secret" > config.txt
# Removing the secret in this example is needed, because in the next stage
# the /app dir will be copied as a whole
RUN rm /app/secret.txt
# Stage 2: Final image without secrets
FROM registry.fedoraproject.org/fedora-minimal
# Nothing is saved from previous stage
WORKDIR /app
# Copy only the necessary files from the builder stage
COPY --from=builder /app/ /app/
```
This approach also helps keeping the images minimal, without any other
leftovers, which also can improve security.
## 8.2 Scanning ## 8.2 Scanning
Images can be scanned for vulnerabilities. This is usefull for any type and
source if images, since vulnerabilities appear even in the most basic
components like language interpreters, libC libraries, etc. There are tools
for manual scanning like [trivy](https://github.com/aquasecurity/trivy), and
some registries like [Harbor](https://goharbor.io/) have builting optional
automatic vulnerability scanning for any stored image.
These tools can provide descriptive analysis of image contents, taking into
account versions of most software stored inside (if supported).
Example fragment of output of trivy scanning a python image:
![trivy](./trivy.jpg)
## 9. Selinux ## 9. Selinux

BIN
trivy.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB