37 Commits

Author SHA1 Message Date
fb3366328b Ajouter .gitattributes 2025-11-01 16:38:21 +01:00
mr
75857dc125 oclib 2025-06-24 16:57:35 +02:00
mr
e7ff288972 nats push 2025-06-24 09:14:59 +02:00
mr
d83208be52 deploy adjust 2025-06-16 09:11:21 +02:00
mr
3d42ce6820 auth 2025-04-01 10:16:26 +02:00
mr
5ca9a10d14 launch mode 2025-03-06 09:46:13 +01:00
mr
a480c9b8a0 neo oclib 2025-02-21 11:24:03 +01:00
mr
6a6fe77c30 traefik 2025-02-19 12:02:44 +01:00
mr
2f8524af01 oclib update 2025-02-18 15:06:32 +01:00
mr
b684ba841f Correction 2025-02-18 09:20:13 +01:00
mr
37a0ceddf4 adjust in docker conf 2025-02-18 08:52:47 +01:00
mr
b18b82ea8c Merge branch 'feature/order' into main 2025-02-18 08:35:12 +01:00
mr
9bb08fc961 Merge branch 'feature/payment' into main 2025-02-13 10:32:46 +01:00
mr
cf08618f83 neo oclib 2025-02-13 10:28:36 +01:00
mr
0989aeb979 neo oc-lib 2025-02-06 08:56:30 +01:00
mr
8f4e33ab80 neo oc lib 2025-02-05 08:43:17 +01:00
plm
8df956bdcd Handling clientID/password from k8s secret 2025-01-22 15:23:18 +01:00
plm
776aac5d43 Fix oc-auth for k8s integration 2025-01-21 15:23:45 +01:00
mr
b84c2ef353 workin oc-auth 2025-01-17 17:24:08 +01:00
plm
27e2df2310 Support CORS 2025-01-15 11:38:12 +01:00
plm
939c8cdd67 Updating go.sum 2025-01-08 21:55:45 +01:00
plm
2a794518d5 upgrading oc-lib 2025-01-08 21:44:50 +01:00
plm
4498afabac Fix dependencies version 2024-12-16 14:26:47 +01:00
plm
f10615888c Pointing on last issue#4 commit to use oc-lib env var fix, removing useless log in Dockerfile building phase 2024-12-16 10:18:23 +01:00
plm
2ce3a380f0 Updating dependencies + fix dockerfile for quicker build + Introducing top Makefile script as unique entry point for building, deployment and high level tasks 2024-12-16 09:14:40 +01:00
plm
36e843d343 Fixing perm connector key (cant be based on perm service url) 2024-12-16 09:12:28 +01:00
plm
3a30e265cf Remove production binary from conf 2024-12-16 09:11:35 +01:00
plm
4add83b0d6 Removing debug binary from conf 2024-12-16 09:11:01 +01:00
mr
fd65220b91 add groups in claims 2024-11-27 12:36:37 +01:00
mr
1722980514 simplify code 2024-11-27 11:54:25 +01:00
mr
01daaae766 Add Group To Keto 2024-11-27 11:12:46 +01:00
mr
be071ec328 oclib + perms naming 2024-11-21 11:07:19 +01:00
mr
9a86604564 test 2024-11-18 15:16:58 +01:00
mr
cc91341547 public key bug 2024-11-18 14:58:26 +01:00
mr
2a8349b0c7 new peer url 2024-11-15 09:40:24 +01:00
mr
f4154136e1 oclib 2024-11-08 14:00:34 +01:00
mr
c73bd264cb oclib 2024-11-07 13:43:01 +01:00
36 changed files with 1375 additions and 1254 deletions

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
# Force Go as the main language
*.go linguist-detectable=true
* linguist-language=Go

View File

@@ -1,32 +1,45 @@
FROM golang:alpine as builder
ARG HOSTNAME=http://localhost
ARG NAME=local
FROM golang:alpine AS deps
WORKDIR /app
COPY go.mod go.sum ./
RUN sed -i '/replace/d' go.mod
RUN cat go.mod
RUN go mod download
COPY . .
#----------------------------------------------------------------------------------------------
FROM golang:alpine AS builder
RUN apk add git
RUN go get github.com/beego/bee/v2 && go install github.com/beego/bee/v2@master
RUN go install github.com/beego/bee/v2@latest
RUN timeout 15 bee run -gendoc=true -downdoc=true -runmode=dev || :
WORKDIR /oc-auth
RUN sed -i 's/http:\/\/127.0.0.1:8080\/swagger\/swagger.json/swagger.json/g' swagger/index.html
COPY --from=deps /go/pkg /go/pkg
COPY --from=deps /app/go.mod /app/go.sum ./
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" .
RUN export CGO_ENABLED=0 && \
export GOOS=linux && \
export GOARCH=amd64 && \
export BUILD_FLAGS="-ldflags='-w -s'"
RUN ls /app
COPY . .
FROM scratch
RUN sed -i '/replace/d' go.mod
RUN bee pack
RUN mkdir -p /app/extracted && tar -zxvf oc-auth.tar.gz -C /app/extracted
RUN sed -i 's/http:\/\/127.0.0.1:8080\/swagger\/swagger.json/swagger.json/g' /app/extracted/swagger/index.html
#----------------------------------------------------------------------------------------------
FROM golang:alpine
WORKDIR /app
COPY --from=builder /app/oc-auth /usr/bin/
COPY --from=builder /app/swagger /app/swagger
COPY docker_auth.json /etc/oc/auth.json
COPY --from=builder /app/extracted/oc-auth /usr/bin
COPY --from=builder /app/extracted/swagger /app/swagger
COPY --from=builder /app/extracted/pem /app/pem
COPY --from=builder /app/extracted/docker_auth.json /etc/oc/auth.json
EXPOSE 8080

40
Makefile Normal file
View File

@@ -0,0 +1,40 @@
.DEFAULT_GOAL := all
build: clean
bee pack
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
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
publish-kind:
kind load docker-image oc/oc-auth:0.0.1 --name opencloud | true
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

View File

@@ -7,6 +7,9 @@ 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"

Binary file not shown.

View File

@@ -1,9 +1,7 @@
{
"port": 8080,
"MONGO_URL":"mongodb://localhost:27017/",
"MONGO_DATABASE":"DC_myDC",
"natsurl":"http://localhost:4080",
"login":"admin",
"password":"admin",
"oidcserver":"http://localhost:8080"
"NATS_URL": "nats://localhost:4222",
"LDAP_ENDPOINTS": "localhost:390",
"port": 8094
}

View File

@@ -1,5 +1,5 @@
appname = oc-auth
httpport = 8080
httpport = 8094
runmode = dev
autorender = false
copyrequestbody = true

View File

