Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v14] Fix repeated installation for Azure and GCP VM auto-discovery #32569

Merged
merged 1 commit into from Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions api/types/constants.go
Expand Up @@ -592,23 +592,23 @@ const (
// SubscriptionIDLabel is used to identify virtual machines by Azure
// subscription ID found via automatic discovery, to avoid re-running
// installation commands on the node.
SubscriptionIDLabel = TeleportNamespace + "/subscription-id"
SubscriptionIDLabel = TeleportInternalLabelPrefix + "subscription-id"
// VMIDLabel is used to identify virtual machines by ID found
// via automatic discovery, to avoid re-running installation commands
// on the node.
VMIDLabel = TeleportNamespace + "/vm-id"
VMIDLabel = TeleportInternalLabelPrefix + "vm-id"
// ProjectIDLabel is used to identify virtual machines by GCP project
// id found via automatic discovery, to avoid re-running
// installation commands on the node.
ProjectIDLabel = TeleportNamespace + "/project-id"
ProjectIDLabel = TeleportInternalLabelPrefix + "project-id"
// ZoneLabek is used to identify virtual machines by GCP zone
// found via automatic discovery, to avoid re-running installation
// commands on the node.
ZoneLabel = TeleportNamespace + "/zone"
ZoneLabel = TeleportInternalLabelPrefix + "zone"
// NameLabel is used to identify virtual machines by GCP VM name
// found via automatic discovery, to avoid re-running installation
// commands on the node.
NameLabel = TeleportNamespace + "/name"
NameLabel = TeleportInternalLabelPrefix + "name"

// CloudLabel is used to identify the cloud where the resource was discovered.
CloudLabel = TeleportNamespace + "/cloud"
Expand Down
20 changes: 10 additions & 10 deletions lib/srv/discovery/discovery_test.go
Expand Up @@ -1657,8 +1657,8 @@ func TestAzureVMDiscovery(t *testing.T) {
Metadata: types.Metadata{
Name: "name",
Labels: map[string]string{
types.SubscriptionIDLabel: "testsub",
types.VMIDLabel: "test-vmid",
"teleport.internal/subscription-id": "testsub",
"teleport.internal/vm-id": "test-vmid",
},
Namespace: defaults.Namespace,
},
Expand Down Expand Up @@ -1689,8 +1689,8 @@ func TestAzureVMDiscovery(t *testing.T) {
Metadata: types.Metadata{
Name: "name",
Labels: map[string]string{
types.SubscriptionIDLabel: "testsub",
types.VMIDLabel: "alternate-vmid",
"teleport.internal/subscription-id": "testsub",
"teleport.internal/vm-id": "alternate-vmid",
},
Namespace: defaults.Namespace,
},
Expand Down Expand Up @@ -1878,9 +1878,9 @@ func TestGCPVMDiscovery(t *testing.T) {
Metadata: types.Metadata{
Name: "name",
Labels: map[string]string{
types.ProjectIDLabel: "myproject",
types.ZoneLabel: "myzone",
types.NameLabel: "myinstance",
"teleport.internal/project-id": "myproject",
"teleport.internal/zone": "myzone",
"teleport.internal/name": "myinstance",
},
Namespace: defaults.Namespace,
},
Expand All @@ -1905,9 +1905,9 @@ func TestGCPVMDiscovery(t *testing.T) {
Metadata: types.Metadata{
Name: "name",
Labels: map[string]string{
types.ProjectIDLabel: "myproject",
types.ZoneLabel: "myzone",
types.NameLabel: "myotherinstance",
"teleport.internal/project-id": "myproject",
"teleport.internal/zone": "myzone",
"teleport.internal/name": "myotherinstance",
},
Namespace: defaults.Namespace,
},
Expand Down
12 changes: 11 additions & 1 deletion lib/srv/server/azure_installer.go
Expand Up @@ -18,6 +18,7 @@ package server

import (
"context"
"crypto/rand"
"fmt"

"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v3"
Expand Down Expand Up @@ -72,5 +73,14 @@ func (ai *AzureInstaller) Run(ctx context.Context, req AzureRunRequest) error {
}

func getInstallerScript(installerName, publicProxyAddr string) string {
return fmt.Sprintf("curl -s -L https://%s/v1/webapi/scripts/installer/%v | bash -s $@", publicProxyAddr, installerName)
// Azure treats scripts with the same content as the same invocation and
// won't run them more than once. This is fine when the installer script
// succeeds, but it makes troubleshooting much harder when it fails. To
// work around this, we generate a random string and append it as a comment
// to the script, forcing Azure to see each invocation as unique.
nonce := make([]byte, 8)
// No big deal if rand.Read fails, the script is still valid.
_, _ = rand.Read(nonce)
return fmt.Sprintf("curl -s -L https://%s/v1/webapi/scripts/installer/%v | bash -s $@ #%x",
publicProxyAddr, installerName, nonce)
}