25 Apr 2024
Hacker News
The AI Lie
25 Apr 2024 1:08am GMT
Show HN: See your current Spotify song in the menu bar
25 Apr 2024 12:47am GMT
24 Apr 2024
Hacker News
Airlines required to refund passengers for canceled, delayed flights
24 Apr 2024 10:29pm GMT
OMG! Ubuntu
Clapper Video Player for Linux Gets First Update in 2 Years
A new version of Clapper, a GTK4-based video player for Linux desktop has been released - the first major update in nearly 2 years. I first wrote about Clapper back in 2021 having been seduced over by its slick user interface (a superficial reason to like a media player, I know), its use of GStreamer, and a small but focused feature set that wasn't trying to distract me with features I'd never need. Subsequent updates to the app refined and expanded those selling points further and player remained my preferred video player, despite the lack of any major update since [β¦]
You're reading Clapper Video Player for Linux Gets First Update in 2 Years, a blog post from OMG! Ubuntu. Do not reproduce elsewhere without permission.
24 Apr 2024 8:05pm GMT
Linuxiac
Nginx 1.26 Released with Experimental HTTP/3 Support
Nginx 1.26 web server debuts with HTTP/3 experimental support, per-server HTTP/2, advanced stream modules, and more.
24 Apr 2024 12:54pm GMT
TrueNAS SCALE 24.04 Rolls Out with Enhanced SMB and NFS Monitoring
TrueNAS SCALE 24.04 (Dragonfish) open storage introduces auditing, sandboxing for devs, and enhanced SMB performance.
24 Apr 2024 10:18am GMT
Ubuntu blog
What’s new in security for Ubuntu 24.04 LTS?
We're excited about the upcoming Ubuntu 24.04 LTS release, Noble Numbat. Like all Ubuntu releases, Ubuntu 24.04 LTS comes with 5 years of free security maintenance for the main repository. Support can be expanded for an extra 5 years, and to include the universe repository, via Ubuntu Pro. Organisations looking to keep their systems secure without needing [β¦]
24 Apr 2024 8:40am GMT
Linuxiac
QEMU 9.0 Debuts with Advanced ARM and RISC-V Capabilities
QEMU 9.0 released: 2700+ commits, 220 authors, featuring multiqueue, gdbstub improvements, and more efficient VM migration.
24 Apr 2024 8:33am GMT
Kubernetes Blog
Kubernetes 1.30: Validating Admission Policy Is Generally Available
On behalf of the Kubernetes project, I am excited to announce that ValidatingAdmissionPolicy has reached general availability as part of Kubernetes 1.30 release. If you have not yet read about this new declarative alternative to validating admission webhooks, it may be interesting to read our previous post about the new feature. If you have already heard about ValidatingAdmissionPolicies and you are eager to try them out, there is no better time to do it than now.
Let's have a taste of a ValidatingAdmissionPolicy, by replacing a simple webhook.
Example admission webhook
First, let's take a look at an example of a simple webhook. Here is an excerpt from a webhook that enforces runAsNonRoot
, readOnlyRootFilesystem
, allowPrivilegeEscalation
, and privileged
to be set to the least permissive values.
func verifyDeployment(deploy *appsv1.Deployment) error {
var errs []error
for i, c := range deploy.Spec.Template.Spec.Containers {
if c.Name == "" {
return fmt.Errorf("container %d has no name", i)
}
if c.SecurityContext == nil {
errs = append(errs, fmt.Errorf("container %q does not have SecurityContext", c.Name))
}
if c.SecurityContext.RunAsNonRoot == nil || !*c.SecurityContext.RunAsNonRoot {
errs = append(errs, fmt.Errorf("container %q must set RunAsNonRoot to true in its SecurityContext", c.Name))
}
if c.SecurityContext.ReadOnlyRootFilesystem == nil || !*c.SecurityContext.ReadOnlyRootFilesystem {
errs = append(errs, fmt.Errorf("container %q must set ReadOnlyRootFilesystem to true in its SecurityContext", c.Name))
}
if c.SecurityContext.AllowPrivilegeEscalation != nil && *c.SecurityContext.AllowPrivilegeEscalation {
errs = append(errs, fmt.Errorf("container %q must NOT set AllowPrivilegeEscalation to true in its SecurityContext", c.Name))
}
if c.SecurityContext.Privileged != nil && *c.SecurityContext.Privileged {
errs = append(errs, fmt.Errorf("container %q must NOT set Privileged to true in its SecurityContext", c.Name))
}
}
return errors.NewAggregate(errs)
}
Check out What are admission webhooks? Or, see the full code of this webhook to follow along with this walkthrough.
The policy
Now let's try to recreate the validation faithfully with a ValidatingAdmissionPolicy.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "pod-security.policy.example.com"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: object.spec.template.spec.containers.all(c, has(c.securityContext) && has(c.securityContext.runAsNonRoot) && c.securityContext.runAsNonRoot)
message: 'all containers must set runAsNonRoot to true'
- expression: object.spec.template.spec.containers.all(c, has(c.securityContext) && has(c.securityContext.readOnlyRootFilesystem) && c.securityContext.readOnlyRootFilesystem)
message: 'all containers must set readOnlyRootFilesystem to true'
- expression: object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.allowPrivilegeEscalation) || !c.securityContext.allowPrivilegeEscalation)
message: 'all containers must NOT set allowPrivilegeEscalation to true'
- expression: object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.Privileged) || !c.securityContext.Privileged)
message: 'all containers must NOT set privileged to true'
Create the policy with kubectl
. Great, no complain so far. But let's get the policy object back and take a look at its status.
kubectl get -oyaml validatingadmissionpolicies/pod-security.policy.example.com
status:
typeChecking:
expressionWarnings:
- fieldRef: spec.validations[3].expression
warning: |
apps/v1, Kind=Deployment: ERROR: <input>:1:76: undefined field 'Privileged'
| object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.Privileged) || !c.securityContext.Privileged)
| ...........................................................................^
ERROR: <input>:1:128: undefined field 'Privileged'
| object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.Privileged) || !c.securityContext.Privileged)
| ...............................................................................................................................^
The policy was checked against its matched type, which is apps/v1.Deployment
. Looking at the fieldRef
, the problem was with the 3rd expression (index starts with 0) The expression in question accessed an undefined Privileged
field. Ahh, looks like it was a copy-and-paste error. The field name should be in lowercase.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "pod-security.policy.example.com"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: object.spec.template.spec.containers.all(c, has(c.securityContext) && has(c.securityContext.runAsNonRoot) && c.securityContext.runAsNonRoot)
message: 'all containers must set runAsNonRoot to true'
- expression: object.spec.template.spec.containers.all(c, has(c.securityContext) && has(c.securityContext.readOnlyRootFilesystem) && c.securityContext.readOnlyRootFilesystem)
message: 'all containers must set readOnlyRootFilesystem to true'
- expression: object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.allowPrivilegeEscalation) || !c.securityContext.allowPrivilegeEscalation)
message: 'all containers must NOT set allowPrivilegeEscalation to true'
- expression: object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.privileged) || !c.securityContext.privileged)
message: 'all containers must NOT set privileged to true'
Check its status again, and you should see all warnings cleared.
Next, let's create a namespace for our tests.
kubectl create namespace policy-test
Then, I bind the policy to the namespace. But at this point, I set the action to Warn
so that the policy prints out warnings instead of rejecting the requests. This is especially useful to collect results from all expressions during development and automated testing.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: "pod-security.policy-binding.example.com"
spec:
policyName: "pod-security.policy.example.com"
validationActions: ["Warn"]
matchResources:
namespaceSelector:
matchLabels:
"kubernetes.io/metadata.name": "policy-test"
Tests out policy enforcement.
kubectl create -n policy-test -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
securityContext:
privileged: true
allowPrivilegeEscalation: true
EOF
Warning: Validation failed for ValidatingAdmissionPolicy 'pod-security.policy.example.com' with binding 'pod-security.policy-binding.example.com': all containers must set runAsNonRoot to true
Warning: Validation failed for ValidatingAdmissionPolicy 'pod-security.policy.example.com' with binding 'pod-security.policy-binding.example.com': all containers must set readOnlyRootFilesystem to true
Warning: Validation failed for ValidatingAdmissionPolicy 'pod-security.policy.example.com' with binding 'pod-security.policy-binding.example.com': all containers must NOT set allowPrivilegeEscalation to true
Warning: Validation failed for ValidatingAdmissionPolicy 'pod-security.policy.example.com' with binding 'pod-security.policy-binding.example.com': all containers must NOT set privileged to true
Error from server: error when creating "STDIN": admission webhook "webhook.example.com" denied the request: [container "nginx" must set RunAsNonRoot to true in its SecurityContext, container "nginx" must set ReadOnlyRootFilesystem to true in its SecurityContext, container "nginx" must NOT set AllowPrivilegeEscalation to true in its SecurityContext, container "nginx" must NOT set Privileged to true in its SecurityContext]
Looks great! The policy and the webhook give equivalent results. After a few other cases, when we are confident with our policy, maybe it is time to do some cleanup.
- For every expression, we repeat access to
object.spec.template.spec.containers
and to eachsecurityContext
; - There is a pattern of checking presence of a field and then accessing it, which looks a bit verbose.
Fortunately, since Kubernetes 1.28, we have new solutions for both issues. Variable Composition allows us to extract repeated sub-expressions into their own variables. Kubernetes enables the optional library for CEL, which are excellent to work with fields that are, you guessed it, optional.
With both features in mind, let's refactor the policy a bit.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "pod-security.policy.example.com"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
variables:
- name: containers
expression: object.spec.template.spec.containers
- name: securityContexts
expression: 'variables.containers.map(c, c.?securityContext)'
validations:
- expression: variables.securityContexts.all(c, c.?runAsNonRoot == optional.of(true))
message: 'all containers must set runAsNonRoot to true'
- expression: variables.securityContexts.all(c, c.?readOnlyRootFilesystem == optional.of(true))
message: 'all containers must set readOnlyRootFilesystem to true'
- expression: variables.securityContexts.all(c, c.?allowPrivilegeEscalation != optional.of(true))
message: 'all containers must NOT set allowPrivilegeEscalation to true'
- expression: variables.securityContexts.all(c, c.?privileged != optional.of(true))
message: 'all containers must NOT set privileged to true'
The policy is now much cleaner and more readable. Update the policy, and you should see it function the same as before.
Now let's change the policy binding from warning to actually denying requests that fail validation.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: "pod-security.policy-binding.example.com"
spec:
policyName: "pod-security.policy.example.com"
validationActions: ["Deny"]
matchResources:
namespaceSelector:
matchLabels:
"kubernetes.io/metadata.name": "policy-test"
And finally, remove the webhook. Now the result should include only messages from the policy.
kubectl create -n policy-test -f- <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
securityContext:
privileged: true
allowPrivilegeEscalation: true
EOF
The deployments "nginx" is invalid: : ValidatingAdmissionPolicy 'pod-security.policy.example.com' with binding 'pod-security.policy-binding.example.com' denied request: all containers must set runAsNonRoot to true
Please notice that, by design, the policy will stop evaluation after the first expression that causes the request to be denied. This is different from what happens when the expressions generate only warnings.
Set up monitoring
Unlike a webhook, a policy is not a dedicated process that can expose its own metrics. Instead, you can use metrics from the API server in their place.
Here are some examples in Prometheus Query Language of common monitoring tasks.
To find the 95th percentile execution duration of the policy shown above.
histogram_quantile(0.95, sum(rate(apiserver_validating_admission_policy_check_duration_seconds_bucket{policy="pod-security.policy.example.com"}[5m])) by (le))
To find the rate of the policy evaluation.
rate(apiserver_validating_admission_policy_check_total{policy="pod-security.policy.example.com"}[5m])
You can read the metrics reference to learn more about the metrics above. The metrics of ValidatingAdmissionPolicy are currently in alpha, and more and better metrics will come while the stability graduates in the future release.
24 Apr 2024 12:00am GMT
23 Apr 2024
OMG! Ubuntu
Ubuntu 24.04 LTS: 20 Major Changes to Look Out For
Anyone making the upgrade to Ubuntu 24.04 LTS from the previous LTS, Ubuntu 22.04, is in for a treat because the amount of improvements on offer is vast. In addition to all of the new features Ubuntu 24.04 has added in the past 6 months LTS upgraders finally get to experience and enjoy the myriad of new features that were added in the Ubuntu 22.10, 23.04, and 23.10 releases. Those upgrading from the previous LTS will find 2 years worth of changes on offer in Ubuntu 24.04 - It amounts to a lot of change! In this post I run-through [β¦]
You're reading Ubuntu 24.04 LTS: 20 Major Changes to Look Out For, a blog post from OMG! Ubuntu. Do not reproduce elsewhere without permission.
23 Apr 2024 11:04pm GMT
The Official Flathub Website Just Got a Fab Revamp
Next time you stop by the Flathub website you will notice it's had a bit of a revamp. The latest UI refresh lands a year after its last big redesign and builds on that look by adding new on-page features. These changes make it easier for Linux users to find the apps they are looking for and come across new software they might not have heard of. - That is unless they regularly read sites like mine, eh π. The Flathub homepage is now topped by a new banner slider (updated weekly) which promotes 5 apps. There's also a new [β¦]
You're reading The Official Flathub Website Just Got a Fab Revamp, a blog post from OMG! Ubuntu. Do not reproduce elsewhere without permission.
23 Apr 2024 3:16pm GMT
Kubernetes Blog
Kubernetes 1.30: Read-only volume mounts can be finally literally read-only
Read-only volume mounts have been a feature of Kubernetes since the beginning. Surprisingly, read-only mounts are not completely read-only under certain conditions on Linux. As of the v1.30 release, they can be made completely read-only, with alpha support for recursive read-only mounts.
Read-only volume mounts are not really read-only by default
Volume mounts can be deceptively complicated.
You might expect that the following manifest makes everything under /mnt
in the containers read-only:
---
apiVersion: v1
kind: Pod
spec:
volumes:
- name: mnt
hostPath:
path: /mnt
containers:
- volumeMounts:
- name: mnt
mountPath: /mnt
readOnly: true
However, any sub-mounts beneath /mnt
may still be writable! For example, consider that /mnt/my-nfs-server
is writeable on the host. Inside the container, writes to /mnt/*
will be rejected but /mnt/my-nfs-server/*
will still be writeable.
New mount option: recursiveReadOnly
Kubernetes 1.30 added a new mount option recursiveReadOnly
so as to make submounts recursively read-only.
The option can be enabled as follows:
---
apiVersion: v1
kind: Pod
spec:
volumes:
- name: mnt
hostPath:
path: /mnt
containers:
- volumeMounts:
- name: mnt
mountPath: /mnt
readOnly: true
# NEW
# Possible values are `Enabled`, `IfPossible`, and `Disabled`.
# Needs to be specified in conjunction with `readOnly: true`.
recursiveReadOnly: Enabled
This is implemented by applying the MOUNT_ATTR_RDONLY
attribute with the AT_RECURSIVE
flag using mount_setattr(2)
added in Linux kernel v5.12.
For backwards compatibility, the recursiveReadOnly
field is not a replacement for readOnly
, but is used in conjunction with it. To get a properly recursive read-only mount, you must set both fields.
Feature availability
To enable recursiveReadOnly
mounts, the following components have to be used:
-
Kubernetes: v1.30 or later, with the
RecursiveReadOnlyMounts
feature gate enabled. As of v1.30, the gate is marked as alpha. -
CRI runtime:
- containerd: v2.0 or later
-
OCI runtime:
- runc: v1.1 or later
- crun: v1.8.6 or later
-
Linux kernel: v5.12 or later
What's next?
Kubernetes SIG Node hope - and expect - that the feature will be promoted to beta and eventually general availability (GA) in future releases of Kubernetes, so that users no longer need to enable the feature gate manually.
The default value of recursiveReadOnly
will still remain Disabled
, for backwards compatibility.
How can I learn more?
Please check out the documentation for the further details of recursiveReadOnly
mounts.
How to get involved?
This feature is driven by the SIG Node community. Please join us to connect with the community and share your ideas and feedback around the above feature and beyond. We look forward to hearing from you!
23 Apr 2024 12:00am GMT
22 Apr 2024
Ubuntu blog
Achieving Performant Single-Tenant Cloud Isolation with IBM Cloud Bare Metal Servers, Ubuntu Core, Snaps, and AMD Pensando Elba Data Processing Unit
Discover how IBM Cloud's bare metal servers offer highly confined and high-performing single-tenant cloud isolation through the use of Ubuntu Core and Snaps, supported by the AMD Pensando Elba DPU (Data Processing Unit). This setup enables the creation of secure and efficient environments for each tenant. Its design ensures the total separation of their servers [β¦]
22 Apr 2024 4:52pm GMT
Kubernetes Blog
Kubernetes 1.30: Beta Support For Pods With User Namespaces
Linux provides different namespaces to isolate processes from each other. For example, a typical Kubernetes pod runs within a network namespace to isolate the network identity and a PID namespace to isolate the processes.
One Linux namespace that was left behind is the user namespace. This namespace allows us to isolate the user and group identifiers (UIDs and GIDs) we use inside the container from the ones on the host.
This is a powerful abstraction that allows us to run containers as "root": we are root inside the container and can do everything root can inside the pod, but our interactions with the host are limited to what a non-privileged user can do. This is great for limiting the impact of a container breakout.
A container breakout is when a process inside a container can break out onto the host using some unpatched vulnerability in the container runtime or the kernel and can access/modify files on the host or other containers. If we run our pods with user namespaces, the privileges the container has over the rest of the host are reduced, and the files outside the container it can access are limited too.
In Kubernetes v1.25, we introduced support for user namespaces only for stateless pods. Kubernetes 1.28 lifted that restriction, and now, with Kubernetes 1.30, we are moving to beta!
What is a user namespace?
Note: Linux user namespaces are a different concept from Kubernetes namespaces. The former is a Linux kernel feature; the latter is a Kubernetes feature.
User namespaces are a Linux feature that isolates the UIDs and GIDs of the containers from the ones on the host. The identifiers in the container can be mapped to identifiers on the host in a way where the host UID/GIDs used for different containers never overlap. Furthermore, the identifiers can be mapped to unprivileged, non-overlapping UIDs and GIDs on the host. This brings two key benefits:
-
Prevention of lateral movement: As the UIDs and GIDs for different containers are mapped to different UIDs and GIDs on the host, containers have a harder time attacking each other, even if they escape the container boundaries. For example, suppose container A runs with different UIDs and GIDs on the host than container B. In that case, the operations it can do on container B's files and processes are limited: only read/write what a file allows to others, as it will never have permission owner or group permission (the UIDs/GIDs on the host are guaranteed to be different for different containers).
-
Increased host isolation: As the UIDs and GIDs are mapped to unprivileged users on the host, if a container escapes the container boundaries, even if it runs as root inside the container, it has no privileges on the host. This greatly protects what host files it can read/write, which process it can send signals to, etc. Furthermore, capabilities granted are only valid inside the user namespace and not on the host, limiting the impact a container escape can have.
Without using a user namespace, a container running as root in the case of a container breakout has root privileges on the node. If some capabilities were granted to the container, the capabilities are valid on the host too. None of this is true when using user namespaces (modulo bugs, of course π).
Changes in 1.30
In Kubernetes 1.30, besides moving user namespaces to beta, the contributors working on this feature:
- Introduced a way for the kubelet to use custom ranges for the UIDs/GIDs mapping
- Have added a way for Kubernetes to enforce that the runtime supports all the features needed for user namespaces. If they are not supported, Kubernetes will show a clear error when trying to create a pod with user namespaces. Before 1.30, if the container runtime didn't support user namespaces, the pod could be created without a user namespace.
- Added more tests, including tests in the cri-tools repository.
You can check the documentation on user namespaces for how to configure custom ranges for the mapping.
Demo
A few months ago, CVE-2024-21626 was disclosed. This vulnerability score is 8.6 (HIGH). It allows an attacker to escape a container and read/write to any path on the node and other pods hosted on the same node.
Rodrigo created a demo that exploits CVE 2024-21626 and shows how the exploit, which works without user namespaces, is mitigated when user namespaces are in use.
Please note that with user namespaces, an attacker can do on the host file system what the permission bits for "others" allow. Therefore, the CVE is not completely prevented, but the impact is greatly reduced.
Node system requirements
There are requirements on the Linux kernel version and the container runtime to use this feature.
On Linux you need Linux 6.3 or greater. This is because the feature relies on a kernel feature named idmap mounts, and support for using idmap mounts with tmpfs was merged in Linux 6.3.
Suppose you are using CRI-O with crun; as always, you can expect support for Kubernetes 1.30 with CRI-O 1.30. Please note you also need crun 1.9 or greater. If you are using CRI-O with runc, this is still not supported.
Containerd support is currently targeted for containerd 2.0, and the same crun version requirements apply. If you are using containerd with runc, this is still not supported.
Please note that containerd 1.7 added experimental support for user namespaces, as implemented in Kubernetes 1.25 and 1.26. We did a redesign in Kubernetes 1.27, which requires changes in the container runtime. Those changes are not present in containerd 1.7, so it only works with user namespaces support in Kubernetes 1.25 and 1.26.
Another limitation of containerd 1.7 is that it needs to change the ownership of every file and directory inside the container image during Pod startup. This has a storage overhead and can significantly impact the container startup latency. Containerd 2.0 will probably include an implementation that will eliminate the added startup latency and storage overhead. Consider this if you plan to use containerd 1.7 with user namespaces in production.
None of these containerd 1.7 limitations apply to CRI-O.
How do I get involved?
You can reach SIG Node by several means:
You can also contact us directly:
- GitHub: @rata @giuseppe @saschagrunert
- Slack: @rata @giuseppe @sascha
22 Apr 2024 12:00am GMT
19 Apr 2024
Ubuntu blog
Letβs talk open design
Why aren't there more design contributions in open source? Help us find out!
19 Apr 2024 10:11am GMT
18 Apr 2024
JavaScript Weekly
Visualizing algorithms
|
18 Apr 2024 12:00am GMT
11 Apr 2024
JavaScript Weekly
An easy way to experiment with signals
|
11 Apr 2024 12:00am GMT
04 Apr 2024
JavaScript Weekly
A signal boost for JavaScript
|
04 Apr 2024 12:00am GMT