-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add GH action workflows #80
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# To get started with Dependabot version updates, you'll need to specify which | ||
# package ecosystems to update and where the package manifests are located. | ||
# Please see the documentation for all configuration options: | ||
# * https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates | ||
# * https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file | ||
version: 2 | ||
updates: | ||
- package-ecosystem: "gomod" | ||
directory: "/" | ||
schedule: | ||
interval: "weekly" | ||
- package-ecosystem: "github-actions" | ||
directory: "/" # For GitHub Actions, set the directory to / to check for workflow files in .github/workflows | ||
schedule: | ||
interval: "weekly" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
name: pr | ||
on: [ pull_request ] | ||
permissions: | ||
contents: read | ||
jobs: | ||
semgrep: | ||
if: ${{ github.actor != 'dependabot[bot]' }} | ||
runs-on: ubuntu-latest | ||
container: | ||
image: returntocorp/semgrep | ||
steps: | ||
# Retrieve the source code for the repository | ||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 | ||
# Fetch the semgrep rules | ||
- run: git clone https://github.com/dgryski/semgrep-go.git | ||
# Run the rule checker using the fetched rules | ||
- run: semgrep ci -f semgrep-go | ||
|
||
check-race: | ||
runs-on: ubuntu-latest | ||
steps: | ||
Comment on lines
+19
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do you propose to test two times: with and without There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Race takes significant longer and that's why it makes sense to break out. |
||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 | ||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 | ||
Comment on lines
+22
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not just an official release version instead of an unclear commit?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for security reasons. Usage of |
||
with: | ||
# https://www.npmjs.com/package/semver#caret-ranges-123-025-004 | ||
go-version: '^1.21' | ||
check-latest: true | ||
- run: go version | ||
- run: go test -race ./... | ||
tests: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 | ||
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 | ||
with: | ||
# https://www.npmjs.com/package/semver#caret-ranges-123-025-004 | ||
go-version: '^1.21' | ||
check-latest: true | ||
- run: go version | ||
- run: go vet ./github ./google ./zalando | ||
- run: go test ./... | ||
- run: go install honnef.co/go/tools/cmd/staticcheck@latest | ||
- run: staticcheck -checks "all" ./github ./google ./zalando | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the staticcheck be in own step. You can use the action from |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,53 +3,53 @@ | |
// webframework. | ||
// | ||
// Example: | ||
// package main | ||
// import ( | ||
// "flag" | ||
// "time" | ||
// "github.com/gin-gonic/gin" | ||
// "github.com/golang/glog" | ||
// "github.com/szuecs/gin-glog" | ||
// "github.com/zalando/gin-oauth2" | ||
// "golang.org/x/oauth2" | ||
// ) | ||
// | ||
// var OAuth2Endpoint = oauth2.Endpoint{ | ||
// AuthURL: "https://token.oauth2.corp.com/access_token", | ||
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo", | ||
// } | ||
// package main | ||
// import ( | ||
// "flag" | ||
// "time" | ||
// "github.com/gin-gonic/gin" | ||
// "github.com/golang/glog" | ||
// "github.com/szuecs/gin-glog" | ||
// "github.com/zalando/gin-oauth2" | ||
// "golang.org/x/oauth2" | ||
// ) | ||
// | ||
// func UidCheck(tc *TokenContainer, ctx *gin.Context) bool { | ||
// uid := tc.Scopes["uid"].(string) | ||
// if uid != "sszuecs" { | ||
// return false | ||
// } | ||
// ctx.Set("uid", uid) | ||
// return true | ||
// } | ||
// var OAuth2Endpoint = oauth2.Endpoint{ | ||
// AuthURL: "https://token.oauth2.corp.com/access_token", | ||
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo", | ||
// } | ||
// | ||
// func main() { | ||
// flag.Parse() | ||
// router := gin.New() | ||
// router.Use(ginglog.Logger(3 * time.Second)) | ||
// router.Use(gin.Recovery()) | ||
// func UidCheck(tc *TokenContainer, ctx *gin.Context) bool { | ||
// uid := tc.Scopes["uid"].(string) | ||
// if uid != "sszuecs" { | ||
// return false | ||
// } | ||
// ctx.Set("uid", uid) | ||
// return true | ||
// } | ||
// | ||
// ginoauth2.VarianceTimer = 300 * time.Millisecond // defaults to 30s | ||
// func main() { | ||
// flag.Parse() | ||
// router := gin.New() | ||
// router.Use(ginglog.Logger(3 * time.Second)) | ||
// router.Use(gin.Recovery()) | ||
// | ||
// public := router.Group("/api") | ||
// public.GET("/", func(c *gin.Context) { | ||
// c.JSON(200, gin.H{"message": "Hello to public world"}) | ||
// }) | ||
// ginoauth2.VarianceTimer = 300 * time.Millisecond // defaults to 30s | ||
// | ||
// private := router.Group("/api/private") | ||
// private.Use(ginoauth2.Auth(UidCheck, OAuth2Endpoint)) | ||
// private.GET("/", func(c *gin.Context) { | ||
// c.JSON(200, gin.H{"message": "Hello from private"}) | ||
// }) | ||
// public := router.Group("/api") | ||
// public.GET("/", func(c *gin.Context) { | ||
// c.JSON(200, gin.H{"message": "Hello to public world"}) | ||
// }) | ||
// | ||
// glog.Info("bootstrapped application") | ||
// router.Run(":8081") | ||
// private := router.Group("/api/private") | ||
// private.Use(ginoauth2.Auth(UidCheck, OAuth2Endpoint)) | ||
// private.GET("/", func(c *gin.Context) { | ||
// c.JSON(200, gin.H{"message": "Hello from private"}) | ||
// }) | ||
// | ||
// glog.Info("bootstrapped application") | ||
// router.Run(":8081") | ||
package ginoauth2 | ||
|
||
import ( | ||
|
@@ -125,12 +125,12 @@ func infofv2(f string, args ...interface{}) { | |
func extractToken(r *http.Request) (*oauth2.Token, error) { | ||
hdr := r.Header.Get("Authorization") | ||
if hdr == "" { | ||
return nil, errors.New("No authorization header") | ||
return nil, errors.New("no authorization header") | ||
} | ||
|
||
th := strings.Split(hdr, " ") | ||
if len(th) != 2 { | ||
return nil, errors.New("Incomplete authorization header") | ||
return nil, errors.New("incomplete authorization header") | ||
} | ||
|
||
return &oauth2.Token{AccessToken: th[1], TokenType: th[0]}, nil | ||
|
@@ -179,10 +179,10 @@ func ParseTokenContainer(t *oauth2.Token, data map[string]interface{}) (*TokenCo | |
exp := data["expires_in"].(float64) | ||
tok := data["access_token"].(string) | ||
if ttype != t.TokenType { | ||
return nil, errors.New("Token type mismatch") | ||
return nil, errors.New("token type mismatch") | ||
} | ||
if tok != t.AccessToken { | ||
return nil, errors.New("Mismatch between verify request and answer") | ||
return nil, errors.New("mismatch between verify request and answer") | ||
} | ||
|
||
scopes := data["scope"].([]interface{}) | ||
|
@@ -219,9 +219,11 @@ func getTokenContainerForToken(o Options, token *oauth2.Token) (*TokenContainer, | |
errorf("[Gin-OAuth] JSON.Unmarshal failed caused by: %s", err) | ||
return nil, err | ||
} | ||
if _, ok := data["error_description"]; ok { | ||
var s string | ||
s = data["error_description"].(string) | ||
if si, ok := data["error_description"]; ok { | ||
s, ok := si.(string) | ||
if !ok { | ||
s = "" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you expect this line to be executed? If yes, why is it okay to ignore |
||
} | ||
errorf("[Gin-OAuth] RequestAuthInfo returned an error: %s", s) | ||
return nil, errors.New(s) | ||
} | ||
|
@@ -254,32 +256,30 @@ func getTokenContainer(o Options, ctx *gin.Context) (*TokenContainer, bool) { | |
return tc, true | ||
} | ||
|
||
// | ||
// TokenContainer | ||
// | ||
// Validates that the AccessToken within TokenContainer is not expired and not empty. | ||
// Valid validates that the AccessToken within TokenContainer is not | ||
// expired and not empty. | ||
func (t *TokenContainer) Valid() bool { | ||
if t.Token == nil { | ||
return false | ||
} | ||
return t.Token.Valid() | ||
} | ||
|
||
// Router middleware that can be used to get an authenticated and authorized service for the whole router group. | ||
// Auth implements a router middleware that can be used to get an | ||
// authenticated and authorized service for the whole router group. | ||
// Example: | ||
// | ||
// var endpoints oauth2.Endpoint = oauth2.Endpoint{ | ||
// AuthURL: "https://token.oauth2.corp.com/access_token", | ||
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo", | ||
// } | ||
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}} | ||
// router := gin.Default() | ||
// private := router.Group("") | ||
// private.Use(ginoauth2.Auth(ginoauth2.UidCheck, ginoauth2.endpoints)) | ||
// private.GET("/api/private", func(c *gin.Context) { | ||
// c.JSON(200, gin.H{"message": "Hello from private"}) | ||
// }) | ||
// | ||
// var endpoints oauth2.Endpoint = oauth2.Endpoint{ | ||
// AuthURL: "https://token.oauth2.corp.com/access_token", | ||
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo", | ||
// } | ||
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}} | ||
// router := gin.Default() | ||
// private := router.Group("") | ||
// private.Use(ginoauth2.Auth(ginoauth2.UidCheck, ginoauth2.endpoints)) | ||
// private.GET("/api/private", func(c *gin.Context) { | ||
// c.JSON(200, gin.H{"message": "Hello from private"}) | ||
// }) | ||
func Auth(accessCheckFunction AccessCheckFunction, endpoints oauth2.Endpoint) gin.HandlerFunc { | ||
return AuthChain(endpoints, accessCheckFunction) | ||
} | ||
|
@@ -289,22 +289,21 @@ func Auth(accessCheckFunction AccessCheckFunction, endpoints oauth2.Endpoint) gi | |
// takes a chain of AccessCheckFunctions and only fails if all of them fails. | ||
// Example: | ||
// | ||
// var endpoints oauth2.Endpoint = oauth2.Endpoint{ | ||
// AuthURL: "https://token.oauth2.corp.com/access_token", | ||
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo", | ||
// } | ||
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}} | ||
// router := gin.Default() | ||
// private := router.Group("") | ||
// checkChain := []AccessCheckFunction{ | ||
// ginoauth2.UidCheck, | ||
// ginoauth2.GroupCheck, | ||
// } | ||
// private.Use(ginoauth2.AuthChain(checkChain, ginoauth2.endpoints)) | ||
// private.GET("/api/private", func(c *gin.Context) { | ||
// c.JSON(200, gin.H{"message": "Hello from private"}) | ||
// }) | ||
// | ||
// var endpoints oauth2.Endpoint = oauth2.Endpoint{ | ||
// AuthURL: "https://token.oauth2.corp.com/access_token", | ||
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo", | ||
// } | ||
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}} | ||
// router := gin.Default() | ||
// private := router.Group("") | ||
// checkChain := []AccessCheckFunction{ | ||
// ginoauth2.UidCheck, | ||
// ginoauth2.GroupCheck, | ||
// } | ||
// private.Use(ginoauth2.AuthChain(checkChain, ginoauth2.endpoints)) | ||
// private.GET("/api/private", func(c *gin.Context) { | ||
// c.JSON(200, gin.H{"message": "Hello from private"}) | ||
// }) | ||
func AuthChain(endpoint oauth2.Endpoint, accessCheckFunctions ...AccessCheckFunction) gin.HandlerFunc { | ||
return AuthChainOptions(Options{Endpoint: endpoint}, accessCheckFunctions...) | ||
} | ||
|
@@ -322,15 +321,15 @@ func AuthChainOptions(o Options, accessCheckFunctions ...AccessCheckFunction) gi | |
if !ok { | ||
// set LOCATION header to auth endpoint such that the user can easily get a new access-token | ||
ctx.Writer.Header().Set("Location", o.Endpoint.AuthURL) | ||
ctx.AbortWithError(http.StatusUnauthorized, errors.New("No token in context")) | ||
ctx.AbortWithError(http.StatusUnauthorized, errors.New("no token in context")) | ||
varianceControl <- false | ||
return | ||
} | ||
|
||
if !tokenContainer.Valid() { | ||
// set LOCATION header to auth endpoint such that the user can easily get a new access-token | ||
ctx.Writer.Header().Set("Location", o.Endpoint.AuthURL) | ||
ctx.AbortWithError(http.StatusUnauthorized, errors.New("Invalid Token")) | ||
ctx.AbortWithError(http.StatusUnauthorized, errors.New("invalid Token")) | ||
varianceControl <- false | ||
return | ||
} | ||
|
@@ -342,7 +341,7 @@ func AuthChainOptions(o Options, accessCheckFunctions ...AccessCheckFunction) gi | |
} | ||
|
||
if len(accessCheckFunctions)-1 == i { | ||
ctx.AbortWithError(http.StatusForbidden, errors.New("Access to the Resource is forbidden")) | ||
ctx.AbortWithError(http.StatusForbidden, errors.New("access to the Resource is forbidden")) | ||
varianceControl <- false | ||
return | ||
} | ||
|
@@ -356,7 +355,7 @@ func AuthChainOptions(o Options, accessCheckFunctions ...AccessCheckFunction) gi | |
return | ||
} | ||
case <-time.After(VarianceTimer): | ||
ctx.AbortWithError(http.StatusGatewayTimeout, errors.New("Authorization check overtime")) | ||
ctx.AbortWithError(http.StatusGatewayTimeout, errors.New("authorization check overtime")) | ||
infofv2("[Gin-OAuth] %12v %s overtime", time.Since(t), ctx.Request.URL.Path) | ||
return | ||
} | ||
|
@@ -375,22 +374,20 @@ func AuthChainOptions(o Options, accessCheckFunctions ...AccessCheckFunction) gi | |
// | ||
// Example: | ||
// | ||
// var endpoints oauth2.Endpoint = oauth2.Endpoint{ | ||
// AuthURL: "https://token.oauth2.corp.com/access_token", | ||
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo", | ||
// } | ||
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}} | ||
// router := gin.Default() | ||
// router.Use(ginoauth2.RequestLogger([]string{"uid"}, "data")) | ||
// | ||
// var endpoints oauth2.Endpoint = oauth2.Endpoint{ | ||
// AuthURL: "https://token.oauth2.corp.com/access_token", | ||
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo", | ||
// } | ||
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}} | ||
// router := gin.Default() | ||
// router.Use(ginoauth2.RequestLogger([]string{"uid"}, "data")) | ||
func RequestLogger(keys []string, contentKey string) gin.HandlerFunc { | ||
return func(c *gin.Context) { | ||
request := c.Request | ||
c.Next() | ||
err := c.Errors | ||
if request.Method != "GET" && err == nil { | ||
data, e := c.Get(contentKey) | ||
if e != false { //key is non existent | ||
if data, ok := c.Get(contentKey); !ok { | ||
values := make([]string, 0) | ||
for _, key := range keys { | ||
val, keyPresent := c.Get(key) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be
[ push ]
to compile on any new commit?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It updates on each push but online if there's an open pr