terraform-provider-docker/internal/provider/authentication_helpers.go
Martin cf3f8d6457
feat: Implement support for insecure registries (#414)
* feat: Add new tests for insecure registries.

* chore: Refactor code into parseImageOptions and add tests.

* feat: normalizeRegistryAddress supports http addresses.

* feat: keys of authConfigs are now stored without protocol.

* chore: Refactor of docker registry fallback in parseImageOptions.

* refactor: Improve tests and implementation of parseImageOptions

* feat: Implement support for http registries.

* fix: authConfig unit tests now reflect newest structure.

* fix: docker_image_registry data source can pull without authentication.

* fix: Refactor setup of http headers for registry requests.

* docs: Add note about http registries.

* docs: Fix linting error in docs.
2022-07-22 11:19:15 +02:00

64 lines
2.4 KiB
Go

package provider
import (
b64 "encoding/base64"
"log"
"net/http"
"regexp"
"strings"
)
// ECR HTTP authentication needs Bearer token in the Authorization header
// This token is an JWT which was b64 encoded again
// Depending on the aws cli command, the returned token is different
// "aws ecr get-login-password" is a simply JWT, which needs to be prefixed with "AWS:" and then b64 encoded
// "aws ecr get-authorization-token" is the best case, everything is encoded properly
// in case someone passes an base64 decoded token from "aws ecr get-authorization-token" we need to b64 encode it again
func normalizeECRPasswordForHTTPUsage(password string) string {
if strings.HasPrefix(password, "ey") {
return b64.StdEncoding.EncodeToString([]byte("AWS:" + password))
} else if strings.HasPrefix(password, "AWS:") {
return b64.StdEncoding.EncodeToString([]byte(password))
}
return password
}
// Docker operations need a JWT, so this function basically does the opposite as `normalizeECRPasswordForHTTPUsage`
// aws ecr get-authorization-token does not return a JWT, but a base64 encoded string which we need to decode
func normalizeECRPasswordForDockerCLIUsage(password string) string {
if strings.HasPrefix(password, "ey") {
return password
}
if !strings.HasPrefix(password, "AWS:") {
decodedPassword, err := b64.StdEncoding.DecodeString(password)
if err != nil {
log.Fatalf("Error creating registry request: %s", err)
}
return string(decodedPassword)
}
return password[4:]
}
func isECRRepositoryURL(url string) bool {
if url == "public.ecr.aws" {
return true
}
// Regexp is based on the ecr urls shown in https://docs.aws.amazon.com/AmazonECR/latest/userguide/registry_auth.html
var ecrRexp = regexp.MustCompile(`^.*?dkr\.ecr\..*?\.amazonaws\.com$`)
return ecrRexp.MatchString(url)
}
func setupHTTPHeadersForRegistryRequests(req *http.Request, fallback bool) {
// We accept schema v2 manifests and manifest lists, and also OCI types
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.v2+json")
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.list.v2+json")
req.Header.Add("Accept", "application/vnd.oci.image.manifest.v1+json")
req.Header.Add("Accept", "application/vnd.oci.image.index.v1+json")
if fallback {
// Fallback to this header if the registry does not support the v2 manifest like gcr.io
req.Header.Set("Accept", "application/vnd.docker.distribution.manifest.v1+prettyjws")
}
}