feat: optionally decode hcloud userdata as base64
When fetching the machine configuration in the hcloud platform implementation, try to decode the data returned from the 'userdata' endpoint as a base64 string. If the data is not in base64 format, decoding does not succeed and the unmodified data is used. Signed-off-by: Philipp Kleber <philipp.t.kleber@gmail.com> Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com> (cherry picked from commit ccbd5aed39b360664d1f80c8b146050e9df9ff7b)
This commit is contained in:
parent
f20a6900db
commit
ce47912518
@ -0,0 +1,10 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package hcloud
|
||||
|
||||
// MaybeBase64Decode is exported for testing.
|
||||
func MaybeBase64Decode(data []byte) []byte {
|
||||
return maybeBase64Decode(data)
|
||||
}
|
@ -7,6 +7,7 @@ package hcloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/netip"
|
||||
@ -156,9 +157,27 @@ func (h *Hcloud) Configuration(ctx context.Context, r state.State) ([]byte, erro
|
||||
|
||||
log.Printf("fetching machine config from: %q", HCloudUserDataEndpoint)
|
||||
|
||||
return download.Download(ctx, HCloudUserDataEndpoint,
|
||||
configBytes, err := download.Download(ctx, HCloudUserDataEndpoint,
|
||||
download.WithErrorOnNotFound(errors.ErrNoConfigSource),
|
||||
download.WithErrorOnEmptyResponse(errors.ErrNoConfigSource))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Try to parse the downloaded config bytes as base64 string, so that users can provide the config in base64 format.
|
||||
// This also allows users to gzip this data, since the calling code will try to un-gzip the data if it detects it.
|
||||
return maybeBase64Decode(configBytes), nil
|
||||
}
|
||||
|
||||
// maybeBase64Decode tries to interpret the provided bytes as base64 string and decode them.
|
||||
// If the provided bytes are not a valid base64 string, the original bytes are returned.
|
||||
func maybeBase64Decode(data []byte) []byte {
|
||||
out, err := base64.StdEncoding.AppendDecode(nil, data)
|
||||
if err != nil {
|
||||
return data
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Mode implements the runtime.Platform interface.
|
||||
|
@ -44,3 +44,17 @@ func TestParseMetadata(t *testing.T) {
|
||||
|
||||
assert.Equal(t, expectedNetworkConfig, string(marshaled))
|
||||
}
|
||||
|
||||
//go:embed testdata/userdata-plain.yaml
|
||||
var userdataPlain []byte
|
||||
|
||||
//go:embed testdata/userdata-base64.txt
|
||||
var userdataBase64 []byte
|
||||
|
||||
func TestParseUserdata(t *testing.T) {
|
||||
decodedUserdataPlain := hcloud.MaybeBase64Decode(userdataPlain)
|
||||
decodedUserdataBase64 := hcloud.MaybeBase64Decode(userdataBase64)
|
||||
|
||||
assert.Equal(t, decodedUserdataPlain, decodedUserdataBase64)
|
||||
assert.Equal(t, userdataPlain, decodedUserdataBase64)
|
||||
}
|
||||
|
1
internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/testdata/userdata-base64.txt
vendored
Normal file
1
internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/testdata/userdata-base64.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
dmVyc2lvbjogdjFhbHBoYTEKZGVidWc6IGZhbHNlCnBlcnNpc3Q6IHRydWUKbWFjaGluZToKICB0eXBlOiBjb250cm9scGxhbmUKICBjZXJ0U0FOczoKICAgIC0gMTAuMC4xLjEwMQogICAgLSAxMC4wLjEuMTAwCiAga3ViZWxldDoKICAgIGltYWdlOiBnaGNyLmlvL3NpZGVyb2xhYnMva3ViZWxldDp2MS4zMS4xCiAgICBleHRyYUFyZ3M6CiAgICAgIGNsb3VkLXByb3ZpZGVyOiBleHRlcm5hbAogICAgICByb3RhdGUtc2VydmVyLWNlcnRpZmljYXRlczogInRydWUiCiAgICBkZWZhdWx0UnVudGltZVNlY2NvbXBQcm9maWxlRW5hYmxlZDogdHJ1ZQogICAgbm9kZUlQOgogICAgICB2YWxpZFN1Ym5ldHM6CiAgICAgICAgLSAxMC4wLjEuMC8yNAogICAgZGlzYWJsZU1hbmlmZXN0c0RpcmVjdG9yeTogdHJ1ZQogIG5ldHdvcms6CiAgICBob3N0bmFtZTogY29udHJvbHBsYW5lLTAwMQogICAgaW50ZXJmYWNlczoKICAgICAgLSBpbnRlcmZhY2U6IGV0aDAKICAgICAgICBkaGNwOiB0cnVlCiAgICBrdWJlc3BhbjoKICAgICAgZW5hYmxlZDogZmFsc2UKICBpbnN0YWxsOgogICAgZGlzazogL2Rldi9zZGEKICAgIGV4dHJhS2VybmVsQXJnczoKICAgICAgLSBpcHY2LmRpc2FibGU9MQogICAgaW1hZ2U6IGdoY3IuaW8vc2lkZXJvbGFicy9pbnN0YWxsZXI6djEuOC4wCiAgICB3aXBlOiBmYWxzZQogIHN5c2N0bHM6CiAgICBuZXQuY29yZS5uZXRkZXZfbWF4X2JhY2tsb2c6ICI0MDk2IgogICAgbmV0LmNvcmUuc29tYXhjb25uOiAiNjU1MzUiCiAgZmVhdHVyZXM6CiAgICByYmFjOiB0cnVlCiAgICBzdGFibGVIb3N0bmFtZTogdHJ1ZQogICAga3ViZXJuZXRlc1RhbG9zQVBJQWNjZXNzOgogICAgICBlbmFibGVkOiB0cnVlCiAgICAgIGFsbG93ZWRSb2xlczoKICAgICAgICAtIG9zOnJlYWRlcgogICAgICBhbGxvd2VkS3ViZXJuZXRlc05hbWVzcGFjZXM6CiAgICAgICAgLSBrdWJlLXN5c3RlbQogICAgYXBpZENoZWNrRXh0S2V5VXNhZ2U6IHRydWUKICAgIGRpc2tRdW90YVN1cHBvcnQ6IHRydWUKICAgIGt1YmVQcmlzbToKICAgICAgZW5hYmxlZDogdHJ1ZQogICAgICBwb3J0OiA3NDQ1CiAgICBob3N0RE5TOgogICAgICBlbmFibGVkOiB0cnVlCiAgICAgIGZvcndhcmRLdWJlRE5TVG9Ib3N0OiB0cnVlCiAgICAgIHJlc29sdmVNZW1iZXJOYW1lczogdHJ1ZQogIGtlcm5lbDoge30KICBub2RlTGFiZWxzOgogICAgbm9kZS5rdWJlcm5ldGVzLmlvL2V4Y2x1ZGUtZnJvbS1leHRlcm5hbC1sb2FkLWJhbGFuY2VyczogIiIKY2x1c3RlcjoKICBjb250cm9sUGxhbmU6CiAgICBlbmRwb2ludDogaHR0cHM6Ly8xMC4wLjEuMTAwOjY0NDMKICBjbHVzdGVyTmFtZTogdGVzdC1jbHVzdGVyCiAgbmV0d29yazoKICAgIGNuaToKICAgICAgbmFtZTogbm9uZQogICAgZG5zRG9tYWluOiBjbHVzdGVyLmxvY2FsCiAgICBwb2RTdWJuZXRzOgogICAgICAtIDEwLjAuMTYuMC8yMAogICAgc2VydmljZVN1Ym5ldHM6CiAgICAgIC0gMTAuMC44LjAvMjEKICBhcGlTZXJ2ZXI6CiAgICBpbWFnZTogcmVnaXN0cnkuazhzLmlvL2t1YmUtYXBpc2VydmVyOnYxLjMxLjEKICAgIGNlcnRTQU5zOgogICAgICAtIDEwLjAuMS4xMDAKICAgICAgLSAxMC4wLjEuMTAxCiAgICAgIC0gMTAuMC4xLjEwMAogICAgZGlzYWJsZVBvZFNlY3VyaXR5UG9saWN5OiB0cnVlCiAgICBhZG1pc3Npb25Db250cm9sOgogICAgICAtIG5hbWU6IFBvZFNlY3VyaXR5CiAgICAgICAgY29uZmlndXJhdGlvbjoKICAgICAgICAgIGFwaVZlcnNpb246IHBvZC1zZWN1cml0eS5hZG1pc3Npb24uY29uZmlnLms4cy5pby92MWFscGhhMQogICAgICAgICAgZGVmYXVsdHM6CiAgICAgICAgICAgIGF1ZGl0OiByZXN0cmljdGVkCiAgICAgICAgICAgIGF1ZGl0LXZlcnNpb246IGxhdGVzdAogICAgICAgICAgICBlbmZvcmNlOiBiYXNlbGluZQogICAgICAgICAgICBlbmZvcmNlLXZlcnNpb246IGxhdGVzdAogICAgICAgICAgICB3YXJuOiByZXN0cmljdGVkCiAgICAgICAgICAgIHdhcm4tdmVyc2lvbjogbGF0ZXN0CiAgICAgICAgICBleGVtcHRpb25zOgogICAgICAgICAgICBuYW1lc3BhY2VzOgogICAgICAgICAgICAgIC0ga3ViZS1zeXN0ZW0KICAgICAgICAgICAgcnVudGltZUNsYXNzZXM6IFtdCiAgICAgICAgICAgIHVzZXJuYW1lczogW10KICAgICAgICAgIGtpbmQ6IFBvZFNlY3VyaXR5Q29uZmlndXJhdGlvbgogICAgYXVkaXRQb2xpY3k6CiAgICAgIGFwaVZlcnNpb246IGF1ZGl0Lms4cy5pby92MQogICAgICBraW5kOiBQb2xpY3kKICAgICAgcnVsZXM6CiAgICAgICAgLSBsZXZlbDogTWV0YWRhdGEKICBjb250cm9sbGVyTWFuYWdlcjoKICAgIGltYWdlOiByZWdpc3RyeS5rOHMuaW8va3ViZS1jb250cm9sbGVyLW1hbmFnZXI6djEuMzEuMQogICAgZXh0cmFBcmdzOgogICAgICBiaW5kLWFkZHJlc3M6IDAuMC4wLjAKICAgICAgY2xvdWQtcHJvdmlkZXI6IGV4dGVybmFsCiAgICAgIG5vZGUtY2lkci1tYXNrLXNpemUtaXB2NDogIjI0IgogIHByb3h5OgogICAgZGlzYWJsZWQ6IHRydWUKICAgIGltYWdlOiByZWdpc3RyeS5rOHMuaW8va3ViZS1wcm94eTp2MS4zMS4xCiAgc2NoZWR1bGVyOgogICAgaW1hZ2U6IHJlZ2lzdHJ5Lms4cy5pby9rdWJlLXNjaGVkdWxlcjp2MS4zMS4xCiAgICBleHRyYUFyZ3M6CiAgICAgIGJpbmQtYWRkcmVzczogMC4wLjAuMAogIGRpc2NvdmVyeToKICAgIGVuYWJsZWQ6IHRydWUKICAgIHJlZ2lzdHJpZXM6CiAgICAgIGt1YmVybmV0ZXM6CiAgICAgICAgZGlzYWJsZWQ6IHRydWUKICAgICAgc2VydmljZToge30KICBldGNkOgogICAgZXh0cmFBcmdzOgogICAgICBsaXN0ZW4tbWV0cmljcy11cmxzOiBodHRwOi8vMC4wLjAuMDoyMzgxCiAgICBhZHZlcnRpc2VkU3VibmV0czoKICAgICAgLSAxMC4wLjEuMC8yNAogIGNvcmVETlM6CiAgICBkaXNhYmxlZDogZmFsc2UKICBleHRlcm5hbENsb3VkUHJvdmlkZXI6CiAgICBlbmFibGVkOiB0cnVlCg==
|
124
internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/testdata/userdata-plain.yaml
vendored
Normal file
124
internal/app/machined/pkg/runtime/v1alpha1/platform/hcloud/testdata/userdata-plain.yaml
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
version: v1alpha1
|
||||
debug: false
|
||||
persist: true
|
||||
machine:
|
||||
type: controlplane
|
||||
certSANs:
|
||||
- 10.0.1.101
|
||||
- 10.0.1.100
|
||||
kubelet:
|
||||
image: ghcr.io/siderolabs/kubelet:v1.31.1
|
||||
extraArgs:
|
||||
cloud-provider: external
|
||||
rotate-server-certificates: "true"
|
||||
defaultRuntimeSeccompProfileEnabled: true
|
||||
nodeIP:
|
||||
validSubnets:
|
||||
- 10.0.1.0/24
|
||||
disableManifestsDirectory: true
|
||||
network:
|
||||
hostname: controlplane-001
|
||||
interfaces:
|
||||
- interface: eth0
|
||||
dhcp: true
|
||||
kubespan:
|
||||
enabled: false
|
||||
install:
|
||||
disk: /dev/sda
|
||||
extraKernelArgs:
|
||||
- ipv6.disable=1
|
||||
image: ghcr.io/siderolabs/installer:v1.8.0
|
||||
wipe: false
|
||||
sysctls:
|
||||
net.core.netdev_max_backlog: "4096"
|
||||
net.core.somaxconn: "65535"
|
||||
features:
|
||||
rbac: true
|
||||
stableHostname: true
|
||||
kubernetesTalosAPIAccess:
|
||||
enabled: true
|
||||
allowedRoles:
|
||||
- os:reader
|
||||
allowedKubernetesNamespaces:
|
||||
- kube-system
|
||||
apidCheckExtKeyUsage: true
|
||||
diskQuotaSupport: true
|
||||
kubePrism:
|
||||
enabled: true
|
||||
port: 7445
|
||||
hostDNS:
|
||||
enabled: true
|
||||
forwardKubeDNSToHost: true
|
||||
resolveMemberNames: true
|
||||
kernel: {}
|
||||
nodeLabels:
|
||||
node.kubernetes.io/exclude-from-external-load-balancers: ""
|
||||
cluster:
|
||||
controlPlane:
|
||||
endpoint: https://10.0.1.100:6443
|
||||
clusterName: test-cluster
|
||||
network:
|
||||
cni:
|
||||
name: none
|
||||
dnsDomain: cluster.local
|
||||
podSubnets:
|
||||
- 10.0.16.0/20
|
||||
serviceSubnets:
|
||||
- 10.0.8.0/21
|
||||
apiServer:
|
||||
image: registry.k8s.io/kube-apiserver:v1.31.1
|
||||
certSANs:
|
||||
- 10.0.1.100
|
||||
- 10.0.1.101
|
||||
- 10.0.1.100
|
||||
disablePodSecurityPolicy: true
|
||||
admissionControl:
|
||||
- name: PodSecurity
|
||||
configuration:
|
||||
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
|
||||
defaults:
|
||||
audit: restricted
|
||||
audit-version: latest
|
||||
enforce: baseline
|
||||
enforce-version: latest
|
||||
warn: restricted
|
||||
warn-version: latest
|
||||
exemptions:
|
||||
namespaces:
|
||||
- kube-system
|
||||
runtimeClasses: []
|
||||
usernames: []
|
||||
kind: PodSecurityConfiguration
|
||||
auditPolicy:
|
||||
apiVersion: audit.k8s.io/v1
|
||||
kind: Policy
|
||||
rules:
|
||||
- level: Metadata
|
||||
controllerManager:
|
||||
image: registry.k8s.io/kube-controller-manager:v1.31.1
|
||||
extraArgs:
|
||||
bind-address: 0.0.0.0
|
||||
cloud-provider: external
|
||||
node-cidr-mask-size-ipv4: "24"
|
||||
proxy:
|
||||
disabled: true
|
||||
image: registry.k8s.io/kube-proxy:v1.31.1
|
||||
scheduler:
|
||||
image: registry.k8s.io/kube-scheduler:v1.31.1
|
||||
extraArgs:
|
||||
bind-address: 0.0.0.0
|
||||
discovery:
|
||||
enabled: true
|
||||
registries:
|
||||
kubernetes:
|
||||
disabled: true
|
||||
service: {}
|
||||
etcd:
|
||||
extraArgs:
|
||||
listen-metrics-urls: http://0.0.0.0:2381
|
||||
advertisedSubnets:
|
||||
- 10.0.1.0/24
|
||||
coreDNS:
|
||||
disabled: false
|
||||
externalCloudProvider:
|
||||
enabled: true
|
Loading…
x
Reference in New Issue
Block a user