Compare commits
	
		
			1 Commits
		
	
	
		
			main
			...
			correct-oc
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 28e6f1e043 | 
| @@ -10,6 +10,9 @@ RUN go mod download | ||||
|  | ||||
| FROM golang:alpine AS builder | ||||
|  | ||||
| ARG HOSTNAME=http://localhost | ||||
| ARG NAME=auth | ||||
|  | ||||
| RUN apk add git | ||||
|  | ||||
| RUN go install github.com/beego/bee/v2@latest | ||||
|   | ||||
							
								
								
									
										21
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								Makefile
									
									
									
									
									
								
							| @@ -6,14 +6,6 @@ build: clean | ||||
| run: | ||||
| 	bee run -gendoc=true -downdoc=true | ||||
|  | ||||
| purge: | ||||
| 	lsof -t -i:8094 | xargs kill | true | ||||
|  | ||||
| run-dev: | ||||
| 	bee generate routers && bee run -gendoc=true -downdoc=true -runmode=prod | ||||
|  | ||||
| dev: purge run-dev | ||||
|  | ||||
| debug: | ||||
| 	bee run -downdebug -gendebug | ||||
|  | ||||
| @@ -21,20 +13,15 @@ clean: | ||||
| 	rm -rf oc-auth oc-auth.tar.gz | ||||
|  | ||||
| docker: | ||||
| 	DOCKER_BUILDKIT=1 docker build -t oc-auth -f Dockerfile . --build-arg=HOST=$(HOST) | ||||
| 	docker tag oc-auth:latest oc/oc-auth:0.0.1 | ||||
| 	DOCKER_BUILDKIT=1 docker build -t oc/oc-auth:0.0.1 -f Dockerfile . | ||||
| 	docker tag oc/oc-auth:0.0.1 oc/oc-auth:latest | ||||
|  | ||||
| publish-kind: | ||||
| 	kind load docker-image oc/oc-auth:0.0.1 --name opencloud | true | ||||
| 	kind load docker-image oc/oc-auth:0.0.1 --name opencloud | ||||
|  | ||||
| publish-registry: | ||||
| 	@echo "TODO" | ||||
|  | ||||
| docker-deploy: | ||||
| 	docker compose up -d | ||||
|  | ||||
| run-docker: docker publish-kind publish-registry docker-deploy | ||||
|  | ||||
| all: docker publish-kind publish-registry | ||||
|  | ||||
| .PHONY: build run clean docker publish-kind publish-registry | ||||
| .PHONY: build run clean docker publish-kind publish-registry | ||||
| @@ -7,9 +7,6 @@ To build : | ||||
|     bee generate routers | ||||
|     bee run -gendoc=true -downdoc=true | ||||
|  | ||||
| OR  | ||||
|     make dev | ||||
|  | ||||
| If default Swagger page is displayed instead of tyour api, change url in swagger/index.html file to : | ||||
|  | ||||
|     url: "swagger.json" | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| { | ||||
|     "port": 8080, | ||||
|     "MONGO_URL":"mongodb://localhost:27017/",  | ||||
|     "MONGO_DATABASE":"DC_myDC", | ||||
|     "NATS_URL": "nats://localhost:4222", | ||||
|     "LDAP_ENDPOINTS": "localhost:390", | ||||
|     "port": 8094 | ||||
|     "natsurl":"http://localhost:4080",  | ||||
|     "login":"admin",  | ||||
|     "password":"admin", | ||||
|     "oidcserver":"http://localhost:8080" | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| appname = oc-auth | ||||
| httpport = 8094 | ||||
| httpport = 8080 | ||||
| runmode = dev | ||||
| autorender = false | ||||
| copyrequestbody = true | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package conf | ||||
| import "sync" | ||||
|  | ||||
| type Config struct { | ||||
| 	SourceMode     string | ||||
| 	AdminRole      string | ||||
| 	PublicKeyPath  string | ||||
| 	PrivateKeyPath string | ||||
| @@ -14,22 +13,16 @@ type Config struct { | ||||
| 	LDAPBaseDN     string | ||||
| 	LDAPRoleBaseDN string | ||||
|  | ||||
| 	ClientSecret                string | ||||
| 	OAuth2ClientSecretName      string | ||||
| 	OAuth2ClientSecretNamespace string | ||||
| 	ClientSecret string | ||||
|  | ||||
| 	Auth                   string | ||||
| 	AuthConnectPublicHost  string | ||||
| 	AuthConnectorHost      string | ||||
| 	AuthConnectorPort      int | ||||
| 	AuthConnectorAdminPort string | ||||
| 	AuthConnectorAdminPort int | ||||
|  | ||||
| 	PermissionConnectorWriteHost string | ||||
| 	PermissionConnectorReadHost  string | ||||
| 	PermissionConnectorPort      string | ||||
| 	PermissionConnectorAdminPort string | ||||
|  | ||||
| 	Local bool | ||||
| 	PermissionConnectorHost      string | ||||
| 	PermissionConnectorPort      int | ||||
| 	PermissionConnectorAdminPort int | ||||
| } | ||||
|  | ||||
| var instance *Config | ||||
|   | ||||
| @@ -19,8 +19,7 @@ type GroupController struct { | ||||
| func (o *GroupController) Post() { | ||||
| 	// store and return Id or post with UUID | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	group, code, err := infrastructure.GetPermissionConnector(clientID).CreateGroup(id) | ||||
| 	group, code, err := infrastructure.GetPermissionConnector().CreateGroup(id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -45,8 +44,7 @@ func (o *GroupController) Post() { | ||||
| // @router /user/:id [get] | ||||
| func (o *GroupController) GetByUser() { | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	group, err := infrastructure.GetPermissionConnector(clientID).GetGroupByUser(id) | ||||
| 	group, err := infrastructure.GetPermissionConnector().GetGroupByUser(id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -69,8 +67,7 @@ func (o *GroupController) GetByUser() { | ||||
| // @Success 200 {group} string | ||||
| // @router / [get] | ||||
| func (o *GroupController) GetAll() { | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	group, err := infrastructure.GetPermissionConnector(clientID).GetGroup("") | ||||
| 	group, err := infrastructure.GetPermissionConnector().GetGroup("") | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -95,8 +92,7 @@ func (o *GroupController) GetAll() { | ||||
| // @router /:id [get] | ||||
| func (o *GroupController) Get() { | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	group, err := infrastructure.GetPermissionConnector(clientID).GetGroup(id) | ||||
| 	group, err := infrastructure.GetPermissionConnector().GetGroup(id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -121,8 +117,7 @@ func (o *GroupController) Get() { | ||||
| // @router /:id [delete] | ||||
| func (o *GroupController) Delete() { | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	group, code, err := infrastructure.GetPermissionConnector(clientID).DeleteGroup(id) | ||||
| 	group, code, err := infrastructure.GetPermissionConnector().DeleteGroup(id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -145,8 +140,7 @@ func (o *GroupController) Delete() { | ||||
| // @Success 200 {string} delete success! | ||||
| // @router /clear [delete] | ||||
| func (o *GroupController) Clear() { | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	group, code, err := infrastructure.GetPermissionConnector(clientID).DeleteGroup("") | ||||
| 	group, code, err := infrastructure.GetPermissionConnector().DeleteGroup("") | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -173,8 +167,7 @@ func (o *GroupController) Clear() { | ||||
| func (o *GroupController) Bind() { | ||||
| 	user_id := o.Ctx.Input.Param(":user_id") | ||||
| 	group_id := o.Ctx.Input.Param(":group_id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	group, code, err := infrastructure.GetPermissionConnector(clientID).BindGroup(user_id, group_id) | ||||
| 	group, code, err := infrastructure.GetPermissionConnector().BindGroup(user_id, group_id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -194,15 +187,14 @@ func (o *GroupController) Bind() { | ||||
|  | ||||
| // @Title UnBind | ||||
| // @Description unbind the group to user | ||||
| // @Param	user_id		path 	string	true		"The group_id you want to unbind" | ||||
| // @Param	group_id		path 	string	true		"The group_id you want to unbind" | ||||
| // @Param	group_id		path 	string	true		"The user_id you want to unbind" | ||||
| // @Success 200 {string} bind success! | ||||
| // @router /:user_id/:group_id [delete] | ||||
| func (o *GroupController) UnBind() { | ||||
| 	user_id := o.Ctx.Input.Param(":user_id") | ||||
| 	group_id := o.Ctx.Input.Param(":group_id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	group, code, err := infrastructure.GetPermissionConnector(clientID).UnBindGroup(user_id, group_id) | ||||
| 	group, code, err := infrastructure.GetPermissionConnector().UnBindGroup(user_id, group_id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
|   | ||||
| @@ -1,17 +1,13 @@ | ||||
| package controllers | ||||
|  | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"oc-auth/conf" | ||||
| 	"oc-auth/infrastructure" | ||||
| 	auth_connectors "oc-auth/infrastructure/auth_connector" | ||||
| 	"oc-auth/infrastructure/claims" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	oclib "cloud.o-forge.io/core/oc-lib" | ||||
| 	model "cloud.o-forge.io/core/oc-lib/models/peer" | ||||
| @@ -26,12 +22,10 @@ type OAuthController struct { | ||||
| // @Title Logout | ||||
| // @Description unauthenticate user | ||||
| // @Param	Authorization		header  string	false "auth token" | ||||
| // @Param   client_id   query    string  true        "the client_id you want to get" | ||||
| // @Success 200 {string} | ||||
| // @router /logout [delete] | ||||
| func (o *OAuthController) LogOut() { | ||||
| // @router /ldap/logout [delete] | ||||
| func (o *OAuthController) LogOutLDAP() { | ||||
| 	// authorize user | ||||
| 	clientID := o.Ctx.Input.Query("client_id") | ||||
| 	reqToken := o.Ctx.Request.Header.Get("Authorization") | ||||
| 	splitToken := strings.Split(reqToken, "Bearer ") | ||||
| 	if len(splitToken) < 2 { | ||||
| @@ -42,15 +36,11 @@ func (o *OAuthController) LogOut() { | ||||
| 	var res auth_connectors.Token | ||||
| 	json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &res) | ||||
|  | ||||
| 	if !conf.GetConfig().Local { | ||||
| 		token, err := infrastructure.GetAuthConnector().Logout(clientID, reqToken) | ||||
| 		if err != nil || token == nil { | ||||
| 			o.Data["json"] = err | ||||
| 		} else { | ||||
| 			o.Data["json"] = token | ||||
| 		} | ||||
| 	token, err := infrastructure.GetAuthConnector().Logout(reqToken) | ||||
| 	if err != nil || token == nil { | ||||
| 		o.Data["json"] = err | ||||
| 	} else { | ||||
| 		o.Data["json"] = reqToken | ||||
| 		o.Data["json"] = token | ||||
| 	} | ||||
| 	o.ServeJSON() | ||||
| } | ||||
| @@ -58,65 +48,30 @@ func (o *OAuthController) LogOut() { | ||||
| // @Title Login | ||||
| // @Description authenticate user | ||||
| // @Param	body		body 	models.workflow	true		"The workflow content" | ||||
| // @Param   client_id   query    string  true        "the client_id you want to get" | ||||
| // @Success 200 {string} | ||||
| // @router /login [post] | ||||
| func (o *OAuthController) Login() { | ||||
| // @router /ldap/login [post] | ||||
| func (o *OAuthController) LoginLDAP() { | ||||
| 	// authorize user | ||||
| 	clientID := o.Ctx.Input.Query("client_id") | ||||
| 	var res auth_connectors.Token | ||||
| 	json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &res) | ||||
|  | ||||
| 	if conf.GetConfig().SourceMode == "ldap" { | ||||
| 		ldap := auth_connectors.New() | ||||
| 		found, err := ldap.Authenticate(o.Ctx.Request.Context(), res.Username, res.Password) | ||||
| 		fmt.Println("login", clientID, found, err) | ||||
| 		if err != nil || !found { | ||||
| 			o.Data["json"] = err | ||||
| 			o.Ctx.ResponseWriter.WriteHeader(401) | ||||
| 			o.ServeJSON() | ||||
| 			return | ||||
| 		} | ||||
| 	ldap := auth_connectors.New() | ||||
| 	found, err := ldap.Authenticate(o.Ctx.Request.Context(), res.Username, res.Password) | ||||
| 	if err != nil || !found { | ||||
| 		o.Data["json"] = err | ||||
| 		o.Ctx.ResponseWriter.WriteHeader(401) | ||||
| 		o.ServeJSON() | ||||
| 		return | ||||
| 	} | ||||
| 	if !conf.GetConfig().Local { | ||||
| 		token, err := infrastructure.GetAuthConnector().Login( | ||||
| 			clientID, res.Username, | ||||
| 			&http.Cookie{ // open a session | ||||
| 				Name:  "csrf_token", | ||||
| 				Value: o.XSRFToken(), | ||||
| 			}) | ||||
| 		fmt.Println("login token", token, err) | ||||
| 		if err != nil || token == nil { | ||||
| 			o.Data["json"] = err | ||||
| 			o.Ctx.ResponseWriter.WriteHeader(401) | ||||
| 		} else { | ||||
| 			o.Data["json"] = token | ||||
| 		} | ||||
| 	token, err := infrastructure.GetAuthConnector().Login(res.Username, | ||||
| 		&http.Cookie{ // open a session | ||||
| 			Name:  "csrf_token", | ||||
| 			Value: o.XSRFToken(), | ||||
| 		}) | ||||
| 	if err != nil || token == nil { | ||||
| 		o.Data["json"] = err | ||||
| 		o.Ctx.ResponseWriter.WriteHeader(401) | ||||
| 	} else { | ||||
| 		t := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), "", "", []string{}, nil).Search( | ||||
| 			nil, fmt.Sprintf("%v", model.SELF.EnumIndex()), false) | ||||
| 		if t.Err == "" && len(t.Data) > 0 { | ||||
| 			token := &auth_connectors.Token{ | ||||
| 				Username:    res.Username, | ||||
| 				Password:    res.Password, | ||||
| 				TokenType:   "Bearer", | ||||
| 				Active:      true, | ||||
| 				ExpiresIn:   3600, | ||||
| 				AccessToken: "localtoken", | ||||
| 			} | ||||
| 			now := time.Now().UTC() | ||||
| 			now = now.Add(time.Duration(token.ExpiresIn) * time.Second) | ||||
| 			unix := now.Unix() | ||||
| 			c := claims.GetClaims().AddClaimsToToken(clientID, res.Username, t.Data[0].(*model.Peer)) | ||||
| 			c.Session.AccessToken["exp"] = unix | ||||
| 			b, _ := json.Marshal(c) | ||||
| 			token.AccessToken = token.AccessToken + "." + base64.StdEncoding.EncodeToString(b) | ||||
| 			o.Data["json"] = token | ||||
|  | ||||
| 		} else { | ||||
| 			o.Data["json"] = t.Err | ||||
| 			o.Ctx.ResponseWriter.WriteHeader(401) | ||||
| 		} | ||||
| 		o.Data["json"] = token | ||||
| 	} | ||||
| 	o.ServeJSON() | ||||
| } | ||||
| @@ -124,24 +79,18 @@ func (o *OAuthController) Login() { | ||||
| // @Title Introspection | ||||
| // @Description introspect token | ||||
| // @Param	body		body 	models.Token	true		"The token info" | ||||
| // @Param   client_id   query    string  true        "the client_id you want to get" | ||||
| // @Success 200 {string} | ||||
| // @router /refresh [post] | ||||
| func (o *OAuthController) Refresh() { | ||||
| 	clientID := o.Ctx.Input.Query("client_id") | ||||
| 	var token auth_connectors.Token | ||||
| 	json.Unmarshal(o.Ctx.Input.CopyBody(100000), &token) | ||||
| 	// refresh token | ||||
| 	if !conf.GetConfig().Local { | ||||
| 		newToken, err := infrastructure.GetAuthConnector().Refresh(clientID, &token) | ||||
| 		if err != nil || newToken == nil { | ||||
| 			o.Data["json"] = err | ||||
| 			o.Ctx.ResponseWriter.WriteHeader(401) | ||||
| 		} else { | ||||
| 			o.Data["json"] = newToken | ||||
| 		} | ||||
| 	newToken, err := infrastructure.GetAuthConnector().Refresh(&token) | ||||
| 	if err != nil || newToken == nil { | ||||
| 		o.Data["json"] = err | ||||
| 		o.Ctx.ResponseWriter.WriteHeader(401) | ||||
| 	} else { | ||||
| 		o.Data["json"] = token | ||||
| 		o.Data["json"] = newToken | ||||
| 	} | ||||
| 	o.ServeJSON() | ||||
| } | ||||
| @@ -159,12 +108,11 @@ func (o *OAuthController) Introspect() { | ||||
| 	} else { | ||||
| 		reqToken = splitToken[1] | ||||
| 	} | ||||
| 	if !conf.GetConfig().Local { | ||||
| 		token, err := infrastructure.GetAuthConnector().Introspect(reqToken) | ||||
| 		if err != nil || !token { | ||||
| 			o.Data["json"] = err | ||||
| 			o.Ctx.ResponseWriter.WriteHeader(401) | ||||
| 		} | ||||
|  | ||||
| 	token, err := infrastructure.GetAuthConnector().Introspect(reqToken) | ||||
| 	if err != nil || !token { | ||||
| 		o.Data["json"] = err | ||||
| 		o.Ctx.ResponseWriter.WriteHeader(401) | ||||
| 	} | ||||
| 	o.ServeJSON() | ||||
| } | ||||
| @@ -201,7 +149,7 @@ func (o *OAuthController) InternalAuthForward() { | ||||
| 	} else { | ||||
| 		reqToken = splitToken[1] | ||||
| 	} | ||||
| 	origin, publicKey, external := o.extractOrigin(o.Ctx.Request) | ||||
| 	origin, publicKey, external := o.extractOrigin() | ||||
| 	if !infrastructure.GetAuthConnector().CheckAuthForward( //reqToken != "" && | ||||
| 		reqToken, publicKey, origin, | ||||
| 		o.Ctx.Request.Header.Get("X-Forwarded-Method"), | ||||
| @@ -213,8 +161,7 @@ func (o *OAuthController) InternalAuthForward() { | ||||
| 	o.ServeJSON() | ||||
| } | ||||
|  | ||||
| func (o *OAuthController) extractOrigin(request *http.Request) (string, string, bool) { | ||||
| 	user, peerID, groups := oclib.ExtractTokenInfo(*request) | ||||
| func (o *OAuthController) extractOrigin() (string, string, bool) { | ||||
| 	external := true | ||||
| 	publicKey := "" | ||||
| 	origin := o.Ctx.Request.Header.Get("X-Forwarded-Host") | ||||
| @@ -227,7 +174,7 @@ func (o *OAuthController) extractOrigin(request *http.Request) (string, string, | ||||
| 	if t != "" { | ||||
| 		searchStr = strings.Replace(searchStr, t, "", -1) | ||||
| 	} | ||||
| 	peer := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search(nil, searchStr, false) | ||||
| 	peer := oclib.Search(nil, searchStr, oclib.LibDataEnum(oclib.PEER)) | ||||
| 	if peer.Code != 200 || len(peer.Data) == 0 { // TODO: add state of partnership | ||||
| 		return "", "", external | ||||
| 	} | ||||
| @@ -243,29 +190,3 @@ func (o *OAuthController) extractOrigin(request *http.Request) (string, string, | ||||
| 	} | ||||
| 	return origin, publicKey, external | ||||
| } | ||||
|  | ||||
| func ExtractClient(request http.Request) string { | ||||
| 	reqToken := request.Header.Get("Authorization") | ||||
| 	splitToken := strings.Split(reqToken, "Bearer ") | ||||
| 	if len(splitToken) < 2 { | ||||
| 		reqToken = "" | ||||
| 	} else { | ||||
| 		reqToken = splitToken[1] | ||||
| 	} | ||||
| 	if reqToken != "" { | ||||
| 		token := strings.Split(reqToken, ".") | ||||
| 		if len(token) > 2 { | ||||
| 			bytes, err := base64.StdEncoding.DecodeString(token[2]) | ||||
| 			if err != nil { | ||||
| 				return "" | ||||
| 			} | ||||
| 			m := map[string]interface{}{} | ||||
| 			err = json.Unmarshal(bytes, &m) | ||||
| 			if err != nil { | ||||
| 				return "" | ||||
| 			} | ||||
| 			return m["session"].(map[string]interface{})["id_token"].(map[string]interface{})["client_id"].(string) | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|   | ||||
| @@ -16,8 +16,7 @@ type PermissionController struct { | ||||
| // @Success 200 {permission} string | ||||
| // @router / [get] | ||||
| func (o *PermissionController) GetAll() { | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, err := infrastructure.GetPermissionConnector(clientID).GetPermission("", "") | ||||
| 	role, err := infrastructure.GetPermissionConnector().GetPermission("", "") | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -42,8 +41,7 @@ func (o *PermissionController) GetAll() { | ||||
| // @router /role/:id [get] | ||||
| func (o *PermissionController) GetByRole() { | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, err := infrastructure.GetPermissionConnector(clientID).GetPermissionByRole(id) | ||||
| 	role, err := infrastructure.GetPermissionConnector().GetPermissionByRole(id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -68,8 +66,7 @@ func (o *PermissionController) GetByRole() { | ||||
| // @router /user/:id [get] | ||||
| func (o *PermissionController) GetByUser() { | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, err := infrastructure.GetPermissionConnector(clientID).GetPermissionByUser(id, true) | ||||
| 	role, err := infrastructure.GetPermissionConnector().GetPermissionByUser(id, true) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -95,8 +92,7 @@ func (o *PermissionController) GetByUser() { | ||||
| func (o *PermissionController) Get() { | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	rel := o.Ctx.Input.Param(":relation") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, err := infrastructure.GetPermissionConnector(clientID).GetPermission(id, rel) | ||||
| 	role, err := infrastructure.GetPermissionConnector().GetPermission(id, rel) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -119,8 +115,7 @@ func (o *PermissionController) Get() { | ||||
| // @Success 200 {string} delete success! | ||||
| // @router /clear [delete] | ||||
| func (o *PermissionController) Clear() { | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector(clientID).DeletePermission("", "", true) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector().DeletePermission("", "", true) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -149,8 +144,7 @@ func (o *PermissionController) Bind() { | ||||
| 	permission_id := o.Ctx.Input.Param(":permission_id") | ||||
| 	role_id := o.Ctx.Input.Param(":role_id") | ||||
| 	rel := o.Ctx.Input.Param(":relation") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector(clientID).BindPermission(role_id, permission_id, rel) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector().BindPermission(role_id, permission_id, rel) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -179,8 +173,7 @@ func (o *PermissionController) UnBind() { | ||||
| 	permission_id := o.Ctx.Input.Param(":permission_id") | ||||
| 	role_id := o.Ctx.Input.Param(":role_id") | ||||
| 	rel := o.Ctx.Input.Param(":relation") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector(clientID).UnBindPermission(role_id, permission_id, rel) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector().UnBindPermission(role_id, permission_id, rel) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
|   | ||||
| @@ -19,8 +19,7 @@ type RoleController struct { | ||||
| func (o *RoleController) Post() { | ||||
| 	// store and return Id or post with UUID | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector(clientID).CreateRole(id) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector().CreateRole(id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -45,8 +44,7 @@ func (o *RoleController) Post() { | ||||
| // @router /user/:id [get] | ||||
| func (o *RoleController) GetByUser() { | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, err := infrastructure.GetPermissionConnector(clientID).GetRoleByUser(id) | ||||
| 	role, err := infrastructure.GetPermissionConnector().GetRoleByUser(id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -69,8 +67,7 @@ func (o *RoleController) GetByUser() { | ||||
| // @Success 200 {role} string | ||||
| // @router / [get] | ||||
| func (o *RoleController) GetAll() { | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, err := infrastructure.GetPermissionConnector(clientID).GetRole("") | ||||
| 	role, err := infrastructure.GetPermissionConnector().GetRole("") | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -95,8 +92,7 @@ func (o *RoleController) GetAll() { | ||||
| // @router /:id [get] | ||||
| func (o *RoleController) Get() { | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, err := infrastructure.GetPermissionConnector(clientID).GetRole(id) | ||||
| 	role, err := infrastructure.GetPermissionConnector().GetRole(id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -121,8 +117,7 @@ func (o *RoleController) Get() { | ||||
| // @router /:id [delete] | ||||
| func (o *RoleController) Delete() { | ||||
| 	id := o.Ctx.Input.Param(":id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector(clientID).DeleteRole(id) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector().DeleteRole(id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -145,8 +140,7 @@ func (o *RoleController) Delete() { | ||||
| // @Success 200 {string} delete success! | ||||
| // @router /clear [delete] | ||||
| func (o *RoleController) Clear() { | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector(clientID).DeleteRole("") | ||||
| 	role, code, err := infrastructure.GetPermissionConnector().DeleteRole("") | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -173,8 +167,7 @@ func (o *RoleController) Clear() { | ||||
| func (o *RoleController) Bind() { | ||||
| 	user_id := o.Ctx.Input.Param(":user_id") | ||||
| 	role_id := o.Ctx.Input.Param(":role_id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector(clientID).BindRole(user_id, role_id) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector().BindRole(user_id, role_id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
| @@ -201,8 +194,7 @@ func (o *RoleController) Bind() { | ||||
| func (o *RoleController) UnBind() { | ||||
| 	user_id := o.Ctx.Input.Param(":user_id") | ||||
| 	role_id := o.Ctx.Input.Param(":role_id") | ||||
| 	clientID := ExtractClient(*o.Ctx.Request) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector(clientID).UnBindRole(user_id, role_id) | ||||
| 	role, code, err := infrastructure.GetPermissionConnector().UnBindRole(user_id, role_id) | ||||
| 	if err != nil { | ||||
| 		o.Data["json"] = map[string]interface{}{ | ||||
| 			"data":  nil, | ||||
|   | ||||
| @@ -14,10 +14,7 @@ type VersionController struct { | ||||
| // @Success 200 | ||||
| // @router / [get] | ||||
| func (c *VersionController) GetAll() { | ||||
| 	c.Data["json"] = map[string]string{ | ||||
| 		"service": "oc-auth", | ||||
| 		"version": "1", | ||||
| 	} | ||||
| 	c.Data["json"] = map[string]string{"version": "1"} | ||||
| 	c.ServeJSON() | ||||
| } | ||||
|  | ||||
| @@ -26,9 +23,6 @@ func (c *VersionController) GetAll() { | ||||
| // @Success 200 | ||||
| // @router /discovery [get] | ||||
| func (c *VersionController) Get() { | ||||
| 	c.Data["json"] = map[string]string{ | ||||
| 		"service": "oc-auth", | ||||
| 		"version": "1", | ||||
| 	} | ||||
| 	c.Data["json"] = map[string]string{"version": "1"} | ||||
| 	c.ServeJSON() | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,22 @@ | ||||
| version: '3.4' | ||||
|  | ||||
| services: | ||||
|   traefik: | ||||
|     image: traefik:v2.10.4 | ||||
|     container_name: traefik | ||||
|     networks: | ||||
|       - catalog | ||||
|     command: | ||||
|       - "--api.insecure=true" | ||||
|       - "--providers.docker=true" | ||||
|       - "--providers.docker.exposedbydefault=false" | ||||
|       - "--entrypoints.web.address=:80" | ||||
|       - "--log.level=DEBUG" | ||||
|     ports: | ||||
|       - "8080:80"    | ||||
|       - "8082:8080"     | ||||
|     volumes: | ||||
|       - /var/run/docker.sock:/var/run/docker.sock | ||||
|   oc-auth: | ||||
|     image: 'oc-auth:latest' | ||||
|     ports: | ||||
| @@ -8,13 +24,8 @@ services: | ||||
|     container_name: oc-auth | ||||
|     labels: | ||||
|       - "traefik.enable=true" | ||||
|       - "traefik.http.routers.auth.entrypoints=web" | ||||
|       - "traefik.http.routers.auth.rule=PathPrefix(`/auth`)" | ||||
|       - "traefik.http.middlewares.auth-rewrite.replacepathregex.regex=^/auth(.*)" | ||||
|       - "traefik.http.middlewares.auth-rewrite.replacepathregex.replacement=/oc$$1" | ||||
|       - "traefik.http.routers.auth.middlewares=auth-rewrite" | ||||
|       - "traefik.http.services.auth.loadbalancer.server.port=8080" | ||||
|       - "traefik.http.middlewares.auth.forwardauth.address=http://oc-auth:8080/oc/forward" | ||||
|       - "traefik.http.routers.workflow.rule=PathPrefix(/auth)" | ||||
|     environment: | ||||
|           LDAP_ENDPOINTS: ldap:389 | ||||
|           LDAP_BINDDN: cn=admin,dc=example,dc=com | ||||
| @@ -22,10 +33,9 @@ services: | ||||
|           LDAP_BASEDN: "dc=example,dc=com" | ||||
|           LDAP_ROLE_BASEDN: "ou=AppRoles,dc=example,dc=com" | ||||
|     networks:  | ||||
|       - oc | ||||
|       - catalog | ||||
|     volumes: | ||||
|       - ./pem/private.pem:/keys/private/private.pem | ||||
|       - ./pem/public.pem:/keys/public/public.pem | ||||
|       - ./pem:/etc/oc/pem | ||||
| networks:  | ||||
|   oc: | ||||
|   catalog: | ||||
|     external: true | ||||
| @@ -2,10 +2,9 @@ | ||||
|     "MONGO_URL":"mongodb://mongo:27017/",  | ||||
|     "MONGO_DATABASE":"DC_myDC", | ||||
|     "NATS_URL": "nats://nats:4222", | ||||
|     "PORT" : 8080, | ||||
|     "AUTH_CONNECTOR_HOST": "hydra", | ||||
|     "AUTH_CONNECTOR_PUBLIC_HOST": "hydra", | ||||
|     "PRIVATE_KEY_PATH": "/keys/private/private.pem", | ||||
|     "PUBLIC_KEY_PATH": "/keys/public/public.pem", | ||||
|     "LDAP_ENDPOINTS": "ldap:389", | ||||
|     "LOCAL": false | ||||
|     "PRIVATE_KEY_PATH": "/etc/oc/pem/private.pem", | ||||
|     "PUBLIC_KEY_PATH": "/etc/oc/pem/public.pem", | ||||
|     "LDAP_ENDPOINTS": "ldap:389" | ||||
| } | ||||
							
								
								
									
										4
									
								
								env.env
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								env.env
									
									
									
									
									
								
							| @@ -1,4 +0,0 @@ | ||||
| KUBERNETES_SERVICE_HOST=192.168.47.20 | ||||
| KUBE_CA="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTVlk3ZHZhNEdYTVdkMy9jMlhLN3JLYjlnWXgyNSthaEE0NmkyNVBkSFAKRktQL2UxSVMyWVF0dzNYZW1TTUQxaStZdzJSaVppNUQrSVZUamNtNHdhcnFvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWtlUVJpNFJiODduME5yRnZaWjZHClc2SU55NnN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnRXA5ck04WmdNclRZSHYxZjNzOW5DZXZZeWVVa3lZUk4KWjUzazdoaytJS1FDSVFDbk05TnVGKzlTakIzNDFacGZ5ays2NEpWdkpSM3BhcmVaejdMd2lhNm9kdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" | ||||
| KUBE_CERT="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJWUxWNkFPQkdrU1F3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOekl6TVRFeU1ETTJNQjRYRFRJME1EZ3dPREV3TVRNMU5sb1hEVEkxTURndwpPREV3TVRNMU5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJGQ2Q1MFdPeWdlQ2syQzcKV2FrOWY4MVAvSkJieVRIajRWOXBsTEo0ck5HeHFtSjJOb2xROFYxdUx5RjBtOTQ2Nkc0RmRDQ2dqaXFVSk92Swp3NVRPNnd5alNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVFJkOFI5cXVWK2pjeUVmL0ovT1hQSzMyS09XekFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQTArbThqTDBJVldvUTZ0dnB4cFo4NVlMalF1SmpwdXM0aDdnSXRxS3NmUVVDSUI2M2ZNdzFBMm5OVWU1TgpIUGZOcEQwSEtwcVN0Wnk4djIyVzliYlJUNklZCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFRc3hXWk9pbnIrcVp4TmFEQjVGMGsvTDF5cE01VHAxOFRaeU92ektJazQKRTFsZWVqUm9STW0zNmhPeVljbnN3d3JoNnhSUnBpMW5RdGhyMzg0S0Z6MlBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTBYZkVmYXJsZm8zTWhIL3lmemx6Cnl0OWlqbHN3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUxJL2dNYnNMT3MvUUpJa3U2WHVpRVMwTEE2cEJHMXgKcnBlTnpGdlZOekZsQWlFQW1wdjBubjZqN3M0MVI0QzFNMEpSL0djNE53MHdldlFmZWdEVGF1R2p3cFk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" | ||||
| KUBE_DATA="LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5ZS1BFb1dhd1NKUzJlRW5oWmlYMk5VZlY1ZlhKV2krSVNnV09TNFE5VTlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUozblJZN0tCNEtUWUx0WnFUMS96VS84a0Z2Sk1lUGhYMm1Vc25pczBiR3FZblkyaVZEeApYVzR2SVhTYjNqcm9iZ1YwSUtDT0twUWs2OHJEbE03ckRBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=" | ||||
							
								
								
									
										36
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								go.mod
									
									
									
									
									
								
							| @@ -1,28 +1,22 @@ | ||||
| module oc-auth | ||||
|  | ||||
| go 1.23.0 | ||||
|  | ||||
| toolchain go1.23.3 | ||||
| go 1.22.0 | ||||
|  | ||||
| require ( | ||||
| 	cloud.o-forge.io/core/oc-lib v0.0.0-20250624102227-e600fedcab06 | ||||
| 	github.com/beego/beego/v2 v2.3.1 | ||||
| 	cloud.o-forge.io/core/oc-lib v0.0.0-20241216081858-245f3adea3ba | ||||
| 	github.com/beego/beego/v2 v2.3.4 | ||||
| 	github.com/smartystreets/goconvey v1.7.2 | ||||
| 	go.uber.org/zap v1.27.0 | ||||
| ) | ||||
|  | ||||
| //replace cloud.o-forge.io/core/oc-lib => ../oc-lib | ||||
| replace cloud.o-forge.io/core/oc-lib => ../oc-lib | ||||
|  | ||||
| require ( | ||||
| 	github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect | ||||
| 	github.com/biter777/countries v1.7.5 // indirect | ||||
| 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect | ||||
| 	github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect | ||||
| 	github.com/gofrs/uuid v4.3.0+incompatible // indirect | ||||
| 	github.com/nats-io/nats.go v1.37.0 // indirect | ||||
| 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect | ||||
| 	github.com/nats-io/nats.go v1.38.0 // indirect | ||||
| 	github.com/robfig/cron v1.2.0 // indirect | ||||
| 	github.com/rogpeppe/go-internal v1.12.0 // indirect | ||||
| 	go.uber.org/multierr v1.10.0 // indirect | ||||
| ) | ||||
|  | ||||
| @@ -30,11 +24,11 @@ require ( | ||||
| 	github.com/beorn7/perks v1.0.1 // indirect | ||||
| 	github.com/cespare/xxhash/v2 v2.3.0 // indirect | ||||
| 	github.com/coocood/freecache v1.2.4 | ||||
| 	github.com/gabriel-vasile/mimetype v1.4.6 // indirect | ||||
| 	github.com/gabriel-vasile/mimetype v1.4.7 // indirect | ||||
| 	github.com/go-ldap/ldap/v3 v3.4.8 | ||||
| 	github.com/go-playground/locales v0.14.1 // indirect | ||||
| 	github.com/go-playground/universal-translator v0.18.1 // indirect | ||||
| 	github.com/go-playground/validator/v10 v10.22.1 // indirect | ||||
| 	github.com/go-playground/validator/v10 v10.23.0 // indirect | ||||
| 	github.com/golang/snappy v0.0.4 // indirect | ||||
| 	github.com/google/uuid v1.6.0 // indirect | ||||
| 	github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect | ||||
| @@ -49,11 +43,11 @@ require ( | ||||
| 	github.com/mitchellh/mapstructure v1.5.0 // indirect | ||||
| 	github.com/montanaflynn/stats v0.7.1 // indirect | ||||
| 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect | ||||
| 	github.com/nats-io/nkeys v0.4.7 // indirect | ||||
| 	github.com/nats-io/nkeys v0.4.9 // indirect | ||||
| 	github.com/nats-io/nuid v1.0.1 // indirect | ||||
| 	github.com/prometheus/client_golang v1.20.5 // indirect | ||||
| 	github.com/prometheus/client_model v0.6.1 // indirect | ||||
| 	github.com/prometheus/common v0.60.1 // indirect | ||||
| 	github.com/prometheus/common v0.61.0 // indirect | ||||
| 	github.com/prometheus/procfs v0.15.1 // indirect | ||||
| 	github.com/rs/zerolog v1.33.0 // indirect | ||||
| 	github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect | ||||
| @@ -63,11 +57,11 @@ require ( | ||||
| 	github.com/xdg-go/stringprep v1.0.4 // indirect | ||||
| 	github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect | ||||
| 	go.mongodb.org/mongo-driver v1.17.1 // indirect | ||||
| 	golang.org/x/crypto v0.28.0 // indirect | ||||
| 	golang.org/x/net v0.30.0 // indirect | ||||
| 	golang.org/x/sync v0.8.0 // indirect | ||||
| 	golang.org/x/sys v0.26.0 // indirect | ||||
| 	golang.org/x/text v0.19.0 // indirect | ||||
| 	google.golang.org/protobuf v1.35.1 // indirect | ||||
| 	golang.org/x/crypto v0.31.0 // indirect | ||||
| 	golang.org/x/net v0.33.0 // indirect | ||||
| 	golang.org/x/sync v0.10.0 // indirect | ||||
| 	golang.org/x/sys v0.28.0 // indirect | ||||
| 	golang.org/x/text v0.21.0 // indirect | ||||
| 	google.golang.org/protobuf v1.36.1 // indirect | ||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||
| ) | ||||
|   | ||||
							
								
								
									
										76
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								go.sum
									
									
									
									
									
								
							| @@ -1,26 +1,12 @@ | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250219104152-3ecb0e9d960b h1:DhRqJdw2VePaYVlsh8OUA3zl+76Q0FWwGu+a+3aOf6s= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250219104152-3ecb0e9d960b/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250219142942-5111c9c8bec7 h1:fh6SzBPenzIxufIIzExtx4jEE4OhFposqn3EbHFr92Q= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250219142942-5111c9c8bec7/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250624064953-2c8dcbe93d14 h1:iCTrYc2+W2BFLOupRK1sD6sOgsK4NIs6WMC+4LiWCaY= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250624064953-2c8dcbe93d14/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250624093207-3fdf5c3ebf29 h1:JitS1izRltTyOaWnvXnmYywHj0napsL6y0nBYiWUCNo= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250624093207-3fdf5c3ebf29/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250624095852-147c7bc3a1d5 h1:0eV0E3kBZkOyoAurRmP9h4eHmFrZajOxSqoBgM3l3dk= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250624095852-147c7bc3a1d5/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250624102227-e600fedcab06 h1:+RSv62uIC7wsmibsp1XTanQMNznNeOGgPpfhb6ZHT4c= | ||||
| cloud.o-forge.io/core/oc-lib v0.0.0-20250624102227-e600fedcab06/go.mod h1:vHWauJsS6ryf7UDqq8hRXoYD5RsONxcFTxeZPOztEuI= | ||||
| github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= | ||||
| github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= | ||||
| github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||||
| github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= | ||||
| github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= | ||||
| github.com/beego/beego/v2 v2.3.1 h1:7MUKMpJYzOXtCUsTEoXOxsDV/UcHw6CPbaWMlthVNsc= | ||||
| github.com/beego/beego/v2 v2.3.1/go.mod h1:5cqHsOHJIxkq44tBpRvtDe59GuVRVv/9/tyVDxd5ce4= | ||||
| github.com/beego/beego/v2 v2.3.4 h1:HurQEOGIEhLlPFCTR6ZDuQkybrUl2Ag2i6CdVD2rGiI= | ||||
| github.com/beego/beego/v2 v2.3.4/go.mod h1:5cqHsOHJIxkq44tBpRvtDe59GuVRVv/9/tyVDxd5ce4= | ||||
| github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= | ||||
| github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= | ||||
| github.com/biter777/countries v1.7.5 h1:MJ+n3+rSxWQdqVJU8eBy9RqcdH6ePPn4PJHocVWUa+Q= | ||||
| github.com/biter777/countries v1.7.5/go.mod h1:1HSpZ526mYqKJcpT5Ti1kcGQ0L0SrXWIaptUWjFfv2E= | ||||
| github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | ||||
| github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= | ||||
| github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | ||||
| @@ -30,15 +16,14 @@ github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc | ||||
| github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= | ||||
| github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= | ||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= | ||||
| github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw= | ||||
| github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= | ||||
| github.com/etcd-io/etcd v3.3.17+incompatible/go.mod h1:cdZ77EstHBwVtD6iTgzgvogwcjo9m4iOqoijouPJ4bs= | ||||
| github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | ||||
| github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= | ||||
| github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= | ||||
| github.com/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA= | ||||
| github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU= | ||||
| github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= | ||||
| github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= | ||||
| github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ= | ||||
| @@ -49,8 +34,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o | ||||
| github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= | ||||
| github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= | ||||
| github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= | ||||
| github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= | ||||
| github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= | ||||
| github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o= | ||||
| github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= | ||||
| github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | ||||
| github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | ||||
| github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= | ||||
| @@ -119,31 +104,30 @@ github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8 | ||||
| github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= | ||||
| github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= | ||||
| github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= | ||||
| github.com/nats-io/nats.go v1.37.0 h1:07rauXbVnnJvv1gfIyghFEo6lUcYRY0WXc3x7x0vUxE= | ||||
| github.com/nats-io/nats.go v1.37.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= | ||||
| github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= | ||||
| github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= | ||||
| github.com/nats-io/nats.go v1.38.0 h1:A7P+g7Wjp4/NWqDOOP/K6hfhr54DvdDQUznt5JFg9XA= | ||||
| github.com/nats-io/nats.go v1.38.0/go.mod h1:IGUM++TwokGnXPs82/wCuiHS02/aKrdYUQkU8If6yjw= | ||||
| github.com/nats-io/nkeys v0.4.9 h1:qe9Faq2Gxwi6RZnZMXfmGMZkg3afLLOtrU+gDZJ35b0= | ||||
| github.com/nats-io/nkeys v0.4.9/go.mod h1:jcMqs+FLG+W5YO36OX6wFIFcmpdAns+w1Wm6D3I/evE= | ||||
| github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= | ||||
| github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= | ||||
| github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g= | ||||
| github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= | ||||
| github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
| github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= | ||||
| github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= | ||||
| github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= | ||||
| github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= | ||||
| github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= | ||||
| github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= | ||||
| github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= | ||||
| github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= | ||||
| github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= | ||||
| github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= | ||||
| github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= | ||||
| github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= | ||||
| github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= | ||||
| github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= | ||||
| github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= | ||||
| github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= | ||||
| github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= | ||||
| github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= | ||||
| github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= | ||||
| github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= | ||||
| @@ -164,8 +148,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P | ||||
| github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | ||||
| github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||||
| github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||||
| github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||
| github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | ||||
| github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||
| github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= | ||||
| github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= | ||||
| github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= | ||||
| @@ -192,8 +176,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y | ||||
| golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= | ||||
| golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= | ||||
| golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= | ||||
| golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= | ||||
| golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= | ||||
| golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= | ||||
| golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= | ||||
| golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= | ||||
| golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= | ||||
| golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||
| @@ -207,13 +191,13 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= | ||||
| golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= | ||||
| golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= | ||||
| golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= | ||||
| golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= | ||||
| golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= | ||||
| golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= | ||||
| golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= | ||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= | ||||
| golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||||
| golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= | ||||
| golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| @@ -228,8 +212,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||
| golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||
| golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= | ||||
| golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||
| golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= | ||||
| golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||||
| golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= | ||||
| @@ -243,16 +227,16 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= | ||||
| golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | ||||
| golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= | ||||
| golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | ||||
| golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= | ||||
| golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= | ||||
| golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= | ||||
| golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||
| golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||
| golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | ||||
| golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= | ||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= | ||||
| google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= | ||||
| google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= | ||||
| google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= | ||||
| gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= | ||||
|   | ||||
| @@ -3,17 +3,16 @@ package auth_connectors | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"oc-auth/conf" | ||||
| 	"strings" | ||||
|  | ||||
| 	"cloud.o-forge.io/core/oc-lib/tools" | ||||
| ) | ||||
|  | ||||
| type AuthConnector interface { | ||||
| 	Status() tools.State | ||||
| 	Login(clientID string, username string, cookies ...*http.Cookie) (*Token, error) | ||||
| 	Logout(clientID string, token string, cookies ...*http.Cookie) (*Token, error) | ||||
| 	Login(username string, cookies ...*http.Cookie) (*Token, error) | ||||
| 	Logout(token string, cookies ...*http.Cookie) (*Token, error) | ||||
| 	Introspect(token string, cookie ...*http.Cookie) (bool, error) | ||||
| 	Refresh(client_id string, token *Token) (*Token, error) | ||||
| 	Refresh(token *Token) (*Token, error) | ||||
| 	CheckAuthForward(reqToken string, publicKey string, host string, method string, forward string, external bool) bool | ||||
| } | ||||
|  | ||||
| @@ -38,10 +37,5 @@ var a = map[string]AuthConnector{ | ||||
| } | ||||
|  | ||||
| func GetAuthConnector() AuthConnector { | ||||
| 	for k := range a { | ||||
| 		if strings.Contains(conf.GetConfig().Auth, k) { | ||||
| 			return a[k] | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| 	return a[conf.GetConfig().Auth] | ||||
| } | ||||
|   | ||||
| @@ -23,18 +23,19 @@ import ( | ||||
| type HydraConnector struct { | ||||
| 	State        string `json:"state"` | ||||
| 	Scopes       string `json:"scope"` | ||||
| 	ClientID     string `json:"client_id"` | ||||
| 	ResponseType string `json:"response_type"` | ||||
|  | ||||
| 	Caller *tools.HTTPCaller | ||||
| } | ||||
|  | ||||
| const test_name = "test-pierre" | ||||
| const test_id = "1234" | ||||
|  | ||||
| func (a HydraConnector) Status() tools.State { | ||||
| 	caller := tools.NewHTTPCaller(map[tools.DataType]map[tools.METHOD]string{}) | ||||
| 	var responseBody map[string]interface{} | ||||
| 	host := conf.GetConfig().AuthConnectPublicHost | ||||
| 	if conf.GetConfig().Local { | ||||
| 		host = "localhost" | ||||
| 	} | ||||
| 	host := conf.GetConfig().AuthConnectorHost | ||||
| 	port := fmt.Sprintf("%v", conf.GetConfig().AuthConnectorPort) | ||||
| 	resp, err := caller.CallGet("http://"+host+":"+port, "/health/ready") | ||||
| 	if err != nil { | ||||
| @@ -47,6 +48,7 @@ func (a HydraConnector) Status() tools.State { | ||||
| 	return tools.ALIVE | ||||
| } | ||||
|  | ||||
|  | ||||
| // urlFormat formats the URL of the peer with the data type API function | ||||
| func (a *HydraConnector) urlFormat(url string, replaceWith string) string { | ||||
| 	// localhost is replaced by the local peer URL | ||||
| @@ -71,7 +73,6 @@ func (a HydraConnector) challenge(username string, url string, challenge string, | ||||
| 	resp, err := a.Caller.CallRaw(http.MethodPut, | ||||
| 		a.getPath(true, true), "/auth/requests/"+challenge+"/accept?"+challenge+"_challenge="+s[1], | ||||
| 		body, "application/json", true, cookies...) // "remember": true, "subject": username | ||||
| 	fmt.Println(a.getPath(true, true), "/auth/requests/"+challenge+"/accept?"+challenge+"_challenge="+s[1], resp, err) | ||||
| 	if err != nil { | ||||
| 		return nil, s[1], cookies, err | ||||
| 	} | ||||
| @@ -80,7 +81,6 @@ func (a HydraConnector) challenge(username string, url string, challenge string, | ||||
| 	if err != nil { | ||||
| 		return nil, s[1], cookies, err | ||||
| 	} | ||||
| 	fmt.Println(string(b)) | ||||
| 	var token Redirect | ||||
| 	err = json.Unmarshal(b, &token) | ||||
| 	if err != nil { | ||||
| @@ -89,7 +89,7 @@ func (a HydraConnector) challenge(username string, url string, challenge string, | ||||
| 	return &token, s[1], cookies, nil | ||||
| } | ||||
|  | ||||
| func (a HydraConnector) Refresh(client_id string, token *Token) (*Token, error) { | ||||
| func (a HydraConnector) Refresh(token *Token) (*Token, error) { | ||||
| 	access := strings.Split(token.AccessToken, ".") | ||||
| 	if len(access) > 2 { | ||||
| 		token.AccessToken = strings.Join(access[0:2], ".") | ||||
| @@ -98,11 +98,11 @@ func (a HydraConnector) Refresh(client_id string, token *Token) (*Token, error) | ||||
| 	if err != nil || !isValid { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	_, err = a.Logout(client_id, token.AccessToken) | ||||
| 	_, err = a.Logout(token.AccessToken) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return a.Login(client_id, token.Username) | ||||
| 	return a.Login(token.Username) | ||||
| } | ||||
|  | ||||
| func (a HydraConnector) tryLog(username string, url string, subpath string, challenge string, cookies ...*http.Cookie) (*Redirect, string, []*http.Cookie, error) { | ||||
| @@ -124,10 +124,9 @@ func (a HydraConnector) tryLog(username string, url string, subpath string, chal | ||||
| 	return a.challenge(username, resp.Request.URL.String(), challenge, cookies...) | ||||
| } | ||||
|  | ||||
| func (a HydraConnector) getClient(clientID string) string { | ||||
| func (a HydraConnector) getClient() string { | ||||
| 	resp, err := a.Caller.CallGet(a.getPath(true, false), "/clients") | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		return "" | ||||
| 	} | ||||
| 	var clients []interface{} | ||||
| @@ -135,26 +134,15 @@ func (a HydraConnector) getClient(clientID string) string { | ||||
| 	if err != nil || len(clients) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	for _, c := range clients { | ||||
| 		if c.(map[string]interface{})["client_name"].(string) == clientID { | ||||
| 			return c.(map[string]interface{})["client_id"].(string) | ||||
| 		} | ||||
| 	} | ||||
| 	return clients[0].(map[string]interface{})["client_id"].(string) | ||||
| } | ||||
|  | ||||
| func (a HydraConnector) Login(clientID string, username string, cookies ...*http.Cookie) (t *Token, err error) { | ||||
| 	clientID = a.getClient(clientID) | ||||
| 	if clientID == "" { | ||||
| 		return nil, errors.New("no client found") | ||||
| 	} | ||||
| func (a HydraConnector) Login(username string, cookies ...*http.Cookie) (t *Token, err error) { | ||||
| 	clientID := a.getClient() | ||||
| 	redirect, _, cookies, err := a.tryLog(username, a.getPath(false, true), | ||||
| 		"/auth?client_id="+clientID+"&response_type="+strings.ReplaceAll(a.ResponseType, " ", "%20")+"&scope="+strings.ReplaceAll(a.Scopes, " ", "%20")+"&state="+a.State, | ||||
| 		"login", cookies...) | ||||
| 	if err != nil || redirect == nil { | ||||
| 		if redirect == nil { | ||||
| 			return nil, errors.New("no oauth redirection " + clientID) | ||||
| 		} | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	redirect, _, cookies, err = a.tryLog(username, a.urlFormat(redirect.RedirectTo, a.getPath(false, true)), "", "consent", cookies...) | ||||
| @@ -184,17 +172,15 @@ func (a HydraConnector) Login(clientID string, username string, cookies ...*http | ||||
| 	var m map[string]interface{} | ||||
| 	defer resp.Body.Close() | ||||
| 	b, err := io.ReadAll(resp.Body) | ||||
| 	fmt.Println("login", b, err, a.getPath(false, true), "/token") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	err = json.Unmarshal(b, &token) | ||||
| 	fmt.Println("login2", token, err) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	json.Unmarshal(b, &m) | ||||
| 	pp := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), "", "", []string{}, nil).Search(nil, strconv.Itoa(peer.SELF.EnumIndex()), false) | ||||
| 	pp := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER),test_name,test_id,nil,nil).Search(nil, strconv.Itoa(peer.SELF.EnumIndex())) | ||||
| 	if len(pp.Data) == 0 || pp.Code >= 300 || pp.Err != "" { | ||||
| 		return nil, errors.New("peer not found") | ||||
| 	} | ||||
| @@ -202,7 +188,7 @@ func (a HydraConnector) Login(clientID string, username string, cookies ...*http | ||||
| 	now = now.Add(time.Duration(token.ExpiresIn) * time.Second) | ||||
| 	unix := now.Unix() | ||||
|  | ||||
| 	c := claims.GetClaims().AddClaimsToToken(clientID, username, pp.Data[0].(*peer.Peer)) | ||||
| 	c := claims.GetClaims().AddClaimsToToken(username, pp.Data[0].(*peer.Peer)) | ||||
| 	c.Session.AccessToken["exp"] = unix | ||||
|  | ||||
| 	b, _ = json.Marshal(c) | ||||
| @@ -212,8 +198,7 @@ func (a HydraConnector) Login(clientID string, username string, cookies ...*http | ||||
| 	return token, nil | ||||
| } | ||||
|  | ||||
| func (a HydraConnector) Logout(clientID string, token string, cookies ...*http.Cookie) (*Token, error) { | ||||
| 	clientID = a.getClient(clientID) | ||||
| func (a HydraConnector) Logout(token string, cookies ...*http.Cookie) (*Token, error) { | ||||
| 	access := strings.Split(token, ".") | ||||
| 	if len(access) > 2 { | ||||
| 		token = strings.Join(access[0:2], ".") | ||||
| @@ -221,7 +206,7 @@ func (a HydraConnector) Logout(clientID string, token string, cookies ...*http.C | ||||
| 	p := a.getPath(false, true) + "/revoke" | ||||
| 	urls := url.Values{} | ||||
| 	urls.Add("token", token) | ||||
| 	urls.Add("client_id", clientID) | ||||
| 	urls.Add("client_id", a.getClient()) | ||||
| 	urls.Add("client_secret", conf.GetConfig().ClientSecret) | ||||
| 	_, err := a.Caller.CallForm(http.MethodPost, p, "", urls, "application/x-www-form-urlencoded", true) | ||||
| 	if err != nil { | ||||
| @@ -261,16 +246,10 @@ func (a HydraConnector) Introspect(token string, cookie ...*http.Cookie) (bool, | ||||
| } | ||||
|  | ||||
| func (a HydraConnector) getPath(isAdmin bool, isOauth bool) string { | ||||
| 	host := conf.GetConfig().AuthConnectPublicHost | ||||
| 	if isAdmin { | ||||
| 		host = conf.GetConfig().AuthConnectorHost | ||||
| 	} | ||||
| 	if conf.GetConfig().Local { | ||||
| 		host = "localhost" | ||||
| 	} | ||||
| 	host := conf.GetConfig().AuthConnectorHost | ||||
| 	port := fmt.Sprintf("%v", conf.GetConfig().AuthConnectorPort) | ||||
| 	if isAdmin { | ||||
| 		port = fmt.Sprintf("%v", conf.GetConfig().AuthConnectorAdminPort) | ||||
| 		port = fmt.Sprintf("%v", conf.GetConfig().AuthConnectorAdminPort) + "/admin" | ||||
| 	} | ||||
| 	oauth := "" | ||||
| 	if isOauth { | ||||
|   | ||||
| @@ -31,9 +31,8 @@ var ( | ||||
|  | ||||
| type conn interface { | ||||
| 	Bind(bindDN, password string) error | ||||
| 	SearchRoles(attrs ...string) ([]map[string][]string, error) | ||||
| 	SearchUser(user string, attrs ...string) ([]map[string][]string, error) | ||||
| 	SearchUserRoles(user string, attrs ...string) ([]map[string][]string, error) | ||||
| 	SearchUser(user string, attrs ...string) ([]map[string]interface{}, error) | ||||
| 	SearchUserRoles(user string, attrs ...string) ([]map[string]interface{}, error) | ||||
| 	Close() error | ||||
| } | ||||
|  | ||||
| @@ -79,7 +78,7 @@ type Client struct { | ||||
| 	cache     *freecache.Cache | ||||
| } | ||||
|  | ||||
| func (cli *Client) Authenticate(ctx context.Context, username string, password string) (bool, error) { | ||||
| func (cli *Client) Authenticate(ctx context.Context, username, password string) (bool, error) { | ||||
| 	if username == "" || password == "" { | ||||
| 		return false, nil | ||||
| 	} | ||||
| @@ -102,8 +101,8 @@ func (cli *Client) Authenticate(ctx context.Context, username string, password s | ||||
| 	if details == nil { | ||||
| 		return false, nil | ||||
| 	} | ||||
| 	a := details["dn"] | ||||
| 	if err := cn.Bind(a[0], password); err != nil { | ||||
|  | ||||
| 	if err := cn.Bind(details["dn"].(string), password); err != nil { | ||||
| 		if err == errInvalidCredentials { | ||||
| 			return false, nil | ||||
| 		} | ||||
| @@ -119,21 +118,6 @@ func (cli *Client) Authenticate(ctx context.Context, username string, password s | ||||
| 	return true, nil | ||||
| } | ||||
|  | ||||
| func (cli *Client) GetRoles(ctx context.Context) (map[string]LDAPRoles, error) { | ||||
| 	var cancel context.CancelFunc | ||||
| 	ctx, cancel = context.WithCancel(ctx) | ||||
|  | ||||
| 	cn, ok := <-cli.connect(ctx) | ||||
| 	cancel() | ||||
| 	if !ok { | ||||
| 		return map[string]LDAPRoles{}, errConnectionTimeout | ||||
| 	} | ||||
| 	defer cn.Close() | ||||
|  | ||||
| 	// Find a user DN by his or her username. | ||||
| 	return cli.findRoles(cn, "dn", "member", "uniqueMember") | ||||
| } | ||||
|  | ||||
| // Claim is the FindOIDCClaims result struct | ||||
| type LDAPClaim struct { | ||||
| 	Code  string      // the root claim name | ||||
| @@ -141,10 +125,6 @@ type LDAPClaim struct { | ||||
| 	Value interface{} // the value | ||||
| } | ||||
|  | ||||
| type LDAPRoles struct { | ||||
| 	Members map[string][]string | ||||
| } | ||||
|  | ||||
| // FindOIDCClaims finds all OIDC claims for a user. | ||||
| func (cli *Client) FindOIDCClaims(ctx context.Context, username string) ([]LDAPClaim, error) { | ||||
| 	if username == "" { | ||||
| @@ -213,12 +193,11 @@ func (cli *Client) FindOIDCClaims(ctx context.Context, username string) ([]LDAPC | ||||
|  | ||||
| 	roles := make(map[string]interface{}) | ||||
| 	for _, entry := range entries { | ||||
| 		roleDNs, ok := entry["dn"] | ||||
| 		if !ok || len(roleDNs) == 0 { | ||||
| 		roleDN, ok := entry["dn"].(string) | ||||
| 		if !ok || roleDN == "" { | ||||
| 			log.Infow("No required LDAP attribute for a role", "ldapAttribute", "dn", "entry", entry) | ||||
| 			continue | ||||
| 		} | ||||
| 		roleDN := roleDNs[0] | ||||
| 		if entry[cli.RoleAttr] == nil { | ||||
| 			log.Infow("No required LDAP attribute for a role", "ldapAttribute", cli.RoleAttr, "roleDN", roleDN) | ||||
| 			continue | ||||
| @@ -228,7 +207,7 @@ func (cli *Client) FindOIDCClaims(ctx context.Context, username string) ([]LDAPC | ||||
| 		// It's sufficient to compare the DN's suffix with the base DN. | ||||
| 		n, k := len(roleDN), len(cli.RoleBaseDN) | ||||
| 		if n < k || !strings.EqualFold(roleDN[n-k:], cli.RoleBaseDN) { | ||||
| 			return nil, errors.New("You should never see that") | ||||
| 			panic("You should never see that") | ||||
| 		} | ||||
| 		// The DN without the role's base DN must contain a CN and OU | ||||
| 		// where the CN is for uniqueness only, and the OU is an application id. | ||||
| @@ -299,79 +278,8 @@ func (cli *Client) connect(ctx context.Context) <-chan conn { | ||||
| 	return ch | ||||
| } | ||||
|  | ||||
| func (cli *Client) findRoles(cn conn, attrs ...string) (map[string]LDAPRoles, error) { | ||||
| 	if cli.BindDN != "" { | ||||
| 		// We need to login to a LDAP server with a service account for retrieving user data. | ||||
| 		if err := cn.Bind(cli.BindDN, cli.BindPass); err != nil { | ||||
| 			return map[string]LDAPRoles{}, errors.New(err.Error() + " : failed to login to a LDAP woth a service account") | ||||
| 		} | ||||
| 	} | ||||
| 	entries, err := cn.SearchRoles(attrs...) | ||||
| 	fmt.Println("entries", entries) | ||||
| 	if err != nil { | ||||
| 		return map[string]LDAPRoles{}, err | ||||
| 	} | ||||
| 	claims := map[string]LDAPRoles{} | ||||
| 	for _, entry := range entries { | ||||
| 		roleDNs, ok := entry["dn"] | ||||
| 		if !ok || len(roleDNs) == 0 { | ||||
| 			continue | ||||
| 		} | ||||
| 		roleDN := roleDNs[0] | ||||
| 		// Ensure that a role's DN is inside of the role's base DN. | ||||
| 		// It's sufficient to compare the DN's suffix with the base DN. | ||||
| 		n, k := len(roleDN), len(cli.RoleBaseDN) | ||||
| 		if n < k || !strings.EqualFold(roleDN[n-k:], cli.RoleBaseDN) { | ||||
| 			return nil, errors.New("You should never see that") | ||||
| 		} | ||||
| 		// The DN without the role's base DN must contain a CN and OU | ||||
| 		// where the CN is for uniqueness only, and the OU is an application id. | ||||
| 		path := strings.Split(roleDN[:n-k-1], ",") | ||||
| 		if len(path) != 2 { | ||||
| 			continue | ||||
| 		} | ||||
| 		appID := path[1][len("OU="):] | ||||
| 		if _, ok := claims[appID]; !ok { | ||||
| 			claims[appID] = LDAPRoles{ | ||||
| 				Members: map[string][]string{}, | ||||
| 			} | ||||
| 		} | ||||
| 		role := path[0][len("cn="):] | ||||
| 		if claims[appID].Members[role] == nil { | ||||
| 			claims[appID].Members[role] = []string{} | ||||
| 		} | ||||
| 		fmt.Println("entry", entry) | ||||
| 		memberDNs, ok := entry["member"] | ||||
| 		for _, memberDN := range memberDNs { | ||||
| 			if !ok || memberDN == "" { | ||||
| 				continue | ||||
| 			} | ||||
| 			path = strings.Split(memberDN[:n-k-1], ",") | ||||
| 			if len(path) < 1 { | ||||
| 				continue | ||||
| 			} | ||||
| 			member := strings.Split(path[0][len("uid="):], ",") | ||||
| 			claims[appID].Members[role] = append(claims[appID].Members[role], member[0]) | ||||
| 		} | ||||
| 		memberDNs, ok = entry["uniqueMember"] | ||||
| 		for _, memberDN := range memberDNs { | ||||
| 			if !ok || memberDN == "" { | ||||
| 				continue | ||||
| 			} | ||||
| 			path = strings.Split(memberDN[:n-k-1], ",") | ||||
| 			if len(path) < 1 { | ||||
| 				continue | ||||
| 			} | ||||
| 			member := strings.Split(path[0][len("uid="):], ",") | ||||
| 			claims[appID].Members[role] = append(claims[appID].Members[role], member[0]) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return claims, nil | ||||
| } | ||||
|  | ||||
| // findBasicUserDetails finds user's LDAP attributes that were specified. It returns nil if no such user. | ||||
| func (cli *Client) findBasicUserDetails(cn conn, username string, attrs []string) (map[string][]string, error) { | ||||
| func (cli *Client) findBasicUserDetails(cn conn, username string, attrs []string) (map[string]interface{}, error) { | ||||
| 	if cli.BindDN != "" { | ||||
| 		// We need to login to a LDAP server with a service account for retrieving user data. | ||||
| 		if err := cn.Bind(cli.BindDN, cli.BindPass); err != nil { | ||||
| @@ -390,7 +298,7 @@ func (cli *Client) findBasicUserDetails(cn conn, username string, attrs []string | ||||
|  | ||||
| 	var ( | ||||
| 		entry   = entries[0] | ||||
| 		details = make(map[string][]string) | ||||
| 		details = make(map[string]interface{}) | ||||
| 	) | ||||
| 	for _, attr := range attrs { | ||||
| 		if v, ok := entry[attr]; ok { | ||||
| @@ -441,40 +349,35 @@ func (c *ldapConn) Bind(bindDN, password string) error { | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func (c *ldapConn) SearchUser(user string, attrs ...string) ([]map[string][]string, error) { | ||||
| func (c *ldapConn) SearchUser(user string, attrs ...string) ([]map[string]interface{}, error) { | ||||
| 	query := fmt.Sprintf( | ||||
| 		"(&(|(objectClass=organizationalPerson)(objectClass=inetOrgPerson))"+ | ||||
| 			"(|(uid=%[1]s)(mail=%[1]s)(userPrincipalName=%[1]s)(sAMAccountName=%[1]s)))", user) | ||||
| 	return c.searchEntries(c.BaseDN, query, attrs) | ||||
| } | ||||
|  | ||||
| func (c *ldapConn) SearchUserRoles(user string, attrs ...string) ([]map[string][]string, error) { | ||||
| func (c *ldapConn) SearchUserRoles(user string, attrs ...string) ([]map[string]interface{}, error) { | ||||
| 	query := fmt.Sprintf("(|"+ | ||||
| 		"(&(|(objectClass=group)(objectClass=groupOfNames)(objectClass=groupofnames))(member=%[1]s))"+ | ||||
| 		"(&(|(objectClass=group)(objectClass=groupOfNames))(member=%[1]s))"+ | ||||
| 		"(&(objectClass=groupOfUniqueNames)(uniqueMember=%[1]s))"+ | ||||
| 		")", user) | ||||
| 	return c.searchEntries(c.RoleBaseDN, query, attrs) | ||||
| } | ||||
|  | ||||
| func (c *ldapConn) SearchRoles(attrs ...string) ([]map[string][]string, error) { | ||||
| 	query := "(|(&(|(objectClass=group)(objectClass=groupOfNames)(objectClass=groupofnames))))" | ||||
| 	return c.searchEntries(c.RoleBaseDN, query, attrs) | ||||
| } | ||||
|  | ||||
| // searchEntries executes a LDAP query, and returns a result as entries where each entry is mapping of LDAP attributes. | ||||
| func (c *ldapConn) searchEntries(baseDN, query string, attrs []string) ([]map[string][]string, error) { | ||||
| func (c *ldapConn) searchEntries(baseDN, query string, attrs []string) ([]map[string]interface{}, error) { | ||||
| 	req := ldap.NewSearchRequest(baseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, query, attrs, nil) | ||||
| 	res, err := c.Search(req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	var entries []map[string][]string | ||||
| 	var entries []map[string]interface{} | ||||
| 	for _, v := range res.Entries { | ||||
| 		entry := map[string][]string{"dn": []string{v.DN}} | ||||
| 		entry := map[string]interface{}{"dn": v.DN} | ||||
| 		for _, attr := range v.Attributes { | ||||
| 			// We need the first value only for the named attribute. | ||||
| 			entry[attr.Name] = attr.Values | ||||
| 			entry[attr.Name] = attr.Values[0] | ||||
| 		} | ||||
| 		entries = append(entries, entry) | ||||
| 	} | ||||
|   | ||||
| @@ -2,14 +2,13 @@ package claims | ||||
|  | ||||
| import ( | ||||
| 	"oc-auth/conf" | ||||
| 	"strings" | ||||
|  | ||||
| 	"cloud.o-forge.io/core/oc-lib/models/peer" | ||||
| ) | ||||
|  | ||||
| // Tokenizer interface | ||||
| type ClaimService interface { | ||||
| 	AddClaimsToToken(clientID string, userId string, peer *peer.Peer) Claims | ||||
| 	AddClaimsToToken(userId string, peer *peer.Peer) Claims | ||||
| 	DecodeClaimsInToken(host string, method string, forward string, sessionClaims Claims, publicKey string, external bool) (bool, error) | ||||
| } | ||||
|  | ||||
| @@ -29,10 +28,5 @@ var t = map[string]ClaimService{ | ||||
| } | ||||
|  | ||||
| func GetClaims() ClaimService { | ||||
| 	for k := range t { | ||||
| 		if strings.Contains(conf.GetConfig().Auth, k) { | ||||
| 			return t[k] | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| 	return t[conf.GetConfig().Auth] | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import ( | ||||
| 	"crypto/sha256" | ||||
| 	"encoding/pem" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"oc-auth/conf" | ||||
| 	"oc-auth/infrastructure/perms_connectors" | ||||
| 	"oc-auth/infrastructure/utils" | ||||
| @@ -120,23 +119,21 @@ func (h HydraClaims) DecodeClaimsInToken(host string, method string, forward str | ||||
| 				Relation: "permits" + strings.ToUpper(meth.String()), | ||||
| 				Object:   p.(string), | ||||
| 			} | ||||
| 			return perms_connectors.GetPermissionConnector("").CheckPermission(perm, nil, true), nil | ||||
| 			return perms_connectors.GetPermissionConnector().CheckPermission(perm, nil, true), nil | ||||
| 		} | ||||
| 	} | ||||
| 	return false, errors.New("no permission found") | ||||
| } | ||||
|  | ||||
| // add claims to token method of HydraTokenizer | ||||
| func (h HydraClaims) AddClaimsToToken(clientID string, userId string, p *peer.Peer) Claims { | ||||
| func (h HydraClaims) AddClaimsToToken(userId string, p *peer.Peer) Claims { | ||||
| 	claims := Claims{} | ||||
| 	perms, err := perms_connectors.KetoConnector{}.GetPermissionByUser(userId, true) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return claims | ||||
| 	} | ||||
| 	claims.Session.AccessToken = make(map[string]interface{}) | ||||
| 	claims.Session.IDToken = make(map[string]interface{}) | ||||
| 	fmt.Println("PERMS err 1", perms, err) | ||||
| 	for _, perm := range perms { | ||||
| 		key, err := h.generateKey(strings.ReplaceAll(perm.Relation, "permits", ""), perm.Subject) | ||||
| 		if err != nil { | ||||
| @@ -148,15 +145,15 @@ func (h HydraClaims) AddClaimsToToken(clientID string, userId string, p *peer.Pe | ||||
| 	if err != nil { | ||||
| 		return claims | ||||
| 	} | ||||
| 	claims.Session.IDToken["username"] = userId | ||||
| 	claims.Session.IDToken["peer_id"] = p.UUID | ||||
| 	// we should get group from user | ||||
| 	groups, err := perms_connectors.KetoConnector{}.GetGroupByUser(userId) | ||||
| 	if err != nil { | ||||
| 		return claims | ||||
| 	} | ||||
| 	claims.Session.IDToken["client_id"] = clientID | ||||
| 	claims.Session.IDToken["groups"] = groups | ||||
| 	claims.Session.IDToken["signature"] = sign | ||||
| 	return claims | ||||
| } | ||||
|  | ||||
| // add signature in the token MISSING | ||||
|   | ||||
| @@ -10,8 +10,8 @@ func GetAuthConnector() auth_connectors.AuthConnector { | ||||
| 	return auth_connectors.GetAuthConnector() | ||||
| } | ||||
|  | ||||
| func GetPermissionConnector(client string) perms_connectors.PermConnector { | ||||
| 	return perms_connectors.GetPermissionConnector(client) | ||||
| func GetPermissionConnector() perms_connectors.PermConnector { | ||||
| 	return perms_connectors.GetPermissionConnector() | ||||
| } | ||||
|  | ||||
| func GetClaims() claims.ClaimService { | ||||
|   | ||||
| @@ -6,29 +6,24 @@ import ( | ||||
| 	"fmt" | ||||
| 	"oc-auth/conf" | ||||
| 	"oc-auth/infrastructure/utils" | ||||
| 	"strings" | ||||
|  | ||||
| 	oclib "cloud.o-forge.io/core/oc-lib" | ||||
| 	"cloud.o-forge.io/core/oc-lib/tools" | ||||
| ) | ||||
|  | ||||
| type KetoConnector struct { | ||||
| 	Client string | ||||
| } | ||||
|  | ||||
| func (k KetoConnector) SetClient(client string) { | ||||
| 	k.Client = client | ||||
| } | ||||
| type KetoConnector struct{} | ||||
|  | ||||
| func (k KetoConnector) namespace() string { | ||||
| 	return "open-cloud" | ||||
| } | ||||
|  | ||||
| func (k KetoConnector) scope() string { | ||||
| 	return "oc-auth-realm" | ||||
| 	return "oc-auth" | ||||
| } | ||||
|  | ||||
| func (f KetoConnector) permToQuery(perm Permission, permDependancies *Permission) string { | ||||
| 	n := "?namespace=" + f.namespace() | ||||
| 	n := "?namespace=" + perm.Namespace() | ||||
| 	if perm.Object != "" { | ||||
| 		n += "&object=" + perm.Object | ||||
| 	} | ||||
| @@ -56,10 +51,7 @@ func (f KetoConnector) permToQuery(perm Permission, permDependancies *Permission | ||||
| func (k KetoConnector) Status() tools.State { | ||||
| 	caller := tools.NewHTTPCaller(map[tools.DataType]map[tools.METHOD]string{}) | ||||
| 	var responseBody map[string]interface{} | ||||
| 	host := conf.GetConfig().PermissionConnectorReadHost | ||||
| 	if conf.GetConfig().Local { | ||||
| 		host = "localhost" | ||||
| 	} | ||||
| 	host := conf.GetConfig().PermissionConnectorHost | ||||
| 	port := fmt.Sprintf("%v", conf.GetConfig().PermissionConnectorPort) | ||||
| 	resp, err := caller.CallGet("http://"+host+":"+port, "/health/ready") | ||||
| 	if err != nil { | ||||
| @@ -81,7 +73,7 @@ func (k KetoConnector) CheckPermission(perm Permission, permDependancies *Permis | ||||
| 	perms, err := k.GetPermission(perm.Object, perm.Relation) | ||||
| 	if err != nil { | ||||
| 		log := oclib.GetLogger() | ||||
| 		log.Error().Msg("CheckPermission " + err.Error()) | ||||
| 		log.Error().Msg(err.Error()) | ||||
| 		return false | ||||
| 	} | ||||
| 	return len(perms) > 0 | ||||
| @@ -197,7 +189,6 @@ func (k KetoConnector) GetPermissionByRole(roleID string) ([]Permission, error) | ||||
| } | ||||
| func (k KetoConnector) GetPermissionByUser(userID string, internal bool) ([]Permission, error) { | ||||
| 	roles, err := k.get("", "member", userID) | ||||
| 	fmt.Println("ROLES", roles, err) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -220,10 +211,7 @@ func (k KetoConnector) GetPermissionByUser(userID string, internal bool) ([]Perm | ||||
| func (k KetoConnector) get(object string, relation string, subject string) ([]Permission, error) { | ||||
| 	t := []Permission{} | ||||
| 	caller := tools.NewHTTPCaller(map[tools.DataType]map[tools.METHOD]string{}) | ||||
| 	host := conf.GetConfig().PermissionConnectorReadHost | ||||
| 	if conf.GetConfig().Local { | ||||
| 		host = "localhost" | ||||
| 	} | ||||
| 	host := conf.GetConfig().PermissionConnectorHost | ||||
| 	port := fmt.Sprintf("%v", conf.GetConfig().PermissionConnectorPort) | ||||
| 	resp, err := caller.CallGet("http://"+host+":"+port, "/relation-tuples"+k.permToQuery( | ||||
| 		Permission{Object: object, Relation: relation, Subject: subject}, nil)) | ||||
| @@ -247,7 +235,7 @@ func (k KetoConnector) get(object string, relation string, subject string) ([]Pe | ||||
| 	return t, nil | ||||
| } | ||||
|  | ||||
| func (k KetoConnector) binds(object string, relation string, subject string) (string, int, error) { | ||||
| func (k KetoConnector) binds(subject string, relation string, object string) (string, int, error) { | ||||
| 	_, code, err := k.createRelationShip(object, relation, subject, nil) | ||||
| 	if err != nil { | ||||
| 		return object, code, err | ||||
| @@ -256,7 +244,6 @@ func (k KetoConnector) binds(object string, relation string, subject string) (st | ||||
| } | ||||
|  | ||||
| func (k KetoConnector) BindRole(userID string, roleID string) (string, int, error) { | ||||
| 	fmt.Println("BIND ROLE", userID, roleID) | ||||
| 	return k.binds(userID, "member", roleID) | ||||
| } | ||||
|  | ||||
| @@ -337,6 +324,9 @@ func (k KetoConnector) UnBindPermission(roleID string, permID string, relation s | ||||
| } | ||||
| func (k KetoConnector) createRelationShip(object string, relation string, subject string, subPerm *Permission) (*Permission, int, error) { | ||||
| 	exist, err := k.get(object, relation, subject) | ||||
| 	if strings.Contains(subject, "/workflow/:id") { | ||||
| 		fmt.Println("subject", subject, relation, exist, err) | ||||
| 	} | ||||
| 	if err == nil && len(exist) > 0 { | ||||
| 		return nil, 409, errors.New("Relation already exist") | ||||
| 	} | ||||
| @@ -348,25 +338,21 @@ func (k KetoConnector) createRelationShip(object string, relation string, subjec | ||||
| 		if err != nil { | ||||
| 			return nil, code, err | ||||
| 		} | ||||
| 		body["subject_set"] = map[string]interface{}{"namespace": k.namespace(), "object": s.Object, "relation": s.Relation, "subject_id": s.Subject} | ||||
| 	} | ||||
| 	host := conf.GetConfig().PermissionConnectorWriteHost | ||||
| 	if conf.GetConfig().Local { | ||||
| 		host = "localhost" | ||||
| 		body["subject_set"] = map[string]interface{}{"namespace": s.Namespace(), "object": s.Object, "relation": s.Relation, "subject_id": s.Subject} | ||||
| 	} | ||||
| 	host := conf.GetConfig().PermissionConnectorHost | ||||
| 	port := fmt.Sprintf("%v", conf.GetConfig().PermissionConnectorAdminPort) | ||||
| 	b, err := caller.CallPut("http://"+host+":"+port, "/relation-tuples", body) | ||||
| 	if err != nil { | ||||
| 		log := oclib.GetLogger() | ||||
| 		log.Error().Msg("createRelationShip" + err.Error()) | ||||
| 		log.Error().Msg(err.Error()) | ||||
| 		return nil, 500, err | ||||
| 	} | ||||
| 	var data map[string]interface{} | ||||
| 	err = json.Unmarshal(b, &data) | ||||
| 	if err != nil { | ||||
| 		fmt.Println(string(b), err) | ||||
| 		log := oclib.GetLogger() | ||||
| 		log.Error().Msg("createRelationShip2" + err.Error()) | ||||
| 		log.Error().Msg(err.Error()) | ||||
| 		return nil, 500, err | ||||
| 	} | ||||
| 	perm := &Permission{ | ||||
| @@ -392,15 +378,12 @@ func (k KetoConnector) deleteRelationShip(object string, relation string, subjec | ||||
| 	} | ||||
| 	caller := tools.NewHTTPCaller(map[tools.DataType]map[tools.METHOD]string{}) | ||||
| 	n := k.permToQuery(Permission{Object: object, Relation: relation, Subject: subject}, subPerm) | ||||
| 	host := conf.GetConfig().PermissionConnectorWriteHost | ||||
| 	if conf.GetConfig().Local { | ||||
| 		host = "localhost" | ||||
| 	} | ||||
| 	host := conf.GetConfig().PermissionConnectorHost | ||||
| 	port := fmt.Sprintf("%v", conf.GetConfig().PermissionConnectorAdminPort) | ||||
| 	b, err := caller.CallDelete("http://"+host+":"+port, "/relation-tuples"+n) | ||||
| 	if err != nil { | ||||
| 		log := oclib.GetLogger() | ||||
| 		log.Error().Msg("deleteRelationShip " + err.Error()) | ||||
| 		log.Error().Msg(err.Error()) | ||||
| 		return nil, 500, err | ||||
| 	} | ||||
| 	var data map[string]interface{} | ||||
|   | ||||
| @@ -1,9 +1,6 @@ | ||||
| package perms_connectors | ||||
|  | ||||
| import ( | ||||
| 	"oc-auth/conf" | ||||
| 	"strings" | ||||
|  | ||||
| 	"cloud.o-forge.io/core/oc-lib/tools" | ||||
| ) | ||||
|  | ||||
| @@ -24,7 +21,6 @@ func (k Permission) Scope() string { | ||||
|  | ||||
| type PermConnector interface { | ||||
| 	Status() tools.State | ||||
| 	SetClient(scope string) | ||||
| 	CheckPermission(perm Permission, permDependancies *Permission, internal bool) bool | ||||
| 	BindRole(userID string, roleID string) (string, int, error) | ||||
| 	BindGroup(userID string, groupID string) (string, int, error) | ||||
| @@ -55,11 +51,6 @@ var c = map[string]PermConnector{ | ||||
| 	"keto": KetoConnector{}, | ||||
| } | ||||
|  | ||||
| func GetPermissionConnector(scope string) PermConnector { | ||||
| 	for k := range c { | ||||
| 		if strings.Contains(conf.GetConfig().PermissionConnectorReadHost, k) { | ||||
| 			return c[k] | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| func GetPermissionConnector() PermConnector { | ||||
| 	return c["keto"] | ||||
| } | ||||
|   | ||||
							
								
								
									
										21
									
								
								keto/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								keto/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| version: '3.4' | ||||
|  | ||||
| services: | ||||
|   keto: | ||||
|     image: oryd/keto:v0.7.0-alpha.1-sqlite | ||||
|     ports: | ||||
|       - "4466:4466" | ||||
|       - "4467:4467" | ||||
|     command: serve -c /home/ory/keto.yml | ||||
|     restart: on-failure | ||||
|     volumes: | ||||
|       - type: bind | ||||
|         source: . | ||||
|         target: /home/ory | ||||
|     container_name: keto | ||||
|     networks:  | ||||
|       - catalog | ||||
|  | ||||
| networks:  | ||||
|   catalog: | ||||
|     external: true | ||||
							
								
								
									
										18
									
								
								keto/keto.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								keto/keto.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| version: v0.6.0-alpha.1 | ||||
|  | ||||
| log: | ||||
|   level: debug | ||||
|  | ||||
| namespaces: | ||||
|   - id: 0 | ||||
|     name: open-cloud | ||||
|  | ||||
| dsn: memory | ||||
|  | ||||
| serve: | ||||
|   read: | ||||
|     host: 0.0.0.0 | ||||
|     port: 4466 | ||||
|   write: | ||||
|     host: 0.0.0.0 | ||||
|     port: 4467 | ||||
							
								
								
									
										79
									
								
								ldap-hydra/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								ldap-hydra/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| version: "3" | ||||
| services:    | ||||
|     hydra-client:  | ||||
|         image: oryd/hydra:v2.2.0 | ||||
|         container_name: hydra-client | ||||
|         environment: | ||||
|             HYDRA_ADMIN_URL: http://hydra:4445 | ||||
|             ORY_SDK_URL: http://hydra:4445 | ||||
|         command: | ||||
|             - create | ||||
|             - oauth2-client | ||||
|             - --skip-tls-verify | ||||
|             - --name | ||||
|             - test-client | ||||
|             - --secret | ||||
|             - oc-auth-got-secret | ||||
|             - --response-type | ||||
|             - id_token,token,code | ||||
|             - --grant-type | ||||
|             - implicit,refresh_token,authorization_code,client_credentials | ||||
|             - --scope | ||||
|             - openid,profile,email,roles | ||||
|             - --token-endpoint-auth-method | ||||
|             - client_secret_post | ||||
|             - --redirect-uri | ||||
|             - http://localhost:3000 | ||||
|  | ||||
|         networks: | ||||
|             - hydra-net | ||||
|             - catalog | ||||
|         deploy: | ||||
|             restart_policy: | ||||
|                 condition: none | ||||
|         depends_on: | ||||
|             - hydra | ||||
|         healthcheck: | ||||
|             test: ["CMD", "curl", "-f", "http://hydra:4445"] | ||||
|             interval: 10s | ||||
|             timeout: 10s | ||||
|             retries: 10 | ||||
|     hydra: | ||||
|         container_name: hydra | ||||
|         image: oryd/hydra:v2.2.0 | ||||
|         environment: | ||||
|             SECRETS_SYSTEM: oc-auth-got-secret | ||||
|             LOG_LEAK_SENSITIVE_VALUES: true | ||||
|             # OAUTH2_TOKEN_HOOK_URL: http://oc-auth:8080/oc/claims | ||||
|             URLS_SELF_ISSUER: http://hydra:4444 | ||||
|             URLS_SELF_PUBLIC: http://hydra:4444 | ||||
|             WEBFINGER_OIDC_DISCOVERY_SUPPORTED_SCOPES: profile,email,phone,roles | ||||
|             WEBFINGER_OIDC_DISCOVERY_SUPPORTED_CLAIMS: name,family_name,given_name,nickname,email,phone_number | ||||
|             DSN: memory | ||||
|         command: serve all --dev | ||||
|         networks: | ||||
|             - hydra-net | ||||
|             - catalog | ||||
|         ports: | ||||
|             - "4444:4444" | ||||
|             - "4445:4445" | ||||
|         deploy: | ||||
|             restart_policy: | ||||
|                 condition: on-failure | ||||
|     ldap: | ||||
|         image: pgarrett/ldap-alpine | ||||
|         container_name: ldap | ||||
|         volumes:   | ||||
|             - "./ldap.ldif:/ldif/ldap.ldif" | ||||
|         networks: | ||||
|             - hydra-net | ||||
|             - catalog | ||||
|         ports: | ||||
|             - "390:389" | ||||
|         deploy: | ||||
|             restart_policy: | ||||
|                 condition: on-failure | ||||
| networks:     | ||||
|     hydra-net: | ||||
|     catalog: | ||||
|         external: true | ||||
							
								
								
									
										24
									
								
								ldap-hydra/ldap.ldif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								ldap-hydra/ldap.ldif
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| dn: uid=admin,ou=Users,dc=example,dc=com | ||||
| objectClass: inetOrgPerson | ||||
| cn: Admin | ||||
| sn: Istrator | ||||
| uid: admin | ||||
| userPassword: admin | ||||
| mail: admin@example.com | ||||
| ou: Users | ||||
|  | ||||
| dn: ou=AppRoles,dc=example,dc=com | ||||
| objectClass: organizationalunit | ||||
| ou: AppRoles | ||||
| description: AppRoles | ||||
|  | ||||
| dn: ou=App1,ou=AppRoles,dc=example,dc=com | ||||
| objectClass: organizationalunit | ||||
| ou: App1 | ||||
| description: App1 | ||||
|  | ||||
| dn: cn=traveler,ou=App1,ou=AppRoles,dc=example,dc=com | ||||
| objectClass: groupofnames | ||||
| cn: traveler | ||||
| description: traveler | ||||
| member: uid=admin,ou=Users,dc=example,dc=com | ||||
							
								
								
									
										99
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										99
									
								
								main.go
									
									
									
									
									
								
							| @@ -1,26 +1,22 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"oc-auth/conf" | ||||
| 	"oc-auth/infrastructure" | ||||
| 	auth_connectors "oc-auth/infrastructure/auth_connector" | ||||
| 	_ "oc-auth/routers" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	oclib "cloud.o-forge.io/core/oc-lib" | ||||
| 	peer "cloud.o-forge.io/core/oc-lib/models/peer" | ||||
| 	"cloud.o-forge.io/core/oc-lib/models/utils" | ||||
| 	"cloud.o-forge.io/core/oc-lib/tools" | ||||
| 	beego "github.com/beego/beego/v2/server/web" | ||||
| 	"github.com/beego/beego/v2/server/web/filter/cors" | ||||
| ) | ||||
|  | ||||
| const test_name = "test-pierre" | ||||
| const appname = "oc-auth" | ||||
|  | ||||
| // @securityDefinitions.apikey Bearer | ||||
| @@ -37,73 +33,32 @@ func main() { | ||||
| 	conf.GetConfig().PublicKeyPath = o.GetStringDefault("PUBLIC_KEY_PATH", "./pem/public.pem") | ||||
| 	conf.GetConfig().PrivateKeyPath = o.GetStringDefault("PRIVATE_KEY_PATH", "./pem/private.pem") | ||||
| 	conf.GetConfig().ClientSecret = o.GetStringDefault("CLIENT_SECRET", "oc-auth-got-secret") | ||||
| 	conf.GetConfig().OAuth2ClientSecretName = o.GetStringDefault("OAUTH2_CLIENT_SECRET_NAME", "oc-oauth2-client-secret") | ||||
| 	conf.GetConfig().OAuth2ClientSecretNamespace = o.GetStringDefault("NAMESPACE", "default") | ||||
|  | ||||
| 	conf.GetConfig().Auth = o.GetStringDefault("AUTH", "hydra") | ||||
| 	conf.GetConfig().AuthConnectorHost = o.GetStringDefault("AUTH_CONNECTOR_HOST", "localhost") | ||||
| 	conf.GetConfig().AuthConnectPublicHost = o.GetStringDefault("AUTH_CONNECTOR_PUBLIC_HOST", "localhost") | ||||
| 	conf.GetConfig().AuthConnectorPort = o.GetIntDefault("AUTH_CONNECTOR_PORT", 4444) | ||||
| 	conf.GetConfig().AuthConnectorAdminPort = o.GetStringDefault("AUTH_CONNECTOR_ADMIN_PORT", "4445/admin") | ||||
| 	conf.GetConfig().PermissionConnectorWriteHost = o.GetStringDefault("PERMISSION_CONNECTOR_WRITE_HOST", "keto") | ||||
| 	conf.GetConfig().PermissionConnectorReadHost = o.GetStringDefault("PERMISSION_CONNECTOR_READ_HOST", "keto") | ||||
| 	conf.GetConfig().PermissionConnectorPort = o.GetStringDefault("PERMISSION_CONNECTOR_PORT", "4466") | ||||
| 	conf.GetConfig().PermissionConnectorAdminPort = o.GetStringDefault("PERMISSION_CONNECTOR_ADMIN_PORT", "4467") | ||||
| 	conf.GetConfig().Local = o.GetBoolDefault("LOCAL", true) | ||||
| 	conf.GetConfig().AuthConnectorAdminPort = o.GetIntDefault("AUTH_CONNECTOR_ADMIN_PORT", 4445) | ||||
| 	conf.GetConfig().PermissionConnectorHost = o.GetStringDefault("PERMISSION_CONNECTOR_HOST", "keto") | ||||
| 	conf.GetConfig().PermissionConnectorPort = o.GetIntDefault("PERMISSION_CONNECTOR_PORT", 4466) | ||||
| 	conf.GetConfig().PermissionConnectorAdminPort = o.GetIntDefault("PERMISSION_CONNECTOR_ADMIN_PORT", 4467) | ||||
|  | ||||
| 	// config LDAP | ||||
| 	conf.GetConfig().SourceMode = o.GetStringDefault("SOURCE_MODE", "ldap") | ||||
| 	conf.GetConfig().LDAPEndpoints = o.GetStringDefault("LDAP_ENDPOINTS", "ldap:389") | ||||
| 	conf.GetConfig().LDAPBindDN = o.GetStringDefault("LDAP_BINDDN", "cn=admin,dc=example,dc=com") | ||||
| 	conf.GetConfig().LDAPBindPW = o.GetStringDefault("LDAP_BINDPW", "password") | ||||
| 	conf.GetConfig().LDAPBaseDN = o.GetStringDefault("LDAP_BASEDN", "dc=example,dc=com") | ||||
| 	conf.GetConfig().LDAPRoleBaseDN = o.GetStringDefault("LDAP_ROLE_BASEDN", "ou=AppRoles,dc=example,dc=com") | ||||
| 	go generateSelfPeer() | ||||
| 	go generateRole() | ||||
| 	go discovery() | ||||
| 	beego.BConfig.Listen.HTTPPort = o.GetIntDefault("port", 8080) | ||||
| 	beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{ | ||||
| 		AllowAllOrigins:  true, | ||||
| 		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, | ||||
| 		AllowHeaders:     []string{"Origin", "Authorization", "Content-Type"}, | ||||
| 		ExposeHeaders:    []string{"Content-Length", "Content-Type"}, | ||||
| 		AllowCredentials: true, | ||||
| 	})) | ||||
| 	err := generateSelfPeer() | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	discovery() | ||||
| 	beego.Run() | ||||
| } | ||||
|  | ||||
| func generateRole() { | ||||
| 	defer func() { | ||||
| 		if r := recover(); r != nil { | ||||
| 			fmt.Println("Recovered in f", r) | ||||
| 		} | ||||
| 	}() | ||||
| 	// if from ldap, create roles from ldap | ||||
| 	if conf.GetConfig().SourceMode == "ldap" { | ||||
| 		ldap := auth_connectors.New() | ||||
| 		roles, err := ldap.GetRoles(context.Background()) | ||||
| 		if err == nil { | ||||
| 			fmt.Println("ROLE", roles) | ||||
| 			for _, role := range roles { | ||||
| 				for r, m := range role.Members { | ||||
| 					infrastructure.GetPermissionConnector("").CreateRole(r) | ||||
| 					for _, p := range m { | ||||
| 						infrastructure.GetPermissionConnector("").BindRole(r, p) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} else { | ||||
| 			time.Sleep(10 * time.Second) // Pause execution for 10 seconds | ||||
| 			generateRole() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func generateSelfPeer() error { | ||||
| 	defer func() { | ||||
| 		if r := recover(); r != nil { | ||||
| 			fmt.Println("Recovered in f", r) | ||||
| 		} | ||||
| 	}() | ||||
| 	requester := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), test_name, "1234", nil, nil) | ||||
|  | ||||
| 	// TODO check if files at private & public path are set | ||||
| 	// check if files at private & public path are set | ||||
| 	if _, err := os.Stat(conf.GetConfig().PrivateKeyPath); errors.Is(err, os.ErrNotExist) { | ||||
| @@ -113,7 +68,8 @@ func generateSelfPeer() error { | ||||
| 		return errors.New("public key path does not exist") | ||||
| 	} | ||||
| 	// check if peer already exists | ||||
| 	p := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), "", "", []string{}, nil).Search(nil, strconv.Itoa(peer.SELF.EnumIndex()), false) | ||||
| 	p := requester.Search(nil,strconv.Itoa(peer.SELF.EnumIndex())) | ||||
| 	// p := oclib.Search(nil, strconv.Itoa(peer.SELF.EnumIndex()), oclib.L	ibDataEnum(oclib.PEER)) | ||||
| 	file := "" | ||||
| 	f, err := os.ReadFile(conf.GetConfig().PublicKeyPath) | ||||
| 	if err != nil { | ||||
| @@ -135,34 +91,21 @@ func generateSelfPeer() error { | ||||
| 		AbstractObject: utils.AbstractObject{ | ||||
| 			Name: o.GetStringDefault("NAME", "local"), | ||||
| 		}, | ||||
| 		PublicKey:     file, | ||||
| 		State:         peer.SELF, | ||||
| 		WalletAddress: "my-wallet", | ||||
| 		PublicKey: file, | ||||
| 		State:     peer.SELF, | ||||
| 	} | ||||
| 	data := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), "", "", []string{}, nil).StoreOne(peer.Serialize(peer)) | ||||
| 	data := requester.StoreOne(peer.Serialize(peer)) | ||||
| 	if data.Err != "" { | ||||
| 		time.Sleep(10 * time.Second) // Pause execution for 10 seconds | ||||
| 		generateSelfPeer() | ||||
| 		return errors.New(data.Err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func discovery() { | ||||
| 	defer func() { | ||||
| 		if r := recover(); r != nil { | ||||
| 			fmt.Println("Recovered in f", r) | ||||
| 		} | ||||
| 	}() | ||||
| 	api := tools.API{} | ||||
| 	conn := infrastructure.GetPermissionConnector("") | ||||
| 	fmt.Println("AdminRole", conn, conf.GetConfig().PermissionConnectorWriteHost) | ||||
| 	_, _, err := conn.CreateRole(conf.GetConfig().AdminRole) | ||||
| 	if err != nil { | ||||
| 		time.Sleep(10 * time.Second) // Pause execution for 10 seconds | ||||
| 		discovery() | ||||
| 		return | ||||
| 	} | ||||
| 	conn := infrastructure.GetPermissionConnector() | ||||
|  | ||||
| 	conn.CreateRole(conf.GetConfig().AdminRole) | ||||
| 	conn.BindRole(conf.GetConfig().AdminRole, "admin") | ||||
| 	addPermissions := func(m map[string]interface{}) { | ||||
| 		for k, v := range m { | ||||
|   | ||||
| @@ -99,8 +99,8 @@ func init() { | ||||
|  | ||||
|     beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"], | ||||
|         beego.ControllerComments{ | ||||
|             Method: "Login", | ||||
|             Router: `/login`, | ||||
|             Method: "LoginLDAP", | ||||
|             Router: `/ldap/login`, | ||||
|             AllowHTTPMethods: []string{"post"}, | ||||
|             MethodParams: param.Make(), | ||||
|             Filters: nil, | ||||
| @@ -108,8 +108,8 @@ func init() { | ||||
|  | ||||
|     beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"], | ||||
|         beego.ControllerComments{ | ||||
|             Method: "LogOut", | ||||
|             Router: `/logout`, | ||||
|             Method: "LogOutLDAP", | ||||
|             Router: `/ldap/logout`, | ||||
|             AllowHTTPMethods: []string{"delete"}, | ||||
|             MethodParams: param.Make(), | ||||
|             Filters: nil, | ||||
|   | ||||
| @@ -191,7 +191,7 @@ | ||||
|                 "parameters": [ | ||||
|                     { | ||||
|                         "in": "path", | ||||
|                         "name": "user_id", | ||||
|                         "name": "group_id", | ||||
|                         "description": "The group_id you want to unbind", | ||||
|                         "required": true, | ||||
|                         "type": "string" | ||||
| @@ -233,7 +233,7 @@ | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "/login": { | ||||
|         "/ldap/login": { | ||||
|             "post": { | ||||
|                 "tags": [ | ||||
|                     "oc-auth/controllersOAuthController" | ||||
| @@ -249,13 +249,6 @@ | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/models.workflow" | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         "in": "query", | ||||
|                         "name": "client_id", | ||||
|                         "description": "the client_id you want to get", | ||||
|                         "required": true, | ||||
|                         "type": "string" | ||||
|                     } | ||||
|                 ], | ||||
|                 "responses": { | ||||
| @@ -265,7 +258,7 @@ | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "/logout": { | ||||
|         "/ldap/logout": { | ||||
|             "delete": { | ||||
|                 "tags": [ | ||||
|                     "oc-auth/controllersOAuthController" | ||||
| @@ -278,13 +271,6 @@ | ||||
|                         "name": "Authorization", | ||||
|                         "description": "auth token", | ||||
|                         "type": "string" | ||||
|                     }, | ||||
|                     { | ||||
|                         "in": "query", | ||||
|                         "name": "client_id", | ||||
|                         "description": "the client_id you want to get", | ||||
|                         "required": true, | ||||
|                         "type": "string" | ||||
|                     } | ||||
|                 ], | ||||
|                 "responses": { | ||||
| @@ -479,13 +465,6 @@ | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/models.Token" | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         "in": "query", | ||||
|                         "name": "client_id", | ||||
|                         "description": "the client_id you want to get", | ||||
|                         "required": true, | ||||
|                         "type": "string" | ||||
|                     } | ||||
|                 ], | ||||
|                 "responses": { | ||||
|   | ||||
| @@ -119,7 +119,7 @@ paths: | ||||
|       operationId: GroupController.UnBind | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: user_id | ||||
|         name: group_id | ||||
|         description: The group_id you want to unbind | ||||
|         required: true | ||||
|         type: string | ||||
| @@ -175,7 +175,7 @@ paths: | ||||
|       responses: | ||||
|         "200": | ||||
|           description: '{string}' | ||||
|   /login: | ||||
|   /ldap/login: | ||||
|     post: | ||||
|       tags: | ||||
|       - oc-auth/controllersOAuthController | ||||
| @@ -190,15 +190,10 @@ paths: | ||||
|         required: true | ||||
|         schema: | ||||
|           $ref: '#/definitions/models.workflow' | ||||
|       - in: query | ||||
|         name: client_id | ||||
|         description: the client_id you want to get | ||||
|         required: true | ||||
|         type: string | ||||
|       responses: | ||||
|         "200": | ||||
|           description: '{string}' | ||||
|   /logout: | ||||
|   /ldap/logout: | ||||
|     delete: | ||||
|       tags: | ||||
|       - oc-auth/controllersOAuthController | ||||
| @@ -211,11 +206,6 @@ paths: | ||||
|         name: Authorization | ||||
|         description: auth token | ||||
|         type: string | ||||
|       - in: query | ||||
|         name: client_id | ||||
|         description: the client_id you want to get | ||||
|         required: true | ||||
|         type: string | ||||
|       responses: | ||||
|         "200": | ||||
|           description: '{string}' | ||||
| @@ -360,11 +350,6 @@ paths: | ||||
|         required: true | ||||
|         schema: | ||||
|           $ref: '#/definitions/models.Token' | ||||
|       - in: query | ||||
|         name: client_id | ||||
|         description: the client_id you want to get | ||||
|         required: true | ||||
|         type: string | ||||
|       responses: | ||||
|         "200": | ||||
|           description: '{string}' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user