Skip to content
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

test action #2652

Closed
wants to merge 42 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
50d12ce
the draft
ljzsmllx Aug 29, 2022
bb90465
the draft
ljzsmllx Aug 29, 2022
eb04071
the draft
ljzsmllx Aug 29, 2022
9ad0838
use coreos/go-oidc and golang/oauth2
ljzsmllx Sep 3, 2022
674db45
use coreos/go-oidc and golang/oauth2
ljzsmllx Sep 3, 2022
f701b3f
add go test files
ljzsmllx Sep 7, 2022
cb2db81
fix the code style
ljzsmllx Sep 8, 2022
c1c1e35
change 'redirect_uri' to 'redirect_url'
ljzsmllx Sep 12, 2022
af85d9e
add e2e test files to api/test/e2e/oidc
ljzsmllx Sep 13, 2022
d8e8dd2
.
ljzsmllx Sep 29, 2022
43f72d8
update oidc e2e test files
ljzsmllx Sep 29, 2022
292d8e1
add 'createUser' block
ljzsmllx Oct 17, 2022
b156580
update oidc_test.go
ljzsmllx Oct 18, 2022
6c82c6f
delete redundancy in code
ljzsmllx Oct 18, 2022
c09a631
fix some problems
ljzsmllx Oct 20, 2022
1ce5c37
fix the problems of e2e test
ljzsmllx Oct 24, 2022
f89333d
fix problems of gitLeaks
ljzsmllx Oct 24, 2022
ee74d0b
fix problems of check-license
ljzsmllx Oct 24, 2022
566e3e6
add actions file
ljzsmllx Oct 24, 2022
6477899
add actions file
ljzsmllx Oct 25, 2022
11f5fca
add files
ljzsmllx Oct 25, 2022
8d76025
add files
ljzsmllx Oct 25, 2022
fe74929
add submodule
ljzsmllx Oct 25, 2022
ae809ae
try
ljzsmllx Oct 26, 2022
b512316
try
ljzsmllx Oct 26, 2022
7d19aec
Merge github.com:ljzsmllx/apisix-dashboard
ljzsmllx Oct 26, 2022
8a4be77
Revert "try"
ljzsmllx Oct 26, 2022
c986144
fix problems of e2e test
ljzsmllx Oct 26, 2022
47a7e2a
Merge github.com:ljzsmllx/apisix-dashboard
ljzsmllx Oct 26, 2022
b1e655b
fix e2e 1st
ljzsmllx Oct 26, 2022
de011a2
fix e2e 2nd
ljzsmllx Oct 26, 2022
32c426a
fix e2e 3rd
ljzsmllx Oct 26, 2022
2b2f0b3
fix e2e 4th
ljzsmllx Oct 26, 2022
a2b0032
fix e2e
ljzsmllx Oct 27, 2022
925c0f4
fix e2e
ljzsmllx Oct 27, 2022
d409d9f
fix e2e
ljzsmllx Oct 27, 2022
693301c
fix e2e
ljzsmllx Oct 27, 2022
5552635
fix e2e
ljzsmllx Oct 27, 2022
27bacb3
fix e2e finally
ljzsmllx Oct 27, 2022
a553270
fix some nits
ljzsmllx Oct 28, 2022
42845cd
fix
starsz Oct 28, 2022
f406355
fix: gitleaks
starsz Oct 28, 2022
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
2 changes: 2 additions & 0 deletions .github/workflows/backend-e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ jobs:
sed -i '[email protected]@0.0.0.0/0@' ./api/conf/conf.yaml
sed -i '/172.16.238.10:2379/a\ - 172.16.238.11:2379' ./api/conf/conf.yaml
sed -i '/172.16.238.10:2379/a\ - 172.16.238.12:2379' ./api/conf/conf.yaml
sed -i '[email protected]/0:[email protected]:9000@' ./api/conf/conf.yaml


- name: download file Dockerfile-apisix
working-directory: ./api/test/docker
Expand Down
12 changes: 7 additions & 5 deletions api/conf/conf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,13 @@ authentication:

oidc:
expire_time: 3600
app_name: authing
client_id:
client_secret:
scope: oidc
redirect_uri: oidc/callback
client_id: dashboard
client_secret: dashboard
auth_url: http://172.17.0.1:8080/auth/realms/master/protocol/openid-connect/auth
token_url: http://172.17.0.1:8080/auth/realms/master/protocol/openid-connect/token
user_info_url: http://172.17.0.1:8080/auth/realms/master/protocol/openid-connect/userinfo
redirect_url: http://127.0.0.1:9000/apisix/admin/oidc/callback
scope: openid

