Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions authd-oidc-brokers/cmd/authd-oidc/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,12 @@ func (a *App) serve(config daemonConfig) error {
}
}

b, err := broker.New(broker.Config{
brokerConfig := broker.Config{
ConfigFile: config.Paths.BrokerConf,
DataDir: config.Paths.DataDir,
})
if err != nil {
return err
}

s, err := dbusservice.New(ctx, b)
s, err := dbusservice.New(ctx, brokerConfig)
if err != nil {
return err
}
Expand Down
11 changes: 9 additions & 2 deletions authd-oidc-brokers/internal/broker/broker.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ import (
)

const (
// LatestAPIVersion is the latest API version supported by the broker. It should be incremented when a non backward
// compatible change is made to the API.
// Note: Remember to also bump the LatestAPIVersion in internal/brokers/dbusbroker.go.
LatestAPIVersion = 2

maxAuthAttempts = 3
maxRequestDuration = 5 * time.Second
)
Expand All @@ -49,7 +54,8 @@ type Config struct {

// Broker is the real implementation of the broker to track sessions and process oidc calls.
type Broker struct {
cfg Config
cfg Config
apiVersion uint

provider providers.Provider
oidcCfg oidc.Config
Expand Down Expand Up @@ -98,7 +104,7 @@ type option struct {
type Option func(*option)

// New returns a new oidc Broker with the providers listed in the configuration file.
func New(cfg Config, args ...Option) (b *Broker, err error) {
func New(cfg Config, apiVersion uint, args ...Option) (b *Broker, err error) {
p := providers.CurrentProvider()

if cfg.ConfigFile != "" {
Expand Down Expand Up @@ -146,6 +152,7 @@ func New(cfg Config, args ...Option) (b *Broker, err error) {

b = &Broker{
cfg: cfg,
apiVersion: apiVersion,
provider: opts.provider,
oidcCfg: oidc.Config{ClientID: clientID},
privateKey: privateKey,
Expand Down
2 changes: 1 addition & 1 deletion authd-oidc-brokers/internal/broker/broker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func TestNew(t *testing.T) {
bCfg := &broker.Config{DataDir: tc.dataDir}
bCfg.SetIssuerURL(tc.issuer)
bCfg.SetClientID(tc.clientID)
b, err := broker.New(*bCfg)
b, err := broker.New(*bCfg, broker.LatestAPIVersion)
if tc.wantErr {
require.Error(t, err, "New should have returned an error")
return
Expand Down
2 changes: 1 addition & 1 deletion authd-oidc-brokers/internal/broker/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func newBrokerForTests(t *testing.T, cfg *brokerForTestConfig) (b *broker.Broker
cfg.SetIssuerURL(issuerURL)
}

b, err := broker.New(cfg.Config, broker.WithCustomProvider(provider))
b, err := broker.New(cfg.Config, broker.LatestAPIVersion, broker.WithCustomProvider(provider))
require.NoError(t, err, "Setup: New should not have returned an error")
return b
}
Expand Down
77 changes: 57 additions & 20 deletions authd-oidc-brokers/internal/dbusservice/dbusservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import (
"github.com/godbus/dbus/v5/introspect"
)

const intro = `
<node>
const (
introspectableHeader = `<node>`
introspectableInterface = `
<interface name="%s">
<method name="NewSession">
<arg type="s" direction="in" name="username"/>
Expand Down Expand Up @@ -50,51 +51,86 @@ const intro = `
<method name="DeleteUser">
<arg type="s" direction="in" name="username"/>
</method>
</interface>` + introspect.IntrospectDataString + `</node> `
</interface>`
introspectableFooter = introspect.IntrospectDataString + `</node> `
)

// Service is the handler exposing our broker methods on the system bus.
// Service is the object representing the dbus service, which contains the exported interfaces and the necessary
// information to disconnect from the bus and stop the service.
type Service struct {
name string
name string
interfaces []*Interface
disconnect func()
serve chan struct{}
}

// Interface is the object representing a dbus interface, which contains the broker to which delegate the calls and the
// name of the interface itself.
type Interface struct {
iface string
broker *broker.Broker
}

serve chan struct{}
disconnect func()
var interfaceNames = []string{
"com.ubuntu.authd.Broker",
"com.ubuntu.authd.Broker2",
}

// New returns a new dbus service after exporting to the system bus our name.
func New(_ context.Context, broker *broker.Broker) (s *Service, err error) {
func New(_ context.Context, brokerConfig broker.Config) (*Service, error) {
name := consts.DbusName
object := dbus.ObjectPath(consts.DbusObject)
iface := "com.ubuntu.authd.Broker"
s = &Service{
name: name,
broker: broker,
serve: make(chan struct{}),

service := &Service{
name: name,
serve: make(chan struct{}),
}

conn, err := s.getBus()
conn, err := service.getBus()
if err != nil {
return nil, err
}

if err := conn.Export(s, object, iface); err != nil {
return nil, err
var introspectableBody string
for i, iface := range interfaceNames {
b, err := broker.New(brokerConfig, uint(i)+1) // There's no 0 version, so we start from 1.
if err != nil {
service.disconnect()
return nil, fmt.Errorf("error initializing broker for %q: %v", iface, err)
}
Comment thread
denisonbarbosa marked this conversation as resolved.

s := &Interface{
iface: iface,
broker: b,
}

if err := conn.Export(s, object, iface); err != nil {
service.disconnect()
return nil, err
}
Comment thread
denisonbarbosa marked this conversation as resolved.

service.interfaces = append(service.interfaces, s)
introspectableBody = introspectableBody + fmt.Sprintf(introspectableInterface, iface)
}
if err := conn.Export(introspect.Introspectable(fmt.Sprintf(intro, iface)), object, "org.freedesktop.DBus.Introspectable"); err != nil {

// Build combined introspection XML for all versioned interfaces and export once.
introspectable := introspect.Introspectable(introspectableHeader + introspectableBody + introspectableFooter)
if err := conn.Export(introspectable, object, "org.freedesktop.DBus.Introspectable"); err != nil {
service.disconnect()
return nil, err
}

reply, err := conn.RequestName(consts.DbusName, dbus.NameFlagDoNotQueue)
if err != nil {
s.disconnect()
service.disconnect()
return nil, err
}
if reply != dbus.RequestNameReplyPrimaryOwner {
s.disconnect()
service.disconnect()
return nil, fmt.Errorf("%q is already taken in the bus", name)
}

return s, nil
return service, nil
}

// Addr returns the address of the service.
Expand All @@ -117,5 +153,6 @@ func (s *Service) Stop() error {
close(s.serve)
s.disconnect()
}

return nil
}
2 changes: 2 additions & 0 deletions authd-oidc-brokers/internal/dbusservice/localbus.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
package dbusservice

import (
"context"
"os"

"github.com/canonical/authd/authd-oidc-brokers/internal/testutils"
"github.com/canonical/authd/log"
"github.com/godbus/dbus/v5"
)

Expand Down
16 changes: 8 additions & 8 deletions authd-oidc-brokers/internal/dbusservice/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

// NewSession is the method through which the broker and the daemon will communicate once dbusInterface.NewSession is called.
func (s *Service) NewSession(username, lang, mode string) (sessionID, encryptionKey string, dbusErr *dbus.Error) {
func (s *Interface) NewSession(username, lang, mode string) (sessionID, encryptionKey string, dbusErr *dbus.Error) {
log.Debugf(context.Background(), "Creating new session (username=%s, lang=%s, mode=%s)", username, lang, mode)
sessionID, encryptionKey, err := s.broker.NewSession(username, lang, mode)
if err != nil {
Expand All @@ -21,7 +21,7 @@ func (s *Service) NewSession(username, lang, mode string) (sessionID, encryption
}

// GetAuthenticationModes is the method through which the broker and the daemon will communicate once dbusInterface.GetAuthenticationModes is called.
func (s *Service) GetAuthenticationModes(sessionID string, supportedUILayouts []map[string]string) (authenticationModes []map[string]string, dbusErr *dbus.Error) {
func (s *Interface) GetAuthenticationModes(sessionID string, supportedUILayouts []map[string]string) (authenticationModes []map[string]string, dbusErr *dbus.Error) {
log.Debugf(context.Background(), "Getting authentication modes for session %s", sessionID)
authenticationModes, err := s.broker.GetAuthenticationModes(sessionID, supportedUILayouts)
if err != nil {
Expand All @@ -32,7 +32,7 @@ func (s *Service) GetAuthenticationModes(sessionID string, supportedUILayouts []
}

// SelectAuthenticationMode is the method through which the broker and the daemon will communicate once dbusInterface.SelectAuthenticationMode is called.
func (s *Service) SelectAuthenticationMode(sessionID, authenticationModeName string) (uiLayoutInfo map[string]string, dbusErr *dbus.Error) {
func (s *Interface) SelectAuthenticationMode(sessionID, authenticationModeName string) (uiLayoutInfo map[string]string, dbusErr *dbus.Error) {
log.Debugf(context.Background(), "Selecting authentication mode %s for session %s", authenticationModeName, sessionID)
uiLayoutInfo, err := s.broker.SelectAuthenticationMode(sessionID, authenticationModeName)
if err != nil {
Expand All @@ -43,7 +43,7 @@ func (s *Service) SelectAuthenticationMode(sessionID, authenticationModeName str
}

// IsAuthenticated is the method through which the broker and the daemon will communicate once dbusInterface.IsAuthenticated is called.
func (s *Service) IsAuthenticated(sessionID, authenticationData string) (access, data string, dbusErr *dbus.Error) {
func (s *Interface) IsAuthenticated(sessionID, authenticationData string) (access, data string, dbusErr *dbus.Error) {
// Do *not* log authenticationData here, because it may contain the user's password in cleartext.
log.Debugf(context.Background(), "Handling IsAuthenticated call for session %s", sessionID)
access, data, err := s.broker.IsAuthenticated(sessionID, authenticationData)
Expand All @@ -59,7 +59,7 @@ func (s *Service) IsAuthenticated(sessionID, authenticationData string) (access,
}

// EndSession is the method through which the broker and the daemon will communicate once dbusInterface.EndSession is called.
func (s *Service) EndSession(sessionID string) (dbusErr *dbus.Error) {
func (s *Interface) EndSession(sessionID string) (dbusErr *dbus.Error) {
log.Debugf(context.Background(), "Ending session %s", sessionID)
err := s.broker.EndSession(sessionID)
if err != nil {
Expand All @@ -69,14 +69,14 @@ func (s *Service) EndSession(sessionID string) (dbusErr *dbus.Error) {
}

// CancelIsAuthenticated is the method through which the broker and the daemon will communicate once dbusInterface.CancelIsAuthenticated is called.
func (s *Service) CancelIsAuthenticated(sessionID string) (dbusErr *dbus.Error) {
func (s *Interface) CancelIsAuthenticated(sessionID string) (dbusErr *dbus.Error) {
log.Debugf(context.Background(), "Cancelling IsAuthenticated call for session %s", sessionID)
s.broker.CancelIsAuthenticated(sessionID)
return nil
}

// UserPreCheck is the method through which the broker and the daemon will communicate once dbusInterface.UserPreCheck is called.
func (s *Service) UserPreCheck(username string) (userinfo string, dbusErr *dbus.Error) {
func (s *Interface) UserPreCheck(username string) (userinfo string, dbusErr *dbus.Error) {
log.Debugf(context.Background(), "UserPreCheck: %s", username)
userinfo, err := s.broker.UserPreCheck(username)
if err != nil {
Expand All @@ -87,7 +87,7 @@ func (s *Service) UserPreCheck(username string) (userinfo string, dbusErr *dbus.
}

// DeleteUser is the method through which the broker and the daemon will communicate once dbusInterface.DeleteUser is called.
func (s *Service) DeleteUser(username string) (dbusErr *dbus.Error) {
func (s *Interface) DeleteUser(username string) (dbusErr *dbus.Error) {
log.Debugf(context.Background(), "DeleteUser: %s", username)
if err := s.broker.DeleteUser(username); err != nil {
return dbus.MakeFailedError(err)
Expand Down
2 changes: 1 addition & 1 deletion e2e-tests/resources/browser_login/browser_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def on_draw_event():
GLib.source_remove(stable_timeout_id)
logger.info("Page is stable now")

def wait_for_pattern(self, pattern, timeout_ms=5000,
def wait_for_pattern(self, pattern, timeout_ms=10000,
poll_interval_ms=100) -> list[str]:
"""Wait until `pattern` is present in the page's visible text and return all matched substrings."""
logger.info(f"Waiting for pattern '{pattern}'...")
Expand Down
Loading
Loading