Skip to content

Commit 91a6b7c

Browse files
authored
[release/v1.45] improve kubeconfig/gcp handling of credentials in e2e tests (#1404) (#1409)
1 parent a456953 commit 91a6b7c

File tree

8 files changed

+47
-18
lines changed

8 files changed

+47
-18
lines changed

docs/cloud-provider.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ tags:
147147
### machine.spec.providerConfig.cloudProviderSpec
148148
149149
```yaml
150-
serviceAccount: "<< GOOGLE_SERVICE_ACCOUNT >>"
150+
# The service account needs to be base64-encoded.
151+
serviceAccount: "<< GOOGLE_SERVICE_ACCOUNT_BASE64 >>"
151152
# See https://cloud.google.com/compute/docs/regions-zones/
152153
zone: "europe-west3-a"
153154
# See https://cloud.google.com/compute/docs/machine-types
@@ -295,8 +296,8 @@ tags:
295296
296297
### machine.spec.providerConfig.cloudProviderSpec
297298
```yaml
298-
# kubeconfig to access KubeVirt cluster
299-
kubeconfig: '<< KUBECONFIG >>'
299+
# base64-encoded kubeconfig to access KubeVirt cluster
300+
kubeconfig: '<< KUBECONFIG_BASE64 >>'
300301
# KubeVirt namespace
301302
namespace: kube-system
302303
# kubernetes storage class

examples/gce-machinedeployment.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ metadata:
66
name: machine-controller-gce
77
namespace: kube-system
88
type: Opaque
9-
stringData:
10-
serviceAccount: "<< GOOGLE_SERVICE_ACCOUNT >>"
9+
data:
10+
# The base64 encoding here is only to satisfy Kubernetes'
11+
# Secret storage and to prevent multiline string replacement
12+
# issues if we used stringData here (because the GCP SA is
13+
# a multiline JSON string).
14+
serviceAccount: "<< GOOGLE_SERVICE_ACCOUNT_BASE64 >>"
15+
1116
---
1217
apiVersion: "cluster.k8s.io/v1alpha1"
1318
kind: MachineDeployment

examples/kubevirt-machinedeployment.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ spec:
3232
cpus: "1"
3333
memory: "2048M"
3434
kubeconfig:
35-
value: '<< KUBECONFIG >>'
35+
# Can also be set via the env var 'KUBEVIRT_KUBECONFIG' on the machine-controller.
36+
# If instead specified directly, this value should be a base64 encoded kubeconfig.
37+
value: "<< KUBECONFIG_BASE64 >>"
3638
namespace: kube-system
3739
# Can also be `centos`, must align with he configured registryImage above
3840
operatingSystem: "ubuntu"

pkg/cloudprovider/provider/gce/config.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -198,19 +198,25 @@ func newConfig(resolver *providerconfig.ConfigVarResolver, spec v1alpha1.Provide
198198
// postprocessServiceAccount processes the service account and creates a JWT configuration
199199
// out of it.
200200
func (cfg *config) postprocessServiceAccount() error {
201-
sa, err := base64.StdEncoding.DecodeString(cfg.serviceAccount)
202-
if err != nil {
203-
return fmt.Errorf("failed to decode base64 service account: %v", err)
201+
sa := cfg.serviceAccount
202+
203+
// safely decode the service account, in case we did not read the value
204+
// from a "known-safe" location (like the MachineDeployment), but from
205+
// an environment variable.
206+
decoded, err := base64.StdEncoding.DecodeString(cfg.serviceAccount)
207+
if err == nil {
208+
sa = string(decoded)
204209
}
210+
205211
sam := map[string]string{}
206-
err = json.Unmarshal(sa, &sam)
212+
err = json.Unmarshal([]byte(sa), &sam)
207213
if err != nil {
208-
return fmt.Errorf("failed unmarshalling service account: %v", err)
214+
return fmt.Errorf("failed unmarshalling service account: %w", err)
209215
}
210216
cfg.projectID = sam["project_id"]
211-
cfg.jwtConfig, err = google.JWTConfigFromJSON(sa, compute.ComputeScope)
217+
cfg.jwtConfig, err = google.JWTConfigFromJSON([]byte(sa), compute.ComputeScope)
212218
if err != nil {
213-
return fmt.Errorf("failed preparing JWT: %v", err)
219+
return fmt.Errorf("failed preparing JWT: %w", err)
214220
}
215221
return nil
216222
}

pkg/cloudprovider/provider/gce/types/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
// CloudProviderSpec contains the specification of the cloud provider taken
3131
// from the provider configuration.
3232
type CloudProviderSpec struct {
33+
// ServiceAccount must be base64-encoded.
3334
ServiceAccount providerconfigtypes.ConfigVarString `json:"serviceAccount,omitempty"`
3435
Zone providerconfigtypes.ConfigVarString `json:"zone"`
3536
MachineType providerconfigtypes.ConfigVarString `json:"machineType"`

test/e2e/provisioning/all_e2e_test.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package provisioning
2020

2121
import (
2222
"context"
23+
"encoding/base64"
2324
"flag"
2425
"fmt"
2526
"os"
@@ -290,12 +291,23 @@ func TestKubevirtProvisioningE2E(t *testing.T) {
290291
selector := OsSelector("ubuntu", "centos", "flatcar")
291292

292293
params := []string{
293-
fmt.Sprintf("<< KUBECONFIG >>=%s", kubevirtKubeconfig),
294+
fmt.Sprintf("<< KUBECONFIG_BASE64 >>=%s", safeBase64Encoding(kubevirtKubeconfig)),
294295
}
295296

296297
runScenarios(t, selector, params, kubevirtManifest, fmt.Sprintf("kubevirt-%s", *testRunIdentifier))
297298
}
298299

300+
// safeBase64Encoding takes a value and encodes it with base64
301+
// if it is not already encoded.
302+
func safeBase64Encoding(value string) string {
303+
// If there was no error, the original value was already encoded.
304+
if _, err := base64.StdEncoding.DecodeString(value); err == nil {
305+
return value
306+
}
307+
308+
return base64.StdEncoding.EncodeToString([]byte(value))
309+
}
310+
299311
func TestOpenstackProvisioningE2E(t *testing.T) {
300312
t.Parallel()
301313

@@ -690,8 +702,9 @@ func TestGCEProvisioningE2E(t *testing.T) {
690702
// Act. GCE does not support CentOS.
691703
selector := OsSelector("ubuntu")
692704
params := []string{
693-
fmt.Sprintf("<< GOOGLE_SERVICE_ACCOUNT >>=%s", googleServiceAccount),
705+
fmt.Sprintf("<< GOOGLE_SERVICE_ACCOUNT_BASE64 >>=%s", safeBase64Encoding(googleServiceAccount)),
694706
}
707+
695708
runScenarios(t, selector, params, GCEManifest, fmt.Sprintf("gce-%s", *testRunIdentifier))
696709
}
697710

test/e2e/provisioning/testdata/machinedeployment-gce.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ spec:
2424
- "<< YOUR_PUBLIC_KEY >>"
2525
cloudProvider: "gce"
2626
cloudProviderSpec:
27-
# If empty, can be set via GOOGLE_SERVICE_ACCOUNT env var
28-
serviceAccount: "<< GOOGLE_SERVICE_ACCOUNT >>"
27+
# If empty, can be set via GOOGLE_SERVICE_ACCOUNT env var. The environment variable
28+
# should be plaintext. The value in the cloudProviderSpec however must be base64-encoded.
29+
serviceAccount: "<< GOOGLE_SERVICE_ACCOUNT_BASE64 >>"
2930
# See https://cloud.google.com/compute/docs/regions-zones/
3031
zone: "europe-west3-a"
3132
# See https://cloud.google.com/compute/docs/machine-types

test/e2e/provisioning/testdata/machinedeployment-kubevirt.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ spec:
3636
nameservers:
3737
- 8.8.8.8
3838
kubeconfig:
39-
value: '<< KUBECONFIG >>'
39+
value: '<< KUBECONFIG_BASE64 >>'
4040
namespace: kube-system
4141
operatingSystem: "<< OS_NAME >>"
4242
operatingSystemSpec:

0 commit comments

Comments
 (0)