未验证 提交 4283814a 编写于 作者: 不羁 提交者: GitHub

fix: get application details failed (#481)

Signed-off-by: Nhongming <talonwan@yunify.com>
上级 836c011e
......@@ -28,6 +28,7 @@ type ServerRunOptions struct {
AdminPassword string
TokenExpireTime string
JWTSecret string
AuthRateLimit string
}
func NewServerRunOptions() *ServerRunOptions {
......@@ -42,5 +43,6 @@ func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.AdminPassword, "admin-password", "passw0rd", "default administrator's password")
fs.StringVar(&s.TokenExpireTime, "token-expire-time", "2h", "token expire time,valid time units are \"ns\",\"us\",\"ms\",\"s\",\"m\",\"h\"")
fs.StringVar(&s.JWTSecret, "jwt-secret", "", "jwt secret")
fs.StringVar(&s.AuthRateLimit, "auth-rate-limit", "5/30m", "specifies the maximum number of authentication attempts permitted and time interval,valid time units are \"s\",\"m\",\"h\"")
s.GenericServerRunOptions.AddFlags(fs)
}
......@@ -75,7 +75,7 @@ func Run(s *options.ServerRunOptions) error {
initializeAdminJenkins()
initializeDevOpsDatabase()
err = iam.Init(s.AdminEmail, s.AdminPassword, expireTime)
err = iam.Init(s.AdminEmail, s.AdminPassword, expireTime, s.AuthRateLimit)
jwtutil.Setup(s.JWTSecret)
if err != nil {
......
......@@ -116,7 +116,7 @@ func addWebService(c *restful.Container) error {
Returns(http.StatusOK, ok, iam.TokenReview{}).
Metadata(restfulspec.KeyOpenAPITags, tags))
ws.Route(ws.POST("/login").
To(iam.LoginHandler).
To(iam.Login).
Doc("KubeSphere APIs support token-based authentication via the Authtoken request header. The POST Login API is used to retrieve the authentication token. After the authentication token is obtained, it must be inserted into the Authtoken header for all requests.").
Reads(iam.LoginRequest{}).
Returns(http.StatusOK, ok, models.Token{}).
......
......@@ -55,7 +55,7 @@ const (
KindTokenReview = "TokenReview"
)
func LoginHandler(req *restful.Request, resp *restful.Response) {
func Login(req *restful.Request, resp *restful.Response) {
var loginRequest LoginRequest
err := req.ReadEntity(&loginRequest)
......@@ -70,6 +70,10 @@ func LoginHandler(req *restful.Request, resp *restful.Response) {
token, err := iam.Login(loginRequest.Username, loginRequest.Password, ip)
if err != nil {
if serviceError, ok := err.(restful.ServiceError); ok {
resp.WriteHeaderAndEntity(serviceError.Code, errors.New(serviceError.Message))
return
}
resp.WriteHeaderAndEntity(http.StatusUnauthorized, errors.Wrap(err))
return
}
......
......@@ -60,7 +60,7 @@ var (
defaultRoles = []rbac.Role{
{ObjectMeta: metav1.ObjectMeta{Name: "admin", Annotations: map[string]string{constants.DescriptionAnnotationKey: adminDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}},
{ObjectMeta: metav1.ObjectMeta{Name: "operator", Annotations: map[string]string{constants.DescriptionAnnotationKey: operatorDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}},
{Verbs: []string{"*"}, APIGroups: []string{"", "apps", "extensions", "batch", "logging.kubesphere.io", "monitoring.kubesphere.io", "iam.kubesphere.io", "resources.kubesphere.io", "autoscaling", "alerting.kubesphere.io", "app.k8s.io", "servicemesh.kubesphere.io"}, Resources: []string{"*"}}}},
{Verbs: []string{"*"}, APIGroups: []string{"", "apps", "extensions", "batch", "logging.kubesphere.io", "monitoring.kubesphere.io", "iam.kubesphere.io", "resources.kubesphere.io", "autoscaling", "alerting.kubesphere.io", "app.k8s.io", "servicemesh.kubesphere.io", "operations.kubesphere.io"}, Resources: []string{"*"}}}},
{ObjectMeta: metav1.ObjectMeta{Name: "viewer", Annotations: map[string]string{constants.DescriptionAnnotationKey: viewerDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}},
}
)
......
......@@ -148,6 +148,11 @@ func getWorkLoads(namespace string, clusterRoles []openpitrix.ClusterRole) (*wor
item, err := informers.SharedInformerFactory().Apps().V1().Deployments().Lister().Deployments(namespace).Get(name)
if err != nil {
// app not ready
if errors.IsNotFound(err) {
continue
}
glog.Error(err)
return nil, err
}
......@@ -159,6 +164,11 @@ func getWorkLoads(namespace string, clusterRoles []openpitrix.ClusterRole) (*wor
name := strings.Split(workLoadName, openpitrix.DaemonSuffix)[0]
item, err := informers.SharedInformerFactory().Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name)
if err != nil {
// app not ready
if errors.IsNotFound(err) {
continue
}
glog.Error(err)
return nil, err
}
works.Daemonsets = append(works.Daemonsets, *item)
......@@ -169,6 +179,11 @@ func getWorkLoads(namespace string, clusterRoles []openpitrix.ClusterRole) (*wor
name := strings.Split(workLoadName, openpitrix.StateSuffix)[0]
item, err := informers.SharedInformerFactory().Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name)
if err != nil {
// app not ready
if errors.IsNotFound(err) {
continue
}
glog.Error(err)
return nil, err
}
works.Statefulsets = append(works.Statefulsets, *item)
......
......@@ -56,10 +56,12 @@ import (
)
var (
adminEmail string
adminPassword string
tokenExpireTime time.Duration
initUsers []initUser
adminEmail string
adminPassword string
tokenExpireTime time.Duration
maxAuthFailed int
authTimeInterval time.Duration
initUsers []initUser
)
type initUser struct {
......@@ -68,14 +70,17 @@ type initUser struct {
}
const (
userInitFile = "/etc/ks-iam/users.json"
userInitFile = "/etc/ks-iam/users.json"
authRateLimitRegex = `(\d+)/(\d+[s|m|h])`
defaultMaxAuthFailed = 5
defaultAuthTimeInterval = 30 * time.Minute
)
func Init(email, password string, t time.Duration) error {
func Init(email, password string, expireTime time.Duration, authRateLimit string) error {
adminEmail = email
adminPassword = password
tokenExpireTime = t
tokenExpireTime = expireTime
maxAuthFailed, authTimeInterval = parseAuthRateLimit(authRateLimit)
conn, err := ldapclient.Client()
if err != nil {
......@@ -101,6 +106,23 @@ func Init(email, password string, t time.Duration) error {
return nil
}
func parseAuthRateLimit(authRateLimit string) (int, time.Duration) {
regex := regexp.MustCompile(authRateLimitRegex)
groups := regex.FindStringSubmatch(authRateLimit)
maxCount := defaultMaxAuthFailed
timeInterval := defaultAuthTimeInterval
if len(groups) == 3 {
maxCount, _ = strconv.Atoi(groups[1])
timeInterval, _ = time.ParseDuration(groups[2])
} else {
glog.Warning("invalid auth rate limit", authRateLimit)
}
return maxCount, timeInterval
}
func checkAndCreateDefaultGroup(conn ldap.Client) error {
groupSearchRequest := ldap.NewSearchRequest(
......@@ -203,9 +225,23 @@ func createGroupsBaseDN(conn ldap.Client) error {
// User login
func Login(username string, password string, ip string) (*models.Token, error) {
redisClient := redis.Client()
records, err := redisClient.Keys(fmt.Sprintf("kubesphere:authfailed:%s:*", username)).Result()
if err != nil {
glog.Error(err)
return nil, err
}
if len(records) >= maxAuthFailed {
return nil, restful.NewError(http.StatusTooManyRequests, "auth rate limit exceeded")
}
conn, err := ldapclient.Client()
if err != nil {
glog.Error(err)
return nil, err
}
......@@ -237,7 +273,13 @@ func Login(username string, password string, ip string) (*models.Token, error) {
err = conn.Bind(dn, password)
if err != nil {
glog.Errorln("auth error", username, err)
glog.Infoln("auth failed", username, err)
if ldap.IsErrorWithCode(err, ldap.LDAPResultInvalidCredentials) {
loginFailedRecord := fmt.Sprintf("kubesphere:authfailed:%s:%d", username, time.Now().UnixNano())
redisClient.Set(loginFailedRecord, "", authTimeInterval)
}
return nil, err
}
......@@ -876,6 +918,17 @@ func UpdateUser(user *models.User) (*models.User, error) {
return nil, err
}
// clear auth failed record
if user.Password != "" {
redisClient := redis.Client()
records, err := redisClient.Keys(fmt.Sprintf("kubesphere:authfailed:%s:*", user.Username)).Result()
if err == nil {
redisClient.Del(records...)
}
}
return GetUserInfo(user.Username)
}
func DeleteGroup(path string) error {
......
......@@ -18,6 +18,7 @@
package resources
import (
"fmt"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/params"
......@@ -45,6 +46,11 @@ func (*nodeSearcher) match(match map[string]string, item *v1.Node) bool {
if !sliceutil.HasString(names, item.Name) {
return false
}
case Role:
labelKey := fmt.Sprintf("node-role.kubernetes.io/%s", v)
if _, ok := item.Labels[labelKey]; !ok {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
return false
......
......@@ -61,6 +61,7 @@ const (
Label = "label"
OwnerKind = "ownerKind"
OwnerName = "ownerName"
Role = "role"
CreateTime = "createTime"
UpdateTime = "updateTime"
LastScheduleTime = "lastScheduleTime"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册