registry.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. package registry
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "encoding/json"
  6. "fmt"
  7. "net/http"
  8. "net/url"
  9. "strings"
  10. "time"
  11. "github.com/aws/aws-sdk-go/service/ecr"
  12. "github.com/porter-dev/porter/internal/models"
  13. "github.com/porter-dev/porter/internal/oauth"
  14. "github.com/porter-dev/porter/internal/repository"
  15. "golang.org/x/oauth2"
  16. ints "github.com/porter-dev/porter/internal/models/integrations"
  17. "github.com/digitalocean/godo"
  18. "github.com/docker/cli/cli/config/configfile"
  19. "github.com/docker/cli/cli/config/types"
  20. )
  21. // Registry wraps the gorm Registry model
  22. type Registry models.Registry
  23. // Repository is a collection of images
  24. type Repository struct {
  25. // Name of the repository
  26. Name string `json:"name"`
  27. // When the repository was created
  28. CreatedAt time.Time `json:"created_at,omitempty"`
  29. // The URI of the repository
  30. URI string `json:"uri"`
  31. }
  32. // Image is a Docker image type
  33. type Image struct {
  34. // The sha256 digest of the image manifest.
  35. Digest string `json:"digest"`
  36. // The tag used for the image.
  37. Tag string `json:"tag"`
  38. // The image manifest associated with the image.
  39. Manifest string `json:"manifest"`
  40. // The name of the repository associated with the image.
  41. RepositoryName string `json:"repository_name"`
  42. }
  43. // ListRepositories lists the repositories for a registry
  44. func (r *Registry) ListRepositories(
  45. repo repository.Repository,
  46. doAuth *oauth2.Config, // only required if using DOCR
  47. ) ([]*Repository, error) {
  48. // switch on the auth mechanism to get a token
  49. if r.AWSIntegrationID != 0 {
  50. return r.listECRRepositories(repo)
  51. }
  52. if r.GCPIntegrationID != 0 {
  53. return r.listGCRRepositories(repo)
  54. }
  55. if r.DOIntegrationID != 0 {
  56. return r.listDOCRRepositories(repo, doAuth)
  57. }
  58. if r.BasicIntegrationID != 0 {
  59. return r.listPrivateRegistryRepositories(repo)
  60. }
  61. return nil, fmt.Errorf("error listing repositories")
  62. }
  63. type gcrJWT struct {
  64. AccessToken string `json:"token"`
  65. ExpiresInSec int `json:"expires_in"`
  66. }
  67. type gcrRepositoryResp struct {
  68. Repositories []string `json:"repositories"`
  69. }
  70. func (r *Registry) GetGCRToken(repo repository.Repository) (*ints.TokenCache, error) {
  71. gcp, err := repo.GCPIntegration.ReadGCPIntegration(
  72. r.GCPIntegrationID,
  73. )
  74. if err != nil {
  75. return nil, err
  76. }
  77. // get oauth2 access token
  78. _, err = gcp.GetBearerToken(
  79. r.getTokenCache,
  80. r.setTokenCacheFunc(repo),
  81. "https://www.googleapis.com/auth/devstorage.read_write",
  82. )
  83. if err != nil {
  84. return nil, err
  85. }
  86. // it's now written to the token cache, so return
  87. cache, err := r.getTokenCache()
  88. if err != nil {
  89. return nil, err
  90. }
  91. return cache, nil
  92. }
  93. func (r *Registry) listGCRRepositories(
  94. repo repository.Repository,
  95. ) ([]*Repository, error) {
  96. gcp, err := repo.GCPIntegration.ReadGCPIntegration(
  97. r.GCPIntegrationID,
  98. )
  99. if err != nil {
  100. return nil, err
  101. }
  102. // Just use service account key to authenticate, since scopes may not be in place
  103. // for oauth. This also prevents us from making more requests.
  104. client := &http.Client{}
  105. req, err := http.NewRequest(
  106. "GET",
  107. "https://gcr.io/v2/_catalog",
  108. nil,
  109. )
  110. if err != nil {
  111. return nil, err
  112. }
  113. req.SetBasicAuth("_json_key", string(gcp.GCPKeyData))
  114. resp, err := client.Do(req)
  115. if err != nil {
  116. return nil, err
  117. }
  118. gcrResp := gcrRepositoryResp{}
  119. if err := json.NewDecoder(resp.Body).Decode(&gcrResp); err != nil {
  120. return nil, fmt.Errorf("Could not read GCR repositories: %v", err)
  121. }
  122. res := make([]*Repository, 0)
  123. parsedURL, err := url.Parse("https://" + r.URL)
  124. if err != nil {
  125. return nil, err
  126. }
  127. for _, repo := range gcrResp.Repositories {
  128. res = append(res, &Repository{
  129. Name: repo,
  130. URI: parsedURL.Host + "/" + repo,
  131. })
  132. }
  133. return res, nil
  134. }
  135. func (r *Registry) listECRRepositories(repo repository.Repository) ([]*Repository, error) {
  136. aws, err := repo.AWSIntegration.ReadAWSIntegration(
  137. r.AWSIntegrationID,
  138. )
  139. if err != nil {
  140. return nil, err
  141. }
  142. sess, err := aws.GetSession()
  143. if err != nil {
  144. return nil, err
  145. }
  146. svc := ecr.New(sess)
  147. resp, err := svc.DescribeRepositories(&ecr.DescribeRepositoriesInput{})
  148. if err != nil {
  149. return nil, err
  150. }
  151. res := make([]*Repository, 0)
  152. for _, repo := range resp.Repositories {
  153. res = append(res, &Repository{
  154. Name: *repo.RepositoryName,
  155. CreatedAt: *repo.CreatedAt,
  156. URI: *repo.RepositoryUri,
  157. })
  158. }
  159. return res, nil
  160. }
  161. func (r *Registry) listDOCRRepositories(
  162. repo repository.Repository,
  163. doAuth *oauth2.Config,
  164. ) ([]*Repository, error) {
  165. oauthInt, err := repo.OAuthIntegration.ReadOAuthIntegration(
  166. r.DOIntegrationID,
  167. )
  168. if err != nil {
  169. return nil, err
  170. }
  171. tok, _, err := oauth.GetAccessToken(oauthInt, doAuth, repo)
  172. if err != nil {
  173. return nil, err
  174. }
  175. client := godo.NewFromToken(tok)
  176. urlArr := strings.Split(r.URL, "/")
  177. if len(urlArr) != 2 {
  178. return nil, fmt.Errorf("invalid digital ocean registry url")
  179. }
  180. name := urlArr[1]
  181. repos, _, err := client.Registry.ListRepositories(context.TODO(), name, &godo.ListOptions{})
  182. if err != nil {
  183. return nil, err
  184. }
  185. res := make([]*Repository, 0)
  186. for _, repo := range repos {
  187. res = append(res, &Repository{
  188. Name: repo.Name,
  189. URI: r.URL + "/" + repo.Name,
  190. })
  191. }
  192. return res, nil
  193. }
  194. func (r *Registry) listPrivateRegistryRepositories(
  195. repo repository.Repository,
  196. ) ([]*Repository, error) {
  197. // handle dockerhub different, as it doesn't implement the docker registry http api
  198. if strings.Contains(r.URL, "docker.io") {
  199. // in this case, we just return the single dockerhub repository that's linked
  200. res := make([]*Repository, 0)
  201. res = append(res, &Repository{
  202. Name: strings.Split(r.URL, "docker.io/")[1],
  203. URI: r.URL,
  204. })
  205. return res, nil
  206. }
  207. basic, err := repo.BasicIntegration.ReadBasicIntegration(
  208. r.BasicIntegrationID,
  209. )
  210. if err != nil {
  211. return nil, err
  212. }
  213. // Just use service account key to authenticate, since scopes may not be in place
  214. // for oauth. This also prevents us from making more requests.
  215. client := &http.Client{}
  216. // get the host and scheme to make the request
  217. parsedURL, err := url.Parse(r.URL)
  218. req, err := http.NewRequest(
  219. "GET",
  220. fmt.Sprintf("%s://%s/v2/_catalog", parsedURL.Scheme, parsedURL.Host),
  221. nil,
  222. )
  223. if err != nil {
  224. return nil, err
  225. }
  226. req.SetBasicAuth(string(basic.Username), string(basic.Password))
  227. resp, err := client.Do(req)
  228. if err != nil {
  229. return nil, err
  230. }
  231. // if the status code is 404, fallback to the Docker Hub implementation
  232. if resp.StatusCode == 404 {
  233. req, err := http.NewRequest(
  234. "GET",
  235. fmt.Sprintf("%s/", r.URL),
  236. nil,
  237. )
  238. if err != nil {
  239. return nil, err
  240. }
  241. req.SetBasicAuth(string(basic.Username), string(basic.Password))
  242. resp, err = client.Do(req)
  243. if err != nil {
  244. return nil, err
  245. }
  246. }
  247. gcrResp := gcrRepositoryResp{}
  248. if err := json.NewDecoder(resp.Body).Decode(&gcrResp); err != nil {
  249. return nil, fmt.Errorf("Could not read private registry repositories: %v", err)
  250. }
  251. res := make([]*Repository, 0)
  252. if err != nil {
  253. return nil, err
  254. }
  255. for _, repo := range gcrResp.Repositories {
  256. res = append(res, &Repository{
  257. Name: repo,
  258. URI: parsedURL.Host + "/" + repo,
  259. })
  260. }
  261. return res, nil
  262. }
  263. func (r *Registry) getTokenCache() (tok *ints.TokenCache, err error) {
  264. return &ints.TokenCache{
  265. Token: r.TokenCache.Token,
  266. Expiry: r.TokenCache.Expiry,
  267. }, nil
  268. }
  269. func (r *Registry) setTokenCacheFunc(
  270. repo repository.Repository,
  271. ) ints.SetTokenCacheFunc {
  272. return func(token string, expiry time.Time) error {
  273. _, err := repo.Registry.UpdateRegistryTokenCache(
  274. &ints.RegTokenCache{
  275. TokenCache: ints.TokenCache{
  276. Token: []byte(token),
  277. Expiry: expiry,
  278. },
  279. RegistryID: r.ID,
  280. },
  281. )
  282. return err
  283. }
  284. }
  285. // CreateRepository creates a repository for a registry, if needed
  286. // (currently only required for ECR)
  287. func (r *Registry) CreateRepository(
  288. repo repository.Repository,
  289. name string,
  290. ) error {
  291. // if aws, create repository
  292. if r.AWSIntegrationID != 0 {
  293. return r.createECRRepository(repo, name)
  294. }
  295. // otherwise, no-op
  296. return nil
  297. }
  298. func (r *Registry) createECRRepository(
  299. repo repository.Repository,
  300. name string,
  301. ) error {
  302. aws, err := repo.AWSIntegration.ReadAWSIntegration(
  303. r.AWSIntegrationID,
  304. )
  305. if err != nil {
  306. return err
  307. }
  308. sess, err := aws.GetSession()
  309. if err != nil {
  310. return err
  311. }
  312. svc := ecr.New(sess)
  313. _, err = svc.CreateRepository(&ecr.CreateRepositoryInput{
  314. RepositoryName: &name,
  315. })
  316. return err
  317. }
  318. // ListImages lists the images for an image repository
  319. func (r *Registry) ListImages(
  320. repoName string,
  321. repo repository.Repository,
  322. doAuth *oauth2.Config, // only required if using DOCR
  323. ) ([]*Image, error) {
  324. // switch on the auth mechanism to get a token
  325. if r.AWSIntegrationID != 0 {
  326. return r.listECRImages(repoName, repo)
  327. }
  328. if r.GCPIntegrationID != 0 {
  329. return r.listGCRImages(repoName, repo)
  330. }
  331. if r.DOIntegrationID != 0 {
  332. return r.listDOCRImages(repoName, repo, doAuth)
  333. }
  334. if r.BasicIntegrationID != 0 {
  335. return r.listPrivateRegistryImages(repoName, repo)
  336. }
  337. return nil, fmt.Errorf("error listing images")
  338. }
  339. func (r *Registry) listECRImages(repoName string, repo repository.Repository) ([]*Image, error) {
  340. aws, err := repo.AWSIntegration.ReadAWSIntegration(
  341. r.AWSIntegrationID,
  342. )
  343. if err != nil {
  344. return nil, err
  345. }
  346. sess, err := aws.GetSession()
  347. if err != nil {
  348. return nil, err
  349. }
  350. svc := ecr.New(sess)
  351. resp, err := svc.ListImages(&ecr.ListImagesInput{
  352. RepositoryName: &repoName,
  353. })
  354. if err != nil {
  355. return nil, err
  356. }
  357. res := make([]*Image, 0)
  358. for _, img := range resp.ImageIds {
  359. res = append(res, &Image{
  360. Digest: *img.ImageDigest,
  361. Tag: *img.ImageTag,
  362. RepositoryName: repoName,
  363. })
  364. }
  365. return res, nil
  366. }
  367. type gcrImageResp struct {
  368. Tags []string `json:"tags"`
  369. }
  370. func (r *Registry) listGCRImages(repoName string, repo repository.Repository) ([]*Image, error) {
  371. gcp, err := repo.GCPIntegration.ReadGCPIntegration(
  372. r.GCPIntegrationID,
  373. )
  374. if err != nil {
  375. return nil, err
  376. }
  377. // use JWT token to request catalog
  378. client := &http.Client{}
  379. parsedURL, err := url.Parse("https://" + r.URL)
  380. if err != nil {
  381. return nil, err
  382. }
  383. trimmedPath := strings.Trim(parsedURL.Path, "/")
  384. req, err := http.NewRequest(
  385. "GET",
  386. fmt.Sprintf("https://%s/v2/%s/%s/tags/list", parsedURL.Host, trimmedPath, repoName),
  387. nil,
  388. )
  389. if err != nil {
  390. return nil, err
  391. }
  392. req.SetBasicAuth("_json_key", string(gcp.GCPKeyData))
  393. resp, err := client.Do(req)
  394. if err != nil {
  395. return nil, err
  396. }
  397. gcrResp := gcrImageResp{}
  398. if err := json.NewDecoder(resp.Body).Decode(&gcrResp); err != nil {
  399. return nil, fmt.Errorf("Could not read GCR repositories: %v", err)
  400. }
  401. res := make([]*Image, 0)
  402. for _, tag := range gcrResp.Tags {
  403. res = append(res, &Image{
  404. RepositoryName: repoName,
  405. Tag: tag,
  406. })
  407. }
  408. return res, nil
  409. }
  410. func (r *Registry) listDOCRImages(
  411. repoName string,
  412. repo repository.Repository,
  413. doAuth *oauth2.Config,
  414. ) ([]*Image, error) {
  415. oauthInt, err := repo.OAuthIntegration.ReadOAuthIntegration(
  416. r.DOIntegrationID,
  417. )
  418. if err != nil {
  419. return nil, err
  420. }
  421. tok, _, err := oauth.GetAccessToken(oauthInt, doAuth, repo)
  422. if err != nil {
  423. return nil, err
  424. }
  425. client := godo.NewFromToken(tok)
  426. urlArr := strings.Split(r.URL, "/")
  427. if len(urlArr) != 2 {
  428. return nil, fmt.Errorf("invalid digital ocean registry url")
  429. }
  430. name := urlArr[1]
  431. tags, _, err := client.Registry.ListRepositoryTags(context.TODO(), name, repoName, &godo.ListOptions{})
  432. if err != nil {
  433. return nil, err
  434. }
  435. res := make([]*Image, 0)
  436. for _, tag := range tags {
  437. res = append(res, &Image{
  438. RepositoryName: repoName,
  439. Tag: tag.Tag,
  440. })
  441. }
  442. return res, nil
  443. }
  444. func (r *Registry) listPrivateRegistryImages(repoName string, repo repository.Repository) ([]*Image, error) {
  445. // handle dockerhub different, as it doesn't implement the docker registry http api
  446. if strings.Contains(r.URL, "docker.io") {
  447. return r.listDockerHubImages(repoName, repo)
  448. }
  449. basic, err := repo.BasicIntegration.ReadBasicIntegration(
  450. r.BasicIntegrationID,
  451. )
  452. if err != nil {
  453. return nil, err
  454. }
  455. // Just use service account key to authenticate, since scopes may not be in place
  456. // for oauth. This also prevents us from making more requests.
  457. client := &http.Client{}
  458. // get the host and scheme to make the request
  459. parsedURL, err := url.Parse(r.URL)
  460. req, err := http.NewRequest(
  461. "GET",
  462. fmt.Sprintf("%s://%s/v2/%s/tags/list", parsedURL.Scheme, parsedURL.Host, repoName),
  463. nil,
  464. )
  465. if err != nil {
  466. return nil, err
  467. }
  468. req.SetBasicAuth(string(basic.Username), string(basic.Password))
  469. resp, err := client.Do(req)
  470. if err != nil {
  471. return nil, err
  472. }
  473. gcrResp := gcrImageResp{}
  474. if err := json.NewDecoder(resp.Body).Decode(&gcrResp); err != nil {
  475. return nil, fmt.Errorf("Could not read private registry repositories: %v", err)
  476. }
  477. res := make([]*Image, 0)
  478. for _, tag := range gcrResp.Tags {
  479. res = append(res, &Image{
  480. RepositoryName: repoName,
  481. Tag: tag,
  482. })
  483. }
  484. return res, nil
  485. }
  486. type dockerHubImageResult struct {
  487. Name string `json:"name"`
  488. }
  489. type dockerHubImageResp struct {
  490. Results []dockerHubImageResult `json:"results"`
  491. }
  492. func (r *Registry) listDockerHubImages(repoName string, repo repository.Repository) ([]*Image, error) {
  493. basic, err := repo.BasicIntegration.ReadBasicIntegration(
  494. r.BasicIntegrationID,
  495. )
  496. if err != nil {
  497. return nil, err
  498. }
  499. client := &http.Client{}
  500. req, err := http.NewRequest(
  501. "GET",
  502. fmt.Sprintf("https://hub.docker.com/v2/repositories/%s/tags", strings.Split(r.URL, "docker.io/")[1]),
  503. nil,
  504. )
  505. if err != nil {
  506. return nil, err
  507. }
  508. req.SetBasicAuth(string(basic.Username), string(basic.Password))
  509. resp, err := client.Do(req)
  510. if err != nil {
  511. return nil, err
  512. }
  513. imageResp := dockerHubImageResp{}
  514. if err := json.NewDecoder(resp.Body).Decode(&imageResp); err != nil {
  515. return nil, fmt.Errorf("Could not read private registry repositories: %v", err)
  516. }
  517. res := make([]*Image, 0)
  518. for _, result := range imageResp.Results {
  519. res = append(res, &Image{
  520. RepositoryName: repoName,
  521. Tag: result.Name,
  522. })
  523. }
  524. return res, nil
  525. }
  526. // GetDockerConfigJSON returns a dockerconfigjson file contents with "auths"
  527. // populated.
  528. func (r *Registry) GetDockerConfigJSON(
  529. repo repository.Repository,
  530. doAuth *oauth2.Config, // only required if using DOCR
  531. ) ([]byte, error) {
  532. var conf *configfile.ConfigFile
  533. var err error
  534. // switch on the auth mechanism to get a token
  535. if r.AWSIntegrationID != 0 {
  536. conf, err = r.getECRDockerConfigFile(repo)
  537. }
  538. if r.GCPIntegrationID != 0 {
  539. conf, err = r.getGCRDockerConfigFile(repo)
  540. }
  541. if r.DOIntegrationID != 0 {
  542. conf, err = r.getDOCRDockerConfigFile(repo, doAuth)
  543. }
  544. if r.BasicIntegrationID != 0 {
  545. conf, err = r.getPrivateRegistryDockerConfigFile(repo)
  546. }
  547. if err != nil {
  548. return nil, err
  549. }
  550. return json.Marshal(conf)
  551. }
  552. func (r *Registry) getECRDockerConfigFile(
  553. repo repository.Repository,
  554. ) (*configfile.ConfigFile, error) {
  555. aws, err := repo.AWSIntegration.ReadAWSIntegration(
  556. r.AWSIntegrationID,
  557. )
  558. if err != nil {
  559. return nil, err
  560. }
  561. sess, err := aws.GetSession()
  562. if err != nil {
  563. return nil, err
  564. }
  565. ecrSvc := ecr.New(sess)
  566. output, err := ecrSvc.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{})
  567. if err != nil {
  568. return nil, err
  569. }
  570. token := *output.AuthorizationData[0].AuthorizationToken
  571. decodedToken, err := base64.StdEncoding.DecodeString(token)
  572. if err != nil {
  573. return nil, err
  574. }
  575. parts := strings.SplitN(string(decodedToken), ":", 2)
  576. if len(parts) < 2 {
  577. return nil, err
  578. }
  579. key := r.URL
  580. if !strings.Contains(key, "http") {
  581. key = "https://" + key
  582. }
  583. return &configfile.ConfigFile{
  584. AuthConfigs: map[string]types.AuthConfig{
  585. key: types.AuthConfig{
  586. Username: parts[0],
  587. Password: parts[1],
  588. Auth: token,
  589. },
  590. },
  591. }, nil
  592. }
  593. func (r *Registry) getGCRDockerConfigFile(
  594. repo repository.Repository,
  595. ) (*configfile.ConfigFile, error) {
  596. gcp, err := repo.GCPIntegration.ReadGCPIntegration(
  597. r.GCPIntegrationID,
  598. )
  599. if err != nil {
  600. return nil, err
  601. }
  602. key := r.URL
  603. if !strings.Contains(key, "http") {
  604. key = "https://" + key
  605. }
  606. parsedURL, _ := url.Parse(key)
  607. return &configfile.ConfigFile{
  608. AuthConfigs: map[string]types.AuthConfig{
  609. parsedURL.Host: types.AuthConfig{
  610. Username: "_json_key",
  611. Password: string(gcp.GCPKeyData),
  612. Auth: generateAuthToken("_json_key", string(gcp.GCPKeyData)),
  613. },
  614. },
  615. }, nil
  616. }
  617. func (r *Registry) getDOCRDockerConfigFile(
  618. repo repository.Repository,
  619. doAuth *oauth2.Config,
  620. ) (*configfile.ConfigFile, error) {
  621. oauthInt, err := repo.OAuthIntegration.ReadOAuthIntegration(
  622. r.DOIntegrationID,
  623. )
  624. if err != nil {
  625. return nil, err
  626. }
  627. tok, _, err := oauth.GetAccessToken(oauthInt, doAuth, repo)
  628. if err != nil {
  629. return nil, err
  630. }
  631. key := r.URL
  632. if !strings.Contains(key, "http") {
  633. key = "https://" + key
  634. }
  635. parsedURL, _ := url.Parse(key)
  636. return &configfile.ConfigFile{
  637. AuthConfigs: map[string]types.AuthConfig{
  638. parsedURL.Host: types.AuthConfig{
  639. Username: tok,
  640. Password: tok,
  641. Auth: generateAuthToken(tok, tok),
  642. },
  643. },
  644. }, nil
  645. }
  646. func (r *Registry) getPrivateRegistryDockerConfigFile(
  647. repo repository.Repository,
  648. ) (*configfile.ConfigFile, error) {
  649. basic, err := repo.BasicIntegration.ReadBasicIntegration(
  650. r.BasicIntegrationID,
  651. )
  652. if err != nil {
  653. return nil, err
  654. }
  655. key := r.URL
  656. if !strings.Contains(key, "http") {
  657. key = "https://" + key
  658. }
  659. parsedURL, _ := url.Parse(key)
  660. authConfigKey := parsedURL.Host
  661. if strings.Contains(r.URL, "index.docker.io") {
  662. authConfigKey = "https://index.docker.io/v1/"
  663. }
  664. return &configfile.ConfigFile{
  665. AuthConfigs: map[string]types.AuthConfig{
  666. authConfigKey: types.AuthConfig{
  667. Username: string(basic.Username),
  668. Password: string(basic.Password),
  669. Auth: generateAuthToken(string(basic.Username), string(basic.Password)),
  670. },
  671. },
  672. }, nil
  673. }
  674. func generateAuthToken(username, password string) string {
  675. return base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
  676. }