blob: 52bc1abd29cabcfd28c7e5d434fc7f834b57b6f1 [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
20 // AllowReauth should be set to true if you grant permission for Gophercloud to cache
21 // your credentials in memory, and to allow Gophercloud to attempt to re-authenticate
22 // automatically if/when your token expires. If you set it to false, it will not cache
23 // these settings, but re-authentication will not be possible. This setting defaults
24 // to false.
25 AllowReauth bool
Samuel A. Falvo II1d3fa662013-06-25 15:29:32 -070026}
27
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070028// AuthContainer provides a JSON encoding wrapper for passing credentials to the Identity
29// service. You will not work with this structure directly.
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070030type AuthContainer struct {
31 Auth Auth `json:"auth"`
32}
33
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070034// Auth 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 Auth struct {
37 PasswordCredentials PasswordCredentials `json:"passwordCredentials"`
Samuel A. Falvo II839428e2013-06-25 18:02:24 -070038 TenantId string `json:"tenantId,omitempty"`
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070039}
40
Samuel A. Falvo II4e895182013-06-26 15:44:18 -070041// PasswordCredentials provides a JSON encoding wrapper for passing credentials to the Identity
42// service. You will not work with this structure directly.
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070043type PasswordCredentials struct {
44 Username string `json:"username"`
45 Password string `json:"password"`
46}
47
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -070048// Access encapsulates the API token and its relevant fields, as well as the
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -070049// services catalog that Identity API returns once authenticated.
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -070050type Access struct {
51 Token Token
52 ServiceCatalog []CatalogEntry
53 User User
Samuel A. Falvo II20f1aa42013-07-31 14:32:03 -070054 provider Provider `json:"-"`
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070055 options AuthOptions `json:"-"`
Samuel A. Falvo II20f1aa42013-07-31 14:32:03 -070056 context *Context `json:"-"`
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -070057}
58
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -070059// Token encapsulates an authentication token and when it expires. It also includes
60// tenant information if available.
61type Token struct {
62 Id, Expires string
63 Tenant Tenant
64}
65
66// Tenant encapsulates tenant authentication information. If, after authentication,
67// no tenant information is supplied, both Id and Name will be "".
68type Tenant struct {
69 Id, Name string
70}
71
72// User encapsulates the user credentials, and provides visibility in what
73// the user can do through its role assignments.
74type User struct {
75 Id, Name string
76 XRaxDefaultRegion string `json:"RAX-AUTH:defaultRegion"`
77 Roles []Role
78}
79
80// Role encapsulates a permission that a user can rely on.
81type Role struct {
82 Description, Id, Name string
83}
84
85// CatalogEntry encapsulates a service catalog record.
86type CatalogEntry struct {
87 Name, Type string
88 Endpoints []EntryEndpoint
89}
90
91// EntryEndpoint encapsulates how to get to the API of some service.
92type EntryEndpoint struct {
93 Region, TenantId string
94 PublicURL, InternalURL string
95 VersionId, VersionInfo, VersionList string
96}
97
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -070098// papersPlease contains the common logic between authentication and re-authentication.
99// The name, obviously a joke on the process of authentication, was chosen because
100// of how many other entities exist in the program containing the word Auth or Authorization.
101// I didn't need another one.
102func (c *Context) papersPlease(p Provider, options AuthOptions) (*Access, error) {
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -0700103 var access *Access
104
Samuel A. Falvo IIfd78c302013-06-25 16:35:32 -0700105 if (options.Username == "") || (options.Password == "") {
106 return nil, ErrCredentials
107 }
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700108
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700109 err := perigee.Post(p.AuthEndpoint, perigee.Options{
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700110 CustomClient: c.httpClient,
Samuel A. Falvo II839428e2013-06-25 18:02:24 -0700111 ReqBody: &AuthContainer{
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700112 Auth: Auth{
113 PasswordCredentials: PasswordCredentials{
114 Username: options.Username,
115 Password: options.Password,
116 },
117 TenantId: options.TenantId,
118 },
119 },
Samuel A. Falvo II4e895182013-06-26 15:44:18 -0700120 Results: &struct {
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -0700121 Access **Access `json:"access"`
122 }{
123 &access,
124 },
Samuel A. Falvo II5d0d74c2013-06-25 17:23:18 -0700125 })
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700126 if err == nil {
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700127 access.options = options
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700128 access.provider = p
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700129 access.context = c
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700130 }
Samuel A. Falvo IId1ee7982013-06-26 14:32:45 -0700131 return access, err
Samuel A. Falvo II1d3fa662013-06-25 15:29:32 -0700132}
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700133
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700134// Authenticate() grants access to the OpenStack-compatible provider API.
135//
136// Providers are identified through a unique key string.
137// See the RegisterProvider() method for more details.
138//
139// The supplied AuthOptions instance allows the client to specify only those credentials
140// relevant for the authentication request. At present, support exists for OpenStack
141// Identity V2 API only; support for V3 will become available as soon as documentation for it
142// becomes readily available.
143//
144// For Identity V2 API requirements, you must provide at least the Username and Password
145// options. The TenantId field is optional, and defaults to "".
146func (c *Context) Authenticate(provider string, options AuthOptions) (*Access, error) {
147 p, err := c.ProviderByName(provider)
148 if err != nil {
149 return nil, err
150 }
151 return c.papersPlease(p, options)
152}
153
154// Reauthenticate attempts to reauthenticate using the configured access credentials, if
155// allowed. This method takes no action unless your AuthOptions has the AllowReauth flag
156// set to true.
157func (a *Access) Reauthenticate() error {
158 var other *Access
159 var err error
160
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700161 if a.options.AllowReauth {
162 other, err = a.context.papersPlease(a.provider, a.options)
Samuel A. Falvo IIfb586692013-07-16 17:00:14 -0700163 if err == nil {
Samuel A. Falvo II9e64f6b2013-07-16 14:26:50 -0700164 *a = *other
165 }
166 }
167 return err
168}
169
Samuel A. Falvo II2e2b8772013-07-04 15:40:15 -0700170// See AccessProvider interface definition for details.
171func (a *Access) FirstEndpointUrlByCriteria(ac ApiCriteria) string {
172 ep := FindFirstEndpointByCriteria(a.ServiceCatalog, ac)
173 urls := []string{ep.PublicURL, ep.InternalURL}
174 return urls[ac.UrlChoice]
175}
Samuel A. Falvo IIbc0d54a2013-07-08 14:45:21 -0700176
177// See AccessProvider interface definition for details.
178func (a *Access) AuthToken() string {
179 return a.Token.Id
180}
Samuel A. Falvo II659e14b2013-07-16 12:04:54 -0700181
182// See AccessProvider interface definition for details.
183func (a *Access) Revoke(tok string) error {
Samuel A. Falvo II0167aaa2013-07-16 12:36:25 -0700184 url := a.provider.AuthEndpoint + "/" + tok
185 err := perigee.Delete(url, perigee.Options{
186 MoreHeaders: map[string]string{
187 "X-Auth-Token": a.AuthToken(),
188 },
189 OkCodes: []int{204},
190 })
191 return err
Samuel A. Falvo II659e14b2013-07-16 12:04:54 -0700192}