-
Notifications
You must be signed in to change notification settings - Fork 1
/
imds.go
122 lines (103 loc) · 3.2 KB
/
imds.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package imds
import (
"context"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
"github.com/Azure/go-autorest/autorest/adal"
"sigs.k8s.io/controller-runtime/pkg/log"
)
const (
timeout = 80 * time.Second
)
// Check performs sanity check on Azure client
func Check(ctx context.Context, clientID string) {
log := log.FromContext(ctx)
resourceEndpoint := os.Getenv("AZURE_RESOURCE_ENDPOINT")
if resourceEndpoint == "" {
resourceEndpoint = "https://management.azure.com/"
}
str, err := CurlIMDSMetadataInstanceEndpoint()
if err != nil {
log.Info("CurlIMDSMetadataInstanceEndpoint", "error", err)
} else {
log.Info("CurlIMDSMetadataInstanceEndpoint", "str", str)
}
t1, err := GetTokenFromIMDS(resourceEndpoint)
if err != nil {
log.Info("GetTokenFromIMDS", "error", err)
}
t2, err := GetTokenFromIMDSWithUserAssignedID(resourceEndpoint, clientID)
if err != nil {
log.Info("GetTokenFromIMDSWithUserAssignedID", "error", err)
}
if t1 == nil || t2 == nil || !strings.EqualFold(t1.AccessToken, t2.AccessToken) {
log.Info("Tokens acquired from IMDS with and without identity client ID do not match")
}
if t1 != nil {
log.Info("Try decoding your token %s at https://jwt.io", t1.AccessToken)
}
}
// CurlIMDSMetadataInstanceEndpoint performs get request to
// IMDS metadata instance endpoint and returns the result
func CurlIMDSMetadataInstanceEndpoint() (string, error) {
client := &http.Client{
Timeout: timeout,
}
req, err := http.NewRequest("GET", "http://169.254.169.254/metadata/instance?api-version=2017-08-01", nil)
if err != nil {
return "", err
}
req.Header.Add("Metadata", "true")
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
//klog.Infof(`curl -H Metadata:true "http://169.254.169.254/metadata/instance?api-version=2017-08-01": %s`, body)
}
// GetTokenFromIMDS get service principal token for the resource
func GetTokenFromIMDS(resourceName string) (*adal.Token, error) {
managedIdentityOpts := &adal.ManagedIdentityOptions{}
spt, err := adal.NewServicePrincipalTokenFromManagedIdentity(resourceName, managedIdentityOpts)
if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
if err := spt.RefreshWithContext(ctx); err != nil {
return nil, err
}
token := spt.Token()
if token.IsZero() {
return nil, fmt.Errorf("%+v is a zero token", token)
}
return &token, nil
}
// GetTokenFromIMDSWithUserAssignedID receives resource and identity client ID
// and returns the service principal token
func GetTokenFromIMDSWithUserAssignedID(resourceName string, identityClientID string) (*adal.Token, error) {
managedIdentityOpts := &adal.ManagedIdentityOptions{ClientID: identityClientID}
spt, err := adal.NewServicePrincipalTokenFromManagedIdentity(resourceName, managedIdentityOpts)
if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
if err := spt.RefreshWithContext(ctx); err != nil {
return nil, err
}
token := spt.Token()
if token.IsZero() {
return nil, fmt.Errorf("%+v is a zero token", token)
}
return &token, nil
}