mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-09 13:50:18 -06:00
The admin user was created as part of the demo user set. But we need the admin to be created always.
168 lines
4.3 KiB
Go
168 lines
4.3 KiB
Go
package command
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"html/template"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/go-ldap/ldif"
|
|
"github.com/libregraph/idm/pkg/ldappassword"
|
|
"github.com/libregraph/idm/pkg/ldbbolt"
|
|
"github.com/libregraph/idm/server"
|
|
"github.com/owncloud/ocis/idm"
|
|
"github.com/owncloud/ocis/idm/pkg/config"
|
|
"github.com/owncloud/ocis/idm/pkg/config/parser"
|
|
"github.com/owncloud/ocis/idm/pkg/logging"
|
|
pkgcrypto "github.com/owncloud/ocis/ocis-pkg/crypto"
|
|
"github.com/owncloud/ocis/ocis-pkg/log"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
// Server is the entrypoint for the server command.
|
|
func Server(cfg *config.Config) *cli.Command {
|
|
return &cli.Command{
|
|
Name: "server",
|
|
Usage: fmt.Sprintf("start %s extension without runtime (unsupervised mode)", cfg.Service.Name),
|
|
Category: "server",
|
|
Before: func(c *cli.Context) error {
|
|
return parser.ParseConfig(cfg)
|
|
},
|
|
Action: func(c *cli.Context) error {
|
|
logger := logging.Configure(cfg.Service.Name, cfg.Log)
|
|
ctx, cancel := func() (context.Context, context.CancelFunc) {
|
|
if cfg.Context == nil {
|
|
return context.WithCancel(context.Background())
|
|
}
|
|
return context.WithCancel(cfg.Context)
|
|
}()
|
|
|
|
defer cancel()
|
|
return start(ctx, logger, cfg)
|
|
},
|
|
}
|
|
}
|
|
|
|
func start(ctx context.Context, logger log.Logger, cfg *config.Config) error {
|
|
servercfg := server.Config{
|
|
Logger: log.LogrusWrap(logger.Logger),
|
|
LDAPHandler: "boltdb",
|
|
LDAPSListenAddr: cfg.IDM.LDAPSAddr,
|
|
TLSCertFile: cfg.IDM.Cert,
|
|
TLSKeyFile: cfg.IDM.Key,
|
|
LDAPBaseDN: "o=libregraph-idm",
|
|
LDAPAdminDN: "uid=libregraph,ou=sysusers,o=libregraph-idm",
|
|
|
|
BoltDBFile: cfg.IDM.DatabasePath,
|
|
}
|
|
|
|
if cfg.IDM.LDAPSAddr != "" {
|
|
// Generate a self-signing cert if no certificate is present
|
|
if err := pkgcrypto.GenCert(cfg.IDM.Cert, cfg.IDM.Key, logger); err != nil {
|
|
logger.Fatal().Err(err).Msgf("Could not generate test-certificate")
|
|
}
|
|
}
|
|
if _, err := os.Stat(servercfg.BoltDBFile); errors.Is(err, os.ErrNotExist) {
|
|
logger.Debug().Msg("Bootstrapping IDM database")
|
|
if err = bootstrap(logger, cfg, servercfg); err != nil {
|
|
logger.Error().Err(err).Msg("failed to bootstrap idm database")
|
|
}
|
|
}
|
|
|
|
svc, err := server.NewServer(&servercfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return svc.Serve(ctx)
|
|
}
|
|
|
|
func bootstrap(logger log.Logger, cfg *config.Config, srvcfg server.Config) error {
|
|
// Hash password if the config does not supply a hash already
|
|
var err error
|
|
|
|
type svcUser struct {
|
|
Name string
|
|
Password string
|
|
}
|
|
|
|
serviceUsers := []svcUser{
|
|
{
|
|
Name: "admin",
|
|
Password: cfg.ServiceUserPasswords.OcisAdmin,
|
|
},
|
|
{
|
|
Name: "libregraph",
|
|
Password: cfg.ServiceUserPasswords.Idm,
|
|
},
|
|
{
|
|
Name: "idp",
|
|
Password: cfg.ServiceUserPasswords.Idp,
|
|
},
|
|
{
|
|
Name: "reva",
|
|
Password: cfg.ServiceUserPasswords.Reva,
|
|
},
|
|
}
|
|
|
|
bdb := &ldbbolt.LdbBolt{}
|
|
|
|
if err := bdb.Configure(srvcfg.Logger, srvcfg.LDAPBaseDN, srvcfg.BoltDBFile, nil); err != nil {
|
|
return err
|
|
}
|
|
defer bdb.Close()
|
|
|
|
if err := bdb.Initialize(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Prepare the initial Data from template. To be able to set the
|
|
// supplied service user passwords
|
|
tmpl, err := template.New("baseldif").Parse(idm.BaseLDIF)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i := range serviceUsers {
|
|
if strings.HasPrefix(serviceUsers[i].Password, "$argon2id$") {
|
|
// password is alread hashed
|
|
serviceUsers[i].Password = "{ARGON2}" + serviceUsers[i].Password
|
|
} else {
|
|
if serviceUsers[i].Password, err = ldappassword.Hash(serviceUsers[i].Password, "{ARGON2}"); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
// We need to treat the hash as binary in the LDIF template to avoid
|
|
// go-ldap/ldif to to any fancy escaping
|
|
serviceUsers[i].Password = base64.StdEncoding.EncodeToString([]byte(serviceUsers[i].Password))
|
|
}
|
|
var tmplWriter strings.Builder
|
|
err = tmpl.Execute(&tmplWriter, serviceUsers)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
bootstrapData := tmplWriter.String()
|
|
if cfg.CreateDemoUsers {
|
|
bootstrapData = bootstrapData + "\n" + idm.DemoUsersLDIF
|
|
}
|
|
|
|
s := strings.NewReader(bootstrapData)
|
|
lf := &ldif.LDIF{}
|
|
err = ldif.Unmarshal(s, lf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, entry := range lf.AllEntries() {
|
|
logger.Debug().Str("dn", entry.DN).Msg("Adding entry")
|
|
if err := bdb.EntryPut(entry); err != nil {
|
|
return fmt.Errorf("error adding Entry '%s': %w", entry.DN, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|