6 Commits

Author SHA1 Message Date
mr
b154532a1a update 2025-11-20 16:31:10 +01:00
mr
a546c1220e gitignore 2025-11-13 09:57:40 +01:00
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
11 changed files with 130 additions and 83 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

2
.gitignore vendored
View File

@@ -20,4 +20,4 @@
# Go workspace file
go.work
env.env

View File

@@ -21,15 +21,20 @@ clean:
rm -rf oc-auth oc-auth.tar.gz
docker:
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
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
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

@@ -22,12 +22,12 @@ type Config struct {
AuthConnectPublicHost string
AuthConnectorHost string
AuthConnectorPort int
AuthConnectorAdminPort int
AuthConnectorAdminPort string
PermissionConnectorWriteHost string
PermissionConnectorReadHost string
PermissionConnectorPort int
PermissionConnectorAdminPort int
PermissionConnectorPort string
PermissionConnectorAdminPort string
Local bool
}

View File

@@ -70,6 +70,7 @@ func (o *OAuthController) Login() {
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)
@@ -84,6 +85,7 @@ func (o *OAuthController) Login() {
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)

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="

2
go.mod
View File

@@ -5,7 +5,7 @@ go 1.23.0
toolchain go1.23.3
require (
cloud.o-forge.io/core/oc-lib v0.0.0-20250219142942-5111c9c8bec7
cloud.o-forge.io/core/oc-lib v0.0.0-20250624102227-e600fedcab06
github.com/beego/beego/v2 v2.3.1
github.com/smartystreets/goconvey v1.7.2
go.uber.org/zap v1.27.0

8
go.sum
View File

@@ -2,6 +2,14 @@ cloud.o-forge.io/core/oc-lib v0.0.0-20250219104152-3ecb0e9d960b h1:DhRqJdw2VePaY
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=

View File

@@ -31,7 +31,7 @@ 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"
}
@@ -80,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 {
@@ -126,6 +127,7 @@ func (a HydraConnector) tryLog(username string, url string, subpath string, chal
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{}
@@ -143,11 +145,16 @@ func (a HydraConnector) getClient(clientID string) 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")
}
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...)
fmt.Println("login", clientID, username, a.getPath(false, true), redirect, err)
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...)
@@ -177,10 +184,12 @@ 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
}
@@ -252,13 +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

@@ -280,7 +280,7 @@ func (cli *Client) connect(ctx context.Context) <-chan conn {
cn, err := cli.connector.Connect(ctx, addr)
if err != nil {
fmt.Println("Failed to create a LDAP connection", "address", addr)
fmt.Println("Failed to create a LDAP connection", "address", addr, err)
return
}
select {

153
main.go
View File

@@ -19,6 +19,7 @@ import (
"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"
"github.com/i-core/rlog"
)
const appname = "oc-auth"
@@ -43,11 +44,11 @@ func main() {
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().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.GetIntDefault("PERMISSION_CONNECTOR_PORT", 4466)
conf.GetConfig().PermissionConnectorAdminPort = o.GetIntDefault("PERMISSION_CONNECTOR_ADMIN_PORT", 4467)
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
@@ -79,21 +80,24 @@ func generateRole() {
}()
// 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)
for {
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)
}
}
}
break
} else {
time.Sleep(10 * time.Second) // Pause execution for 10 seconds
continue
}
} else {
time.Sleep(10 * time.Second) // Pause execution for 10 seconds
generateRole()
}
}
}
@@ -104,47 +108,54 @@ func generateSelfPeer() error {
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) {
return errors.New("private key path does not exist")
}
if _, err := os.Stat(conf.GetConfig().PublicKeyPath); errors.Is(err, os.ErrNotExist) {
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)
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
// compare the public key from file with the one in the database
if !strings.Contains(file, p.Data[0].(*peer.Peer).PublicKey) {
return errors.New("public key is different from the one in the database")
log := rlog.FromContext(context.Background()).Sugar()
for {
// 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) {
return errors.New("private key path does not exist")
}
return nil
}
// create a new peer
o := oclib.GetConfLoader()
peer := &peer.Peer{
Url: o.GetStringDefault("HOSTNAME", "http://localhost"),
AbstractObject: utils.AbstractObject{
Name: o.GetStringDefault("NAME", "local"),
},
PublicKey: file,
State: peer.SELF,
WalletAddress: "my-wallet",
}
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)
if _, err := os.Stat(conf.GetConfig().PublicKeyPath); errors.Is(err, os.ErrNotExist) {
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)
file := ""
f, err := os.ReadFile(conf.GetConfig().PublicKeyPath)
if err != nil {
time.Sleep(10 * time.Second)
log.Error(err)
continue
}
file = string(f)
if len(p.Data) > 0 {
// check public key with the one in the database
// compare the public key from file with the one in the database
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
}
// create a new peer
o := oclib.GetConfLoader()
peer := &peer.Peer{
Url: o.GetStringDefault("HOSTNAME", "http://localhost"),
AbstractObject: utils.AbstractObject{
Name: o.GetStringDefault("NAME", "local"),
},
PublicKey: file,
State: peer.SELF,
WalletAddress: "my-wallet",
}
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
log.Error(err)
continue
}
break
}
return nil
}
@@ -154,23 +165,25 @@ func discovery() {
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.BindRole(conf.GetConfig().AdminRole, "admin")
addPermissions := func(m map[string]interface{}) {
for k, v := range m {
for _, p := range v.([]interface{}) {
conn.CreatePermission(k, p.(string), true)
for {
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
continue
}
conn.BindRole(conf.GetConfig().AdminRole, "admin")
addPermissions := func(m map[string]interface{}) {
for k, v := range m {
for _, p := range v.([]interface{}) {
conn.CreatePermission(k, p.(string), true)
}
}
}
api.ListenRouter(addPermissions)
tools.NewNATSCaller().SetNATSPub("api", tools.DISCOVERY, map[string]interface{}{})
break
}
api.ListenRouter(addPermissions)
tools.NewNATSCaller().SetNATSPub("api", tools.DISCOVERY, map[string]interface{}{})
}