-
-
Save btoews/a3999342ab7d377e9f0818e5d14d0a4d to your computer and use it in GitHub Desktop.
Kurt token stuff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"os" | |
"strings" | |
"github.com/superfly/macaroon" | |
"github.com/superfly/macaroon/flyio" | |
) | |
var ( | |
// this secret should be loaded from an environment variable. it just needs | |
// to be 32 random bytes. | |
ThirdPartyKey = macaroon.NewEncryptionKey() | |
// the value of this isn't super important, but it identifies the app behind | |
// your third party caveat. | |
ThirdPartyLocation = "https://kurt.app" | |
) | |
func main() { | |
tok := strings.Join(os.Args[1:], " ") | |
if tok == "" { | |
fmt.Println("usage: attenuate-token $(fly tokens deploy -x1h -a myapp)") | |
os.Exit(1) | |
} | |
tok, err := AttenuateToken(tok) | |
if err != nil { | |
fmt.Println("error attenuating token:", err) | |
os.Exit(1) | |
} | |
fmt.Printf("attenuated:\n%s\n\n", tok) | |
tok, err = DischargeToken(tok) | |
if err != nil { | |
fmt.Println("error discharging token:", err) | |
os.Exit(1) | |
} | |
fmt.Printf("discharged:\n%s\n\n", tok) | |
fmt.Printf(` | |
Try running: | |
APP=myapp | |
MACHINE=mymachine | |
TOKEN="%s" | |
curl -H "Authorization: $TOKEN" -H 'Content-Type: application/json' --data '{"command": ["whoami"]}' https://api.machines.dev/v1/apps/$APP/machines/$MACHINE/exec | |
`, tok) | |
} | |
// attenuateToken takes a token returned by `flyctl tokens deploy` and | |
// attenuates it so it can only be used for exec'ing commands on machines and so | |
// that it can't be used by anyone without first passing it through | |
// DischargeToken. The returned value is what you would give to users. | |
func AttenuateToken(token string) (string, error) { | |
bun, err := flyio.ParseBundle(token) | |
if err != nil { | |
return "", fmt.Errorf("error parsing token: %v", err) | |
} | |
// A third party caveat. This will need to be discharged before the token is | |
// used against any other service. | |
tpCav, err := macaroon.NewCaveat3P(ThirdPartyKey, ThirdPartyLocation) | |
if err != nil { | |
return "", fmt.Errorf("error creating third party caveat: %v", err) | |
} | |
// This restricts the token to only be allowed for exec'ing commands on | |
// machines. You can tweak this to allow only certain commands or command | |
// prefixes. | |
comCav := &flyio.Commands{flyio.Command{}} | |
if err := bun.Attenuate(tpCav, comCav); err != nil { | |
return "", fmt.Errorf("error attenuating token: %v", err) | |
} | |
return bun.Header(), nil | |
} | |
// DischargeToken takes a token that was attenuated by AttenuateToken and | |
// discharges it so we can use it against the machines API to exec commands. | |
func DischargeToken(token string) (string, error) { | |
bun, err := flyio.ParseBundle(token) | |
if err != nil { | |
return "", fmt.Errorf("error parsing token: %v", err) | |
} | |
if err := bun.Discharge(ThirdPartyLocation, ThirdPartyKey, rejectCaveatsIn3P); err != nil { | |
return "", fmt.Errorf("error discharging token: %v", err) | |
} | |
return bun.Header(), nil | |
} | |
// You can include caveats in a 3p caveat that tell the third party the | |
// conditions under which they should discharge. We aren't adding any of those | |
// restrictions, so this callback just rejects any caveats found inside the 3p | |
// caveat. | |
func rejectCaveatsIn3P(cavs []macaroon.Caveat) ([]macaroon.Caveat, error) { | |
if len(cavs) != 0 { | |
return nil, fmt.Errorf("unexpected caveats in 3p caveat: %v", cavs) | |
} | |
return nil, nil | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module kurtauth | |
go 1.22.1 | |
require github.com/superfly/macaroon v0.2.14-0.20250124173236-5d85b206bb04 | |
require ( | |
github.com/google/uuid v1.3.0 // indirect | |
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect | |
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect | |
github.com/sirupsen/logrus v1.9.3 // indirect | |
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect | |
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect | |
golang.org/x/crypto v0.12.0 // indirect | |
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect | |
golang.org/x/sys v0.11.0 // indirect | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
github.com/alecthomas/assert/v2 v2.3.0 h1:mAsH2wmvjsuvyBvAmCtm7zFsBlb8mIHx5ySLVdDZXL0= | |
github.com/alecthomas/assert/v2 v2.3.0/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= | |
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= | |
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= | |
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | |
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= | |
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | |
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= | |
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= | |
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= | |
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= | |
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= | |
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= | |
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= | |
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= | |
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | |
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | |
github.com/superfly/macaroon v0.2.14-0.20250124173236-5d85b206bb04 h1:mGeQ5kRsAmhUnenGN3fNplCu+EuU9FF7GXbrmAPP27E= | |
github.com/superfly/macaroon v0.2.14-0.20250124173236-5d85b206bb04/go.mod h1:ZAmlRD/Hmp/ddTxE8IonZ7NdTny2DcOffRvZhapQwJw= | |
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= | |
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= | |
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= | |
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= | |
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= | |
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= | |
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= | |
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= | |
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= | |
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | |
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment