Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating validity check for default credentials. Closes Issue #37 #46

Merged
merged 1 commit into from
Apr 5, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 32 additions & 29 deletions cmd/eiam/internal/appconfig/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package appconfig

import (
"context"
"encoding/json"
"fmt"
"os"
"os/exec"
"path"
"strings"

credentials "cloud.google.com/go/iam/credentials/apiv1"
"github.com/manifoldco/promptui"
"github.com/spf13/viper"
"google.golang.org/api/oauth2/v1"

util "github.com/jessesomerville/ephemeral-iam/cmd/eiam/internal/eiamutil"
"github.com/jessesomerville/ephemeral-iam/cmd/eiam/internal/gcpclient"
Expand All @@ -38,7 +37,10 @@ func init() {
if !util.Contains(allConfigKeys, "binarypaths.gcloud") && !util.Contains(allConfigKeys, "binarypaths.kubectl") {
util.CheckError(checkDependencies())
}
checkADCExists()

if err := checkValidADCExists(); err != nil {
util.Logger.WithError(err).Fatal("setup error")
}

if err := createLogDir(); err != nil {
util.Logger.WithError(err).Fatal("setup error")
Expand Down Expand Up @@ -76,9 +78,11 @@ func CheckCommandExists(command string) (string, error) {
return path, nil
}

func checkADCExists() {
// checkValidADCExists checks that application default credentials exist, that
// they are valid, and that they are for the correct user
func checkValidADCExists() error {
ctx := context.Background()
_, err := credentials.NewIamCredentialsClient(ctx)
oauth2Service, err := oauth2.NewService(ctx)
if err != nil {
if strings.Contains(err.Error(), "could not find default credentials") {
util.Logger.Warn("No Application Default Credentials were found, attempting to generate them\n")
Expand All @@ -88,50 +92,47 @@ func checkADCExists() {
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
if err := cmd.Run(); err != nil {
util.Logger.WithError(err).Error("unable to create application default credentials")
return fmt.Errorf("unable to create application default credentials: %v", err)
}
fmt.Println()
util.Logger.Info("Application default credentials were successfully created")
} else {
fmt.Println()
util.Logger.Fatalf("failed to check if application default credentials exist: %v", err)
return fmt.Errorf("failed to check if application default credentials exist: %v", err)
}
} else if adcPath := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"); adcPath != "" {
util.Logger.Warnf("The GOOGLE_APPLICATION_CREDENTIALS environment variable is set:\n\tADC Path: %s\n\n", adcPath)
if err := checkADCIdentity(adcPath); err != nil {
util.Logger.Fatal(err)
} else {
util.Logger.Debug("Checking validity of application default credentials")
tokenInfo, err := oauth2Service.Tokeninfo().Do()
if err != nil {
return fmt.Errorf("failed to parse OAuth2 Token: %v", err)
}

return checkADCIdentity(tokenInfo.Email)
}
return nil
}

func checkADCIdentity(path string) error {
data, err := os.ReadFile(path)
func checkADCIdentity(tokenEmail string) error {
account, err := gcpclient.CheckActiveAccountSet()
if err != nil {
return fmt.Errorf("failed to read ADC file %s: %v", path, err)
return err
}

var adcMap map[string]interface{}
if err := json.Unmarshal(data, &adcMap); err != nil {
return fmt.Errorf("failed to unmarshal ADC file %s: %v", path, err)
}

if email, ok := adcMap["client_email"]; ok {
account, err := gcpclient.CheckActiveAccountSet()
if err != nil {
return fmt.Errorf("failed to get account from gcloud config: %v", err)
}
util.Logger.Warnf("API calls made by eiam will not be authenticated as your default account:\n\tAccount Set: %s\n\tDefault Account: %s\n\n", email, account)
util.Logger.Debugf("OAuth 2.0 Token Email: %s", tokenEmail)
if account != tokenEmail {
util.Logger.Warnf("API calls made by eiam will not be authenticated as your default account:\n\tAccount Set: %s\n\tDefault Account: %s\n\n", tokenEmail, account)

prompt := promptui.Prompt{
Label: fmt.Sprintf("Authenticate as %s", email),
Label: fmt.Sprintf("Authenticate as %s", tokenEmail),
IsConfirm: true,
}

if _, err := prompt.Run(); err != nil {
fmt.Print("\n\n")
util.Logger.Info("Attempting to reconfigure eiam's authenticated account")
os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", "")
checkADCExists()
if err := checkValidADCExists(); err != nil {
util.Logger.Fatal(err)
}
util.Logger.Infof("Success. You should now be authenticated as %s", account)
}
}
Expand Down Expand Up @@ -165,7 +166,9 @@ func createTempKubeConfigDir() error {
return fmt.Errorf("failed to find temp kubeconfig dir %s: %v", kubeConfigDir, err)
}
// Clear any leftover kubeconfigs from improper shutdowns
os.RemoveAll(kubeConfigDir)
if err := os.RemoveAll(kubeConfigDir); err != nil {
return fmt.Errorf("failed to clear old kubeconfigs: %v", err)
}
if err := os.MkdirAll(kubeConfigDir, 0o755); err != nil {
return fmt.Errorf("failed to recreate temp kubeconfig directory: %v", err)
}
Expand Down