blob: 35972446d25486aeda1db02182c9ca2eaf8d64fd [file] [log] [blame]
Samuel A. Falvo II1d3fa662013-06-25 15:29:32 -07001package gophercloud
2
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -07003import (
4 "github.com/racker/perigee"
5)
6
Samuel A. Falvo II4e895182013-06-26 15:44:18 -07007// AuthOptions lets anyone calling Authenticate() supply the required access credentials.
8// At present, only Identity V2 API support exists; therefore, only Username, Password,
9// and optionally, TenantId are provided. If future Identity API versions become available,
10// alternative fields unique to those versions may appear here.
Samuel A. Falvo II1d3fa662013-06-25 15:29:32 -070011type AuthOptions struct {
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070012 // Username and Password are required if using Identity V2 API.
13 // Consult with your provider's control panel to discover your
14 // account's username and password.
15 Username, Password string
16
Rafael Garciaed5dd7f2013-12-06 17:00:32 -030017 // ApiKey used for providers that support Api Key authentication
18 ApiKey string
19
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070020 // The TenantId field is optional for the Identity V2 API.
21 TenantId string
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070022
Justin Santa Barbara21682a42013-08-31 17:56:13 -070023 // The TenantName can be specified instead of the TenantId
24 TenantName string
25
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070026 // AllowReauth should be set to true if you grant permission for Gophercloud to cache
27 // your credentials in memory, and to allow Gophercloud to attempt to re-authenticate
28 // automatically if/when your token expires. If you set it to false, it will not cache
29 // these settings, but re-authentication will not be possible. This setting defaults
30 // to false.
31 AllowReauth bool
Samuel A. Falvo II1d3fa662013-06-25 15:29:32 -070032}
33
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070034// AuthContainer provides a JSON encoding wrapper for passing credentials to the Identity
35// service. You will not work with this structure directly.
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070036type AuthContainer struct {
37 Auth Auth `json:"auth"`
38}
39
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070040// Auth provides a JSON encoding wrapper for passing credentials to the Identity
41// service. You will not work with this structure directly.
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070042type Auth struct {
Rafael Garciaed5dd7f2013-12-06 17:00:32 -030043 PasswordCredentials *PasswordCredentials `json:"passwordCredentials,omitempty"`
44 ApiKeyCredentials *ApiKeyCredentials `json:"RAX-KSKEY:apiKeyCredentials,omitempty"`
Samuel A. Falvo II839428e2013-06-25 18:02:24 -070045 TenantId string `json:"tenantId,omitempty"`
Justin Santa Barbara21682a42013-08-31 17:56:13 -070046 TenantName string `json:"tenantName,omitempty"`
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070047}
48
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070049// PasswordCredentials provides a JSON encoding wrapper for passing credentials to the Identity
50// service. You will not work with this structure directly.
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070051type PasswordCredentials struct {
52 Username string `json:"username"`
53 Password string `json:"password"`
54}
55
Rafael Garciaed5dd7f2013-12-06 17:00:32 -030056
57type ApiKeyCredentials struct {
58 Username string `json:"username"`
59 ApiKey string `json:"apiKey"`
60}
61
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -070062// Access encapsulates the API token and its relevant fields, as well as the
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -070063// services catalog that Identity API returns once authenticated.
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -070064type Access struct {
65 Token Token
66 ServiceCatalog []CatalogEntry
67 User User
Samuel A. Falvo II20f1aa42013-07-31 14:32:03 -070068 provider Provider `json:"-"`
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070069 options AuthOptions `json:"-"`
Samuel A. Falvo II20f1aa42013-07-31 14:32:03 -070070 context *Context `json:"-"`
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070071}
72
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -070073// Token encapsulates an authentication token and when it expires. It also includes
74// tenant information if available.
75type Token struct {
76 Id, Expires string
77 Tenant Tenant
78}
79
80// Tenant encapsulates tenant authentication information. If, after authentication,
81// no tenant information is supplied, both Id and Name will be "".
82type Tenant struct {
83 Id, Name string
84}
85
86// User encapsulates the user credentials, and provides visibility in what
87// the user can do through its role assignments.
88type User struct {
89 Id, Name string
90 XRaxDefaultRegion string `json:"RAX-AUTH:defaultRegion"`
91 Roles []Role
92}
93
94// Role encapsulates a permission that a user can rely on.
95type Role struct {
96 Description, Id, Name string
97}
98
99// CatalogEntry encapsulates a service catalog record.
100type CatalogEntry struct {
101 Name, Type string
102 Endpoints []EntryEndpoint
103}
104
105// EntryEndpoint encapsulates how to get to the API of some service.
106type EntryEndpoint struct {
107 Region, TenantId string
108 PublicURL, InternalURL string
109 VersionId, VersionInfo, VersionList string
110}
111
Rafael Garciaed5dd7f2013-12-06 17:00:32 -0300112
113//
114func getAuthCredentials(options AuthOptions) Auth {
115 if (options.ApiKey == "") {
116 return Auth{
117 PasswordCredentials: &PasswordCredentials{
118 Username: options.Username,
119 Password: options.Password,
120 },
121 TenantId: options.TenantId,
122 TenantName: options.TenantName,
123 };
124 } else {
125 return Auth{
126 ApiKeyCredentials: &ApiKeyCredentials{
127 Username: options.Username,
128 ApiKey: options.ApiKey,
129 },
130 TenantId: options.TenantId,
131 TenantName: options.TenantName,
132 };
133 }
134}
135
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700136// papersPlease contains the common logic between authentication and re-authentication.
137// The name, obviously a joke on the process of authentication, was chosen because
138// of how many other entities exist in the program containing the word Auth or Authorization.
139// I didn't need another one.
140func (c *Context) papersPlease(p Provider, options AuthOptions) (*Access, error) {
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -0700141 var access *Access
142
Rafael Garciaed5dd7f2013-12-06 17:00:32 -0300143 if (options.Username == "") || (options.Password == "" && options.ApiKey == "") {
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -0700144 return nil, ErrCredentials
145 }
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700146
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700147 err := perigee.Post(p.AuthEndpoint, perigee.Options{
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700148 CustomClient: c.httpClient,
Samuel A. Falvo II839428e2013-06-25 18:02:24 -0700149 ReqBody: &AuthContainer{
Rafael Garciaed5dd7f2013-12-06 17:00:32 -0300150 Auth: getAuthCredentials(options),
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700151 },
Samuel A. Falvo II4e895182013-06-26 15:44:18 -0700152 Results: &struct {
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -0700153 Access **Access `json:"access"`
154 }{
155 &access,
156 },
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700157 })
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700158 if err == nil {
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700159 access.options = options
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700160 access.provider = p
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700161 access.context = c
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700162 }
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -0700163 return access, err
Samuel A. Falvo II1d3fa662013-06-25 15:29:32 -0700164}
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700165
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700166// Authenticate() grants access to the OpenStack-compatible provider API.
167//
168// Providers are identified through a unique key string.
169// See the RegisterProvider() method for more details.
170//
171// The supplied AuthOptions instance allows the client to specify only those credentials
172// relevant for the authentication request. At present, support exists for OpenStack
173// Identity V2 API only; support for V3 will become available as soon as documentation for it
174// becomes readily available.
175//
176// For Identity V2 API requirements, you must provide at least the Username and Password
177// options. The TenantId field is optional, and defaults to "".
178func (c *Context) Authenticate(provider string, options AuthOptions) (*Access, error) {
179 p, err := c.ProviderByName(provider)
180 if err != nil {
181 return nil, err
182 }
183 return c.papersPlease(p, options)
184}
185
186// Reauthenticate attempts to reauthenticate using the configured access credentials, if
187// allowed. This method takes no action unless your AuthOptions has the AllowReauth flag
188// set to true.
189func (a *Access) Reauthenticate() error {
190 var other *Access
191 var err error
192
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700193 if a.options.AllowReauth {
194 other, err = a.context.papersPlease(a.provider, a.options)
Samuel A. Falvo IIfb586692013-07-16 17:00:14 -0700195 if err == nil {
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700196 *a = *other
197 }
198 }
199 return err
200}
201
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700202// See AccessProvider interface definition for details.
203func (a *Access) FirstEndpointUrlByCriteria(ac ApiCriteria) string {
204 ep := FindFirstEndpointByCriteria(a.ServiceCatalog, ac)
205 urls := []string{ep.PublicURL, ep.InternalURL}
206 return urls[ac.UrlChoice]
207}
Samuel A. Falvo IIbc0d54a2013-07-08 14:45:21 -0700208
209// See AccessProvider interface definition for details.
210func (a *Access) AuthToken() string {
211 return a.Token.Id
212}
Samuel A. Falvo II659e14b2013-07-16 12:04:54 -0700213
214// See AccessProvider interface definition for details.
215func (a *Access) Revoke(tok string) error {
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700216 url := a.provider.AuthEndpoint + "/" + tok
217 err := perigee.Delete(url, perigee.Options{
218 MoreHeaders: map[string]string{
219 "X-Auth-Token": a.AuthToken(),
220 },
221 OkCodes: []int{204},
222 })
223 return err
Samuel A. Falvo II659e14b2013-07-16 12:04:54 -0700224}
Samuel A. Falvo IIdbc4e9e2013-11-19 14:39:37 -0800225
226// See ServiceCatalogerForIdentityV2 interface definition for details.
227// Note that the raw slice is returend; be careful not to alter the fields of any members,
228// for other components of Gophercloud may depend upon them.
229// If this becomes a problem in the future,
230// a future revision may return a deep-copy of the service catalog instead.
231func (a *Access) V2ServiceCatalog() []CatalogEntry {
232 return a.ServiceCatalog
233}