Skip to content
This repository has been archived by the owner on May 6, 2022. It is now read-only.

Commit

Permalink
remove viper
Browse files Browse the repository at this point in the history
  • Loading branch information
srinandan committed Jan 8, 2020
1 parent 2127370 commit 9842dfb
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 23 deletions.
32 changes: 32 additions & 0 deletions apiclient/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

package apiclient

import (
"os"
)

//BaseURL is the Apigee control plane endpoint
const BaseURL = "https://apigee.googleapis.com/v1/organizations/"

Expand All @@ -31,90 +35,118 @@ type ApigeeClientOptions struct {

var options = ApigeeClientOptions{SkipCache: false, SkipCheck: true, SkipLogInfo: true}

//NewApigeeClient sets up options to invoke Apigee APIs
func NewApigeeClient(o ApigeeClientOptions) {
options = o
}

//SetApigeeOrg sets the org variable
func SetApigeeOrg(org string) {
options.Org = org
}

//GetApigeeOrg gets the org variable
func GetApigeeOrg() string {
return options.Org
}

//GetApigeeOrgP gets the pointer to org variable
func GetApigeeOrgP() *string {
return &options.Org
}

//SetApigeeEnv set the env variable
func SetApigeeEnv(env string) {
options.Env = env
}

//GetApigeeEnv gets the env variable
func GetApigeeEnv() string {
return options.Env
}

//GetApigeeEnvP gets the pointer to env variable
func GetApigeeEnvP() *string {
return &options.Env
}

//SetApigeeToken sets the access token for use with Apigee API calls
func SetApigeeToken(token string) {
options.Token = token
}

//GetApigeeToken get the access token value in client opts (does not generate it)
func GetApigeeToken() string {
return options.Token
}

//GetApigeeToken get the access token pointer
func GetApigeeTokenP() *string {
return &options.Token
}

//SetProjectID sets the project id
func SetProjectID(projectID string) {
options.ProjectID = projectID
}

//GetProjectID gets the project id
func GetProjectID() string {
return options.ProjectID
}

//GetProjectID gets the project id pointer
func GetProjectIDP() *string {
return &options.ProjectID
}

//SetServiceAccount
func SetServiceAccount(serviceAccount string) {
options.ServiceAccount = serviceAccount
}

//GetServiceAccount
func GetServiceAccount() string {
if options.ServiceAccount == "" {
envVar := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")
if envVar != "" {
options.ServiceAccount = envVar
}
}
return options.ServiceAccount
}

//GetServiceAccountP
func GetServiceAccountP() *string {
return &options.ServiceAccount
}

//IsSkipCheck
func IsSkipCheck() bool {
return options.SkipCheck
}

//SkipCheck
func SkipCheck() *bool {
return &options.SkipCheck
}

//IsSkipCache
func IsSkipCache() bool {
return options.SkipCache
}

//SkipCache
func SkipCache() *bool {
return &options.SkipCache
}

//IsSkipLogInfo
func IsSkipLogInfo() bool {
return options.SkipLogInfo
}

//SkipLogInfo
func SkipLogInfo() *bool {
return &options.SkipLogInfo
}
64 changes: 49 additions & 15 deletions apiclient/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,35 @@ import (
"net/url"
"os/user"
"path"
"reflect"
"strconv"
"strings"
"time"

"github.com/lestrrat/go-jwx/jwa"
"github.com/lestrrat/go-jwx/jwt"
"github.com/spf13/viper"
"github.com/srinandan/apigeecli/clilog"
)

const accessTokenFile = ".access_token"

func getPrivateKey() (interface{}, error) {
pemPrivateKey := fmt.Sprintf("%v", viper.Get("private_key"))
type serviceAccount struct {
Type string `json:"type,omitempty"`
ProjectID string `json:"project_id,omitempty"`
PrivateKeyID string `json:"private_key_id,omitempty"`
PrivateKey string `json:"private_key,omitempty"`
ClientEmail string `json:"client_email,omitempty"`
ClientID string `json:"client_id,omitempty"`
AuthURI string `json:"auth_uri,omitempty"`
TokenURI string `json:"token_uri,omitempty"`
AuthProviderCertURL string `json:"auth_provider_x509_cert_url,omitempty"`
ClientCertURL string `json:"client_x509_cert_url,omitempty"`
}

var account = serviceAccount{}

func getPrivateKey(privateKey string) (interface{}, error) {
pemPrivateKey := fmt.Sprintf("%v", privateKey)
block, _ := pem.Decode([]byte(pemPrivateKey))
privKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
Expand All @@ -48,11 +63,11 @@ func getPrivateKey() (interface{}, error) {
return privKey, nil
}

func generateJWT() (string, error) {
func generateJWT(privateKey string) (string, error) {
const aud = "https://www.googleapis.com/oauth2/v4/token"
const scope = "https://www.googleapis.com/auth/cloud-platform"

privKey, err := getPrivateKey()
privKey, err := getPrivateKey(privateKey)

if err != nil {
return "", err
Expand All @@ -62,7 +77,7 @@ func generateJWT() (string, error) {
token := jwt.New()

_ = token.Set(jwt.AudienceKey, aud)
_ = token.Set(jwt.IssuerKey, viper.Get("client_email"))
_ = token.Set(jwt.IssuerKey, getServiceAccountProperty("ClientEmail"))
_ = token.Set("scope", scope)
_ = token.Set(jwt.IssuedAtKey, now.Unix())
_ = token.Set(jwt.ExpirationKey, now.Unix())
Expand All @@ -76,8 +91,8 @@ func generateJWT() (string, error) {
return string(payload), nil
}

//GenerateAccessToken generates a Google OAuth access token from a service account
func GenerateAccessToken() (string, error) {
//generateAccessToken generates a Google OAuth access token from a service account
func generateAccessToken(privateKey string) (string, error) {

const tokenEndpoint = "https://www.googleapis.com/oauth2/v4/token"
const grantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"
Expand All @@ -89,7 +104,7 @@ func GenerateAccessToken() (string, error) {
TokenType string `json:"token_type,omitempty"`
}

token, err := generateJWT()
token, err := generateJWT(privateKey)

if err != nil {
return "", nil
Expand Down Expand Up @@ -132,6 +147,25 @@ func GenerateAccessToken() (string, error) {
return accessToken.AccessToken, nil
}

func readServiceAccount(serviceAccountPath string) error {
content, err := ioutil.ReadFile(serviceAccountPath)
if err != nil {
return err
}

err = json.Unmarshal(content, &account)
if err != nil {
return err
}
return nil
}

func getServiceAccountProperty(key string) (value string) {
r := reflect.ValueOf(&account)
field := reflect.Indirect(r).FieldByName(key)
return field.String()
}

func readAccessToken() error {
usr, err := user.Current()
if err != nil {
Expand Down Expand Up @@ -215,18 +249,18 @@ func SetAccessToken() error {
return fmt.Errorf("token expired: request a new access token or pass the service account")
}
if GetServiceAccount() != "" {
viper.SetConfigFile(GetServiceAccount())
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
err := readServiceAccount(GetServiceAccount())
if err != nil { // Handle errors reading the config file
return fmt.Errorf("error reading config file: %s", err)
}
if viper.Get("private_key") == "" {
privateKey := getServiceAccountProperty("PrivateKey")
if privateKey == "" {
return fmt.Errorf("private key missing in the service account")
}
if viper.Get("client_email") == "" {
if getServiceAccountProperty("ClientEmail") == "" {
return fmt.Errorf("client email missing in the service account")
}
_, err = GenerateAccessToken()
_, err = generateAccessToken(privateKey)
if err != nil {
return fmt.Errorf("fatal error generating access token: %s", err)
}
Expand Down
7 changes: 1 addition & 6 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package cmd

import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/srinandan/apigeecli/apiclient"
"github.com/srinandan/apigeecli/clilog"
"github.com/srinandan/apigeecli/cmd/apis"
Expand Down Expand Up @@ -58,11 +57,9 @@ func init() {

RootCmd.PersistentFlags().StringVarP(apiclient.GetApigeeTokenP(), "token", "t",
"", "Google OAuth Token")
_ = viper.BindPFlag("token", RootCmd.PersistentFlags().Lookup("token"))

RootCmd.PersistentFlags().StringVarP(apiclient.GetServiceAccountP(), "account", "a",
"", "Path Service Account private key in JSON")
_ = viper.BindPFlag("account", RootCmd.PersistentFlags().Lookup("account"))

RootCmd.PersistentFlags().BoolVar(apiclient.SkipCache(), "skipCache",
false, "Skip caching Google OAuth Token")
Expand Down Expand Up @@ -91,9 +88,7 @@ func init() {
}

func initConfig() {
viper.SetEnvPrefix("APIGEE")
viper.AutomaticEnv() // read in environment variables that match
viper.SetConfigType("json")

}

// GetRootCmd returns the root of the cobra command-tree.
Expand Down
4 changes: 2 additions & 2 deletions cmd/token/cachetk/cachetk.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ var Cmd = &cobra.Command{

RunE: func(cmd *cobra.Command, args []string) error {
clilog.Init(apiclient.IsSkipLogInfo())
token, err := apiclient.GenerateAccessToken()
fmt.Printf("Token %s cached\n", token)
err := apiclient.SetAccessToken()
fmt.Printf("Token %s cached\n", apiclient.GetApigeeToken())
return err
},
}
Expand Down

0 comments on commit 9842dfb

Please sign in to comment.