| /* |
| * |
| * Copyright 2018 gRPC authors. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package alts |
| |
| import ( |
| "context" |
| "errors" |
| "fmt" |
| "io" |
| "io/ioutil" |
| "log" |
| "os" |
| "os/exec" |
| "regexp" |
| "runtime" |
| "strings" |
| |
| "google.golang.org/grpc/peer" |
| ) |
| |
| const ( |
| linuxProductNameFile = "/sys/class/dmi/id/product_name" |
| windowsCheckCommand = "powershell.exe" |
| windowsCheckCommandArgs = "Get-WmiObject -Class Win32_BIOS" |
| powershellOutputFilter = "Manufacturer" |
| windowsManufacturerRegex = ":(.*)" |
| ) |
| |
| type platformError string |
| |
| func (k platformError) Error() string { |
| return fmt.Sprintf("%s is not supported", string(k)) |
| } |
| |
| var ( |
| // The following two variables will be reassigned in tests. |
| runningOS = runtime.GOOS |
| manufacturerReader = func() (io.Reader, error) { |
| switch runningOS { |
| case "linux": |
| return os.Open(linuxProductNameFile) |
| case "windows": |
| cmd := exec.Command(windowsCheckCommand, windowsCheckCommandArgs) |
| out, err := cmd.Output() |
| if err != nil { |
| return nil, err |
| } |
| |
| for _, line := range strings.Split(strings.TrimSuffix(string(out), "\n"), "\n") { |
| if strings.HasPrefix(line, powershellOutputFilter) { |
| re := regexp.MustCompile(windowsManufacturerRegex) |
| name := re.FindString(line) |
| name = strings.TrimLeft(name, ":") |
| return strings.NewReader(name), nil |
| } |
| } |
| |
| return nil, errors.New("cannot determine the machine's manufacturer") |
| default: |
| return nil, platformError(runningOS) |
| } |
| } |
| vmOnGCP bool |
| ) |
| |
| // isRunningOnGCP checks whether the local system, without doing a network request is |
| // running on GCP. |
| func isRunningOnGCP() bool { |
| manufacturer, err := readManufacturer() |
| if os.IsNotExist(err) { |
| return false |
| } |
| if err != nil { |
| log.Fatalf("failure to read manufacturer information: %v", err) |
| } |
| name := string(manufacturer) |
| switch runningOS { |
| case "linux": |
| name = strings.TrimSpace(name) |
| return name == "Google" || name == "Google Compute Engine" |
| case "windows": |
| name = strings.Replace(name, " ", "", -1) |
| name = strings.Replace(name, "\n", "", -1) |
| name = strings.Replace(name, "\r", "", -1) |
| return name == "Google" |
| default: |
| log.Fatal(platformError(runningOS)) |
| } |
| return false |
| } |
| |
| func readManufacturer() ([]byte, error) { |
| reader, err := manufacturerReader() |
| if err != nil { |
| return nil, err |
| } |
| if reader == nil { |
| return nil, errors.New("got nil reader") |
| } |
| manufacturer, err := ioutil.ReadAll(reader) |
| if err != nil { |
| return nil, fmt.Errorf("failed reading %v: %v", linuxProductNameFile, err) |
| } |
| return manufacturer, nil |
| } |
| |
| // AuthInfoFromContext extracts the alts.AuthInfo object from the given context, |
| // if it exists. This API should be used by gRPC server RPC handlers to get |
| // information about the communicating peer. For client-side, use grpc.Peer() |
| // CallOption. |
| func AuthInfoFromContext(ctx context.Context) (AuthInfo, error) { |
| p, ok := peer.FromContext(ctx) |
| if !ok { |
| return nil, errors.New("no Peer found in Context") |
| } |
| return AuthInfoFromPeer(p) |
| } |
| |
| // AuthInfoFromPeer extracts the alts.AuthInfo object from the given peer, if it |
| // exists. This API should be used by gRPC clients after obtaining a peer object |
| // using the grpc.Peer() CallOption. |
| func AuthInfoFromPeer(p *peer.Peer) (AuthInfo, error) { |
| altsAuthInfo, ok := p.AuthInfo.(AuthInfo) |
| if !ok { |
| return nil, errors.New("no alts.AuthInfo found in Peer") |
| } |
| return altsAuthInfo, nil |
| } |