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()
}
|