Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Commit

Permalink
first running version behind eliona's nginx reverse proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
christian-stauffer committed Feb 6, 2024
1 parent dcdada6 commit 2d1c82d
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 78 deletions.
66 changes: 17 additions & 49 deletions apiservices/api_configuration_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ package apiservices

import (
"context"
"errors"
"net/http"
"saml-sso/apiserver"
"saml-sso/conf"
)

// ConfigurationApiService is a service that implements the logic for the ConfigurationAPIServicer
Expand All @@ -35,88 +35,56 @@ func NewConfigurationApiService() apiserver.ConfigurationAPIServicer {

// GetAdvancedConfiguration - Get Advanced Configuration
func (s *ConfigurationApiService) GetAdvancedConfiguration(ctx context.Context) (apiserver.ImplResponse, error) {
// TODO - update GetAdvancedConfiguration with the required logic for this service method.
// Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
advCnf, err := conf.GetAdvancedConfig(ctx)

//TODO: Uncomment the next line to return response Response(200, AdvancedConfiguration{}) or use other options such as http.Ok ...
//return Response(200, AdvancedConfiguration{}), nil

return apiserver.Response(http.StatusNotImplemented, nil), errors.New("GetAdvancedConfiguration method not implemented")
return apiserver.Response(http.StatusOK, advCnf), err
}

// GetAttributeMapping - Get Attribute Mapping
func (s *ConfigurationApiService) GetAttributeMapping(ctx context.Context) (apiserver.ImplResponse, error) {
// TODO - update GetAttributeMapping with the required logic for this service method.
// Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

//TODO: Uncomment the next line to return response Response(200, AttributeMap{}) or use other options such as http.Ok ...
//return Response(200, AttributeMap{}), nil
attrMap, err := conf.GetAttributeMapping(ctx)

return apiserver.Response(http.StatusNotImplemented, nil), errors.New("GetAttributeMapping method not implemented")
return apiserver.Response(http.StatusOK, attrMap), err
}

// GetBasicConfiguration - Get Basic Configurations
func (s *ConfigurationApiService) GetBasicConfiguration(ctx context.Context) (apiserver.ImplResponse, error) {
// TODO - update GetBasicConfiguration with the required logic for this service method.
// Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
basicCnf, err := conf.GetBasicConfig(ctx)

//TODO: Uncomment the next line to return response Response(200, BasicConfiguration{}) or use other options such as http.Ok ...
//return Response(200, BasicConfiguration{}), nil

return apiserver.Response(http.StatusNotImplemented, nil), errors.New("GetBasicConfiguration method not implemented")
return apiserver.Response(http.StatusOK, basicCnf), err
}

// GetPermissionMapping - Get Permission Mapping
func (s *ConfigurationApiService) GetPermissionMapping(ctx context.Context) (apiserver.ImplResponse, error) {
// TODO - update GetPermissionMapping with the required logic for this service method.
// Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

//TODO: Uncomment the next line to return response Response(200, Permissions{}) or use other options such as http.Ok ...
//return Response(200, Permissions{}), nil
permMap, err := conf.GetPermissionSettings(ctx)

return apiserver.Response(http.StatusNotImplemented, nil), errors.New("GetPermissionMapping method not implemented")
return apiserver.Response(http.StatusOK, permMap), err
}

// PutAdvancedConfiguration - Creates or Update Advanced Configuration
func (s *ConfigurationApiService) PutAdvancedConfiguration(ctx context.Context, advancedConfiguration apiserver.AdvancedConfiguration) (apiserver.ImplResponse, error) {
// TODO - update PutAdvancedConfiguration with the required logic for this service method.
// Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
cnfRet, err := conf.SetAdvancedConfig(ctx, &advancedConfiguration)

//TODO: Uncomment the next line to return response Response(200, AdvancedConfiguration{}) or use other options such as http.Ok ...
//return Response(200, AdvancedConfiguration{}), nil

return apiserver.Response(http.StatusNotImplemented, nil), errors.New("PutAdvancedConfiguration method not implemented")
return apiserver.Response(http.StatusOK, cnfRet), err
}

// PutAttributeMapping - Creates or Update Attribute Mapping
func (s *ConfigurationApiService) PutAttributeMapping(ctx context.Context, attributeMap apiserver.AttributeMap) (apiserver.ImplResponse, error) {
// TODO - update PutAttributeMapping with the required logic for this service method.
// Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

//TODO: Uncomment the next line to return response Response(200, AttributeMap{}) or use other options such as http.Ok ...
//return Response(200, AttributeMap{}), nil
mapRet, err := conf.SetAttributeMapping(ctx, &attributeMap)

return apiserver.Response(http.StatusNotImplemented, nil), errors.New("PutAttributeMapping method not implemented")
return apiserver.Response(http.StatusOK, mapRet), err
}

// PutBasicConfiguration - Creates or Update Basic Configuration
func (s *ConfigurationApiService) PutBasicConfiguration(ctx context.Context, basicConfiguration apiserver.BasicConfiguration) (apiserver.ImplResponse, error) {
// TODO - update PutBasicConfiguration with the required logic for this service method.
// Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
cnfRet, err := conf.SetBasicConfig(ctx, &basicConfiguration)

//TODO: Uncomment the next line to return response Response(200, BasicConfiguration{}) or use other options such as http.Ok ...
//return Response(200, BasicConfiguration{}), nil

return apiserver.Response(http.StatusNotImplemented, nil), errors.New("PutBasicConfiguration method not implemented")
return apiserver.Response(http.StatusOK, cnfRet), err
}

// PutPermissionMapping - Creates or Update Permission Mapping Configurations
func (s *ConfigurationApiService) PutPermissionMapping(ctx context.Context, permissions apiserver.Permissions) (apiserver.ImplResponse, error) {
// TODO - update PutPermissionMapping with the required logic for this service method.
// Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

//TODO: Uncomment the next line to return response Response(200, Permissions{}) or use other options such as http.Ok ...
//return Response(200, Permissions{}), nil
permRet, err := conf.SetPermissionSettings(ctx, &permissions)

return apiserver.Response(http.StatusNotImplemented, nil), errors.New("PutPermissionMapping method not implemented")
return apiserver.Response(http.StatusOK, permRet), err
}
11 changes: 8 additions & 3 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package main

import (
"context"
"fmt"
"io"
"net/http"
"saml-sso/apiserver"
Expand All @@ -34,7 +33,7 @@ import (
const (
LOG_REGIO = "app"
API_SERVER_PORT = 3000
SSO_SERVER_PORT = 8081 // Publicly accessible. See wiki.
SSO_SERVER_PORT = 8081 // Publicly accessible without auth. See wiki.

SAML_SPECIFIC_ENDPOINT_PATH = "/saml/"
)
Expand Down Expand Up @@ -83,7 +82,8 @@ func run() {
apiPort := common.Getenv("API_SERVER_PORT", strconv.Itoa(API_SERVER_PORT))
samlSpPort := common.Getenv("SSO_SERVER_PORT", strconv.Itoa(SSO_SERVER_PORT))

fmt.Println(basicConfig.OwnUrl + ":" + apiPort)
log.Debug(LOG_REGIO, "own url: %v, api port: %v", basicConfig.OwnUrl, apiPort)

sp, err := saml.NewServiceProviderAdvanced(
basicConfig.ServiceProviderCertificate,
basicConfig.ServiceProviderPrivateKey,
Expand Down Expand Up @@ -129,6 +129,11 @@ func run() {
sp.GetMiddleWare().RequireAccount(authHandleFunc))
http.Handle(SAML_SPECIFIC_ENDPOINT_PATH, sp.GetMiddleWare())

// for backwards compatibility, can be removed when the frontend is reworked to the new generic /sso/* endpoints
http.Handle("/adfs/active/", activeHandleFunc)
http.Handle("/adfs/auth/",
sp.GetMiddleWare().RequireAccount(authHandleFunc))

log.Info(LOG_REGIO, "started @ %v", samlSpPort)
err = http.ListenAndServe(":"+samlSpPort, nil)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions conf/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ CREATE TABLE IF NOT EXISTS saml_sp.advanced_config (

CREATE TABLE IF NOT EXISTS saml_sp.permissions (
id INT PRIMARY KEY NOT NULL DEFAULT 1 REFERENCES saml_sp.basic_config(id) ON UPDATE CASCADE,
default_system_role TEXT NOT NULL DEFAULT 'regular' , -- reference to is maybe a bad idea (due to the new ACL)
default_proj_role TEXT NOT NULL DEFAULT 'operator' ,
default_system_role TEXT NOT NULL DEFAULT 'System user' , -- reference to is maybe a bad idea (due to the new ACL)
default_proj_role TEXT NOT NULL DEFAULT 'Project user' ,
system_role_saml_attribute TEXT ,
system_role_map JSON ,
proj_role_saml_attribute TEXT ,
Expand Down
44 changes: 43 additions & 1 deletion eliona/others.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ const (
"JOIN public.eliona_secret " +
"USING (schema), public.claim_jwt(role, now() + validity,user_id,null) jwt " +
"WHERE lower(u.email) = lower($1) AND NOT u.archived)"

OTHERS_GET_JWT_QUERY_V12 = "(SELECT public.make_jwt(jwt,secret) " +
"FROM public.eliona_user u " +
"JOIN public.acl_role r ON (u.role_id = r.role_id) " +
"JOIN public.project_user USING (user_id) " +
"JOIN public.eliona_secret USING (schema), " +
"public.claim_jwt(role, now() + validity,user_id,proj_id,r.role_id::text,schema) jwt " +
"WHERE lower(u.email) = lower($1) AND NOT u.archived)"
)

func GetElionaJsonWebToken(email string) (*string, error) {
Expand Down Expand Up @@ -70,9 +78,13 @@ func GetElionaJsonWebToken(email string) (*string, error) {
if strings.Contains(version, "v10.") {
log.Debug(LOG_REGIO, "eliona v10")
jwtQuery = OTHERS_GET_JWT_QUERY_V10
} else if strings.Contains(version, "v11.") &&
!strings.Contains(version, "v11.1.5") {
log.Debug(LOG_REGIO, "eliona v11")
jwtQuery = OTHERS_GET_JWT_QUERY_V11
} else {
// assume, that the version is newer (with ACL)
jwtQuery = OTHERS_GET_JWT_QUERY_V11
jwtQuery = OTHERS_GET_JWT_QUERY_V12
}

row = db.QueryRow(jwtQuery, email)
Expand All @@ -96,6 +108,36 @@ func UpdateElionaUserArchivedPhone(email string, phone *string, archived bool) e
return err
}

func GetFirstProjectId() (projectId string, err error) {
row := getDb().QueryRow("SELECT proj_id FROM eliona_project ORDER BY proj_id LIMIT 1")

if err = row.Err(); err != nil {
return
}

err = row.Scan(&projectId)
return
}

func GetRoleIdByDisplayName(displayName string) (roleId int, err error) {
row := getDb().QueryRow("SELECT role_id FROM acl_role WHERE displayname = $1", displayName)

if err = row.Err(); err != nil {
return
}

err = row.Scan(&roleId)
return
}

func SetProjectUser(projectId string, userId *string, roleId int) (err error) {

_, err = getDb().Exec("INSERT INTO project_user (proj_id, user_id, role_id) "+
"VALUES ($1, $2, $3)", projectId, userId, roleId)

return
}

func getDb() *sql.DB {
return db.Database(app.AppName())
}
56 changes: 38 additions & 18 deletions eliona/single_sign_on.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package eliona
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"saml-sso/apiserver"
"saml-sso/conf"
Expand Down Expand Up @@ -79,7 +79,9 @@ func (s *SingleSignOn) ActiveHandle(w http.ResponseWriter, r *http.Request) {
}
}

w.Header().Add("Content-Type", "application/json")
w.WriteHeader(responseCode)

_, err = w.Write(responseMsg)
if err != nil {
log.Error(LOG_REGIO, "write internal server error: %v", err)
Expand All @@ -94,8 +96,9 @@ func (s *SingleSignOn) Authentication(w http.ResponseWriter, r *http.Request) {

mapping *apiserver.AttributeMap

loginEmail, userIp string
firstname, lastname, phone string
loginEmail, userIp string
firstname, lastname string
phone *string

user *api.User
jwt *string
Expand Down Expand Up @@ -133,7 +136,8 @@ func (s *SingleSignOn) Authentication(w http.ResponseWriter, r *http.Request) {
lastname = samlsp.AttributeFromContext(r.Context(), *mapping.LastName)
}
if mapping.Phone != nil && *mapping.Phone != "" {
phone = samlsp.AttributeFromContext(r.Context(), *mapping.Phone)
phoneS := samlsp.AttributeFromContext(r.Context(), *mapping.Phone)
phone = &phoneS
}

log.Info(LOG_REGIO, "User with firstname: %v, lastname: %v, email/login: "+
Expand All @@ -156,18 +160,19 @@ func (s *SingleSignOn) Authentication(w http.ResponseWriter, r *http.Request) {
errorMessage = []byte(err.Error())
goto internalServerError
}
}

err = UpdateElionaUserArchivedPhone(user.Email, &phone, s.userToArchive)
if err != nil {
log.Error(LOG_REGIO, "cannot set phone and archive flag: %v", err)
errorMessage = []byte(err.Error())
goto internalServerError
}
err = UpdateElionaUserArchivedPhone(user.Email, phone, s.userToArchive)
if err != nil {
log.Error(LOG_REGIO, "cannot set phone and archive flag: %v", err)
errorMessage = []byte(err.Error())
goto internalServerError
}

err = s.setUserPermissions(user.Email)
if err != nil {
log.Error(LOG_REGIO, "cannot set user permissions")
err = s.setUserPermissions(user.Id.Get())
if err != nil {
log.Error(LOG_REGIO, "cannot set user permissions: %v", err)
goto notAuthenticated
}
}

// obtain a jwt to login via cookies
Expand Down Expand Up @@ -218,7 +223,7 @@ internalServerError:
}
}

func (s *SingleSignOn) setUserPermissions(email string) error {
func (s *SingleSignOn) setUserPermissions(userId *string) error {

var (
err error
Expand All @@ -231,9 +236,24 @@ func (s *SingleSignOn) setUserPermissions(email string) error {
}

log.Info(LOG_REGIO,
"ToDo: add user to a project and set permissions according the configurations. %v",
"ToDo: permission map not finished yet. %v",
permissions)

err = errors.New("not implemented")
return err
projectId, err := GetFirstProjectId()
if err != nil {
return fmt.Errorf("cannot look up project id: %v", err)
}

roleId, err := GetRoleIdByDisplayName(permissions.DefaultProjRole)
if err != nil {
return fmt.Errorf("cannot get role id for role %s: %v",
permissions.DefaultProjRole, err)
}

if roleId <= 0 {
return fmt.Errorf("cannot get role id for %s",
permissions.DefaultProjRole)
}

return SetProjectUser(projectId, userId, roleId)
}
10 changes: 5 additions & 5 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -474,14 +474,14 @@ components:
type: string
readOnly: false
nullable: false
default: 'regular'
example: 'regular'
default: 'System user'
example: 'System user'
default_proj_role:
type: string
nullable: false
readOnly: false
default: 'operator'
example: 'operator'
default: 'Project user'
example: 'Project user'
system_role_saml_attribute:
type: string
nullable: true
Expand Down Expand Up @@ -512,7 +512,7 @@ components:
elionaRole:
type: string
nullable: false
example: 'admin'
example: 'System user'
samlValue:
type: string
nullable: false
Expand Down

0 comments on commit 2d1c82d

Please sign in to comment.