From 88ab61579725b396dbf712f18087c7e647d6c30c Mon Sep 17 00:00:00 2001 From: avi Date: Fri, 16 Feb 2018 23:05:03 +0530 Subject: [PATCH] Initial import --- .gitignore | 20 +++++++++++ .goreleaser.yml | 8 +++++ Gopkg.lock | 15 ++++++++ Gopkg.toml | 34 ++++++++++++++++++ LICENSE | 24 +++++++++++++ README.md | 26 ++++++++++++++ main.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 223 insertions(+) create mode 100644 .gitignore create mode 100644 .goreleaser.yml create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..df3257d --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +vendor/ +dist/ + +# gh private key +private_key.pem + +# binary +fidelius \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..d3ee62b --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,8 @@ +builds: + - binary: fidelius + goos: + - windows + - darwin + - linux + goarch: + - amd64 diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..e969b4f --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/dgrijalva/jwt-go" + packages = ["."] + revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29" + version = "v3.1.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "6dfa883d6a10f63168648fb73e4081319272cda9456721d44d20510fb519884e" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..5e6fab0 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,34 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/dgrijalva/jwt-go" + version = "3.1.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/README.md b/README.md new file mode 100644 index 0000000..c8f20ea --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Fidelius + +## Usage + +If you want to generate a temporary access token: + + $ fidelius --gh-integration-id=1234 --gh-installation-id=5678 --gh-private-key='/root/fidelius-charm.2018-02-12.private-key.pem' + # will print the token + v1.437ad23ce1a4a71b1f3222bc198de653619a9570 + +If you want to generate a proper `.gitconfig` file: + + $ fidelius --gh-integration-id=1234 --gh-installation-id=5678 --gh-private-key='/root/fidelius-charm.2018-02-12.private-key.pem' --git-config-out='/root/.gitconfig' + +or if you want to modify an existing `.gitconfig`: + + $ export GH_TOKEN=$(fidelius --gh-integration-id=1234 --gh-installation-id=5678 --gh-private-key='/root/fidelius-charm.2018-02-12.private-key.pem') + $ git config --global url.https://x-access-token:$GH_TOKEN@github.com/.insteadOf https://github.com/ + +## Name + +[Fidelius Charm](http://harrypotter.wikia.com/wiki/Fidelius_Charm) + +## License + +Released under Unlicense. Check the `LICENSE` for more details. \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..781a272 --- /dev/null +++ b/main.go @@ -0,0 +1,96 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "html/template" + "io/ioutil" + "log" + "net/http" + "os" + "path/filepath" + "time" + + jwt "github.com/dgrijalva/jwt-go" +) + +var ( + OutDir string + IntegrationId string + InstallationId int64 + PrivateKeyFile string +) + +type GHResponse struct { + Token string `json:"token,omitempty"` + ExpiresAt time.Time `json:"expires_at,omitempty"` +} + +func init() { + flag.StringVar(&OutDir, "git-config-out", "", "path where we will write the .gitconfig file") + flag.StringVar(&IntegrationId, "gh-integration-id", "1234", "Github Integration's id") + flag.StringVar(&PrivateKeyFile, "gh-private-key", "private_key.pem", "Full path to the Github Integration's private key") + flag.Int64Var(&InstallationId, "gh-installation-id", 5678, "Github Integtation's installation id") +} + +func fatalErr(err error) { + if err != nil { + log.Fatalln(err) + } +} + +func main() { + flag.Parse() + data, err := ioutil.ReadFile(PrivateKeyFile) + fatalErr(err) + key, err := jwt.ParseRSAPrivateKeyFromPEM(data) + fatalErr(err) + token, err := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.StandardClaims{ + IssuedAt: time.Now().Unix(), + ExpiresAt: time.Now().Add(10 * time.Minute).Unix(), + Issuer: IntegrationId, + }).SignedString(key) + fatalErr(err) + + var result GHResponse + req, err := http.NewRequest("POST", fmt.Sprintf("https://api.github.com/installations/%d/access_tokens", InstallationId), nil) + fatalErr(err) + + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token)) + req.Header.Add("Accept", "application/vnd.github.machine-man-preview+json") + fatalErr(JsonResponse(req, &result)) + + if OutDir == "" { + fmt.Print(result.Token) + } else { + path, err := filepath.Abs(OutDir) + fatalErr(err) + f, err := os.Create(path) + fatalErr(err) + defer f.Close() + t := template.Must(template.New("t1"). + Parse(`[url "https://x-access-token:{{.}}@github.com/"] + insteadOf = https://github.com/`)) + fatalErr(t.Execute(f, result.Token)) + } +} + +func JsonResponse(req *http.Request, target interface{}) error { + client := &http.Client{ + Timeout: 10 * time.Second, + } + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusCreated { + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Println(err) + } + log.Fatalln(string(data)) + } + return json.NewDecoder(resp.Body).Decode(target) +}