@@ -3,6 +3,7 @@ package conf
import "sync"
type Config struct {
SourceMode string
AdminRole string
PublicKeyPath string
PrivateKeyPath string
@@ -13,16 +14,22 @@ type Config struct {
LDAPBaseDN string
LDAPRoleBaseDN string
ClientSecret string
ClientSecret string
OAuth2ClientSecretName string
OAuth2ClientSecretNamespace string
Auth string
AuthConnectPublicHost string
AuthConnectorHost string
AuthConnectorPort int
AuthConnectorAdminPort int
AuthConnectorAdminPort string
PermissionConnectorHost string
PermissionConnectorPort int
PermissionConnectorAdminPort int
PermissionConnectorWriteHost string
PermissionConnectorReadHost string
PermissionConnectorPort string
PermissionConnectorAdminPort string
Local bool
}
var instance *Config

221
controllers/group.go Normal file
View File

@@ -0,0 +1,221 @@
package controllers
import (
"oc-auth/infrastructure"
beego "github.com/beego/beego/v2/server/web"
)
// Operations about auth
type GroupController struct {
beego.Controller
}
// @Title Create
// @Description create group
// @Param id path string true "the id you want to get"
// @Success 200 {auth} create success!
// @router /:id [post]
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)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
"error": err.Error(),
"code": code,
}
} else {
o.Data["json"] = map[string]interface{}{
"data": group,
"error": nil,
"code": 200,
}
}
o.ServeJSON()
}
// @Title GetByUser
// @Description find group by user id
// @Param id path string true "the id you want to get"
// @Success 200 {auth} string
// @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)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
"error": err.Error(),
"code": 200,
}
} else {
o.Data["json"] = map[string]interface{}{
"data": group,
"error": nil,
"code": 200,
}
}
o.ServeJSON()
}
// @Title GetAll
// @Description find groups
// @Success 200 {group} string
// @router / [get]
func (o *GroupController) GetAll() {
clientID := ExtractClient(*o.Ctx.Request)
group, err := infrastructure.GetPermissionConnector(clientID).GetGroup("")
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
"error": err.Error(),
"code": 200,
}
} else {
o.Data["json"] = map[string]interface{}{
"data": group,
"error": nil,
"code": 200,
}
}
o.ServeJSON()
}
// @Title Get
// @Description find group by id
// @Param id path string true "the id you want to get"
// @Success 200 {group} string
// @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)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
"error": err.Error(),
"code": 200,
}
} else {
o.Data["json"] = map[string]interface{}{
"data": group,
"error": nil,
"code": 200,
}
}
o.ServeJSON()
}
// @Title Delete
// @Description delete the group
// @Param id path string true "The id you want to delete"
// @Success 200 {string} delete success!
// @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)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
"error": err.Error(),
"code": code,
}
} else {
o.Data["json"] = map[string]interface{}{
"data": group,
"error": nil,
"code": 200,
}
}
o.ServeJSON()
}
// @Title Clear
// @Description clear the group
// @Success 200 {string} delete success!
// @router /clear [delete]
func (o *GroupController) Clear() {
clientID := ExtractClient(*o.Ctx.Request)
group, code, err := infrastructure.GetPermissionConnector(clientID).DeleteGroup("")
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
"error": err.Error(),
"code": code,
}
} else {
o.Data["json"] = map[string]interface{}{
"data": group,
"error": nil,
"code": 200,
}
}
o.ServeJSON()
}
// @Title Bind
// @Description bind the group to user
// @Param user_id path string true "The user_id you want to bind"
// @Param group_id path string true "The group_id you want to bind"
// @Success 200 {string} bind success!
// @router /:user_id/:group_id [post]
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)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
"error": err.Error(),
"code": code,
}
} else {
o.Data["json"] = map[string]interface{}{
"data": group,
"error": nil,
"code": 200,
}
}
o.ServeJSON()
}
// @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 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)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
"error": err.Error(),
"code": code,
}
} else {
o.Data["json"] = map[string]interface{}{
"data": group,
"error": nil,
"code": 200,
}
}
o.ServeJSON()
}

View File

