chartmuseum/auth
Go library for generating ChartMuseum JWT Tokens, authorizing HTTP requests, etc.
How to Use
Generating a JWT token (example)
Source
Clone this repo and run go run testcmd/getjwt/main.go
to run this example
package main
import (
"fmt"
"time"
cmAuth "github.com/chartmuseum/auth"
)
func main() {
cmTokenGenerator, err := cmAuth.NewTokenGenerator(&cmAuth.TokenGeneratorOptions{
PrivateKeyPath: "./testdata/server.key",
})
if err != nil {
panic(err)
}
access := []cmAuth.AccessEntry{
{
Name: "org1/repo1",
Type: cmAuth.AccessEntryType,
Actions: []string{cmAuth.PushAction},
},
}
signedString, err := cmTokenGenerator.GenerateToken(access, time.Minute*5)
if err != nil {
panic(err)
}
fmt.Println(signedString)
}
This token will be formatted as a valid JSON Web Token (JWT)
and resemble the following:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDM5NTk3OTMsImlhdCI6MTU0Mzk1OTQ5MywiYWNjZXNzIjpbeyJ0eXBlIjoiYXJ0aWZhY3QtcmVwb3NpdG9yeSIsIm5hbWUiOiJvcmcxL3JlcG8xIiwiYWN0aW9ucyI6WyJwdXNoIl19XX0.giLd83d8eK8QbTFnCLmgATV2ohiIb59dIhrg35XYFz-6EHqvirUsfZBdWXMRy2sQUOOIHouVEamv_qErKPbFQYGYureJ9BJmVKA3N2SL8aSiXaa8ZasyjRmayOqri55gNf-LE1XddtO8al6-e6vcXe_0YnkGyfw-ODej83wdoLHjB3VgLGXDdbTyXMJEs0aULmBUxbnyaGFTNWgowfqr8W3Sk64LgRvEJ3gJtTN5r_vjgDDVyMX9SIk0yvlCATN7fJvbiVotoLJTGRKV6PVRN79A16SqSGYsN3Nvym8BUwJgXLPM24ozngje1y2s6YmwOOnKItTIXwU12IqbzlmGRg
You can decode this token on https://jwt.io
or with something like jwt-cli.
The decoded payload of this token will look like the following:
{
"exp": 1543959726,
"iat": 1543959426,
"access": [
{
"type": "artifact-repository",
"name": "org1/repo1",
"actions": [
"push"
]
}
]
}
Making requests to ChartMuseum
First, obtain the token with the necessary access entries (see example above).
Then use this token to make requests to ChartMuseum,
passing it in the Authorization
header:
> GET /api/charts HTTP/1.1
> Host: localhost:8080
> Authorization: Bearer <token>
Validating a JWT token (example)
Source
Clone this repo and run go run testcmd/decodejwt/main.go <token>
to run this example
package main
import (
"encoding/json"
"fmt"
"os"
cmAuth "github.com/chartmuseum/auth"
"github.com/golang-jwt/jwt"
)
func main() {
signedString := os.Args[1]
cmTokenDecoder, err := cmAuth.NewTokenDecoder(&cmAuth.TokenDecoderOptions{
PublicKeyPath: "./testdata/server.pem",
})
if err != nil {
panic(err)
}
token, err := cmTokenDecoder.DecodeToken(signedString)
if err != nil {
panic(err)
}
c := token.Claims.(jwt.MapClaims)
byteData, err := json.MarshalIndent(c, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(byteData))
}
Authorizing an incoming request (example)
Source
Clone this repo and run go run testcmd/authorizer/main.go <token>
to run this example
package main
import (
"fmt"
"os"
cmAuth "github.com/chartmuseum/auth"
)
func main() {
signedString := os.Args[1]
authHeader := fmt.Sprintf("Bearer %s", signedString)
cmAuthorizer, err := cmAuth.NewAuthorizer(&cmAuth.AuthorizerOptions{
Realm: "https://my.site.io/oauth2/token",
Service: "my.site.io",
PublicKeyPath: "./testdata/server.pem",
})
if err != nil {
panic(err)
}
permissions, err := cmAuthorizer.Authorize(authHeader, cmAuth.PushAction, "org1/repo1")
if err != nil {
panic(err)
}
if permissions.Allowed {
fmt.Println("ACCESS GRANTED")
} else {
fmt.Println("ACCESS DENIED")
fmt.Println(fmt.Sprintf("WWW-Authenticate: %s", permissions.WWWAuthenticateHeader))
}
}
If access denied, the WWW-Authenticate
header returned will resemble the following:
WWW-Authenticate: Bearer realm="https://my.site.io/oauth2/token",service="my.site.io",scope="artifact-repository:org1/repo1:push"
Using a custom access entry type
By default, the "Type" of each claim checked for upon authorization is artifact-repository
.
If you wish, you may customize this field upon construction of the Authorizer:
For example, for custom type "myartifact", you do the following:
myAuthorizer, err = NewAuthorizer(&AuthorizerOptions{
Realm: "https://my.site.io/oauth2/token",
Service: "my.site.io",
PublicKeyPath: myPublicKey,
AccessEntryType: "myartifact",
})
Adding aud
and iss
fields to token claims
If you wish to add the aud
and iss
fields to token claims (Audience and Issuer),
you may construct the TokenGenerator like so:
cmTokenGenerator, err := cmAuth.NewTokenGenerator(&cmAuth.TokenGeneratorOptions{
PrivateKeyPath: "./testdata/server.key",
Audience: "registry.my.site.io",
Issuer: "auth.my.site.io",
})
The kid
header is a fingerprint representing the ID of the key which was used to sign the token.
If you wish to add this to generate tokens, you can do it like so:
cmTokenGenerator, err := cmAuth.NewTokenGenerator(&cmAuth.TokenGeneratorOptions{
PrivateKeyPath: "./testdata/server.key",
AddKIDHeader: true,
})
Supported JWT Signing Algorithms