Skip to content

Commit 0c45468

Browse files
authored
Merge pull request #927 from cpanato/GH-909
🌱 AzureMachinePool/AzureManagedControlPlane: generate ssh key when is not set
2 parents 20517fd + f3e7a35 commit 0c45468

20 files changed

+695
-43
lines changed

api/v1alpha3/azuremachine_default.go

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,22 @@ limitations under the License.
1717
package v1alpha3
1818

1919
import (
20-
"crypto/rand"
21-
"crypto/rsa"
2220
"encoding/base64"
2321

24-
"github.com/pkg/errors"
2522
"golang.org/x/crypto/ssh"
23+
24+
utilSSH "sigs.k8s.io/cluster-api-provider-azure/util/ssh"
2625
)
2726

2827
// SetDefaultSSHPublicKey sets the default SSHPublicKey for an AzureMachine
2928
func (m *AzureMachine) SetDefaultSSHPublicKey() error {
3029
sshKeyData := m.Spec.SSHPublicKey
3130
if sshKeyData == "" {
32-
privateKey, perr := rsa.GenerateKey(rand.Reader, 2048)
33-
if perr != nil {
34-
return errors.Wrap(perr, "Failed to generate private key")
31+
_, publicRsaKey, err := utilSSH.GenerateSSHKey()
32+
if err != nil {
33+
return err
3534
}
3635

37-
publicRsaKey, perr := ssh.NewPublicKey(&privateKey.PublicKey)
38-
if perr != nil {
39-
return errors.Wrap(perr, "Failed to generate public key")
40-
}
4136
m.Spec.SSHPublicKey = base64.StdEncoding.EncodeToString(ssh.MarshalAuthorizedKey(publicRsaKey))
4237
}
4338

docs/book/src/topics/ephemeral-os.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ disk SKU limits. Instead they will always be capable of saturating the
77
VM level limits. This can significantly improve performance on the OS
88
disk. Ephemeral storage used for the OS will not persist between
99
maintenance events and VM redeployments. This is ideal for stateless
10-
base OS disks, where any stateful data is kept elsewhere.
10+
base OS disks, where any stateful data is kept elsewhere.
1111

1212
There are a few kinds of local storage devices available on Azure VMs.
1313
Each VM size will have a different combination. For example, some sizes
@@ -56,6 +56,6 @@ spec:
5656
managedDisk:
5757
storageAccountType: Standard_LRS
5858
osType: Linux
59-
sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64}
59+
sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64:=""}
6060
vmSize: ${AZURE_NODE_MACHINE_TYPE}
6161
````

docs/book/src/topics/managedcluster.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export AZURE_LOCATION="southcentralus"
3333
export AZURE_RESOURCE_GROUP="${CLUSTER_NAME}"
3434
# set AZURE_SUBSCRIPTION_ID to the GUID of your subscription
3535
# this example uses an sdk authentication file and parses the subscriptionId with jq
36-
# this file may be created using
36+
# this file may be created using
3737
#
3838
# `az ad sp create-for-rbac --sdk-auth [roles] > sp.json`
3939
#
@@ -92,7 +92,7 @@ spec:
9292
name: agentpool0
9393
location: southcentralus
9494
resourceGroup: foo-bar
95-
sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64}
95+
sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64:=""}
9696
subscriptionID: fae7cc14-bfba-4471-9435-f945b42a16dd # fake uuid
9797
version: v1.17.4
9898
networkPolicy: azure # or calico
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha3
18+
19+
import (
20+
"encoding/base64"
21+
22+
"golang.org/x/crypto/ssh"
23+
24+
utilSSH "sigs.k8s.io/cluster-api-provider-azure/util/ssh"
25+
)
26+
27+
// SetDefaultSSHPublicKey sets the default SSHPublicKey for an AzureMachinePool
28+
func (amp *AzureMachinePool) SetDefaultSSHPublicKey() error {
29+
sshKeyData := amp.Spec.Template.SSHPublicKey
30+
if sshKeyData == "" {
31+
_, publicRsaKey, err := utilSSH.GenerateSSHKey()
32+
if err != nil {
33+
return err
34+
}
35+
36+
amp.Spec.Template.SSHPublicKey = base64.StdEncoding.EncodeToString(ssh.MarshalAuthorizedKey(publicRsaKey))
37+
}
38+
39+
return nil
40+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha3
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/gomega"
23+
)
24+
25+
func TestAzureMachinePool_SetDefaultSSHPublicKey(t *testing.T) {
26+
g := NewWithT(t)
27+
28+
type test struct {
29+
amp *AzureMachinePool
30+
}
31+
32+
existingPublicKey := "testpublickey"
33+
publicKeyExistTest := test{amp: createMachinePoolWithSSHPublicKey(t, existingPublicKey)}
34+
publicKeyNotExistTest := test{amp: createMachinePoolWithSSHPublicKey(t, "")}
35+
36+
err := publicKeyExistTest.amp.SetDefaultSSHPublicKey()
37+
g.Expect(err).To(BeNil())
38+
g.Expect(publicKeyExistTest.amp.Spec.Template.SSHPublicKey).To(Equal(existingPublicKey))
39+
40+
err = publicKeyNotExistTest.amp.SetDefaultSSHPublicKey()
41+
g.Expect(err).To(BeNil())
42+
g.Expect(publicKeyNotExistTest.amp.Spec.Template.SSHPublicKey).NotTo(BeEmpty())
43+
}
44+
45+
func createMachinePoolWithSSHPublicKey(t *testing.T, sshPublicKey string) *AzureMachinePool {
46+
return hardcodedAzureMachinePoolWithSSHKey(sshPublicKey)
47+
}
48+
49+
func hardcodedAzureMachinePoolWithSSHKey(sshPublicKey string) *AzureMachinePool {
50+
return &AzureMachinePool{
51+
Spec: AzureMachinePoolSpec{
52+
Template: AzureMachineTemplate{
53+
SSHPublicKey: sshPublicKey,
54+
},
55+
},
56+
}
57+
}

exp/api/v1alpha3/azuremachinepool_webhook.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ var _ webhook.Defaulter = &AzureMachinePool{}
4545
// Default implements webhook.Defaulter so a webhook will be registered for the type
4646
func (amp *AzureMachinePool) Default() {
4747
azuremachinepoollog.Info("default", "name", amp.Name)
48+
49+
err := amp.SetDefaultSSHPublicKey()
50+
if err != nil {
51+
azuremachinepoollog.Error(err, "SetDefaultSshPublicKey failed")
52+
}
4853
}
4954

5055
// +kubebuilder:webhook:verbs=create;update,path=/validate-exp-cluster-x-k8s-io-x-k8s-io-v1alpha3-azuremachinepool,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=exp.cluster.x-k8s.io.x-k8s.io,resources=azuremachinepools,versions=v1alpha3,name=vazuremachinepool.kb.io,sideEffects=None
@@ -74,6 +79,7 @@ func (amp *AzureMachinePool) Validate() error {
7479
validators := []func() error{
7580
amp.ValidateImage,
7681
amp.ValidateTerminateNotificationTimeout,
82+
amp.ValidateSSHKey,
7783
}
7884

7985
var errs []error
@@ -100,6 +106,7 @@ func (amp *AzureMachinePool) ValidateImage() error {
100106
return agg
101107
}
102108
}
109+
103110
return nil
104111
}
105112

@@ -118,3 +125,17 @@ func (amp *AzureMachinePool) ValidateTerminateNotificationTimeout() error {
118125

119126
return nil
120127
}
128+
129+
// ValidateSSHKey validates an SSHKey
130+
func (amp *AzureMachinePool) ValidateSSHKey() error {
131+
if amp.Spec.Template.SSHPublicKey != "" {
132+
sshKey := amp.Spec.Template.SSHPublicKey
133+
if errs := infrav1.ValidateSSHKey(sshKey, field.NewPath("sshKey")); len(errs) > 0 {
134+
agg := kerrors.NewAggregate(errs.ToAggregate().Errors())
135+
azuremachinepoollog.Info("Invalid sshKey: %s", agg.Error())
136+
return agg
137+
}
138+
}
139+
140+
return nil
141+
}

0 commit comments

Comments
 (0)