|
- /*
- *
- * 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 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
- }
|