Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions .github/workflow/ci.yml → .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name: Go CI

on:
on:
pull_request:
branches: [develop, master]
push:
branches:
- 'main'
- 'develop'
branches: [develop, master]

jobs:
build-linux:
Expand All @@ -13,39 +13,39 @@ jobs:
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Go
uses: actions/setup-go@v5.0.2
uses: actions/setup-go@v5.2.0
with:
go-version: '1.18'
cache: false
go-version: '1.21'
- name: Build
run: go build -v ./...
run: go version && go build -v ./...

build-windows:
name: Build Ferrum on windows
runs-on: windows-latest
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Go
uses: actions/setup-go@v5.0.2
uses: actions/setup-go@v5.2.0
with:
go-version: '1.18'
cache: false
go-version: '1.21'
- name: Build
run: go build -v ./...
run: go version && go build -v ./...

all-tests-linux:
name: Run all tests on linux
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Go
uses: actions/setup-go@v5.0.2
uses: actions/setup-go@v5.2.0
with:
go-version: '1.21'
- name: Set up Redis Stack server
run: docker compose up -d redis
- name: Get Redis logs
run: docker logs $(docker ps -aqf "name=wissance_ferrum_db")
- name: Test all
run: go test -v ./...
run: go version && go mod tidy && go test -v ./...

#all-tests-windows:
# name: Run all tests on windows
Expand All @@ -68,12 +68,11 @@ jobs:
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Go
uses: actions/setup-go@v5.0.2
uses: actions/setup-go@v5.2.0
with:
go-version: '1.18'
cache: false
go-version: '1.21'
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v6.1.0
with:
version: v1.50.1
args: --timeout 3m --config .golangci.yaml
version: v1.63.4
args: --timeout 3m --config .golangci.yaml
76 changes: 76 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
run:
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 30m

modules-download-mode: readonly

go: '1.21'

output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions
# default is "colored-line-number"
formats: code-climate

linters:
enable-all: false
disable:
- exhaustruct
- gofumpt
- testpackage
- depguard
- tagliatelle
- ireturn
- varnamelen
- wrapcheck

linters-settings:
stylecheck:
# Select the Go version to target. The default is '1.13'.
# https://staticcheck.io/docs/options#checks
checks: [ "all", "-ST1000" ]
funlen:
lines: 100
gci:
sections:
- standard
- default
- prefix(github.com/wissance/Ferrum)
gocyclo:
min-complexity: 5
varnamelen:
ignore-names:
- id
ignore-decls:
- ok bool
wrapcheck:
ignorePackageGlobs:
- google.golang.org/grpc/status
- github.com/pkg/errors
- golang.org/x/sync/errgroup
gosec:
excludes:
- G204

