1package swift 2 3import ( 4 "bytes" 5 "encoding/json" 6 "net/http" 7 "strings" 8) 9 10const ( 11 v3AuthMethodToken = "token" 12 v3AuthMethodPassword = "password" 13 v3CatalogTypeObjectStore = "object-store" 14) 15 16// V3 Authentication request 17// http://docs.openstack.org/developer/keystone/api_curl_examples.html 18// http://developer.openstack.org/api-ref-identity-v3.html 19type v3AuthRequest struct { 20 Auth struct { 21 Identity struct { 22 Methods []string `json:"methods"` 23 Password *v3AuthPassword `json:"password,omitempty"` 24 Token *v3AuthToken `json:"token,omitempty"` 25 } `json:"identity"` 26 Scope *v3Scope `json:"scope,omitempty"` 27 } `json:"auth"` 28} 29 30type v3Scope struct { 31 Project *v3Project `json:"project,omitempty"` 32 Domain *v3Domain `json:"domain,omitempty"` 33 Trust *v3Trust `json:"OS-TRUST:trust,omitempty"` 34} 35 36type v3Domain struct { 37 Id string `json:"id,omitempty"` 38 Name string `json:"name,omitempty"` 39} 40 41type v3Project struct { 42 Name string `json:"name,omitempty"` 43 Id string `json:"id,omitempty"` 44 Domain *v3Domain `json:"domain,omitempty"` 45} 46 47type v3Trust struct { 48 Id string `json:"id"` 49} 50 51type v3User struct { 52 Domain *v3Domain `json:"domain,omitempty"` 53 Id string `json:"id,omitempty"` 54 Name string `json:"name,omitempty"` 55 Password string `json:"password,omitempty"` 56} 57 58type v3AuthToken struct { 59 Id string `json:"id"` 60} 61 62type v3AuthPassword struct { 63 User v3User `json:"user"` 64} 65 66// V3 Authentication response 67type v3AuthResponse struct { 68 Token struct { 69 Expires_At, Issued_At string 70 Methods []string 71 Roles []struct { 72 Id, Name string 73 Links struct { 74 Self string 75 } 76 } 77 78 Project struct { 79 Domain struct { 80 Id, Name string 81 } 82 Id, Name string 83 } 84 85 Catalog []struct { 86 Id, Namem, Type string 87 Endpoints []struct { 88 Id, Region_Id, Url, Region string 89 Interface EndpointType 90 } 91 } 92 93 User struct { 94 Id, Name string 95 Domain struct { 96 Id, Name string 97 Links struct { 98 Self string 99 } 100 } 101 } 102 103 Audit_Ids []string 104 } 105} 106 107type v3Auth struct { 108 Region string 109 Auth *v3AuthResponse 110 Headers http.Header 111} 112 113func (auth *v3Auth) Request(c *Connection) (*http.Request, error) { 114 auth.Region = c.Region 115 116 var v3i interface{} 117 118 v3 := v3AuthRequest{} 119 120 if c.UserName == "" && c.UserId == "" { 121 v3.Auth.Identity.Methods = []string{v3AuthMethodToken} 122 v3.Auth.Identity.Token = &v3AuthToken{Id: c.ApiKey} 123 } else { 124 v3.Auth.Identity.Methods = []string{v3AuthMethodPassword} 125 v3.Auth.Identity.Password = &v3AuthPassword{ 126 User: v3User{ 127 Name: c.UserName, 128 Id: c.UserId, 129 Password: c.ApiKey, 130 }, 131 } 132 133 var domain *v3Domain 134 135 if c.Domain != "" { 136 domain = &v3Domain{Name: c.Domain} 137 } else if c.DomainId != "" { 138 domain = &v3Domain{Id: c.DomainId} 139 } 140 v3.Auth.Identity.Password.User.Domain = domain 141 } 142 143 if c.TrustId != "" { 144 v3.Auth.Scope = &v3Scope{Trust: &v3Trust{Id: c.TrustId}} 145 } else if c.TenantId != "" || c.Tenant != "" { 146 147 v3.Auth.Scope = &v3Scope{Project: &v3Project{}} 148 149 if c.TenantId != "" { 150 v3.Auth.Scope.Project.Id = c.TenantId 151 } else if c.Tenant != "" { 152 v3.Auth.Scope.Project.Name = c.Tenant 153 switch { 154 case c.TenantDomain != "": 155 v3.Auth.Scope.Project.Domain = &v3Domain{Name: c.TenantDomain} 156 case c.TenantDomainId != "": 157 v3.Auth.Scope.Project.Domain = &v3Domain{Id: c.TenantDomainId} 158 case c.Domain != "": 159 v3.Auth.Scope.Project.Domain = &v3Domain{Name: c.Domain} 160 case c.DomainId != "": 161 v3.Auth.Scope.Project.Domain = &v3Domain{Id: c.DomainId} 162 default: 163 v3.Auth.Scope.Project.Domain = &v3Domain{Name: "Default"} 164 } 165 } 166 } 167 168 v3i = v3 169 170 body, err := json.Marshal(v3i) 171 172 if err != nil { 173 return nil, err 174 } 175 176 url := c.AuthUrl 177 if !strings.HasSuffix(url, "/") { 178 url += "/" 179 } 180 url += "auth/tokens" 181 req, err := http.NewRequest("POST", url, bytes.NewBuffer(body)) 182 if err != nil { 183 return nil, err 184 } 185 req.Header.Set("Content-Type", "application/json") 186 req.Header.Set("User-Agent", c.UserAgent) 187 return req, nil 188} 189 190func (auth *v3Auth) Response(resp *http.Response) error { 191 auth.Auth = &v3AuthResponse{} 192 auth.Headers = resp.Header 193 err := readJson(resp, auth.Auth) 194 return err 195} 196 197func (auth *v3Auth) endpointUrl(Type string, endpointType EndpointType) string { 198 for _, catalog := range auth.Auth.Token.Catalog { 199 if catalog.Type == Type { 200 for _, endpoint := range catalog.Endpoints { 201 if endpoint.Interface == endpointType && (auth.Region == "" || (auth.Region == endpoint.Region)) { 202 return endpoint.Url 203 } 204 } 205 } 206 } 207 return "" 208} 209 210func (auth *v3Auth) StorageUrl(Internal bool) string { 211 endpointType := EndpointTypePublic 212 if Internal { 213 endpointType = EndpointTypeInternal 214 } 215 return auth.StorageUrlForEndpoint(endpointType) 216} 217 218func (auth *v3Auth) StorageUrlForEndpoint(endpointType EndpointType) string { 219 return auth.endpointUrl("object-store", endpointType) 220} 221 222func (auth *v3Auth) Token() string { 223 return auth.Headers.Get("X-Subject-Token") 224} 225 226func (auth *v3Auth) CdnUrl() string { 227 return "" 228} 229