blob: 076c73180e2d509cfcaa5407157ba1f66f15b6c5 [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
17 // The TenantId field is optional for the Identity V2 API.
18 TenantId string
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070019
Justin Santa Barbara21682a42013-08-31 17:56:13 -070020 // The TenantName can be specified instead of the TenantId
21 TenantName string
22
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070023 // AllowReauth should be set to true if you grant permission for Gophercloud to cache
24 // your credentials in memory, and to allow Gophercloud to attempt to re-authenticate
25 // automatically if/when your token expires. If you set it to false, it will not cache
26 // these settings, but re-authentication will not be possible. This setting defaults
27 // to false.
28 AllowReauth bool
Samuel A. Falvo II1d3fa662013-06-25 15:29:32 -070029}
30
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070031// AuthContainer provides a JSON encoding wrapper for passing credentials to the Identity
32// service. You will not work with this structure directly.
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070033type AuthContainer struct {
34 Auth Auth `json:"auth"`
35}
36
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070037// Auth provides a JSON encoding wrapper for passing credentials to the Identity
38// service. You will not work with this structure directly.
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070039type Auth struct {
40 PasswordCredentials PasswordCredentials `json:"passwordCredentials"`
Samuel A. Falvo II839428e2013-06-25 18:02:24 -070041 TenantId string `json:"tenantId,omitempty"`
Justin Santa Barbara21682a42013-08-31 17:56:13 -070042 TenantName string `json:"tenantName,omitempty"`
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070043}
44
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070045// PasswordCredentials provides a JSON encoding wrapper for passing credentials to the Identity
46// service. You will not work with this structure directly.
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070047type PasswordCredentials struct {
48 Username string `json:"username"`
49 Password string `json:"password"`
50}
51
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -070052// Access encapsulates the API token and its relevant fields, as well as the
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -070053// services catalog that Identity API returns once authenticated.
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -070054type Access struct {
55 Token Token
56 ServiceCatalog []CatalogEntry
57 User User
Samuel A. Falvo II20f1aa42013-07-31 14:32:03 -070058 provider Provider `json:"-"`
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070059 options AuthOptions `json:"-"`
Samuel A. Falvo II20f1aa42013-07-31 14:32:03 -070060 context *Context `json:"-"`
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070061}
62
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -070063// Token encapsulates an authentication token and when it expires. It also includes
64// tenant information if available.
65type Token struct {
66 Id, Expires string
67 Tenant Tenant
68}
69
70// Tenant encapsulates tenant authentication information. If, after authentication,
71// no tenant information is supplied, both Id and Name will be "".
72type Tenant struct {
73 Id, Name string
74}
75
76// User encapsulates the user credentials, and provides visibility in what
77// the user can do through its role assignments.
78type User struct {
79 Id, Name string
80 XRaxDefaultRegion string `json:"RAX-AUTH:defaultRegion"`
81 Roles []Role
82}
83
84// Role encapsulates a permission that a user can rely on.
85type Role struct {
86 Description, Id, Name string
87}
88
89// CatalogEntry encapsulates a service catalog record.
90type CatalogEntry struct {
91 Name, Type string
92 Endpoints []EntryEndpoint
93}
94
95// EntryEndpoint encapsulates how to get to the API of some service.
96type EntryEndpoint struct {
97 Region, TenantId string
98 PublicURL, InternalURL string
99 VersionId, VersionInfo, VersionList string
100}
101
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700102// papersPlease contains the common logic between authentication and re-authentication.
103// The name, obviously a joke on the process of authentication, was chosen because
104// of how many other entities exist in the program containing the word Auth or Authorization.
105// I didn't need another one.
106func (c *Context) papersPlease(p Provider, options AuthOptions) (*Access, error) {
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -0700107 var access *Access
108
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -0700109 if (options.Username == "") || (options.Password == "") {
110 return nil, ErrCredentials
111 }
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700112
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700113 err := perigee.Post(p.AuthEndpoint, perigee.Options{
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700114 CustomClient: c.httpClient,
Samuel A. Falvo II839428e2013-06-25 18:02:24 -0700115 ReqBody: &AuthContainer{
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700116 Auth: Auth{
117 PasswordCredentials: PasswordCredentials{
118 Username: options.Username,
119 Password: options.Password,
120 },
Justin Santa Barbara21682a42013-08-31 17:56:13 -0700121 TenantId: options.TenantId,
122 TenantName: options.TenantName,
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700123 },
124 },
Samuel A. Falvo II4e895182013-06-26 15:44:18 -0700125 Results: &struct {
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -0700126 Access **Access `json:"access"`
127 }{
128 &access,
129 },
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700130 })
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700131 if err == nil {
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700132 access.options = options
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700133 access.provider = p
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700134 access.context = c
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700135 }
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -0700136 return access, err
Samuel A. Falvo II1d3fa662013-06-25 15:29:32 -0700137}
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700138
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700139// Authenticate() grants access to the OpenStack-compatible provider API.
140//
141// Providers are identified through a unique key string.
142// See the RegisterProvider() method for more details.
143//
144// The supplied AuthOptions instance allows the client to specify only those credentials
145// relevant for the authentication request. At present, support exists for OpenStack
146// Identity V2 API only; support for V3 will become available as soon as documentation for it
147// becomes readily available.
148//
149// For Identity V2 API requirements, you must provide at least the Username and Password
150// options. The TenantId field is optional, and defaults to "".
151func (c *Context) Authenticate(provider string, options AuthOptions) (*Access, error) {
152 p, err := c.ProviderByName(provider)
153 if err != nil {
154 return nil, err
155 }
156 return c.papersPlease(p, options)
157}
158
159// Reauthenticate attempts to reauthenticate using the configured access credentials, if
160// allowed. This method takes no action unless your AuthOptions has the AllowReauth flag
161// set to true.
162func (a *Access) Reauthenticate() error {
163 var other *Access
164 var err error
165
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700166 if a.options.AllowReauth {
167 other, err = a.context.papersPlease(a.provider, a.options)
Samuel A. Falvo IIfb586692013-07-16 17:00:14 -0700168 if err == nil {
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700169 *a = *other
170 }
171 }
172 return err
173}
174
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700175// See AccessProvider interface definition for details.
176func (a *Access) FirstEndpointUrlByCriteria(ac ApiCriteria) string {
177 ep := FindFirstEndpointByCriteria(a.ServiceCatalog, ac)
178 urls := []string{ep.PublicURL, ep.InternalURL}
179 return urls[ac.UrlChoice]
180}
Samuel A. Falvo IIbc0d54a2013-07-08 14:45:21 -0700181
182// See AccessProvider interface definition for details.
183func (a *Access) AuthToken() string {
184 return a.Token.Id
185}
Samuel A. Falvo II659e14b2013-07-16 12:04:54 -0700186
187// See AccessProvider interface definition for details.
188func (a *Access) Revoke(tok string) error {
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700189 url := a.provider.AuthEndpoint + "/" + tok
190 err := perigee.Delete(url, perigee.Options{
191 MoreHeaders: map[string]string{
192 "X-Auth-Token": a.AuthToken(),
193 },
194 OkCodes: []int{204},
195 })
196 return err
Samuel A. Falvo II659e14b2013-07-16 12:04:54 -0700197}
Samuel A. Falvo IIcfb352a2013-11-19 14:39:37 -0800198
199// See ServiceCatalogerForIdentityV2 interface definition for details.
200// Note that the raw slice is returend; be careful not to alter the fields of any members,
201// for other components of Gophercloud may depend upon them.
202// If this becomes a problem in the future,
203// a future revision may return a deep-copy of the service catalog instead.
204func (a *Access) V2ServiceCatalog() []CatalogEntry {
205 return a.ServiceCatalog
206}