Samuel A. Falvo II | 8a549ef | 2014-01-24 15:20:54 -0800 | [diff] [blame^] | 1 | package identity |
| 2 | |
| 3 | import ( |
| 4 | "github.com/racker/perigee" |
| 5 | ) |
| 6 | |
| 7 | type AuthResults map[string]interface{} |
| 8 | |
| 9 | // AuthOptions lets anyone calling Authenticate() supply the required access credentials. |
| 10 | // At present, only Identity V2 API support exists; therefore, only Username, Password, |
| 11 | // and optionally, TenantId are provided. If future Identity API versions become available, |
| 12 | // alternative fields unique to those versions may appear here. |
| 13 | type AuthOptions struct { |
| 14 | // Endpoint specifies the HTTP endpoint offering the Identity V2 API. |
| 15 | // Required. |
| 16 | Endpoint string |
| 17 | |
| 18 | // Username is required if using Identity V2 API. |
| 19 | // Consult with your provider's control panel to discover your |
| 20 | // account's username. |
| 21 | Username string |
| 22 | |
| 23 | // At most one of Password or ApiKey is required if using Identity V2 API. |
| 24 | // Consult with your provider's control panel to discover your |
| 25 | // account's preferred method of authentication. |
| 26 | Password, ApiKey string |
| 27 | |
| 28 | // The TenantId field is optional for the Identity V2 API. |
| 29 | TenantId string |
| 30 | |
| 31 | // The TenantName can be specified instead of the TenantId |
| 32 | TenantName string |
| 33 | |
| 34 | // AllowReauth should be set to true if you grant permission for Gophercloud to cache |
| 35 | // your credentials in memory, and to allow Gophercloud to attempt to re-authenticate |
| 36 | // automatically if/when your token expires. If you set it to false, it will not cache |
| 37 | // these settings, but re-authentication will not be possible. This setting defaults |
| 38 | // to false. |
| 39 | AllowReauth bool |
| 40 | } |
| 41 | |
| 42 | func Authenticate(options AuthOptions) (AuthResults, error) { |
| 43 | var ar AuthResults |
| 44 | |
| 45 | if options.Endpoint == "" { |
| 46 | return nil, ErrEndpoint |
| 47 | } |
| 48 | |
| 49 | if (options.Username == "") || (options.Password == "" && options.ApiKey == "") { |
| 50 | return nil, ErrCredentials |
| 51 | } |
| 52 | |
| 53 | err := perigee.Post(options.Endpoint, perigee.Options{ |
| 54 | ReqBody: &AuthContainer{ |
| 55 | Auth: getAuthCredentials(options), |
| 56 | }, |
| 57 | Results: &ar, |
| 58 | }) |
| 59 | return ar, err |
| 60 | } |
| 61 | |
| 62 | func getAuthCredentials(options AuthOptions) Auth { |
| 63 | if options.ApiKey == "" { |
| 64 | return Auth{ |
| 65 | PasswordCredentials: &struct { |
| 66 | Username string `json:"username"` |
| 67 | Password string `json:"password"` |
| 68 | }{ |
| 69 | Username: options.Username, |
| 70 | Password: options.Password, |
| 71 | }, |
| 72 | TenantId: options.TenantId, |
| 73 | TenantName: options.TenantName, |
| 74 | } |
| 75 | } else { |
| 76 | return Auth{ |
| 77 | ApiKeyCredentials: &struct { |
| 78 | Username string `json:"username"` |
| 79 | ApiKey string `json:"apiKey"` |
| 80 | }{ |
| 81 | Username: options.Username, |
| 82 | ApiKey: options.ApiKey, |
| 83 | }, |
| 84 | TenantId: options.TenantId, |
| 85 | TenantName: options.TenantName, |
| 86 | } |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | // AuthContainer provides a JSON encoding wrapper for passing credentials to the Identity |
| 91 | // service. You will not work with this structure directly. |
| 92 | type AuthContainer struct { |
| 93 | Auth Auth `json:"auth"` |
| 94 | } |
| 95 | |
| 96 | // Auth provides a JSON encoding wrapper for passing credentials to the Identity |
| 97 | // service. You will not work with this structure directly. |
| 98 | type Auth struct { |
| 99 | PasswordCredentials interface{} `json:"passwordCredentials,omitempty"` |
| 100 | ApiKeyCredentials interface{} `json:"RAX-KSKEY:apiKeyCredentials,omitempty"` |
| 101 | TenantId string `json:"tenantId,omitempty"` |
| 102 | TenantName string `json:"tenantName,omitempty"` |
| 103 | } |