github.com/Cloud-Foundations/Dominator@v0.3.4/lib/srpc/metadata.go (about) 1 package srpc 2 3 import ( 4 "crypto/tls" 5 "crypto/x509" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "io" 10 "net/http" 11 "sync" 12 "time" 13 14 "github.com/Cloud-Foundations/Dominator/lib/constants" 15 "github.com/Cloud-Foundations/Dominator/lib/format" 16 "github.com/Cloud-Foundations/Dominator/lib/stringutil" 17 proto "github.com/Cloud-Foundations/Dominator/proto/hypervisor" 18 ) 19 20 var ( 21 smallStackOwnersLock sync.Mutex 22 _smallStackOwners *smallStackOwnersType 23 startedReadingSmallStack sync.Once 24 ) 25 26 type smallStackOwnersType struct { 27 groups []string 28 users map[string]struct{} 29 } 30 31 func checkSmallStack() bool { 32 resp, err := http.Get(constants.MetadataUrl + 33 constants.SmallStackDataSource) 34 if err != nil { 35 return false 36 } 37 if resp.StatusCode != http.StatusOK { 38 return false 39 } 40 defer resp.Body.Close() 41 buffer := make([]byte, 10) 42 if length, _ := resp.Body.Read(buffer); length >= 4 { 43 if string(buffer[:4]) == "true" { 44 return true 45 } 46 } 47 return false 48 } 49 50 func getSmallStackOwners() *smallStackOwnersType { 51 smallStackOwnersLock.Lock() 52 defer smallStackOwnersLock.Unlock() 53 return _smallStackOwners 54 } 55 56 func loadCertificatesFromMetadata(timeout time.Duration, errorIfMissing bool, 57 errorIfExpired bool) ( 58 *tls.Certificate, error) { 59 certPEM, err := readMetadataFile(constants.MetadataIdentityCert, timeout) 60 if err != nil { 61 if errorIfMissing { 62 return nil, err 63 } 64 return nil, nil 65 } 66 keyPEM, err := readMetadataFile(constants.MetadataIdentityKey, timeout) 67 if err != nil { 68 if errorIfMissing { 69 return nil, err 70 } 71 return nil, nil 72 } 73 tlsCert, err := tls.X509KeyPair(certPEM, keyPEM) 74 if err != nil { 75 return nil, err 76 } 77 x509Cert, err := x509.ParseCertificate(tlsCert.Certificate[0]) 78 if err != nil { 79 return nil, err 80 } 81 if errorIfExpired { 82 now := time.Now() 83 if notYet := x509Cert.NotBefore.Sub(now); notYet > 0 { 84 return nil, fmt.Errorf("cert will not be valid for %s", 85 format.Duration(notYet)) 86 } 87 if expired := now.Sub(x509Cert.NotAfter); expired > 0 { 88 return nil, fmt.Errorf("cert expired %s ago", 89 format.Duration(expired)) 90 } 91 } 92 tlsCert.Leaf = x509Cert 93 return &tlsCert, nil 94 } 95 96 func readMetadataFile(filename string, timeout time.Duration) ([]byte, error) { 97 client := http.Client{Timeout: timeout} 98 resp, err := client.Get(constants.MetadataUrl + filename) 99 if err != nil { 100 return nil, err 101 } 102 if resp.StatusCode != http.StatusOK { 103 return nil, errors.New(resp.Status) 104 } 105 defer resp.Body.Close() 106 data, err := io.ReadAll(resp.Body) 107 if err != nil { 108 return nil, err 109 } 110 return data, nil 111 } 112 113 func readSmallStackMetaData() { 114 var vmInfo proto.VmInfo 115 resp, err := http.Get(constants.MetadataUrl + constants.MetadataIdentityDoc) 116 if err != nil { 117 return 118 } 119 if resp.StatusCode != http.StatusOK { 120 return 121 } 122 defer resp.Body.Close() 123 decoder := json.NewDecoder(resp.Body) 124 if err := decoder.Decode(&vmInfo); err != nil { 125 return 126 } 127 smallStackOwners := &smallStackOwnersType{ 128 groups: vmInfo.OwnerGroups, 129 users: stringutil.ConvertListToMap(vmInfo.OwnerUsers, false), 130 } 131 logger.Debugf(1, "VM OwnerUsers: %v, OwnerGroups: %v\n", 132 vmInfo.OwnerUsers, vmInfo.OwnerGroups) 133 smallStackOwnersLock.Lock() 134 defer smallStackOwnersLock.Unlock() 135 _smallStackOwners = smallStackOwners 136 } 137 138 func readSmallStackMetaDataLoop() { 139 if !checkSmallStack() { 140 return 141 } 142 logger.Debugln(0, 143 "Running on SmallStack: will grant method access to VM owners") 144 for ; true; time.Sleep(10 * time.Second) { 145 readSmallStackMetaData() 146 } 147 } 148 149 func startReadingSmallStackMetaData() { 150 if !*srpcTrustVmOwners { 151 return 152 } 153 startedReadingSmallStack.Do(func() { go readSmallStackMetaDataLoop() }) 154 }