-
Custom Root Trust with HttpClient in .NET
Custom root trust is a security practice where an application or system is configured to trust only a specific set of root certificates. This approach restricts the application’s trust to a limited, predefined list of Certificate Authorities, enhancing security by preventing reliance on external or unverified certificates. The practise is also use in a corporate setting to limit trust to an internal root certificate.
Custom root trust is similar to, but differs from Certificate Pinning, where Certificate Pinning is the act of trusting a specific certificate and custom root trust is trusting all certificates issued by the trusted root certificate.
Implementing custom root trust has been pretty straight forward with
HttpClient
ever since .NET 5.X509Certificate2 trustedRoot = new X509Certificate2("corp-root-ca.pem"); HttpClientHandler handler = new() { ServerCertificateCustomValidationCallback = (_, certificate, chain, errors) => { // If errors are present, but they are not Remote Certificate Chain Errors, fail the validation. if ((errors & ~SslPolicyErrors.RemoteCertificateChainErrors) != 0) { return false; } // Add intermediate certificates from the server's chain for the verification process. foreach (X509ChainElement intermediateElements in chain.ChainElements.Skip(1)) { chain.ChainPolicy.ExtraStore.Add(intermediateElements.Certificate); } // Clear any potential existing trusted root certificates. chain.ChainPolicy.CustomTrustStore.Clear(); // Enforce Custom Root Trust. chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; // Add desired root certificate. chain.ChainPolicy.CustomTrustStore.Add(trustedRoot); // Verify the validity of the chain of trust and the server's certificate return chain.Build(certificate); } }; HttpClient client = new(handler); HttpResponseMessage response = await client.GetAsync("https://intranet.corp.local");
-
Workarounds for creating Azure Hybrid Connections with Terraform
UPDATE: The bug has been fixed and released in 3.98. The workarounds are no longer needed.
Due to some bugs in the current Terraform azurerm provider (v3.80.0), certain workarounds are needed to create a working hybrid connection.
The issue is present for both Function Apps and Web Apps.
Following the official documentation’s examples, the following code will not work and will result in a seemingly successful deployment, but the hybrid connection will not work. No connection will be able to be established, but everything looks fine in the Azure Portal.
I have two workarounds for this issue and a workaround idea.
Workaround 1 - Run a Provisioner after Deployment of Function App Hybrid Connection
resource "azurerm_function_app_hybrid_connection" "example" { function_app_id = azurerm_linux_function_app.example.id relay_id = azurerm_relay_hybrid_connection.example.id hostname = "server.example.local" port = 443 send_key_name = azurerm_relay_hybrid_connection_authorization_rule.example.name lifecycle { ignore_changes = [ relay_id ] } provisioner "local-exec" { command = "az functionapp hybrid-connection add --hybrid-connection ${azurerm_relay_hybrid_connection.example.name} --namespace ${azurerm_relay_namespace.example.name} -n ${azurerm_linux_function_app.example.name} -g ${azurerm_resource_group.example.name} --subscription ${var.subscription_id}" } }
The thing to note in this workaround is that the provisioner will change the
relay_id
which differs in letter casing from what Terraform expects. This will cause Terraform to see the resource as changed and will recreate the hybrid connection on every run. To prevent this, use the lifecycle meta-argument forignore_changes
onrelay_id
.Workaround 2 - Use a Null Resource and Provisioners to create the Hybrid Connection with Azure CLI
resource "null_resource" "function_app_hybrid_connection" { triggers = { function_app_name = azurerm_linux_function_app.example.name resource_group_name = azurerm_resource_group.example.name namespace_name = azurerm_relay_namespace.example.name hybrid_connection_name = azurerm_relay_hybrid_connection.example.name subscription_id = var.subscription_id } provisioner "local-exec" { command = "az functionapp hybrid-connection add --hybrid-connection ${self.triggers.hybrid_connection_name} --namespace ${self.triggers.namespace_name} -n ${self.triggers.function_app_name} -g ${self.triggers.resource_group_name} --subscription ${self.triggers.subscription_id}" } provisioner "local-exec" { when = destroy command = "az functionapp hybrid-connection remove --hybrid-connection ${self.triggers.hybrid_connection_name} --namespace ${self.triggers.namespace_name} -n ${self.triggers.function_app_name} -g ${self.triggers.resource_group_name} --subscription ${self.triggers.subscription_id}" } }
This workaround will not use the
azurerm_function_app_hybrid_connection
resource at all, but instead use anull_resource
with provisioners to create the hybrid connection with Azure CLI. The method prevents Terraform from seeing changes to the resource and will not recreate the hybrid connection on every run, but nor will it be able to update the hybrid connection if it is changed in the Azure Portal.Workaround 3 - The Idea
This is but an idea and I have not attempted it. It may be possible to make an ARM template and use the
azurerm_resource_group_template_deployment
to deploy the Function App Hybrid Connection.As with Workaround 2, this would not detect the changes to the resource. The benefit though would be having no dependence on Azure CLI.
Remember the Metadata
When creating the Hybrid Connection in the Azure Relay, remember to add the metadata
endpoint
with the value of the hostname and port of the server you want to connect to, otherwise the provisioner will fail and the Azure Portal will not display the information correctly.resource "azurerm_relay_hybrid_connection" "example" { name = "example" resource_group_name = azurerm_resource_group.example.name relay_namespace_name = azurerm_relay_namespace.example.name requires_client_authorization = true user_metadata = jsonencode( [ { key = "endpoint", value = "server.example.local:443" } ]) }
-
Improving the Bambu Studio Update Script for Linux
UPDATE: Bambu Studio has now been released as a Flatpak and if you run an operating system supporting Flatpak, I would highly suggest using that instead. Huge thanks to hadess and may I suggest thanking him through his wishlist.
Earlier, I wrote about updating Bambu Studio on Fedora Linux. I have since then made a few improvements, such as checking if a newer version exists.
#!/bin/bash set -euo pipefail IFS=$'\n\t' URL=https://api.github.com/repos/bambulab/BambuStudio/releases DISTRO=Fedora # or ubuntu (ubuntu is lowercase on the release page) OUTPUT=./BambuStudio.AppImage VERSION_FILE="$OUTPUT.ver" RELEASES=$(curl -s $URL) LATEST=$(jq -r .[].tag_name <<< $RELEASES | sort -Vr | head -n 1) [[ -e $VERSION_FILE ]] && CURRENT=$(cat $VERSION_FILE) || CURRENT="" if [[ $CURRENT != $LATEST ]]; then DOWNLOAD_URL=$(jq -r ".[] | select(.tag_name == \"$LATEST\") | .assets[] | select(.name | contains(\"$DISTRO\")) | .browser_download_url" <<< $RELEASES) wget -O $OUTPUT $DOWNLOAD_URL echo $LATEST > $VERSION_FILE echo "Bambu Studio is updated to $LATEST." else echo "Bambu Studio is already up-to-date." fi
-
Update Bambu Studio on Fedora Linux
UPDATE: Consider taking a look at the the improved script here.
UPDATE 2: Bambu Studio has now been released as a Flatpak and if you run an operating system supporting Flatpak, I would highly suggest using that instead. Huge thanks to hadess and may I suggest thanking him through his wishlist.
To avoid having to visit GitHub to download new versions of Bambu Studio for Linux, use the below script to download and update your AppImage.
#!/bin/bash URL=https://api.github.com/repos/bambulab/BambuStudio/releases DISTRO=Fedora # or ubuntu (ubuntu is lowercase on the release page) OUTPUT=./BambuStudio.AppImage wget -O $OUTPUT $(curl -s $URL | jq -r ".[0].assets[] | select(.name | contains (\"$DISTRO\")) | .browser_download_url") chmod +x $OUTPUT
-
Bambu Studio on Fedora Silverblue
UPDATE: Bambu Studio has now been released as a Flatpak. Huge thanks to hadess and may I suggest thanking him through his wishlist.
Bambu Studio for Linux is only distributed as an AppImage, not as a Flatpak and when running on Fedora, Bambu Studio requires extra dependencies to be installed.
This fact makes it challenging to run on an immutable operating system like Fedora Silverblue.
To workaround this challenge, tools like Silverblue’s built-in Toolbox or Distrobox can be used.
The following is a
distrobox.ini
for Distrobox Assemble which will allow you to run Bambu Studio’s AppImage in a container.[bambulabs] image=fedora-toolbox:38 additional_packages="fuse fuse-libs" additional_packages="mesa-libGL mesa-libGLU" additional_packages="wayland-devel wayland-protocols-devel libxkbcommon" additional_packages="gtk3 webkit2gtk3" additional_packages="gstreamer1 gstreamer1-plugins-base gstreamer1-plugin-openh264" additional_packages="mesa-libOSMesa"
I will suggest creating a
BambuStudio.desktop
in your~/.local/share/applications
to launch the program from your host OS.[Desktop Entry] Name=Bambu Studio GenericName=Bambu Studio Comment=Bambu Labs Slicer Categories=Utility Exec=/usr/bin/distrobox enter bambulabs -- ~/Applications/BambuStudio.AppImage Icon=bambustudio Terminal=false NoDisplay=true Type=Application
This example assumes your Bambu Studio AppImage is located as ~/Applications/BambuStudio.AppImage.