@@ -1,13 +1,17 @@
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"
@@ -22,10 +26,12 @@ 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 /ldap/logout [delete]
func (o *OAuthController) LogOutLDAP() {
// @router /logout [delete]
func (o *OAuthController) LogOut() {
// 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 {
@@ -36,11 +42,15 @@ func (o *OAuthController) LogOutLDAP() {
var res auth_connectors.Token
json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &res)
token, err := infrastructure.GetAuthConnector().Logout(reqToken)
if err != nil || token == nil {
o.Data["json"] = err
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
}
} else {
o.Data["json"] = token
o.Data["json"] = reqToken
}
o.ServeJSON()
}
@@ -48,30 +58,65 @@ func (o *OAuthController) LogOutLDAP() {
// @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 /ldap/login [post]
func (o *OAuthController) LoginLDAP() {
// @router /login [post]
func (o *OAuthController) Login() {
// authorize user
clientID := o.Ctx.Input.Query("client_id")
var res auth_connectors.Token
json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &res)
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().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
}
}
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)
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
}
} else {
o.Data["json"] = token
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.ServeJSON()
}
@@ -79,18 +124,24 @@ func (o *OAuthController) LoginLDAP() {
// @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
newToken, err := infrastructure.GetAuthConnector().Refresh(&token)
if err != nil || newToken == nil {
o.Data["json"] = err
o.Ctx.ResponseWriter.WriteHeader(401)
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
}
} else {
o.Data["json"] = newToken
o.Data["json"] = token
}
o.ServeJSON()
}
@@ -108,11 +159,12 @@ func (o *OAuthController) Introspect() {
} else {
reqToken = splitToken[1]
}
token, err := infrastructure.GetAuthConnector().Introspect(reqToken)
if err != nil || !token {
o.Data["json"] = err
o.Ctx.ResponseWriter.WriteHeader(401)
if !conf.GetConfig().Local {
token, err := infrastructure.GetAuthConnector().Introspect(reqToken)
if err != nil || !token {
o.Data["json"] = err
o.Ctx.ResponseWriter.WriteHeader(401)
}
}
o.ServeJSON()
}
@@ -149,7 +201,7 @@ func (o *OAuthController) InternalAuthForward() {
} else {
reqToken = splitToken[1]
}
origin, publicKey, external := o.extractOrigin()
origin, publicKey, external := o.extractOrigin(o.Ctx.Request)
if !infrastructure.GetAuthConnector().CheckAuthForward( //reqToken != "" &&
reqToken, publicKey, origin,
o.Ctx.Request.Header.Get("X-Forwarded-Method"),
@@ -161,7 +213,8 @@ func (o *OAuthController) InternalAuthForward() {
o.ServeJSON()
}
func (o *OAuthController) extractOrigin() (string, string, bool) {
func (o *OAuthController) extractOrigin(request *http.Request) (string, string, bool) {
user, peerID, groups := oclib.ExtractTokenInfo(*request)
external := true
publicKey := ""
origin := o.Ctx.Request.Header.Get("X-Forwarded-Host")
@@ -174,7 +227,7 @@ func (o *OAuthController) extractOrigin() (string, string, bool) {
if t != "" {
searchStr = strings.Replace(searchStr, t, "", -1)
}
peer := oclib.Search(nil, searchStr, oclib.LibDataEnum(oclib.PEER))
peer := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search(nil, searchStr, false)
if peer.Code != 200 || len(peer.Data) == 0 { // TODO: add state of partnership
return "", "", external
}
@@ -190,3 +243,29 @@ func (o *OAuthController) extractOrigin() (string, string, bool) {
}
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 ""
}

View File

@@ -16,7 +16,8 @@ type PermissionController struct {
// @Success 200 {permission} string
// @router / [get]
func (o *PermissionController) GetAll() {
role, err := infrastructure.GetPermissionConnector().GetPermission("", "")
clientID := ExtractClient(*o.Ctx.Request)
role, err := infrastructure.GetPermissionConnector(clientID).GetPermission("", "")
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -41,7 +42,8 @@ func (o *PermissionController) GetAll() {
// @router /role/:id [get]
func (o *PermissionController) GetByRole() {
id := o.Ctx.Input.Param(":id")
role, err := infrastructure.GetPermissionConnector().GetPermissionByRole(id)
clientID := ExtractClient(*o.Ctx.Request)
role, err := infrastructure.GetPermissionConnector(clientID).GetPermissionByRole(id)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -66,7 +68,8 @@ func (o *PermissionController) GetByRole() {
// @router /user/:id [get]
func (o *PermissionController) GetByUser() {
id := o.Ctx.Input.Param(":id")
role, err := infrastructure.GetPermissionConnector().GetPermissionByUser(id, true)
clientID := ExtractClient(*o.Ctx.Request)
role, err := infrastructure.GetPermissionConnector(clientID).GetPermissionByUser(id, true)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -92,7 +95,8 @@ func (o *PermissionController) GetByUser() {
func (o *PermissionController) Get() {
id := o.Ctx.Input.Param(":id")
rel := o.Ctx.Input.Param(":relation")
role, err := infrastructure.GetPermissionConnector().GetPermission(id, rel)
clientID := ExtractClient(*o.Ctx.Request)
role, err := infrastructure.GetPermissionConnector(clientID).GetPermission(id, rel)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -115,7 +119,8 @@ func (o *PermissionController) Get() {
// @Success 200 {string} delete success!
// @router /clear [delete]
func (o *PermissionController) Clear() {
role, code, err := infrastructure.GetPermissionConnector().DeletePermission("", "", true)
clientID := ExtractClient(*o.Ctx.Request)
role, code, err := infrastructure.GetPermissionConnector(clientID).DeletePermission("", "", true)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -144,7 +149,8 @@ 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")
role, code, err := infrastructure.GetPermissionConnector().BindPermission(role_id, permission_id, rel)
clientID := ExtractClient(*o.Ctx.Request)
role, code, err := infrastructure.GetPermissionConnector(clientID).BindPermission(role_id, permission_id, rel)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -173,7 +179,8 @@ 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")
role, code, err := infrastructure.GetPermissionConnector().UnBindPermission(role_id, permission_id, rel)
clientID := ExtractClient(*o.Ctx.Request)
role, code, err := infrastructure.GetPermissionConnector(clientID).UnBindPermission(role_id, permission_id, rel)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,

View File

@@ -19,7 +19,8 @@ type RoleController struct {
func (o *RoleController) Post() {
// store and return Id or post with UUID
id := o.Ctx.Input.Param(":id")
role, code, err := infrastructure.GetPermissionConnector().CreateRole(id)
clientID := ExtractClient(*o.Ctx.Request)
role, code, err := infrastructure.GetPermissionConnector(clientID).CreateRole(id)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -44,7 +45,8 @@ func (o *RoleController) Post() {
// @router /user/:id [get]
func (o *RoleController) GetByUser() {
id := o.Ctx.Input.Param(":id")
role, err := infrastructure.GetPermissionConnector().GetRoleByUser(id)
clientID := ExtractClient(*o.Ctx.Request)
role, err := infrastructure.GetPermissionConnector(clientID).GetRoleByUser(id)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -67,7 +69,8 @@ func (o *RoleController) GetByUser() {
// @Success 200 {role} string
// @router / [get]
func (o *RoleController) GetAll() {
role, err := infrastructure.GetPermissionConnector().GetRole("")
clientID := ExtractClient(*o.Ctx.Request)
role, err := infrastructure.GetPermissionConnector(clientID).GetRole("")
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -92,7 +95,8 @@ func (o *RoleController) GetAll() {
// @router /:id [get]
func (o *RoleController) Get() {
id := o.Ctx.Input.Param(":id")
role, err := infrastructure.GetPermissionConnector().GetRole(id)
clientID := ExtractClient(*o.Ctx.Request)
role, err := infrastructure.GetPermissionConnector(clientID).GetRole(id)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -117,7 +121,8 @@ func (o *RoleController) Get() {
// @router /:id [delete]
func (o *RoleController) Delete() {
id := o.Ctx.Input.Param(":id")
role, code, err := infrastructure.GetPermissionConnector().DeleteRole(id)
clientID := ExtractClient(*o.Ctx.Request)
role, code, err := infrastructure.GetPermissionConnector(clientID).DeleteRole(id)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -140,7 +145,8 @@ func (o *RoleController) Delete() {
// @Success 200 {string} delete success!
// @router /clear [delete]
func (o *RoleController) Clear() {
role, code, err := infrastructure.GetPermissionConnector().DeleteRole("")
clientID := ExtractClient(*o.Ctx.Request)
role, code, err := infrastructure.GetPermissionConnector(clientID).DeleteRole("")
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -167,7 +173,8 @@ func (o *RoleController) Clear() {
func (o *RoleController) Bind() {
user_id := o.Ctx.Input.Param(":user_id")
role_id := o.Ctx.Input.Param(":role_id")
role, code, err := infrastructure.GetPermissionConnector().BindRole(user_id, role_id)
clientID := ExtractClient(*o.Ctx.Request)
role, code, err := infrastructure.GetPermissionConnector(clientID).BindRole(user_id, role_id)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,
@@ -194,7 +201,8 @@ func (o *RoleController) Bind() {
func (o *RoleController) UnBind() {
user_id := o.Ctx.Input.Param(":user_id")
role_id := o.Ctx.Input.Param(":role_id")
role, code, err := infrastructure.GetPermissionConnector().UnBindRole(user_id, role_id)
clientID := ExtractClient(*o.Ctx.Request)
role, code, err := infrastructure.GetPermissionConnector(clientID).UnBindRole(user_id, role_id)
if err != nil {
o.Data["json"] = map[string]interface{}{
"data": nil,

View File

@@ -14,7 +14,10 @@ type VersionController struct {
// @Success 200
// @router / [get]
func (c *VersionController) GetAll() {
c.Data["json"] = map[string]string{"version": "1"}
c.Data["json"] = map[string]string{
"service": "oc-auth",
"version": "1",
}
c.ServeJSON()
}
@@ -23,6 +26,9 @@ func (c *VersionController) GetAll() {
// @Success 200
// @router /discovery [get]
func (c *VersionController) Get() {
c.Data["json"] = map[string]string{"version": "1"}
c.Data["json"] = map[string]string{
"service": "oc-auth",
"version": "1",
}
c.ServeJSON()
}

View File

@@ -1,22 +1,6 @@
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:
@@ -24,8 +8,13 @@ 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
@@ -33,9 +22,10 @@ services:
LDAP_BASEDN: "dc=example,dc=com"
LDAP_ROLE_BASEDN: "ou=AppRoles,dc=example,dc=com"
networks:
- catalog
- oc
volumes:
- ./pem:/etc/oc/pem
- ./pem/private.pem:/keys/private/private.pem
- ./pem/public.pem:/keys/public/public.pem
networks:
catalog:
oc:
external: true

View File

@@ -2,9 +2,10 @@
"MONGO_URL":"mongodb://mongo:27017/",
"MONGO_DATABASE":"DC_myDC",
"NATS_URL": "nats://nats:4222",
"PORT" : 8080,
"AUTH_CONNECTOR_HOST": "hydra",
"PRIVATE_KEY_PATH": "/etc/oc/pem/private.pem",
"PUBLIC_KEY_PATH": "/etc/oc/pem/public.pem",
"LDAP_ENDPOINTS": "ldap:389"
"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
}

4
env.env Normal file
View File

@@ -0,0 +1,4 @@
KUBERNETES_SERVICE_HOST=192.168.47.20
KUBE_CA="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTVlk3ZHZhNEdYTVdkMy9jMlhLN3JLYjlnWXgyNSthaEE0NmkyNVBkSFAKRktQL2UxSVMyWVF0dzNYZW1TTUQxaStZdzJSaVppNUQrSVZUamNtNHdhcnFvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWtlUVJpNFJiODduME5yRnZaWjZHClc2SU55NnN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnRXA5ck04WmdNclRZSHYxZjNzOW5DZXZZeWVVa3lZUk4KWjUzazdoaytJS1FDSVFDbk05TnVGKzlTakIzNDFacGZ5ays2NEpWdkpSM3BhcmVaejdMd2lhNm9kdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
KUBE_CERT="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJWUxWNkFPQkdrU1F3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOekl6TVRFeU1ETTJNQjRYRFRJME1EZ3dPREV3TVRNMU5sb1hEVEkxTURndwpPREV3TVRNMU5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJGQ2Q1MFdPeWdlQ2syQzcKV2FrOWY4MVAvSkJieVRIajRWOXBsTEo0ck5HeHFtSjJOb2xROFYxdUx5RjBtOTQ2Nkc0RmRDQ2dqaXFVSk92Swp3NVRPNnd5alNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVFJkOFI5cXVWK2pjeUVmL0ovT1hQSzMyS09XekFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQTArbThqTDBJVldvUTZ0dnB4cFo4NVlMalF1SmpwdXM0aDdnSXRxS3NmUVVDSUI2M2ZNdzFBMm5OVWU1TgpIUGZOcEQwSEtwcVN0Wnk4djIyVzliYlJUNklZCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFRc3hXWk9pbnIrcVp4TmFEQjVGMGsvTDF5cE01VHAxOFRaeU92ektJazQKRTFsZWVqUm9STW0zNmhPeVljbnN3d3JoNnhSUnBpMW5RdGhyMzg0S0Z6MlBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTBYZkVmYXJsZm8zTWhIL3lmemx6Cnl0OWlqbHN3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUxJL2dNYnNMT3MvUUpJa3U2WHVpRVMwTEE2cEJHMXgKcnBlTnpGdlZOekZsQWlFQW1wdjBubjZqN3M0MVI0QzFNMEpSL0djNE53MHdldlFmZWdEVGF1R2p3cFk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
KUBE_DATA="LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5ZS1BFb1dhd1NKUzJlRW5oWmlYMk5VZlY1ZlhKV2krSVNnV09TNFE5VTlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUozblJZN0tCNEtUWUx0WnFUMS96VS84a0Z2Sk1lUGhYMm1Vc25pczBiR3FZblkyaVZEeApYVzR2SVhTYjNqcm9iZ1YwSUtDT0twUWs2OHJEbE03ckRBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="

85
go.mod
View File

@@ -1,82 +1,29 @@
module oc-auth
go 1.22.0
go 1.23.0
toolchain go1.23.3
require (
cloud.o-forge.io/core/oc-lib v0.0.0-20241030105814-5f05b73366ab
cloud.o-forge.io/core/oc-lib v0.0.0-20250624102227-e600fedcab06
github.com/beego/beego/v2 v2.3.1
github.com/nats-io/nats.go v1.37.0
github.com/ory/hydra-client-go v1.11.8
github.com/smartystreets/goconvey v1.7.2
go.uber.org/zap v1.27.0
golang.org/x/oauth2 v0.23.0
)
//replace cloud.o-forge.io/core/oc-lib => ../oc-lib
require (
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // 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/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gobuffalo/pop/v6 v6.0.8 // indirect
github.com/gofrs/uuid v4.3.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v1.2.0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/goveralls v0.0.12 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
github.com/ory/go-acc v0.2.9-0.20230103102148-6b1c9a70dbbe // indirect
github.com/ory/go-convenience v0.1.0 // indirect
github.com/ory/x v0.0.575 // indirect
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/seatgeek/logrus-gelf-formatter v0.0.0-20210414080842-5b05eb8ff761 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.16.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.42.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect
go.opentelemetry.io/contrib/propagators/b3 v1.17.0 // indirect
go.opentelemetry.io/contrib/propagators/jaeger v1.17.0 // indirect
go.opentelemetry.io/contrib/samplers/jaegerremote v0.11.0 // indirect
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/jaeger v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/zipkin v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/atomic v1.9.0 // 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/robfig/cron v1.2.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/grpc v1.63.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
require (
@@ -88,7 +35,6 @@ require (
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/golang/protobuf v1.5.4 // 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
@@ -96,10 +42,7 @@ require (
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/i-core/rlog v1.0.0
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/justinas/nosurf v1.1.1
github.com/kelseyhightower/envconfig v1.4.0
github.com/klauspost/compress v1.17.11 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
@@ -108,13 +51,10 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nats-io/nkeys v0.4.7 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/ory/fosite v0.47.0
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/procfs v0.15.1 // indirect
github.com/purnaresa/bulwark v0.0.0-20201001150757-1cec324746b2
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rs/zerolog v1.33.0 // indirect
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect
github.com/smartystreets/assertions v1.2.0 // indirect
@@ -128,7 +68,6 @@ require (
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/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.35.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

831
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -3,16 +3,17 @@ 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(username string, cookies ...*http.Cookie) (*Token, error)
Logout(token string, cookies ...*http.Cookie) (*Token, error)
Login(clientID string, username string, cookies ...*http.Cookie) (*Token, error)
Logout(clientID string, token string, cookies ...*http.Cookie) (*Token, error)
Introspect(token string, cookie ...*http.Cookie) (bool, error)
Refresh(token *Token) (*Token, error)
Refresh(client_id string, token *Token) (*Token, error)
CheckAuthForward(reqToken string, publicKey string, host string, method string, forward string, external bool) bool
}
@@ -37,5 +38,10 @@ var a = map[string]AuthConnector{
}
func GetAuthConnector() AuthConnector {
return a[conf.GetConfig().Auth]
for k := range a {
if strings.Contains(conf.GetConfig().Auth, k) {
return a[k]
}
}
return nil
}

View File

@@ -23,7 +23,6 @@ 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
@@ -32,7 +31,10 @@ type HydraConnector struct {
func (a HydraConnector) Status() tools.State {
caller := tools.NewHTTPCaller(map[tools.DataType]map[tools.METHOD]string{})
var responseBody map[string]interface{}
host := conf.GetConfig().AuthConnectorHost
host := conf.GetConfig().AuthConnectPublicHost
if conf.GetConfig().Local {
host = "localhost"
}
port := fmt.Sprintf("%v", conf.GetConfig().AuthConnectorPort)
resp, err := caller.CallGet("http://"+host+":"+port, "/health/ready")
if err != nil {
@@ -69,6 +71,7 @@ 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
}
@@ -77,6 +80,7 @@ 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 {
@@ -85,7 +89,7 @@ func (a HydraConnector) challenge(username string, url string, challenge string,
return &token, s[1], cookies, nil
}
func (a HydraConnector) Refresh(token *Token) (*Token, error) {
func (a HydraConnector) Refresh(client_id string, token *Token) (*Token, error) {
access := strings.Split(token.AccessToken, ".")
if len(access) > 2 {
token.AccessToken = strings.Join(access[0:2], ".")
@@ -94,11 +98,11 @@ func (a HydraConnector) Refresh(token *Token) (*Token, error) {
if err != nil || !isValid {
return nil, err
}
_, err = a.Logout(token.AccessToken)
_, err = a.Logout(client_id, token.AccessToken)
if err != nil {
return nil, err
}
return a.Login(token.Username)
return a.Login(client_id, token.Username)
}
func (a HydraConnector) tryLog(username string, url string, subpath string, challenge string, cookies ...*http.Cookie) (*Redirect, string, []*http.Cookie, error) {
@@ -120,9 +124,10 @@ 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() string {
func (a HydraConnector) getClient(clientID string) string {
resp, err := a.Caller.CallGet(a.getPath(true, false), "/clients")
if err != nil {
fmt.Println(err)
return ""
}
var clients []interface{}
@@ -130,15 +135,26 @@ func (a HydraConnector) getClient() 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(username string, cookies ...*http.Cookie) (t *Token, err error) {
clientID := a.getClient()
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")
}
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...)
@@ -168,24 +184,26 @@ func (a HydraConnector) Login(username string, cookies ...*http.Cookie) (t *Toke
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.Search(nil, strconv.Itoa(peer.SELF.EnumIndex()), oclib.LibDataEnum(oclib.PEER))
pp := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), "", "", []string{}, nil).Search(nil, strconv.Itoa(peer.SELF.EnumIndex()), false)
if len(pp.Data) == 0 || pp.Code >= 300 || pp.Err != "" {
return nil, errors.New("peer not found")
}
now := time.Now().UTC()
now = now.Add(time.Duration(token.ExpiresIn) * time.Second)
token.ExpiresIn = now.Unix()
unix := now.Unix()
c := claims.GetClaims().AddClaimsToToken(username, pp.Data[0].(*peer.Peer).Url)
c.Session.AccessToken["exp"] = token.ExpiresIn
c := claims.GetClaims().AddClaimsToToken(clientID, username, pp.Data[0].(*peer.Peer))
c.Session.AccessToken["exp"] = unix
b, _ = json.Marshal(c)
@@ -194,7 +212,8 @@ func (a HydraConnector) Login(username string, cookies ...*http.Cookie) (t *Toke
return token, nil
}
func (a HydraConnector) Logout(token string, cookies ...*http.Cookie) (*Token, error) {
func (a HydraConnector) Logout(clientID string, token string, cookies ...*http.Cookie) (*Token, error) {
clientID = a.getClient(clientID)
access := strings.Split(token, ".")
if len(access) > 2 {
token = strings.Join(access[0:2], ".")
@@ -202,7 +221,7 @@ func (a HydraConnector) Logout(token string, cookies ...*http.Cookie) (*Token, e
p := a.getPath(false, true) + "/revoke"
urls := url.Values{}
urls.Add("token", token)
urls.Add("client_id", a.getClient())
urls.Add("client_id", clientID)
urls.Add("client_secret", conf.GetConfig().ClientSecret)
_, err := a.Caller.CallForm(http.MethodPost, p, "", urls, "application/x-www-form-urlencoded", true)
if err != nil {
@@ -242,10 +261,16 @@ func (a HydraConnector) Introspect(token string, cookie ...*http.Cookie) (bool,
}
func (a HydraConnector) getPath(isAdmin bool, isOauth bool) string {
host := conf.GetConfig().AuthConnectorHost
host := conf.GetConfig().AuthConnectPublicHost
if isAdmin {
host = conf.GetConfig().AuthConnectorHost
}
if conf.GetConfig().Local {
host = "localhost"
}
port := fmt.Sprintf("%v", conf.GetConfig().AuthConnectorPort)
if isAdmin {
port = fmt.Sprintf("%v", conf.GetConfig().AuthConnectorAdminPort) + "/admin"
port = fmt.Sprintf("%v", conf.GetConfig().AuthConnectorAdminPort)
}
oauth := ""
if isOauth {

View File

@@ -31,8 +31,9 @@ var (
type conn interface {
Bind(bindDN, password string) error
SearchUser(user string, attrs ...string) ([]map[string]interface{}, error)
SearchUserRoles(user string, attrs ...string) ([]map[string]interface{}, 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)
Close() error
}
@@ -78,7 +79,7 @@ type Client struct {
cache *freecache.Cache
}
func (cli *Client) Authenticate(ctx context.Context, username, password string) (bool, error) {
func (cli *Client) Authenticate(ctx context.Context, username string, password string) (bool, error) {
if username == "" || password == "" {
return false, nil
}
@@ -101,8 +102,8 @@ func (cli *Client) Authenticate(ctx context.Context, username, password string)
if details == nil {
return false, nil
}
if err := cn.Bind(details["dn"].(string), password); err != nil {
a := details["dn"]
if err := cn.Bind(a[0], password); err != nil {
if err == errInvalidCredentials {
return false, nil
}
@@ -118,6 +119,21 @@ func (cli *Client) Authenticate(ctx context.Context, username, password string)
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
@@ -125,6 +141,10 @@ 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 == "" {
@@ -193,11 +213,12 @@ func (cli *Client) FindOIDCClaims(ctx context.Context, username string) ([]LDAPC
roles := make(map[string]interface{})
for _, entry := range entries {
roleDN, ok := entry["dn"].(string)
if !ok || roleDN == "" {
roleDNs, ok := entry["dn"]
if !ok || len(roleDNs) == 0 {
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
@@ -207,7 +228,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) {
panic("You should never see that")
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.
@@ -278,8 +299,79 @@ 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]interface{}, error) {
func (cli *Client) findBasicUserDetails(cn conn, username string, attrs []string) (map[string][]string, 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 {
@@ -298,7 +390,7 @@ func (cli *Client) findBasicUserDetails(cn conn, username string, attrs []string
var (
entry = entries[0]
details = make(map[string]interface{})
details = make(map[string][]string)
)
for _, attr := range attrs {
if v, ok := entry[attr]; ok {
@@ -349,35 +441,40 @@ func (c *ldapConn) Bind(bindDN, password string) error {
return err
}
func (c *ldapConn) SearchUser(user string, attrs ...string) ([]map[string]interface{}, error) {
func (c *ldapConn) SearchUser(user string, attrs ...string) ([]map[string][]string, 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]interface{}, error) {
func (c *ldapConn) SearchUserRoles(user string, attrs ...string) ([]map[string][]string, error) {
query := fmt.Sprintf("(|"+
"(&(|(objectClass=group)(objectClass=groupOfNames))(member=%[1]s))"+
"(&(|(objectClass=group)(objectClass=groupOfNames)(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]interface{}, error) {
func (c *ldapConn) searchEntries(baseDN, query string, attrs []string) ([]map[string][]string, 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]interface{}
var entries []map[string][]string
for _, v := range res.Entries {
entry := map[string]interface{}{"dn": v.DN}
entry := map[string][]string{"dn": []string{v.DN}}
for _, attr := range v.Attributes {
// We need the first value only for the named attribute.
entry[attr.Name] = attr.Values[0]
entry[attr.Name] = attr.Values
}
entries = append(entries, entry)
}

View File

@@ -1,10 +1,15 @@
package claims
import "oc-auth/conf"
import (
"oc-auth/conf"
"strings"
"cloud.o-forge.io/core/oc-lib/models/peer"
)
// Tokenizer interface
type ClaimService interface {
AddClaimsToToken(userId string, host string) Claims
AddClaimsToToken(clientID string, userId string, peer *peer.Peer) Claims
DecodeClaimsInToken(host string, method string, forward string, sessionClaims Claims, publicKey string, external bool) (bool, error)
}
@@ -24,5 +29,10 @@ var t = map[string]ClaimService{
}
func GetClaims() ClaimService {
return t[conf.GetConfig().Auth]
for k := range t {
if strings.Contains(conf.GetConfig().Auth, k) {
return t[k]
}
}
return nil
}

View File

@@ -4,6 +4,7 @@ import (
"crypto/sha256"
"encoding/pem"
"errors"
"fmt"
"oc-auth/conf"
"oc-auth/infrastructure/perms_connectors"
"oc-auth/infrastructure/utils"
@@ -11,6 +12,7 @@ import (
"strings"
"time"
"cloud.o-forge.io/core/oc-lib/models/peer"
"cloud.o-forge.io/core/oc-lib/tools"
)
@@ -22,7 +24,7 @@ func (h HydraClaims) generateKey(relation string, path string) (string, error) {
return "", err
}
p := strings.ReplaceAll(strings.ToUpper(path), "/", "_")
return strings.ToLower(method.String()) + "_" + strings.ReplaceAll(p, ":", ""), nil
return strings.ToUpper(method.String()) + "_" + strings.ReplaceAll(p, ":", ""), nil
}
// decode key expect to extract method and path from key
@@ -38,7 +40,7 @@ func (h HydraClaims) decodeKey(key string, external bool) (tools.METHOD, string,
if err != nil {
return meth, "", err
}
p := strings.ReplaceAll(strings.ToLower(s[1]), "_", "/")
p := strings.ReplaceAll(strings.ToUpper(s[1]), "_", "/")
return meth, p, nil
}
@@ -118,21 +120,23 @@ 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(userId string, host string) Claims {
func (h HydraClaims) AddClaimsToToken(clientID string, 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 {
@@ -140,12 +144,19 @@ func (h HydraClaims) AddClaimsToToken(userId string, host string) Claims {
}
claims.Session.AccessToken[key] = perm.Subject
}
sign, err := h.encodeSignature(host)
sign, err := h.encodeSignature(p.Url)
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

View File

@@ -10,8 +10,8 @@ func GetAuthConnector() auth_connectors.AuthConnector {
return auth_connectors.GetAuthConnector()
}
func GetPermissionConnector() perms_connectors.PermConnector {
return perms_connectors.GetPermissionConnector()
func GetPermissionConnector(client string) perms_connectors.PermConnector {
return perms_connectors.GetPermissionConnector(client)
}
func GetClaims() claims.ClaimService {

View File

@@ -11,18 +11,24 @@ import (
"cloud.o-forge.io/core/oc-lib/tools"
)
type KetoConnector struct{}
type KetoConnector struct {
Client string
}
func (k KetoConnector) SetClient(client string) {
k.Client = client
}
func (k KetoConnector) namespace() string {
return "open-cloud"
}
func (k KetoConnector) scope() string {
return "oc-auth"
return "oc-auth-realm"
}
func (f KetoConnector) permToQuery(perm Permission, permDependancies *Permission) string {
n := "?namespace=" + perm.Namespace()
n := "?namespace=" + f.namespace()
if perm.Object != "" {
n += "&object=" + perm.Object
}
@@ -50,7 +56,10 @@ 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().PermissionConnectorHost
host := conf.GetConfig().PermissionConnectorReadHost
if conf.GetConfig().Local {
host = "localhost"
}
port := fmt.Sprintf("%v", conf.GetConfig().PermissionConnectorPort)
resp, err := caller.CallGet("http://"+host+":"+port, "/health/ready")
if err != nil {
@@ -72,19 +81,27 @@ 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(err.Error())
log.Error().Msg("CheckPermission " + err.Error())
return false
}
return len(perms) > 0
}
func (k KetoConnector) DeleteRole(roleID string) (string, int, error) {
k.deleteRelationShip("", "", roleID, nil)
_, code, err := k.deleteRelationShip(roleID, "", k.scope(), nil)
func (k KetoConnector) deletes(object string, relation string, subject string, relation2 string) (string, int, error) {
k.deleteRelationShip(object, relation, subject, nil)
_, code, err := k.deleteRelationShip(subject, relation2, k.scope(), nil)
if err != nil {
return "", code, err
}
return roleID, 200, nil
return subject, 200, nil
}
func (k KetoConnector) DeleteRole(roleID string) (string, int, error) {
return k.deletes("", "member", roleID, "is")
}
func (k KetoConnector) DeleteGroup(groupID string) (string, int, error) {
return k.deletes("", "groups", groupID, "groupin")
}
func (k KetoConnector) DeletePermission(permID string, relation string, internal bool) (string, int, error) {
@@ -95,20 +112,15 @@ func (k KetoConnector) DeletePermission(permID string, relation string, internal
}
return "", 200, err
}
k.deleteRelationShip("", "", permID, nil)
_, code, err := k.deleteRelationShip(permID, "permits"+meth.String(), k.scope(), nil)
if err != nil {
return "", code, err
}
return permID, 200, nil
return k.deletes("", "groups", permID, "permits"+meth.String())
}
func (k KetoConnector) CreateRole(roleID string) (string, int, error) {
p, code, err := k.createRelationShip(roleID, "is", k.scope(), nil)
if err != nil {
return "", code, err
}
return p.Object, 200, nil
return k.creates(roleID, "is", k.scope())
}
func (k KetoConnector) CreateGroup(groupID string) (string, int, error) {
return k.creates(groupID, "groupin", k.scope())
}
func (k KetoConnector) CreatePermission(permID string, relation string, internal bool) (string, int, error) {
@@ -116,9 +128,12 @@ func (k KetoConnector) CreatePermission(permID string, relation string, internal
if err != nil {
return "", 422, err
}
k.BindPermission("admin", permID, "permits"+meth.String())
p, code, err := k.createRelationShip(permID, "permits"+meth.String(), k.scope(), nil)
return k.creates(permID, "permits"+meth.String(), k.scope())
}
func (k KetoConnector) creates(object string, relation string, subject string) (string, int, error) {
p, code, err := k.createRelationShip(object, relation, subject, nil)
if err != nil {
return "", code, err
}
@@ -126,25 +141,29 @@ func (k KetoConnector) CreatePermission(permID string, relation string, internal
}
func (k KetoConnector) GetRole(roleID string) ([]string, error) {
arr := []string{}
roles, err := k.get(roleID, "is", k.scope())
if err != nil {
return arr, err
}
for _, role := range roles {
arr = append(arr, role.Object)
}
return arr, nil
return k.gets(roleID, "is", k.scope())
}
func (k KetoConnector) GetGroup(groupID string) ([]string, error) {
return k.gets(groupID, "groupin", k.scope())
}
func (k KetoConnector) GetRoleByUser(userID string) ([]string, error) {
return k.gets("", "member", userID)
}
func (k KetoConnector) GetGroupByUser(userID string) ([]string, error) {
return k.gets("", "groups", userID)
}
func (k KetoConnector) gets(object string, relation string, subject string) ([]string, error) {
arr := []string{}
roles, err := k.get("", "member", userID)
objs, err := k.get(object, relation, subject)
if err != nil {
return arr, err
}
for _, role := range roles {
arr = append(arr, role.Object)
for _, obj := range objs {
arr = append(arr, obj.Object)
}
return arr, nil
}
@@ -178,6 +197,7 @@ 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
}
@@ -200,7 +220,10 @@ 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().PermissionConnectorHost
host := conf.GetConfig().PermissionConnectorReadHost
if conf.GetConfig().Local {
host = "localhost"
}
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))
@@ -224,40 +247,63 @@ func (k KetoConnector) get(object string, relation string, subject string) ([]Pe
return t, nil
}
func (k KetoConnector) BindRole(userID string, roleID string) (string, int, error) {
_, code, err := k.createRelationShip(roleID, "member", userID, nil)
func (k KetoConnector) binds(object string, relation string, subject string) (string, int, error) {
_, code, err := k.createRelationShip(object, relation, subject, nil)
if err != nil {
return roleID, code, err
return object, code, err
}
return roleID, 200, nil
return object, 200, nil
}
func (k KetoConnector) BindRole(userID string, roleID string) (string, int, error) {
fmt.Println("BIND ROLE", userID, roleID)
return k.binds(userID, "member", roleID)
}
func (k KetoConnector) BindGroup(userID string, groupID string) (string, int, error) {
return k.binds(userID, "groups", groupID)
}
func (k KetoConnector) BindPermission(roleID string, permID string, relation string) (*Permission, int, error) {
perms, err := k.GetPermission(permID, relation)
if err != nil || len(perms) != 1 {
if len(perms) == 0 {
count := 0
for _, p := range perms {
if p.Relation == relation {
count++
}
}
if count == 0 {
return nil, 404, errors.New("Permission not found")
} else if len(perms) > 1 {
} else if count > 1 {
return nil, 409, errors.New("Multiple permission found")
}
}
_, code, err := k.createRelationShip(roleID, perms[0].Relation, permID, nil)
_, code, err := k.createRelationShip(roleID, relation, permID, nil)
if err != nil {
return nil, code, err
}
return &Permission{
Object: roleID,
Relation: perms[0].Relation,
Relation: relation,
Subject: permID,
}, 200, nil
}
func (k KetoConnector) UnBindRole(userID string, roleID string) (string, int, error) {
_, code, err := k.deleteRelationShip(roleID, "member", userID, nil)
func (k KetoConnector) unbinds(subject string, relation string, object string) (string, int, error) {
_, code, err := k.deleteRelationShip(object, relation, subject, nil)
if err != nil {
return roleID, code, err
return object, code, err
}
return roleID, 200, nil
return object, 200, nil
}
func (k KetoConnector) UnBindRole(userID string, roleID string) (string, int, error) {
return k.unbinds(userID, "member", roleID)
}
func (k KetoConnector) UnBindGroup(userID string, groupID string) (string, int, error) {
return k.unbinds(userID, "groups", groupID)
}
func (k KetoConnector) UnBindPermission(roleID string, permID string, relation string) (*Permission, int, error) {
@@ -267,9 +313,15 @@ func (k KetoConnector) UnBindPermission(roleID string, permID string, relation s
}
perms, err := k.GetPermission(permID, meth.String())
if err != nil || len(perms) != 1 {
if len(perms) == 0 {
count := 0
for _, p := range perms {
if p.Relation == relation {
count++
}
}
if count == 0 {
return nil, 404, errors.New("Permission not found")
} else if len(perms) > 1 {
} else if count > 1 {
return nil, 409, errors.New("Multiple permission found")
}
}
@@ -296,21 +348,25 @@ func (k KetoConnector) createRelationShip(object string, relation string, subjec
if err != nil {
return nil, code, err
}
body["subject_set"] = map[string]interface{}{"namespace": s.Namespace(), "object": s.Object, "relation": s.Relation, "subject_id": s.Subject}
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"
}
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(err.Error())
log.Error().Msg("createRelationShip" + 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(err.Error())
log.Error().Msg("createRelationShip2" + err.Error())
return nil, 500, err
}
perm := &Permission{
@@ -336,12 +392,15 @@ 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().PermissionConnectorHost
host := conf.GetConfig().PermissionConnectorWriteHost
if conf.GetConfig().Local {
host = "localhost"
}
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(err.Error())
log.Error().Msg("deleteRelationShip " + err.Error())
return nil, 500, err
}
var data map[string]interface{}

View File

@@ -2,6 +2,7 @@ package perms_connectors
import (
"oc-auth/conf"
"strings"
"cloud.o-forge.io/core/oc-lib/tools"
)
@@ -23,23 +24,30 @@ 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)
BindPermission(roleID string, permID string, relation string) (*Permission, int, error)
UnBindRole(userID string, roleID string) (string, int, error)
UnBindGroup(userID string, groupID string) (string, int, error)
UnBindPermission(roleID string, permID string, relation string) (*Permission, int, error)
CreateRole(roleID string) (string, int, error)
CreateGroup(groupID string) (string, int, error)
CreatePermission(permID string, relation string, internal bool) (string, int, error)
DeleteRole(roleID string) (string, int, error)
DeleteGroup(groupID string) (string, int, error)
DeletePermission(permID string, relation string, internal bool) (string, int, error)
GetRoleByUser(userID string) ([]string, error)
GetGroupByUser(userID string) ([]string, error)
GetPermissionByRole(roleID string) ([]Permission, error)
GetPermissionByUser(userID string, internal bool) ([]Permission, error)
GetRole(roleID string) ([]string, error)
GetGroup(groupID string) ([]string, error)
GetPermission(permID string, relation string) ([]Permission, error)
}
@@ -47,6 +55,11 @@ var c = map[string]PermConnector{
"keto": KetoConnector{},
}
func GetPermissionConnector() PermConnector {
return c[conf.GetConfig().PermissionConnectorHost]
func GetPermissionConnector(scope string) PermConnector {
for k := range c {
if strings.Contains(conf.GetConfig().PermissionConnectorReadHost, k) {
return c[k]
}
}
return nil
}

View File

@@ -1,21 +0,0 @@
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

View File

@@ -1,18 +0,0 @@
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

View File

@@ -1,79 +0,0 @@
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

View File

@@ -1,24 +0,0 @@
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

107
main.go
View File

@@ -1,20 +1,24 @@
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 appname = "oc-auth"
@@ -33,30 +37,73 @@ 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.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)
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)
// 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")
err := generateSelfPeer()
if err != nil {
panic(err)
}
discovery()
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,
}))
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)
}
}()
// 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) {
@@ -66,15 +113,17 @@ func generateSelfPeer() error {
return errors.New("public key path does not exist")
}
// check if peer already exists
p := oclib.Search(nil, strconv.Itoa(peer.SELF.EnumIndex()), oclib.LibDataEnum(oclib.PEER))
p := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), "", "", []string{}, nil).Search(nil, strconv.Itoa(peer.SELF.EnumIndex()), false)
file := ""
f, err := os.ReadFile(conf.GetConfig().PublicKeyPath)
if err != nil {
return err
}
file = string(f)
if len(p.Data) > 0 {
// check public key with the one in the database
f, err := os.ReadFile(conf.GetConfig().PublicKeyPath)
if err != nil {
return err
}
// compare the public key from file with the one in the database
if !strings.Contains(string(f), p.Data[0].(*peer.Peer).PublicKey) {
if !strings.Contains(file, p.Data[0].(*peer.Peer).PublicKey) {
return errors.New("public key is different from the one in the database")
}
return nil
@@ -86,22 +135,34 @@ func generateSelfPeer() error {
AbstractObject: utils.AbstractObject{
Name: o.GetStringDefault("NAME", "local"),
},
PublicKey: conf.GetConfig().PublicKeyPath,
State: peer.SELF,
PublicKey: file,
State: peer.SELF,
WalletAddress: "my-wallet",
}
data := oclib.StoreOne(oclib.LibDataEnum(oclib.PEER), peer.Serialize())
data := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), "", "", []string{}, nil).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() {
fmt.Println("Discovered")
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
api := tools.API{}
conn := infrastructure.GetPermissionConnector()
conn.CreateRole(conf.GetConfig().AdminRole)
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.BindRole(conf.GetConfig().AdminRole, "admin")
addPermissions := func(m map[string]interface{}) {
for k, v := range m {

BIN
oc-auth

Binary file not shown.

View File

@@ -7,6 +7,78 @@ import (
func init() {
beego.GlobalControllerRouter["oc-auth/controllers:GroupController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:GroupController"],
beego.ControllerComments{
Method: "GetAll",
Router: `/`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-auth/controllers:GroupController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:GroupController"],
beego.ControllerComments{
Method: "Post",
Router: `/:id`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-auth/controllers:GroupController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:GroupController"],
beego.ControllerComments{
Method: "Get",
Router: `/:id`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-auth/controllers:GroupController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:GroupController"],
beego.ControllerComments{
Method: "Delete",
Router: `/:id`,
AllowHTTPMethods: []string{"delete"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-auth/controllers:GroupController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:GroupController"],
beego.ControllerComments{
Method: "Bind",
Router: `/:user_id/:group_id`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-auth/controllers:GroupController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:GroupController"],
beego.ControllerComments{
Method: "UnBind",
Router: `/:user_id/:group_id`,
AllowHTTPMethods: []string{"delete"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-auth/controllers:GroupController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:GroupController"],
beego.ControllerComments{
Method: "Clear",
Router: `/clear`,
AllowHTTPMethods: []string{"delete"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-auth/controllers:GroupController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:GroupController"],
beego.ControllerComments{
Method: "GetByUser",
Router: `/user/:id`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"],
beego.ControllerComments{
Method: "InternalAuthForward",
@@ -27,8 +99,8 @@ func init() {
beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"],
beego.ControllerComments{
Method: "LoginLDAP",
Router: `/ldap/login`,
Method: "Login",
Router: `/login`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
@@ -36,8 +108,8 @@ func init() {
beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"] = append(beego.GlobalControllerRouter["oc-auth/controllers:OAuthController"],
beego.ControllerComments{
Method: "LogOutLDAP",
Router: `/ldap/logout`,
Method: "LogOut",
Router: `/logout`,
AllowHTTPMethods: []string{"delete"},
MethodParams: param.Make(),
Filters: nil,

View File

@@ -18,6 +18,11 @@ func init() {
beego.NSInclude(
&controllers.OAuthController{},
),
beego.NSNamespace("/group",
beego.NSInclude(
&controllers.GroupController{},
),
),
beego.NSNamespace("/role",
beego.NSInclude(
&controllers.RoleController{},

View File

@@ -37,6 +37,180 @@
}
}
},
"/group/": {
"get": {
"tags": [
"group"
],
"description": "find groups\n\u003cbr\u003e",
"operationId": "GroupController.GetAll",
"responses": {
"200": {
"description": "{group} string"
}
}
}
},
"/group/clear": {
"delete": {
"tags": [
"group"
],
"description": "clear the group\n\u003cbr\u003e",
"operationId": "GroupController.Clear",
"responses": {
"200": {
"description": "{string} delete success!"
}
}
}
},
"/group/user/{id}": {
"get": {
"tags": [
"group"
],
"description": "find group by user id\n\u003cbr\u003e",
"operationId": "GroupController.GetByUser",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the id you want to get",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{auth} string"
}
}
}
},
"/group/{id}": {
"get": {
"tags": [
"group"
],
"description": "find group by id\n\u003cbr\u003e",
"operationId": "GroupController.Get",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the id you want to get",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{group} string"
}
}
},
"post": {
"tags": [
"group"
],
"description": "create group\n\u003cbr\u003e",
"operationId": "GroupController.Create",
"parameters": [
{
"in": "path",
"name": "id",
"description": "the id you want to get",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{auth} create success!"
}
}
},
"delete": {
"tags": [
"group"
],
"description": "delete the group\n\u003cbr\u003e",
"operationId": "GroupController.Delete",
"parameters": [
{
"in": "path",
"name": "id",
"description": "The id you want to delete",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{string} delete success!"
}
}
}
},
"/group/{user_id}/{group_id}": {
"post": {
"tags": [
"group"
],
"description": "bind the group to user\n\u003cbr\u003e",
"operationId": "GroupController.Bind",
"parameters": [
{
"in": "path",
"name": "user_id",
"description": "The user_id you want to bind",
"required": true,
"type": "string"
},
{
"in": "path",
"name": "group_id",
"description": "The group_id you want to bind",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{string} bind success!"
}
}
},
"delete": {
"tags": [
"group"
],
"description": "unbind the group to user\n\u003cbr\u003e",
"operationId": "GroupController.UnBind",
"parameters": [
{
"in": "path",
"name": "user_id",
"description": "The group_id you want to unbind",
"required": true,
"type": "string"
},
{
"in": "path",
"name": "group_id",
"description": "The user_id you want to unbind",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "{string} bind success!"
}
}
}
},
"/introspect": {
"get": {
"tags": [
@@ -59,7 +233,7 @@
}
}
},
"/ldap/login": {
"/login": {
"post": {
"tags": [
"oc-auth/controllersOAuthController"
@@ -75,6 +249,13 @@
"schema": {
"$ref": "#/definitions/models.workflow"
}
},
{
"in": "query",
"name": "client_id",
"description": "the client_id you want to get",
"required": true,
"type": "string"
}
],
"responses": {
@@ -84,7 +265,7 @@
}
}
},
"/ldap/logout": {
"/logout": {
"delete": {
"tags": [
"oc-auth/controllersOAuthController"
@@ -97,6 +278,13 @@
"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": {
@@ -291,6 +479,13 @@
"schema": {
"$ref": "#/definitions/models.Token"
}
},
{
"in": "query",
"name": "client_id",
"description": "the client_id you want to get",
"required": true,
"type": "string"
}
],
"responses": {
@@ -518,6 +713,10 @@
"name": "oc-auth/controllersOAuthController",
"description": "Operations about auth\n"
},
{
"name": "group",
"description": "Operations about auth\n"
},
{
"name": "role",
"description": "Operations about auth\n"

View File

@@ -28,6 +28,137 @@ paths:
responses:
"200":
description: '{string}'
/group/:
get:
tags:
- group
description: |-
find groups
<br>
operationId: GroupController.GetAll
responses:
"200":
description: '{group} string'
/group/{id}:
get:
tags:
- group
description: |-
find group by id
<br>
operationId: GroupController.Get
parameters:
- in: path
name: id
description: the id you want to get
required: true
type: string
responses:
"200":
description: '{group} string'
post:
tags:
- group
description: |-
create group
<br>
operationId: GroupController.Create
parameters:
- in: path
name: id
description: the id you want to get
required: true
type: string
responses:
"200":
description: '{auth} create success!'
delete:
tags:
- group
description: |-
delete the group
<br>
operationId: GroupController.Delete
parameters:
- in: path
name: id
description: The id you want to delete
required: true
type: string
responses:
"200":
description: '{string} delete success!'
/group/{user_id}/{group_id}:
post:
tags:
- group
description: |-
bind the group to user
<br>
operationId: GroupController.Bind
parameters:
- in: path
name: user_id
description: The user_id you want to bind
required: true
type: string
- in: path
name: group_id
description: The group_id you want to bind
required: true
type: string
responses:
"200":
description: '{string} bind success!'
delete:
tags:
- group
description: |-
unbind the group to user
<br>
operationId: GroupController.UnBind
parameters:
- in: path
name: user_id
description: The group_id you want to unbind
required: true
type: string
- in: path
name: group_id
description: The user_id you want to unbind
required: true
type: string
responses:
"200":
description: '{string} bind success!'
/group/clear:
delete:
tags:
- group
description: |-
clear the group
<br>
operationId: GroupController.Clear
responses:
"200":
description: '{string} delete success!'
/group/user/{id}:
get:
tags:
- group
description: |-
find group by user id
<br>
operationId: GroupController.GetByUser
parameters:
- in: path
name: id
description: the id you want to get
required: true
type: string
responses:
"200":
description: '{auth} string'
/introspect:
get:
tags:
@@ -44,7 +175,7 @@ paths:
responses:
"200":
description: '{string}'
/ldap/login:
/login:
post:
tags:
- oc-auth/controllersOAuthController
@@ -59,10 +190,15 @@ 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}'
/ldap/logout:
/logout:
delete:
tags:
- oc-auth/controllersOAuthController
@@ -75,6 +211,11 @@ 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}'
@@ -219,6 +360,11 @@ 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}'
@@ -386,6 +532,9 @@ tags:
- name: oc-auth/controllersOAuthController
description: |
Operations about auth
- name: group
description: |
Operations about auth
- name: role
description: |
Operations about auth