issues:
exclude-rules:
- path: _test\.go
linters:
- containedctx
- gocyclo
- cyclop
- funlen
- goerr113
- varnamelen
- staticcheck
- maintidx
- lll
- paralleltest
- dupl
- typecheck
- wsl
- govet
- path: main\.go
linters:
- gochecknoglobals
- lll
- funlen
4 changes: 2 additions & 2 deletions api/admin/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ func main() {
case operations.ClientResource:
var clientNew data.Client
if unmarshalErr := json.Unmarshal(value, &clientNew); unmarshalErr != nil {
log.Fatalf(sf.Format("json.Unmarshal failed: {0}", unmarshalErr.Error()))
log.Fatal(sf.Format("json.Unmarshal failed: {0}", unmarshalErr.Error()))
}
if createErr := manager.CreateClient(params, clientNew); createErr != nil {
log.Fatalf(sf.Format("CreateClient failed: {0}", createErr.Error()))
log.Fatal(sf.Format("CreateClient failed: {0}", createErr.Error()))
}
log.Print(sf.Format("Client: \"{0}\" successfully created", clientNew.Name))

Expand Down
16 changes: 8 additions & 8 deletions api/admin/cli/operations/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ type ResourceType string

const (
RealmResource ResourceType = "realm"
ClientResource = "client"
UserResource = "user"
UserFederationConfigResource = "user_federation"
ClientResource ResourceType = "client"
UserResource ResourceType = "user"
UserFederationConfigResource ResourceType = "user_federation"
)

type OperationType string

const (
GetOperation OperationType = "get"
CreateOperation = "create"
DeleteOperation = "delete"
UpdateOperation = "update"
ChangePassword = "change_password"
ResetPassword = "reset_password"
CreateOperation OperationType = "create"
DeleteOperation OperationType = "delete"
UpdateOperation OperationType = "update"
ChangePassword OperationType = "change_password"
ResetPassword OperationType = "reset_password"
)
6 changes: 3 additions & 3 deletions api/rest/web_api_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (wCtx *WebApiContext) IssueNewToken(respWriter http.ResponseWriter, request
issueTokens := false
// 0. Check whether we deal with issuing a new token or refresh previous one
isRefresh := isTokenRefreshRequest(&tokenGenerationData)
if isRefresh == true {
if isRefresh {
// 1-2. Validate refresh token and check is it fresh enough
session := (*wCtx.Security).GetSessionByRefreshToken(realm, &tokenGenerationData.RefreshToken)
if session == nil {
Expand Down Expand Up @@ -192,7 +192,7 @@ func (wCtx *WebApiContext) GetUserInfo(respWriter http.ResponseWriter, request *
realm := vars[globals.RealmPathVar]
if !Validate(realm) {
wCtx.Logger.Debug(sf.Format("Get UserInfo: is invalid realmName: '{0}'", realm))
status := http.StatusBadRequest
status = http.StatusBadRequest
result := dto.ErrorDetails{Msg: sf.Format(errors.InvalidRealm, realm)}
afterHandle(&respWriter, status, &result)
return
Expand Down Expand Up @@ -240,7 +240,6 @@ func (wCtx *WebApiContext) GetUserInfo(respWriter http.ResponseWriter, request *
result = dto.ErrorDetails{Msg: errors.InvalidTokenMsg, Description: errors.InvalidTokenDesc}
} else {
user, _ := (*wCtx.DataProvider).GetUserById(realmPtr.Name, session.UserId)
status = http.StatusOK
if user != nil {
result = user.GetUserInfo()
}
Expand Down Expand Up @@ -434,6 +433,7 @@ func isTokenRefreshRequest(tokenIssueData *dto.TokenGenerationData) bool {
}

// reserved for future use
// nolint unused
func getUserIP(r *http.Request) string {
IPAddress := r.Header.Get("X-Real-Ip")
if IPAddress == "" {
Expand Down
31 changes: 16 additions & 15 deletions api/routing_fuzzing_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package api

import (
"context"
"encoding/base64"
"encoding/json"
"io"
Expand Down Expand Up @@ -74,9 +75,9 @@ func FuzzTestIssueNewTokenWithWrongClientId(f *testing.F) {
f.Add("")
f.Add("0")
f.Add("00")

f.Fuzz(func(t *testing.T, clientId string) {
initApp(t)
t.Parallel()
issueNewToken(t, clientId, testClient1Secret, "vano", "1234567890", 400)
})
}
Expand All @@ -85,9 +86,9 @@ func FuzzTestIssueNewTokenWithWrongClientSecret(f *testing.F) {
f.Add("\x00fb6Z4RsOadVycQoeQiN57xpu8w8wplYz")
f.Add("fb6Z4RsOadVycQoeQiN57xpu8w8wplYz_!")
f.Add("")

f.Fuzz(func(t *testing.T, clientSecret string) {
initApp(t)
t.Parallel()
issueNewToken(t, testClient1, clientSecret, "vano", "1234567890", 400)
})
}
Expand All @@ -96,9 +97,9 @@ func FuzzTestIssueNewTokenWithWrongUsername(f *testing.F) {
f.Add("\x00vano")
f.Add("!")
f.Add("")

f.Fuzz(func(t *testing.T, username string) {
initApp(t)
t.Parallel()
issueNewToken(t, testClient1, testClient1Secret, username, "1234567890", 401)
})
}
Expand All @@ -107,9 +108,9 @@ func FuzzTestIssueNewTokenWithWrongPassword(f *testing.F) {
f.Add("\x001234567890")
f.Add("!")
f.Add("")

f.Fuzz(func(t *testing.T, password string) {
initApp(t)
t.Parallel()
issueNewToken(t, testClient1, testClient1Secret, "vano", password, 401)
})
}
Expand All @@ -118,9 +119,9 @@ func FuzzTestIntrospectTokenWithWrongClientId(f *testing.F) {
f.Add("\x001234567890")
f.Add("!")
f.Add("")

f.Fuzz(func(t *testing.T, clientId string) {
initApp(t)
t.Parallel()
token := getToken(t)
checkIntrospectToken(t, token.AccessToken, clientId, testClient1Secret, testRealm1, 401)
})
Expand All @@ -130,9 +131,9 @@ func FuzzTestIntrospectTokenWithWrongSecret(f *testing.F) {
f.Add("\x001234567890")
f.Add("!")
f.Add("")

f.Fuzz(func(t *testing.T, clientSecret string) {
initApp(t)
t.Parallel()
token := getToken(t)
checkIntrospectToken(t, token.AccessToken, testClient1, clientSecret, testRealm1, 401)
})
Expand All @@ -143,9 +144,9 @@ func FuzzTestIntrospectTokenWithWrongToken(f *testing.F) {
f.Add("\x001234567890")
f.Add("!")
f.Add("")

f.Fuzz(func(t *testing.T, token string) {
initApp(t)
t.Parallel()
checkIntrospectToken(t, token, testClient1, testClient1Secret, testRealm1, 401)
})
}
Expand All @@ -156,9 +157,9 @@ func FuzzTestRefreshTokenWithWrongToken(f *testing.F) {
f.Add("")
f.Add("0")
f.Add("00")

f.Fuzz(func(t *testing.T, token string) {
initApp(t)
t.Parallel()
refreshToken(t, testClient1, testClient1Secret, token, 401)
})
}
Expand All @@ -168,14 +169,13 @@ func FuzzTestGetUserInfoWithWrongToken(f *testing.F) {
f.Add("00")
f.Add(" ")
f.Add("\n\n")

f.Fuzz(func(t *testing.T, token string) {
initApp(t)
expectedStatusCode := 401
if !isTokenValid(t, token) || len(token) == 0 {
expectedStatusCode = 400
}
initApp(t)
t.Parallel()
t.Helper()
userInfoUrlTemplate := "{0}/auth/realms/{1}/protocol/openid-connect/userinfo/"
doRequest(
t, "GET", userInfoUrlTemplate, testRealm1, nil,
Expand All @@ -188,7 +188,8 @@ func initApp(t *testing.T) application.AppRunner {
t.Helper()
app := application.CreateAppWithData(&httpAppConfig, &testServerData, testKey, true)
t.Cleanup(func() {
app.Stop()
_, err := app.Stop(context.Background())
require.NoError(t, err)
})
res, err := app.Init()
assert.True(t, res)
Expand Down Expand Up @@ -229,12 +230,11 @@ func setGetTokenFormData(clientId, clientSecret, grantType, username, password,

func doPostForm(t *testing.T, reqUrl string, urlData url.Values, expectedStatus int) *http.Response {
t.Helper()
response, _ := http.PostForm(reqUrl, urlData)
response, err := http.PostForm(reqUrl, urlData)
require.NoError(t, err)
if response != nil {
require.Equal(t, response.StatusCode, expectedStatus)
}
// todo(yurishang): sometimes there is an Net Op error when running a fuzz test
// in line 'response, _ := http.PostForm(reqUrl, urlData)'
return response
}

Expand Down Expand Up @@ -309,6 +309,7 @@ func getDataFromResponse[TR dto.Token | dto.ErrorDetails](t *testing.T, response
func isTokenValid(t *testing.T, token string) bool {
// Checking that the token doesn't contains space characters only.
// If yes, then the token is not valid - the expected status code is 400. Otherwise - 401.
t.Helper()
pattern := "[ \n\t]+"
match, _ := regexp.MatchString(pattern, token)
return !match
Expand Down
Loading
Loading