mod_credentials.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package identity
  15. import (
  16. "encoding/base64"
  17. "fmt"
  18. "net/url"
  19. "strings"
  20. "time"
  21. "yunion.io/x/jsonutils"
  22. "yunion.io/x/pkg/errors"
  23. "yunion.io/x/pkg/util/seclib"
  24. api "yunion.io/x/onecloud/pkg/apis/identity"
  25. "yunion.io/x/onecloud/pkg/httperrors"
  26. "yunion.io/x/onecloud/pkg/mcclient"
  27. "yunion.io/x/onecloud/pkg/mcclient/modulebase"
  28. "yunion.io/x/onecloud/pkg/mcclient/modules"
  29. "yunion.io/x/onecloud/pkg/util/seclib2"
  30. )
  31. type SCredentialManager struct {
  32. modulebase.ResourceManager
  33. }
  34. const (
  35. DEFAULT_PROJECT = api.DEFAULT_PROJECT
  36. ACCESS_SECRET_TYPE = api.ACCESS_SECRET_TYPE
  37. TOTP_TYPE = api.TOTP_TYPE
  38. RECOVERY_SECRETS_TYPE = api.RECOVERY_SECRETS_TYPE
  39. OIDC_CREDENTIAL_TYPE = api.OIDC_CREDENTIAL_TYPE
  40. ENCRYPT_KEY_TYPE = api.ENCRYPT_KEY_TYPE
  41. )
  42. type STotpSecret struct {
  43. Totp string `json:"totp"`
  44. Timestamp int64 `json:"timestamp"`
  45. }
  46. type SRecoverySecret struct {
  47. Question string `json:"question"`
  48. Answer string `json:"answer"`
  49. }
  50. type SAccessKeySecret struct {
  51. KeyId string `json:"-"`
  52. ProjectId string `json:"-"`
  53. TimeStamp time.Time `json:"-"`
  54. api.SAccessKeySecretBlob
  55. }
  56. type SRecoverySecretSet struct {
  57. Questions []SRecoverySecret
  58. Timestamp int64
  59. }
  60. type SOpenIDConnectCredential struct {
  61. ClientId string `json:"client_id"`
  62. // Secret string `json:"secret"`
  63. RedirectUri string `json:"redirect_uri"`
  64. api.SAccessKeySecretBlob
  65. }
  66. type SEncryptKeySecret struct {
  67. KeyId string `json:"-"`
  68. KeyName string `json:"-"`
  69. Alg seclib2.TSymEncAlg `json:"alg"`
  70. Key string `json:"key"`
  71. TimeStamp time.Time `json:"-"`
  72. UserId string `json:"user_id"`
  73. User string `json:"user"`
  74. Domain string `json:"domain"`
  75. DomainId string `json:"domain_id"`
  76. }
  77. func (key SEncryptKeySecret) Marshal() jsonutils.JSONObject {
  78. json := jsonutils.NewDict()
  79. json.Add(jsonutils.NewString(string(key.Alg)), "alg")
  80. json.Add(jsonutils.NewString(key.KeyId), "key_id")
  81. json.Add(jsonutils.NewString(key.KeyName), "key_name")
  82. json.Add(jsonutils.NewTimeString(key.TimeStamp), "timestamp")
  83. json.Add(jsonutils.NewString(key.UserId), "user_id")
  84. json.Add(jsonutils.NewString(key.User), "user")
  85. json.Add(jsonutils.NewString(key.DomainId), "domain_id")
  86. json.Add(jsonutils.NewString(key.Domain), "domain")
  87. return json
  88. }
  89. func (key SEncryptKeySecret) Encrypt(secret []byte) ([]byte, error) {
  90. bKey, err := base64.StdEncoding.DecodeString(key.Key)
  91. if err != nil {
  92. return nil, errors.Wrap(err, "base64.StdEncoding.DecodeString")
  93. }
  94. return seclib2.Alg(key.Alg).CbcEncode(secret, bKey)
  95. }
  96. func (key SEncryptKeySecret) Decrypt(secret []byte) ([]byte, error) {
  97. bKey, err := base64.StdEncoding.DecodeString(key.Key)
  98. if err != nil {
  99. return nil, errors.Wrap(err, "base64.StdEncoding.DecodeString")
  100. }
  101. return seclib2.Alg(key.Alg).CbcDecode(secret, bKey)
  102. }
  103. func (key SEncryptKeySecret) EncryptBase64(secret []byte) (string, error) {
  104. bKey, err := base64.StdEncoding.DecodeString(key.Key)
  105. if err != nil {
  106. return "", errors.Wrap(err, "base64.StdEncoding.DecodeString")
  107. }
  108. return seclib2.Alg(key.Alg).CbcEncodeBase64(secret, bKey)
  109. }
  110. func (key SEncryptKeySecret) DecryptBase64(secret string) ([]byte, error) {
  111. bKey, err := base64.StdEncoding.DecodeString(key.Key)
  112. if err != nil {
  113. return nil, errors.Wrap(err, "base64.StdEncoding.DecodeString")
  114. }
  115. return seclib2.Alg(key.Alg).CbcDecodeBase64(secret, bKey)
  116. }
  117. func (manager *SCredentialManager) fetchCredentials(s *mcclient.ClientSession, secType string, uid string, pid string) ([]jsonutils.JSONObject, error) {
  118. query := jsonutils.NewDict()
  119. query.Add(jsonutils.NewString(secType), "type")
  120. if len(uid) > 0 {
  121. query.Add(jsonutils.NewString(uid), "user_id")
  122. }
  123. if len(pid) > 0 {
  124. query.Add(jsonutils.NewString(pid), "project_id")
  125. }
  126. query.Add(jsonutils.JSONTrue, "details")
  127. results, err := manager.List(s, query)
  128. if err != nil {
  129. return nil, err
  130. }
  131. return results.Data, nil
  132. }
  133. func (manager *SCredentialManager) FetchAccessKeySecrets(s *mcclient.ClientSession, uid string, pid string) ([]jsonutils.JSONObject, error) {
  134. return manager.fetchCredentials(s, ACCESS_SECRET_TYPE, uid, pid)
  135. }
  136. func (manager *SCredentialManager) FetchTotpSecrets(s *mcclient.ClientSession, uid string) ([]jsonutils.JSONObject, error) {
  137. return manager.fetchCredentials(s, TOTP_TYPE, uid, "")
  138. }
  139. func (manager *SCredentialManager) FetchRecoverySecrets(s *mcclient.ClientSession, uid string) ([]jsonutils.JSONObject, error) {
  140. return manager.fetchCredentials(s, RECOVERY_SECRETS_TYPE, uid, "")
  141. }
  142. func (manager *SCredentialManager) FetchOIDCSecrets(s *mcclient.ClientSession, uid string, pid string) ([]jsonutils.JSONObject, error) {
  143. return manager.fetchCredentials(s, OIDC_CREDENTIAL_TYPE, uid, pid)
  144. }
  145. func (manager *SCredentialManager) FetchEncryptionKeys(s *mcclient.ClientSession, uid string) ([]jsonutils.JSONObject, error) {
  146. return manager.fetchCredentials(s, ENCRYPT_KEY_TYPE, uid, "")
  147. }
  148. func (manager *SCredentialManager) GetTotpSecret(s *mcclient.ClientSession, uid string) (string, error) {
  149. secrets, err := manager.FetchTotpSecrets(s, uid)
  150. if err != nil {
  151. return "", err
  152. }
  153. latestTotp := STotpSecret{}
  154. find := false
  155. for i := range secrets {
  156. blobStr, _ := secrets[i].GetString("blob")
  157. blobJson, _ := jsonutils.ParseString(blobStr)
  158. if blobJson != nil {
  159. totp := STotpSecret{}
  160. blobJson.Unmarshal(&totp)
  161. if latestTotp.Timestamp == 0 || totp.Timestamp > latestTotp.Timestamp {
  162. latestTotp = totp
  163. find = true
  164. }
  165. }
  166. }
  167. if !find {
  168. return "", httperrors.NewNotFoundError("no totp for %s", uid)
  169. }
  170. return latestTotp.Totp, nil
  171. }
  172. func (manager *SCredentialManager) GetRecoverySecrets(s *mcclient.ClientSession, uid string) ([]SRecoverySecret, error) {
  173. secrets, err := manager.FetchRecoverySecrets(s, uid)
  174. if err != nil {
  175. return nil, err
  176. }
  177. latestQ := SRecoverySecretSet{}
  178. find := false
  179. for i := range secrets {
  180. blobStr, _ := secrets[i].GetString("blob")
  181. blobJson, _ := jsonutils.ParseString(blobStr)
  182. if blobJson != nil {
  183. curr := SRecoverySecretSet{}
  184. blobJson.Unmarshal(&curr)
  185. if latestQ.Timestamp == 0 || curr.Timestamp > latestQ.Timestamp {
  186. latestQ = curr
  187. find = true
  188. }
  189. }
  190. }
  191. if !find {
  192. return nil, httperrors.NewNotFoundError("no recovery secrets for %s", uid)
  193. }
  194. return latestQ.Questions, nil
  195. }
  196. func DecodeAccessKeySecret(secret jsonutils.JSONObject) (SAccessKeySecret, error) {
  197. curr := SAccessKeySecret{}
  198. blobStr, err := secret.GetString("blob")
  199. if err != nil {
  200. return curr, errors.Wrap(err, "secret.GetString")
  201. }
  202. blobJson, err := jsonutils.ParseString(blobStr)
  203. if err != nil {
  204. return curr, errors.Wrap(err, "jsonutils.ParseString")
  205. }
  206. err = blobJson.Unmarshal(&curr)
  207. if err != nil {
  208. return curr, errors.Wrap(err, "blobJson.Unmarshal")
  209. }
  210. curr.ProjectId, err = secret.GetString("project_id")
  211. if err != nil {
  212. return curr, errors.Wrap(err, "secret.GetString('project_id')")
  213. }
  214. curr.TimeStamp, err = secret.GetTime("created_at")
  215. if err != nil {
  216. return curr, errors.Wrap(err, "secret.GetTime('created_at')")
  217. }
  218. curr.KeyId, err = secret.GetString("id")
  219. if err != nil {
  220. return curr, errors.Wrap(err, "secret.GetString('id')")
  221. }
  222. return curr, nil
  223. }
  224. func (manager *SCredentialManager) GetAccessKeySecrets(s *mcclient.ClientSession, uid string, pid string) ([]SAccessKeySecret, error) {
  225. secrets, err := manager.FetchAccessKeySecrets(s, uid, pid)
  226. if err != nil {
  227. return nil, err
  228. }
  229. aksk := make([]SAccessKeySecret, 0)
  230. for i := range secrets {
  231. curr, err := DecodeAccessKeySecret(secrets[i])
  232. if err != nil {
  233. return nil, errors.Wrap(err, "DecodeAccessKeySecret")
  234. }
  235. aksk = append(aksk, curr)
  236. }
  237. return aksk, nil
  238. }
  239. func DecodeOIDCSecret(secret jsonutils.JSONObject) (SOpenIDConnectCredential, error) {
  240. curr := SOpenIDConnectCredential{}
  241. blobStr, err := secret.GetString("blob")
  242. if err != nil {
  243. return curr, errors.Wrap(err, "secret.GetString")
  244. }
  245. blobJson, err := jsonutils.ParseString(blobStr)
  246. if err != nil {
  247. return curr, errors.Wrap(err, "jsonutils.ParseString")
  248. }
  249. err = blobJson.Unmarshal(&curr)
  250. if err != nil {
  251. return curr, errors.Wrap(err, "blobJson.Unmarshal")
  252. }
  253. curr.ClientId, err = secret.GetString("id")
  254. if err != nil {
  255. return curr, errors.Wrap(err, "secret.GetString('id')")
  256. }
  257. return curr, nil
  258. }
  259. func (manager *SCredentialManager) GetOIDCSecret(s *mcclient.ClientSession, uid string, pid string) ([]SOpenIDConnectCredential, error) {
  260. secrets, err := manager.FetchOIDCSecrets(s, uid, pid)
  261. if err != nil {
  262. return nil, err
  263. }
  264. oidcCreds := make([]SOpenIDConnectCredential, 0)
  265. for i := range secrets {
  266. curr, err := DecodeOIDCSecret(secrets[i])
  267. if err != nil {
  268. return nil, errors.Wrap(err, "DecodeOIDCSecret")
  269. }
  270. oidcCreds = append(oidcCreds, curr)
  271. }
  272. return oidcCreds, nil
  273. }
  274. func DecodeEncryptKey(secret jsonutils.JSONObject) (SEncryptKeySecret, error) {
  275. curr := SEncryptKeySecret{}
  276. blobStr, err := secret.GetString("blob")
  277. if err != nil {
  278. return curr, errors.Wrap(err, "secret.GetString")
  279. }
  280. blobJson, err := jsonutils.ParseString(blobStr)
  281. if err != nil {
  282. return curr, errors.Wrap(err, "jsonutils.ParseString")
  283. }
  284. err = blobJson.Unmarshal(&curr)
  285. if err != nil {
  286. return curr, errors.Wrap(err, "blobJson.Unmarshal")
  287. }
  288. curr.KeyId, err = secret.GetString("id")
  289. if err != nil {
  290. return curr, errors.Wrap(err, "secret.GetString('id')")
  291. }
  292. curr.KeyName, err = secret.GetString("name")
  293. if err != nil {
  294. return curr, errors.Wrap(err, "secret.GetString('name')")
  295. }
  296. curr.TimeStamp, err = secret.GetTime("created_at")
  297. if err != nil {
  298. return curr, errors.Wrap(err, "secret.GetTime('created_at')")
  299. }
  300. curr.User, err = secret.GetString("user")
  301. if err != nil {
  302. return curr, errors.Wrap(err, "secret.GetString('user')")
  303. }
  304. curr.UserId, err = secret.GetString("user_id")
  305. if err != nil {
  306. return curr, errors.Wrap(err, "secret.GetString('user_id')")
  307. }
  308. curr.Domain, err = secret.GetString("domain")
  309. if err != nil {
  310. return curr, errors.Wrap(err, "secret.GetString('domain')")
  311. }
  312. curr.DomainId, err = secret.GetString("domain_id")
  313. if err != nil {
  314. return curr, errors.Wrap(err, "secret.GetString('domain_id')")
  315. }
  316. return curr, nil
  317. }
  318. func (manager *SCredentialManager) GetEncryptKeysRpc(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.
  319. JSONObject, error) {
  320. keys, err := manager.GetEncryptKeys(s, "")
  321. if err != nil {
  322. return nil, errors.Wrap(err, "GetEncryptKeys")
  323. }
  324. ret := jsonutils.NewArray()
  325. for _, key := range keys {
  326. ret.Add(key.Marshal())
  327. }
  328. return ret, nil
  329. }
  330. func (manager *SCredentialManager) GetEncryptKeys(s *mcclient.ClientSession, uid string) ([]SEncryptKeySecret, error) {
  331. secrets, err := manager.FetchEncryptionKeys(s, uid)
  332. if err != nil {
  333. return nil, errors.Wrap(err, "FetchAesKeys")
  334. }
  335. aesKeys := make([]SEncryptKeySecret, 0)
  336. for i := range secrets {
  337. curr, err := DecodeEncryptKey(secrets[i])
  338. if err != nil {
  339. return nil, errors.Wrap(err, "DecodeAesKey")
  340. }
  341. aesKeys = append(aesKeys, curr)
  342. }
  343. return aesKeys, nil
  344. }
  345. func (manager *SCredentialManager) DoCreateAccessKeySecret(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  346. key, err := manager.CreateAccessKeySecret(s, "", "", time.Time{})
  347. if err != nil {
  348. return nil, err
  349. }
  350. result := jsonutils.Marshal(key)
  351. result.(*jsonutils.JSONDict).Add(jsonutils.NewString(key.KeyId), "key_id")
  352. return result, nil
  353. }
  354. func (manager *SCredentialManager) CreateAccessKeySecret(s *mcclient.ClientSession, uid string, pid string, expireAt time.Time) (SAccessKeySecret, error) {
  355. aksk := SAccessKeySecret{}
  356. aksk.Secret = base64.URLEncoding.EncodeToString([]byte(seclib.RandomPassword(32)))
  357. if !expireAt.IsZero() {
  358. aksk.Expire = expireAt.Unix()
  359. }
  360. blobJson := jsonutils.Marshal(&aksk)
  361. params := jsonutils.NewDict()
  362. name := fmt.Sprintf("%s-%s-%d", uid, pid, time.Now().Unix())
  363. if len(pid) > 0 {
  364. params.Add(jsonutils.NewString(pid), "project_id")
  365. }
  366. params.Add(jsonutils.NewString(ACCESS_SECRET_TYPE), "type")
  367. if len(uid) > 0 {
  368. params.Add(jsonutils.NewString(uid), "user_id")
  369. }
  370. params.Add(jsonutils.NewString(blobJson.String()), "blob")
  371. params.Add(jsonutils.NewString(name), "name")
  372. result, err := manager.Create(s, params)
  373. if err != nil {
  374. return aksk, err
  375. }
  376. aksk.ProjectId = pid
  377. aksk.TimeStamp, _ = result.GetTime("created_at")
  378. aksk.KeyId, _ = result.GetString("id")
  379. return aksk, nil
  380. }
  381. func (manager *SCredentialManager) DoCreateOidcSecret(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  382. redirectUri, _ := params.GetString("redirect_uri")
  383. key, err := manager.CreateOIDCSecret(s, "", "", redirectUri)
  384. if err != nil {
  385. return nil, errors.Wrap(err, "CreateOIDCSecret")
  386. }
  387. result := jsonutils.Marshal(key)
  388. // result.(*jsonutils.JSONDict).Add(jsonutils.NewString(key.ClientId), "client_id")
  389. return result, nil
  390. }
  391. func isValidRedirectURL(redirectUri string) error {
  392. if len(redirectUri) == 0 {
  393. return errors.Wrap(httperrors.ErrInputParameter, "empty redirect uri")
  394. }
  395. if !strings.HasPrefix(redirectUri, "http://") && !strings.HasPrefix(redirectUri, "https://") {
  396. return errors.Wrap(httperrors.ErrInputParameter, "invalid schema")
  397. }
  398. _, err := url.Parse(redirectUri)
  399. if err != nil {
  400. return errors.Wrapf(httperrors.ErrInputParameter, "invalid redirect_uri %s", redirectUri)
  401. }
  402. return nil
  403. }
  404. func (manager *SCredentialManager) CreateOIDCSecret(s *mcclient.ClientSession, uid string, pid string, redirectUri string) (SOpenIDConnectCredential, error) {
  405. oidcCred := SOpenIDConnectCredential{}
  406. err := isValidRedirectURL(redirectUri)
  407. if err != nil {
  408. return oidcCred, errors.Wrap(err, "isValidRedirectURL")
  409. }
  410. oidcCred.Secret = base64.URLEncoding.EncodeToString([]byte(seclib.RandomPassword(32)))
  411. oidcCred.RedirectUri = redirectUri
  412. blobJson := jsonutils.Marshal(&oidcCred)
  413. params := jsonutils.NewDict()
  414. name := fmt.Sprintf("oidc-%s-%s-%d", uid, pid, time.Now().Unix())
  415. if len(pid) > 0 {
  416. params.Add(jsonutils.NewString(pid), "project_id")
  417. }
  418. params.Add(jsonutils.NewString(OIDC_CREDENTIAL_TYPE), "type")
  419. if len(uid) > 0 {
  420. params.Add(jsonutils.NewString(uid), "user_id")
  421. }
  422. params.Add(jsonutils.NewString(blobJson.String()), "blob")
  423. params.Add(jsonutils.NewString(name), "name")
  424. result, err := manager.Create(s, params)
  425. if err != nil {
  426. return oidcCred, err
  427. }
  428. oidcCred.ClientId, _ = result.GetString("id")
  429. return oidcCred, nil
  430. }
  431. func (manager *SCredentialManager) CreateTotpSecret(s *mcclient.ClientSession, uid string) (string, error) {
  432. _, err := manager.GetTotpSecret(s, uid)
  433. if err == nil {
  434. return "", httperrors.NewConflictError("totp secret exists")
  435. }
  436. totp := STotpSecret{
  437. Totp: seclib.RandomPassword(20),
  438. Timestamp: time.Now().Unix(),
  439. }
  440. blobJson := jsonutils.Marshal(&totp)
  441. params := jsonutils.NewDict()
  442. params.Add(jsonutils.NewString(DEFAULT_PROJECT), "project_id")
  443. params.Add(jsonutils.NewString(TOTP_TYPE), "type")
  444. params.Add(jsonutils.NewString(uid), "user_id")
  445. params.Add(jsonutils.NewString(blobJson.String()), "blob")
  446. _, err = manager.Create(s, params)
  447. if err != nil {
  448. return "", err
  449. }
  450. return totp.Totp, nil
  451. }
  452. func (manager *SCredentialManager) CreateContainerImageSecret(s *mcclient.ClientSession, projectId string, name string, blob *api.CredentialContainerImageBlob) (jsonutils.JSONObject, error) {
  453. blobJson := jsonutils.Marshal(blob)
  454. input := &api.CredentialCreateInput{
  455. Type: api.CONTAINER_IMAGE_TYPE,
  456. ProjectId: projectId,
  457. Blob: blobJson.String(),
  458. }
  459. input.Name = name
  460. obj, err := manager.Create(s, jsonutils.Marshal(input))
  461. if err != nil {
  462. return nil, errors.Wrap(err, "CreateContainerImageSecret")
  463. }
  464. return obj, nil
  465. }
  466. func (manager *SCredentialManager) SaveRecoverySecrets(s *mcclient.ClientSession, uid string, questions []SRecoverySecret) error {
  467. _, err := manager.GetRecoverySecrets(s, uid)
  468. if err == nil {
  469. return httperrors.NewConflictError("totp secret exists")
  470. }
  471. sec := SRecoverySecretSet{
  472. Questions: questions,
  473. Timestamp: time.Now().Unix(),
  474. }
  475. blobJson := jsonutils.Marshal(&sec)
  476. params := jsonutils.NewDict()
  477. params.Add(jsonutils.NewString(DEFAULT_PROJECT), "project_id")
  478. params.Add(jsonutils.NewString(RECOVERY_SECRETS_TYPE), "type")
  479. params.Add(jsonutils.NewString(uid), "user_id")
  480. params.Add(jsonutils.NewString(blobJson.String()), "blob")
  481. _, err = manager.Create(s, params)
  482. if err != nil {
  483. return err
  484. }
  485. return nil
  486. }
  487. func (manager *SCredentialManager) DoCreateEncryptKey(s *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  488. name, _ := params.GetString("name")
  489. alg, _ := params.GetString("alg")
  490. uid, _ := params.GetString("uid")
  491. key, err := manager.CreateEncryptKey(s, uid, name, alg)
  492. if err != nil {
  493. return nil, err
  494. }
  495. result := jsonutils.Marshal(key)
  496. result.(*jsonutils.JSONDict).Add(jsonutils.NewString(key.KeyId), "key_id")
  497. return result, nil
  498. }
  499. func (manager *SCredentialManager) CreateEncryptKey(s *mcclient.ClientSession, uid string, name string, algName string) (SEncryptKeySecret, error) {
  500. aesKey := SEncryptKeySecret{}
  501. alg := seclib2.Alg(seclib2.TSymEncAlg(algName))
  502. rawKey := alg.GenerateKey()
  503. aesKey.Key = base64.StdEncoding.EncodeToString([]byte(rawKey))
  504. aesKey.Alg = alg.Name()
  505. blobJson := jsonutils.Marshal(&aesKey)
  506. params := jsonutils.NewDict()
  507. params.Add(jsonutils.NewString(ENCRYPT_KEY_TYPE), "type")
  508. if len(uid) > 0 {
  509. params.Add(jsonutils.NewString(uid), "user_id")
  510. }
  511. params.Add(jsonutils.NewString(api.DEFAULT_PROJECT), "project_id")
  512. params.Add(jsonutils.NewString(blobJson.String()), "blob")
  513. params.Add(jsonutils.NewString(name), "generate_name")
  514. result, err := manager.Create(s, params)
  515. if err != nil {
  516. return aesKey, errors.Wrap(err, "Create")
  517. }
  518. aesKey.KeyId, _ = result.GetString("id")
  519. aesKey.KeyName, _ = result.GetString("name")
  520. aesKey.TimeStamp, _ = result.GetTime("created_at")
  521. return aesKey, nil
  522. }
  523. func (manager *SCredentialManager) removeCredentials(s *mcclient.ClientSession, secType string, uid string, pid string) error {
  524. secrets, err := manager.fetchCredentials(s, secType, uid, pid)
  525. if err != nil {
  526. return err
  527. }
  528. for i := range secrets {
  529. sid, _ := secrets[i].GetString("id")
  530. if len(sid) > 0 {
  531. _, err := manager.Delete(s, sid, nil)
  532. if err != nil {
  533. return err
  534. }
  535. }
  536. }
  537. return nil
  538. }
  539. func (manager *SCredentialManager) RemoveAccessKeySecrets(s *mcclient.ClientSession, uid string, pid string) error {
  540. return manager.removeCredentials(s, ACCESS_SECRET_TYPE, uid, pid)
  541. }
  542. func (manager *SCredentialManager) RemoveTotpSecrets(s *mcclient.ClientSession, uid string) error {
  543. return manager.removeCredentials(s, TOTP_TYPE, uid, "")
  544. }
  545. func (manager *SCredentialManager) RemoveRecoverySecrets(s *mcclient.ClientSession, uid string) error {
  546. return manager.removeCredentials(s, RECOVERY_SECRETS_TYPE, uid, "")
  547. }
  548. func (manager *SCredentialManager) RemoveOIDCSecrets(s *mcclient.ClientSession, uid string, pid string) error {
  549. return manager.removeCredentials(s, OIDC_CREDENTIAL_TYPE, uid, pid)
  550. }
  551. func (manager *SCredentialManager) RemoveEncryptKeys(s *mcclient.ClientSession, uid string) error {
  552. return manager.removeCredentials(s, ENCRYPT_KEY_TYPE, uid, "")
  553. }
  554. func (manager *SCredentialManager) EncryptKeyEncrypt(s *mcclient.ClientSession, keyId string, secret []byte) ([]byte, error) {
  555. aesKey, err := manager.GetEncryptKey(s, keyId)
  556. if err != nil {
  557. return nil, errors.Wrap(err, "GetEncryptKey")
  558. }
  559. return aesKey.Encrypt(secret)
  560. }
  561. func (manager *SCredentialManager) EncryptKeyDecrypt(s *mcclient.ClientSession, keyId string, secret []byte) ([]byte, error) {
  562. aesKey, err := manager.GetEncryptKey(s, keyId)
  563. if err != nil {
  564. return nil, errors.Wrap(err, "GetEncryptKey")
  565. }
  566. return aesKey.Decrypt(secret)
  567. }
  568. func (manager *SCredentialManager) EncryptKeyEncryptBase64(s *mcclient.ClientSession, keyId string, secret []byte) (string, error) {
  569. aesKey, err := manager.GetEncryptKey(s, keyId)
  570. if err != nil {
  571. return "", errors.Wrap(err, "GetEncryptKey")
  572. }
  573. return aesKey.EncryptBase64(secret)
  574. }
  575. func (manager *SCredentialManager) EncryptKeyDecryptBase64(s *mcclient.ClientSession, keyId string, secret string) ([]byte, error) {
  576. aesKey, err := manager.GetEncryptKey(s, keyId)
  577. if err != nil {
  578. return nil, errors.Wrap(err, "GetEncryptKey")
  579. }
  580. return aesKey.DecryptBase64(secret)
  581. }
  582. func (manager *SCredentialManager) GetEncryptKey(s *mcclient.ClientSession, kid string) (SEncryptKeySecret, error) {
  583. ret := SEncryptKeySecret{}
  584. cred, err := manager.Get(s, kid, nil)
  585. if err != nil {
  586. return ret, errors.Wrap(err, "Get")
  587. }
  588. ret, err = DecodeEncryptKey(cred)
  589. if err != nil {
  590. return ret, errors.Wrap(err, "DecodeAesKey")
  591. }
  592. return ret, nil
  593. }
  594. var (
  595. Credentials SCredentialManager
  596. )
  597. func init() {
  598. Credentials = SCredentialManager{
  599. modules.NewIdentityV3Manager("credential", "credentials",
  600. []string{},
  601. []string{"ID", "Type", "user_id", "project_id", "blob"}),
  602. }
  603. modules.Register(&Credentials)
  604. }