...

Source file src/golang.conradwood.net/go-easyops/tokens/tokens.go

Documentation: golang.conradwood.net/go-easyops/tokens

     1  /*
     2  mostly deprecated. internal use only.
     3  */
     4  package tokens
     5  
     6  import (
     7  	"context"
     8  	"flag"
     9  	"fmt"
    10  	"golang.conradwood.net/go-easyops/cmdline"
    11  	"golang.conradwood.net/go-easyops/utils"
    12  	"google.golang.org/grpc/metadata"
    13  	"io/ioutil"
    14  	"os"
    15  	"os/user"
    16  	"strings"
    17  	"time"
    18  )
    19  
    20  var (
    21  	e_token                  = cmdline.ENV("GE_USERTOKEN", "a service token")
    22  	e_usertoken              = cmdline.ENV("GE_USERTOKEN", "a usertoken")
    23  	token                    = flag.String("token", "", "service token")
    24  	disusertoken             = flag.Bool("ge_disable_user_token", false, "if true disable reading of user token (for testing)")
    25  	tokenwasread             = false
    26  	usertoken                string
    27  	last_token_read_registry string
    28  	cloudname                = "yacloud.eu"
    29  	debug                    = flag.Bool("ge_debug_tokens", false, "debug user token stuff")
    30  )
    31  
    32  const (
    33  	METANAME = "goeasyops_meta" // marshaled proto
    34  // METANAME2 = "goeasyopsv2_meta" // marshaled proto
    35  )
    36  
    37  func DisableUserToken() {
    38  	tokenwasread = true
    39  	usertoken = ""
    40  }
    41  
    42  // OUTBOUND metadata...
    43  func buildMeta() metadata.MD {
    44  	panic("obsolete codepath")
    45  }
    46  
    47  // this builds a *NEW* token (detached from previous contexts)
    48  // if there is neither a -token parameter nor a user token it will
    49  // look at Environment variable GE_CTX and deserialise it
    50  // this function is deprecated, obsolete and broken. use authremote.Context() instead
    51  func DISContextWithToken() context.Context {
    52  	// we need to allow this as long as we have OLD contexts that need deserialising
    53  	/*
    54  		if cmdline.ContextWithBuilder() {
    55  			utils.NotImpl("(context_with_builder) tokens.ContextWithToken - V1 context only\n")
    56  		}
    57  	*/
    58  	md := buildMeta()
    59  	ctx, cnc := context.WithTimeout(context.Background(), time.Duration(10)*time.Second)
    60  	go func(cf context.CancelFunc) {
    61  		time.Sleep(time.Duration((10)+5) * time.Second)
    62  		cnc()
    63  	}(cnc)
    64  	return metadata.NewOutgoingContext(ctx, md)
    65  
    66  }
    67  
    68  // this function is deprecated, obsolete and broken. use authremote.Context() instead
    69  func DISContextWithTokenAndTimeout(seconds uint64) context.Context {
    70  	if cmdline.ContextWithBuilder() {
    71  		utils.NotImpl("contextv2 incomplete")
    72  	}
    73  	md := buildMeta()
    74  	ctx, cnc := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
    75  	go func(cf context.CancelFunc, s uint64) {
    76  		time.Sleep(time.Duration(s+5) * time.Second)
    77  		cnc()
    78  	}(cnc, seconds)
    79  	return metadata.NewOutgoingContext(ctx, md)
    80  }
    81  
    82  // this function is deprecated, obsolete and broken. use authremote.Context() instead
    83  func DISContext2WithTokenAndTimeout(seconds uint64) (context.Context, context.CancelFunc) {
    84  	if cmdline.ContextWithBuilder() {
    85  		panic("contextv2 incomplete")
    86  	}
    87  	md := buildMeta()
    88  	ctx, cnc := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
    89  	ctx = metadata.NewOutgoingContext(ctx, md)
    90  	return ctx, cnc
    91  }
    92  
    93  func SetServiceTokenParameter(tok string) {
    94  	*token = tok
    95  }
    96  func GetServiceTokenParameter() string {
    97  	if *token != "" {
    98  		return *token
    99  	}
   100  	return e_token.Value()
   101  }
   102  func readToken(token string) string {
   103  	if *disusertoken {
   104  		panic("codepath bug. user token is disabled but attempted to read it")
   105  	}
   106  	var tok string
   107  	var btok []byte
   108  	var fname string
   109  	fname = "n/a"
   110  	usr, err := user.Current()
   111  	if err != nil {
   112  		fmt.Printf("[go-easyops] Failed to determine current user: %s\n", err)
   113  		return ""
   114  	}
   115  	fnames := []string{
   116  		fmt.Sprintf("%s/.go-easyops/tokens/%s.%s", usr.HomeDir, token, cloudname),
   117  		fmt.Sprintf("%s/.go-easyops/tokens/%s.%s", usr.HomeDir, token, cmdline.GetRegistryAddress()),
   118  		fmt.Sprintf("%s/.go-easyops/tokens/%s", usr.HomeDir, token),
   119  	}
   120  	for _, fname = range fnames {
   121  		if _, err := os.Stat(fname); os.IsNotExist(err) {
   122  			if *debug {
   123  				fmt.Printf("File \"%s\" does not exist - ignoring.\n", fname)
   124  			}
   125  			continue
   126  		}
   127  		break
   128  	}
   129  
   130  	if _, err := os.Stat(fname); os.IsNotExist(err) {
   131  		// services usually don't have such file. don't throw errors in that case. it's confusing
   132  		return ""
   133  	}
   134  	if *debug {
   135  		fmt.Printf("[go-easyops] Reading file \"%s\", parsing as token\n", fname)
   136  	}
   137  	btok, err = ioutil.ReadFile(fname)
   138  	if err != nil {
   139  		fmt.Printf("[go-easyops] Failed to read user token: %s\n", err)
   140  		return ""
   141  	} else if len(btok) == 0 {
   142  		fmt.Printf("[go-easyops] Failed to read user token from %s\n", fname)
   143  		return ""
   144  
   145  	} else {
   146  		tok = string(btok)
   147  	}
   148  	tok = strings.TrimSpace(tok)
   149  	//	fmt.Printf("[go-easyops] read token from \"%s\"\n", fname)
   150  	if *debug {
   151  		fmt.Printf("[go-easyops] token is empty\n")
   152  		if len(tok) < 5 {
   153  			fmt.Printf("[go-easyops] token is too short\n")
   154  		} else {
   155  			fmt.Printf("[go-easyops] token: %s...\n", tok[:3])
   156  		}
   157  	}
   158  	return tok
   159  }
   160  
   161  /*
   162  get a usertoken parameter from:
   163  
   164  1. GE_USERTOKEN
   165  
   166  2. ~/.go-easyops/user_token
   167  
   168  if ge_disable_user_token is true, return "" (empty string)
   169  
   170  if GE_TOKEN is set, does not read file (but honour GE_USERTOKEN)
   171  */
   172  func GetUserTokenParameter() string {
   173  	if *disusertoken {
   174  		//fmt.Printf("[go-easyops] tokens: user token disabled\n")
   175  		return ""
   176  	}
   177  
   178  	ut := e_usertoken.Value()
   179  	if ut != "" {
   180  		if *debug {
   181  			fmt.Printf("[go-easyops] tokens: getting user token from e_usertoken\n")
   182  		}
   183  		return ut
   184  	}
   185  	// if token is set either as parameter or as ENV variable GE_TOKEN, then return ""
   186  	// because we are a service (services do not run as users)
   187  	/*
   188  		// fix: we never return -token=XX as UserToken
   189  				if *token != "" {
   190  					if *debug {
   191  						fmt.Printf("[go-easyops] tokens: getting user token from *token\n")
   192  					}
   193  					return *token
   194  				}
   195  	*/
   196  	if e_token.Value() != "" {
   197  		return e_token.Value()
   198  	}
   199  
   200  	if tokenwasread && last_token_read_registry == cmdline.GetClientRegistryAddress() {
   201  		return usertoken
   202  	}
   203  	u := readToken("user_token")
   204  	usertoken = u
   205  	tokenwasread = true
   206  	last_token_read_registry = cmdline.GetClientRegistryAddress()
   207  	/*
   208  		if usertoken == "" {
   209  			fmt.Printf("[go-easyops] tokens: reading usertoken, but is empty\n")
   210  		} else {
   211  			fmt.Printf("[go-easyops] got usertoken\n")
   212  		}
   213  	*/
   214  	return usertoken
   215  }
   216  
   217  func SaveUserToken(token string) error {
   218  	usr, err := user.Current()
   219  	if err != nil {
   220  		err := fmt.Errorf("Failed to determine current operating system user: %s (are you logged in to your computer?)\n", err)
   221  		return err
   222  	}
   223  	dir := fmt.Sprintf("%s/.go-easyops/tokens", usr.HomeDir)
   224  	os.MkdirAll(dir, 0700)
   225  	fname := fmt.Sprintf("%s/.go-easyops/tokens/user_token", usr.HomeDir)
   226  	err = utils.WriteFile(fname, []byte(token))
   227  	if err != nil {
   228  		fmt.Printf("Failed to save access token: %s\n", err)
   229  		return err
   230  	}
   231  	tokenwasread = false
   232  	return nil
   233  }
   234  func GetCloudName() string {
   235  	return cloudname
   236  }
   237  func SetCloudName(xcloudname string) {
   238  	if xcloudname != "" && xcloudname != cloudname {
   239  		if *debug {
   240  			fmt.Printf("setting cloud name to \"%s\"\n", xcloudname)
   241  		}
   242  		cloudname = xcloudname
   243  		tokenwasread = false // force re-read of token
   244  	}
   245  }
   246  

View as plain text