File: server.go

package info (click to toggle)
golang-github-canonical-candid 1.12.3-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 3,016 kB
  • sloc: python: 1,903; sh: 235; makefile: 81
file content (176 lines) | stat: -rw-r--r-- 5,479 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package candid

import (
	"html/template"
	"net/http"
	"sort"
	"time"

	"github.com/go-macaroon-bakery/macaroon-bakery/v3/bakery"
	"github.com/juju/aclstore/v2"
	"github.com/juju/utils/v2/debugstatus"
	"gopkg.in/errgo.v1"

	"github.com/canonical/candid/idp"
	"github.com/canonical/candid/idp/agent"
	"github.com/canonical/candid/internal/debug"
	"github.com/canonical/candid/internal/discharger"
	"github.com/canonical/candid/internal/identity"
	"github.com/canonical/candid/internal/mfa"
	v1 "github.com/canonical/candid/internal/v1"
	"github.com/canonical/candid/meeting"
	"github.com/canonical/candid/store"
)

// Versions of the API that can be served.
const (
	Debug      = "debug"
	Discharger = "discharger"
	V1         = "v1"
)

var versions = map[string]identity.NewAPIHandlerFunc{
	Debug:      debug.NewAPIHandler,
	Discharger: discharger.NewAPIHandler,
	V1:         v1.NewAPIHandler,
}

// Versions returns all known API version strings in alphabetical order.
func Versions() []string {
	vs := make([]string, 0, len(versions))
	for v := range versions {
		vs = append(vs, v)
	}
	sort.Strings(vs)
	return vs
}

// ServerParams contains configuration parameters for a server.
type ServerParams struct {
	// MeetingStore holds the storage that will be used to store
	// rendezvous information.
	MeetingStore meeting.Store

	// ProviderDataStore holds the storeage that can be used by
	// identity providers to store data that is not associated with
	// an individual identity.
	ProviderDataStore store.ProviderDataStore

	// RootKeyStore holds the root key store that will be used to
	// store macaroon root keys within the identity server.
	RootKeyStore bakery.RootKeyStore

	// Store holds the identities store for the identity server.
	Store store.Store

	// AdminPassword holds the password for admin login.
	AdminPassword string

	// Key holds the keypair to use with the bakery service.
	Key *bakery.KeyPair

	// Location holds a URL representing the externally accessible
	// base URL of the service, without a trailing slash.
	Location string

	// PrivateAddr should hold a dialable address that will be used
	// for communication between identity servers. Note that this
	// should not contain a port.
	PrivateAddr string

	// IdentityProviders contains the set of identity providers that
	// should be initialised by the service.
	IdentityProviders []idp.IdentityProvider

	// MFAAuthenticator holds the multi-factor authenticator.
	MFAAuthenticator *mfa.Authenticator

	// DebugTeams contains the set of launchpad teams that may access
	// the restricted debug endpoints.
	// TODO remove this.
	DebugTeams []string

	// AdminAgentPublicKey contains the public key of the admin agent.
	AdminAgentPublicKey *bakery.PublicKey

	// StaticFileSystem contains an http.FileSystem that can be used
	// to serve static files.
	StaticFileSystem http.FileSystem

	// Template contains a set of templates that are used to generate
	// html output.
	Template *template.Template

	// DebugStatusCheckerFuncs contains functions that will be
	// executed as part of a /debug/status check.
	DebugStatusCheckerFuncs []debugstatus.CheckerFunc

	// RendezvousTimeout holds the time after which an interactive discharge wait
	// request will time out.
	RendezvousTimeout time.Duration

	// ACLStore holds the ACLStore for the identity server.
	ACLStore aclstore.ACLStore

	// RedirectLoginTrustedURLs contains a list of URLs that are
	// trusted to be used as return_to URLs during an interactive
	// login.
	RedirectLoginTrustedURLs []string

	// RedirectLoginTrustedDomains contains a list of domain names that
	// are fully trusted to be used as return_to URLs during an
	// interactive login. If the domain starts with the sequence "*."
	// then all subdomains of the subsequent domain will be trusted.
	RedirectLoginTrustedDomains []string

	// APIMacaroonTimeout is the maximum life of an API macaroon.
	APIMacaroonTimeout time.Duration

	// DischargeMacaroonTimeout is the maximum life of a Discharge
	// macaroon.
	DischargeMacaroonTimeout time.Duration

	// DischargeTokenTimeout is the maximum life of a Discharge
	// token.
	DischargeTokenTimeout time.Duration

	// SkipLocationForCookiePaths instructs if the Cookie Paths are to
	// be set relative to the Location Path or not.
	SkipLocationForCookiePaths bool

	// EnableEmailLogin enables the login with email address link on the
	// authentication required page.
	EnableEmailLogin bool
}

// NewServer returns a new handler that handles identity service requests and
// stores its data in the given database. The handler will serve the specified
// versions of the API.
func NewServer(params ServerParams, serveVersions ...string) (HandlerCloser, error) {
	// Remove the agent identity provider if it is specified as it is no longer used.
	idps := make([]idp.IdentityProvider, 0, len(params.IdentityProviders))
	for _, idp := range params.IdentityProviders {
		if idp == agent.IdentityProvider {
			continue
		}
		idps = append(idps, idp)
	}
	params.IdentityProviders = idps
	newAPIs := make(map[string]identity.NewAPIHandlerFunc)
	for _, vers := range serveVersions {
		newAPI := versions[vers]
		if newAPI == nil {
			return nil, errgo.Newf("unknown version %q", vers)
		}
		newAPIs[vers] = newAPI
	}
	return identity.New(identity.ServerParams(params), newAPIs)
}

type HandlerCloser interface {
	http.Handler
	Close()
}