plugins: # plugin list (sorted in alphabetical order)
- api-breaker
Expand Down
9 changes: 5 additions & 4 deletions api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ replace github.com/coreos/bbolt => go.etcd.io/bbolt v1.3.5
require (
github.com/coreos/bbolt v1.3.2 // indirect
github.com/coreos/etcd v3.3.25+incompatible // indirect
github.com/coreos/go-oidc/v3 v3.3.0
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
Expand All @@ -19,6 +20,7 @@ require (
github.com/gin-gonic/gin v1.6.3
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.2.0 // indirect
github.com/gorilla/sessions v1.2.1
github.com/gorilla/websocket v1.4.2 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
Expand All @@ -32,16 +34,15 @@ require (
github.com/sony/sonyflake v1.0.0
github.com/spf13/cobra v0.0.3
github.com/spf13/viper v1.8.1
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.7.1
github.com/tidwall/gjson v1.6.7
github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966 // indirect
github.com/xeipuuv/gojsonschema v1.2.0
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da
go.etcd.io/etcd v3.3.25+incompatible
go.uber.org/zap v1.17.0
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect
golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
)
174 changes: 163 additions & 11 deletions api/go.sum

Large diffs are not rendered by default.

27 changes: 21 additions & 6 deletions api/internal/conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ import (
"runtime"
"strings"

"github.com/gorilla/sessions"
"github.com/spf13/viper"
"github.com/tidwall/gjson"
"golang.org/x/oauth2"

"github.com/apisix/manager-api/internal/utils"
)
Expand All @@ -39,6 +41,7 @@ const (
EnvTEST = "test"

WebDir = "html/"
State = "123456"
)

var (
Expand All @@ -58,12 +61,16 @@ var (
AccessLogPath = "logs/access.log"
UserList = make(map[string]User, 2)
AuthConf Authentication
OidcConf Oidc
SSLDefaultStatus = 1 //enable ssl by default
ImportSizeLimit = 10 * 1024 * 1024
AllowList []string
Plugins = map[string]bool{}
SecurityConf Security
CookieStore = sessions.NewCookieStore([]byte("oidc"))
OidcId string
OidcConfig oauth2.Config
OidcExpireTime int
OidcUserInfoURL string
)

type MTLS struct {
Expand Down Expand Up @@ -129,11 +136,13 @@ type Authentication struct {

type Oidc struct {
ExpireTime int `mapstructure:"expire_time" yaml:"expire_time"`
AppName string `mapstructure:"app_name"`
ClientId string `mapstructure:"client_id"`
ClientID string `mapstructure:"client_id"`
ClientSecret string `mapstructure:"client_secret"`
AuthURL string `mapstructure:"auth_url"`
TokenURL string `mapstructure:"token_url"`
UserInfoURL string `mapstructure:"user_info_url"`
RedirectURL string `mapstructure:"redirect_url"`
Scope string
RedirectUri string `mapstructure:"redirect_uri"`
}

type Config struct {
Expand Down Expand Up @@ -267,7 +276,7 @@ func setupConfig() {
// set authentication
initAuthentication(config.Authentication)

//set Oidc
// set Oidc
initOidc(config.Oidc)

// set plugin
Expand Down Expand Up @@ -298,7 +307,13 @@ func initAuthentication(conf Authentication) {
}

func initOidc(conf Oidc) {
OidcConf = conf
OidcExpireTime = conf.ExpireTime
OidcConfig.ClientID = conf.ClientID
OidcConfig.ClientSecret = conf.ClientSecret
OidcConfig.Endpoint = oauth2.Endpoint{AuthURL: conf.AuthURL, TokenURL: conf.TokenURL, AuthStyle: 1}
OidcConfig.Scopes = append(OidcConfig.Scopes, conf.Scope)
OidcConfig.RedirectURL = conf.RedirectURL
OidcUserInfoURL = conf.UserInfoURL
}

func initPlugins(plugins []string) {
Expand Down
75 changes: 41 additions & 34 deletions api/internal/filter/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
package filter

import (
"net/http"
"strings"

"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt"
"net/http"
"strings"

"github.com/apisix/manager-api/internal/conf"
"github.com/apisix/manager-api/internal/log"
Expand All @@ -36,46 +35,54 @@ func Authentication() gin.HandlerFunc {
return
}

tokenStr := c.GetHeader("Authorization")
// verify token
token, err := jwt.ParseWithClaims(tokenStr, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(conf.AuthConf.Secret), nil
})

cookie, _ := conf.CookieStore.Get(c.Request, "oidc")
errResp := gin.H{
"code": 010013,
"message": "request unauthorized",
}

if err != nil || token == nil || !token.Valid {
log.Warnf("token validate failed: %s", err)
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}
if cookie.IsNew {
tokenStr := c.GetHeader("Authorization")
// verify token
token, err := jwt.ParseWithClaims(tokenStr, &jwt.StandardClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(conf.AuthConf.Secret), nil
})

claims, ok := token.Claims.(*jwt.StandardClaims)
if !ok {
log.Warnf("token validate failed: %s, %v", err, token.Valid)
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}
if err != nil || token == nil || !token.Valid {
log.Warnf("token validate failed: %s", err)
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}

if err := token.Claims.Valid(); err != nil {
log.Warnf("token claims validate failed: %s", err)
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}
claims, ok := token.Claims.(*jwt.StandardClaims)
if !ok {
log.Warnf("token validate failed: %s, %v", err, token.Valid)
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}

if claims.Subject == "" {
log.Warn("token claims subject empty")
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}
if err := token.Claims.Valid(); err != nil {
log.Warnf("token claims validate failed: %s", err)
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}

if _, ok := conf.UserList[claims.Subject]; !ok {
log.Warnf("user not exists by token claims subject %s", claims.Subject)
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
if claims.Subject == "" {
log.Warn("token claims subject empty")
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}

if _, ok := conf.UserList[claims.Subject]; !ok {
log.Warnf("user not exists by token claims subject %s", claims.Subject)
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}
} else {
if cookie.Values["oidc_id"] != conf.OidcId {
c.AbortWithStatusJSON(http.StatusUnauthorized, errResp)
return
}
}

c.Next()
Expand Down
100 changes: 100 additions & 0 deletions api/internal/filter/oidc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package filter

import (
"net/http"

"github.com/coreos/go-oidc/v3/oidc"
"github.com/gin-gonic/gin"
"golang.org/x/oauth2"

"github.com/apisix/manager-api/internal/conf"
"github.com/apisix/manager-api/internal/log"
)

type Token struct {
AccessToken string
}

func (token *Token) Token() (*oauth2.Token, error) {
oauth2Token := &oauth2.Token{AccessToken: token.AccessToken}
return oauth2Token, nil
}

func Oidc() gin.HandlerFunc {
return func(c *gin.Context) {
if c.Request.URL.Path == "/apisix/admin/oidc/login" {
url := conf.OidcConfig.AuthCodeURL(conf.State)
c.Redirect(302, url)
c.Abort()
return
}

if c.Request.URL.Path == "/apisix/admin/oidc/callback" {
state := c.Query("state")
if state != conf.State {
log.Warn("the state does not match")
c.AbortWithStatus(http.StatusForbidden)
return
}

// in exchange for token
oauth2Token, err := conf.OidcConfig.Exchange(c, c.Query("code"))
if err != nil {
log.Warnf("exchange code for token failed: %s", err)
c.AbortWithStatus(http.StatusForbidden)
return
}

// in exchange for user's information
token := &Token{oauth2Token.AccessToken}
providerConfig := oidc.ProviderConfig{UserInfoURL: conf.OidcUserInfoURL}
provider := providerConfig.NewProvider(c)
userInfo, err := provider.UserInfo(c, token)
if err != nil {
log.Warnf("exchange access_token for user's information failed: %s", err)
c.AbortWithStatus(http.StatusForbidden)
return
}

// set the cookie
conf.CookieStore.MaxAge(conf.OidcExpireTime)
cookie, _ := conf.CookieStore.Get(c.Request, "oidc")
cookie.Values["oidc_id"] = userInfo.Subject
conf.OidcId = userInfo.Subject
cookie.Save(c.Request, c.Writer)
c.AbortWithStatus(http.StatusOK)
return
}

if c.Request.URL.Path == "/apisix/admin/oidc/logout" {
cookie, _ := conf.CookieStore.Get(c.Request, "oidc")
if cookie.IsNew {
c.AbortWithStatus(http.StatusForbidden)
return
}

cookie.Options.MaxAge = -1
cookie.Save(c.Request, c.Writer)
c.AbortWithStatus(http.StatusOK)
return
}

c.Next()
}
}
2 changes: 1 addition & 1 deletion api/internal/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func SetUpRouter() *gin.Engine {
r := gin.New()
logger := log.GetLogger(log.AccessLog)
// security
r.Use(filter.RequestLogHandler(logger), filter.IPFilter(), filter.InvalidRequest(), filter.Authentication())
r.Use(filter.RequestLogHandler(logger), filter.IPFilter(), filter.InvalidRequest(), filter.Oidc(), filter.Authentication())

// misc
r.Use(gzip.Gzip(gzip.DefaultCompression), filter.CORS(), filter.RequestId(), filter.SchemaCheck(), filter.RecoverHandler())
Expand Down
9 changes: 9 additions & 0 deletions api/test/docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,15 @@ services:
apisix_dashboard_e2e:
ipv4_address: 172.16.238.50

keycloak:
image: jboss/keycloak:9.0.2
environment:
- KEYCLOAK_USER=admin
- KEYCLOAK_PASSWORD=admin
- DB_VENDOR=h2
ports:
- "8080:8080"

networks:
apisix_dashboard_e2e:
driver: bridge
Expand Down
5 changes: 4 additions & 1 deletion api/test/e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ module github.com/apisix/manager-api/test/e2e
go 1.15

require (
github.com/Nerzal/gocloak/v11 v11.2.0
github.com/PuerkitoBio/goquery v1.8.0
github.com/gavv/httpexpect/v2 v2.3.1
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.16.0
github.com/stretchr/testify v1.7.0
github.com/savsgio/gotils v0.0.0-20210617111740-97865ed5a873
github.com/stretchr/testify v1.7.1
github.com/tidwall/gjson v1.11.0
)
Loading