// Copyright 2022 Google LLC. // 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 // // https://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 util provides helper functions for the client. package util import ( "encoding/json" "errors" "io" "os" "os/user" "path/filepath" "runtime" "strings" ) const configFileName = "certificate_config.json" // EnterpriseCertificateConfig contains parameters for initializing signer. type EnterpriseCertificateConfig struct { Libs Libs `json:"libs"` } // Libs specifies the locations of helper libraries. type Libs struct { ECP string `json:"ecp"` } // ErrConfigUnavailable is a sentinel error that indicates ECP config is unavailable, // possibly due to entire config missing or missing binary path. var ErrConfigUnavailable = errors.New("Config is unavailable") // LoadSignerBinaryPath retrieves the path of the signer binary from the config file. func LoadSignerBinaryPath(configFilePath string) (path string, err error) { jsonFile, err := os.Open(configFilePath) if err != nil { if errors.Is(err, os.ErrNotExist) { return "", ErrConfigUnavailable } return "", err } byteValue, err := io.ReadAll(jsonFile) if err != nil { return "", err } var config EnterpriseCertificateConfig err = json.Unmarshal(byteValue, &config) if err != nil { return "", err } signerBinaryPath := config.Libs.ECP if signerBinaryPath == "" { return "", ErrConfigUnavailable } signerBinaryPath = strings.ReplaceAll(signerBinaryPath, "~", guessHomeDir()) signerBinaryPath = strings.ReplaceAll(signerBinaryPath, "$HOME", guessHomeDir()) return signerBinaryPath, nil } func guessHomeDir() string { // Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470 if v := os.Getenv("HOME"); v != "" { return v } // Else, fall back to user.Current: if u, err := user.Current(); err == nil { return u.HomeDir } return "" } func getDefaultConfigFileDirectory() (directory string) { if runtime.GOOS == "windows" { return filepath.Join(os.Getenv("APPDATA"), "gcloud") } return filepath.Join(guessHomeDir(), ".config/gcloud") } // GetDefaultConfigFilePath returns the default path of the enterprise certificate config file created by gCloud. func GetDefaultConfigFilePath() (path string) { return filepath.Join(getDefaultConfigFileDirectory(), configFileName) } // GetConfigFilePathFromEnv returns the path associated with environment variable GOOGLE_API_CERTIFICATE_CONFIG func GetConfigFilePathFromEnv() (path string) { return os.Getenv("GOOGLE_API_CERTIFICATE_CONFIG") }