blob: 018f18d7b0844ac9492e4c75163a97defc35e8d5 [file] [log] [blame]
// +build linux
package main
/*
Obtain an OAuth2 token from a service account key. Expects to run as root in a cron job.
*/
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"syscall"
"go.skia.org/infra/go/auth"
"go.skia.org/infra/go/common"
"go.skia.org/infra/go/sklog"
"go.skia.org/infra/skolo/go/service_accounts"
compute "google.golang.org/api/compute/v1"
)
// checkFilePerms returns an error if the given file is not owned and readable
// only by root. Requires that we're running on Linux.
func checkFilePerms(fp string) error {
info, err := os.Stat(fp)
if err != nil {
return fmt.Errorf("Failed to read file: %s", err)
}
fi, ok := info.Sys().(*syscall.Stat_t)
if !ok {
return fmt.Errorf("Got wrong type for FileInfo.Sys()!")
}
if fi.Uid != 0 {
return fmt.Errorf("File is not owned by root (UID = %d).", fi.Uid)
}
if fi.Gid != 0 {
return fmt.Errorf("File is not owned by root group (GID = %d).", fi.Gid)
}
if info.Mode() != 0600 {
return fmt.Errorf("File mode must be 0600 (is %d).", info.Mode())
}
return nil
}
func processServiceAccount(nickname string) error {
serviceAccountFile := fmt.Sprintf("/etc/service_account_%s.json", nickname)
dest := fmt.Sprintf("/var/local/token_%s.json", nickname)
// Verify that the key file is owned and readable only by root.
if err := checkFilePerms(serviceAccountFile); err != nil {
sklog.Fatal(err)
}
if dest == "" {
sklog.Fatalf("--dest is required.")
}
src, err := auth.NewJWTServiceAccountTokenSource("#bogus", serviceAccountFile, compute.CloudPlatformScope, auth.SCOPE_USERINFO_EMAIL)
if err != nil {
sklog.Fatal(err)
}
tok, err := src.Token()
if err != nil {
sklog.Fatal(err)
}
b, err := json.Marshal(tok)
if err != nil {
sklog.Fatal(err)
}
if err := ioutil.WriteFile(dest, b, 0644); err != nil {
sklog.Fatal(err)
}
sklog.Infof("Wrote new auth token: %s", tok.AccessToken[len(tok.AccessToken)-8:])
return nil
}
func main() {
common.Init()
hostname, err := os.Hostname()
if err != nil {
sklog.Fatal(err)
}
serviceAccounts, ok := service_accounts.JumphostServiceAccountMapping[hostname]
if !ok {
sklog.Fatalf("Hostname not in jumphost mapping: %s", hostname)
}
sklog.Infof("Obtaining new auth token.")
for _, sa := range serviceAccounts {
if err := processServiceAccount(sa.Nickname); err != nil {
sklog.Fatal(err)
}
}
}