Blame SOURCES/internal-providers-aws-probe-the-IMDS-token-URL.patch

d8c0d7
From 74ffe3749d70b9d115a9b9790969b8dcb4a76e12 Mon Sep 17 00:00:00 2001
d8c0d7
From: Stephen Lowrie <stephen.lowrie@gmail.com>
d8c0d7
Date: Mon, 11 Jan 2021 11:27:12 -0600
d8c0d7
Subject: [PATCH] internal/providers/aws: probe the IMDS token URL
d8c0d7
d8c0d7
Probing the `/latest` path causes a 401 Unauthorized when running with
d8c0d7
IMDSv2 only. Instead ping the token URL.
d8c0d7
---
d8c0d7
 internal/providers/aws/aws.go | 37 +++++++++++++++++++----------------
d8c0d7
 1 file changed, 20 insertions(+), 17 deletions(-)
d8c0d7
d8c0d7
diff --git a/internal/providers/aws/aws.go b/internal/providers/aws/aws.go
d8c0d7
index 54373dbb..4a6655f0 100644
d8c0d7
--- a/internal/providers/aws/aws.go
d8c0d7
+++ b/internal/providers/aws/aws.go
d8c0d7
@@ -40,11 +40,6 @@ var (
d8c0d7
 		Host:   "169.254.169.254",
d8c0d7
 		Path:   "2019-10-01/user-data",
d8c0d7
 	}
d8c0d7
-	metadataServiceProbeURL = url.URL{
d8c0d7
-		Scheme: "http",
d8c0d7
-		Host:   "169.254.169.254",
d8c0d7
-		Path:   "latest",
d8c0d7
-	}
d8c0d7
 	imdsTokenURL = url.URL{
d8c0d7
 		Scheme: "http",
d8c0d7
 		Host:   "169.254.169.254",
d8c0d7
@@ -78,17 +73,17 @@ func NewFetcher(l *log.Logger) (resource.Fetcher, error) {
d8c0d7
 // Init prepares the fetcher for this platform
d8c0d7
 func Init(f *resource.Fetcher) error {
d8c0d7
 	// During the fetch stage we might be running before the networking
d8c0d7
-	// is fully ready. Perform an HTTP fetch against the metadata probe
d8c0d7
-	// URL to ensure that networking is up before we attempt to fetch
d8c0d7
-	// the region hint from ec2metadata.
d8c0d7
+	// is fully ready. Perform an HTTP fetch against the IMDS token URL
d8c0d7
+	// to ensure that networking is up before we attempt to fetch the
d8c0d7
+	// region hint from ec2metadata.
d8c0d7
 	//
d8c0d7
-	// NOTE: the FetchToBuffer call against the metadata service probe
d8c0d7
-	// URL is a temporary solution to handle waiting for networking
d8c0d7
-	// before fetching from the AWS API. We do this instead of an
d8c0d7
-	// infinite retry loop on the API call because, without a clear
d8c0d7
-	// understanding of the failure cases, that would risk provisioning
d8c0d7
-	// failures due to quirks of the ec2metadata API.  Additionally a
d8c0d7
-	// finite retry loop would have to time out quickly enough to avoid
d8c0d7
+	// NOTE: the FetchToBuffer call against the IMDS token URL is a
d8c0d7
+	// temporary solution to handle waiting for networking before
d8c0d7
+	// fetching from the AWS API. We do this instead of an infinite
d8c0d7
+	// retry loop on the API call because, without a clear understanding
d8c0d7
+	// of the failure cases, that would risk provisioning failures due
d8c0d7
+	// to quirks of the ec2metadata API.  Additionally a finite retry
d8c0d7
+	// loop would have to time out quickly enough to avoid
d8c0d7
 	// extraordinarily long boots on failure (since this code runs in
d8c0d7
 	// every stage) but that would risk premature timeouts if the
d8c0d7
 	// network takes a while to come up.
d8c0d7
@@ -102,8 +97,16 @@ func Init(f *resource.Fetcher) error {
d8c0d7
 	// NOTE: FetchToBuffer is handling the ErrNeedNet case.  If we move
d8c0d7
 	// to an alternative method, we will need to handle the detection in
d8c0d7
 	// this function.
d8c0d7
-	_, err := f.FetchToBuffer(metadataServiceProbeURL, resource.FetchOptions{})
d8c0d7
-	if err != nil {
d8c0d7
+	opts := resource.FetchOptions{
d8c0d7
+		Headers: http.Header{
d8c0d7
+			"x-aws-ec2-metadata-token-ttl-seconds": []string{"21600"},
d8c0d7
+		},
d8c0d7
+		HTTPVerb: "PUT",
d8c0d7
+	}
d8c0d7
+	_, err := f.FetchToBuffer(imdsTokenURL, opts)
d8c0d7
+	// ErrNotFound would just mean that the instance might not have
d8c0d7
+	// IMDSv2 enabled
d8c0d7
+	if err != nil && err != resource.ErrNotFound {
d8c0d7
 		return err
d8c0d7
 	}
d8c0d7
 
d8c0d7
-- 
d8c0d7
2.29.2