diff --git a/.drone.yml b/.drone.yml index afa0d92..2599920 100644 --- a/.drone.yml +++ b/.drone.yml @@ -60,6 +60,23 @@ steps: exclude: - pull_request +- name: acr + image: plugins/docker + settings: + repo: plugins/kaniko-acr + auto_tag: true + auto_tag_suffix: linux-amd64 + daemon_off: false + dockerfile: docker/acr/Dockerfile.linux.amd64 + username: + from_secret: docker_username + password: + from_secret: docker_password + when: + event: + exclude: + - pull_request + - name: docker-kaniko-v1-8 image: plugins/docker settings: @@ -94,6 +111,7 @@ steps: exclude: - pull_request + - name: ecr-kaniko-v1-8 image: plugins/docker settings: @@ -144,6 +162,18 @@ steps: username: from_secret: docker_username +- name: manifest-acr + pull: always + image: plugins/manifest + settings: + auto_tag: true + ignore_missing: true + password: + from_secret: docker_password + spec: docker/acr/manifest.tmpl + username: + from_secret: docker_username + - name: manifest-ecr pull: always image: plugins/manifest diff --git a/cmd/kaniko-acr/main.go b/cmd/kaniko-acr/main.go new file mode 100644 index 0000000..d3dd09c --- /dev/null +++ b/cmd/kaniko-acr/main.go @@ -0,0 +1,379 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "os" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/urfave/cli" + + kaniko "github.com/drone/drone-kaniko" + "github.com/drone/drone-kaniko/pkg/artifact" + "github.com/drone/drone-kaniko/pkg/docker" +) + +const ( + dockerPath string = "/kaniko/.docker" + clientIdEnv string = "AZURE_CLIENT_ID" + clientSecretKeyEnv string = "AZURE_CLIENT_SECRET" + tenantKeyEnv string = "AZURE_TENANT_ID" + certPathEnv string = "AZURE_CLIENT_CERTIFICATE_PATH" + dockerConfigPath string = "/kaniko/.docker/config.json" + defaultDigestFile string = "/kaniko/digest-file" +) + +var ( + ACRCertPath = "/kaniko/acr-cert.pem" + pluginVersion = "unknown" + username = "00000000-0000-0000-0000-000000000000" +) + +func main() { + // TODO Add the env file functionality + app := cli.NewApp() + app.Name = "kaniko docker plugin" + app.Usage = "kaniko docker plugin" + app.Action = run + app.Version = pluginVersion + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "dockerfile", + Usage: "build dockerfile", + Value: "Dockerfile", + EnvVar: "PLUGIN_DOCKERFILE", + }, + cli.StringFlag{ + Name: "context", + Usage: "build context", + Value: ".", + EnvVar: "PLUGIN_CONTEXT", + }, + cli.StringFlag{ + Name: "drone-commit-ref", + Usage: "git commit ref passed by Drone", + EnvVar: "DRONE_COMMIT_REF", + }, + cli.StringFlag{ + Name: "drone-repo-branch", + Usage: "git repository default branch passed by Drone", + EnvVar: "DRONE_REPO_BRANCH", + }, + cli.StringSliceFlag{ + Name: "tags", + Usage: "build tags", + Value: &cli.StringSlice{"latest"}, + EnvVar: "PLUGIN_TAGS", + FilePath: ".tags", + }, + cli.BoolFlag{ + Name: "expand-tag", + Usage: "enable for semver tagging", + EnvVar: "PLUGIN_EXPAND_TAG", + }, + cli.BoolFlag{ + Name: "auto-tag", + Usage: "enable auto generation of build tags", + EnvVar: "PLUGIN_AUTO_TAG", + }, + cli.StringFlag{ + Name: "auto-tag-suffix", + Usage: "the suffix of auto build tags", + EnvVar: "PLUGIN_AUTO_TAG_SUFFIX", + }, + cli.StringSliceFlag{ + Name: "args", + Usage: "build args", + EnvVar: "PLUGIN_BUILD_ARGS", + }, + cli.StringFlag{ + Name: "target", + Usage: "build target", + EnvVar: "PLUGIN_TARGET", + }, + cli.StringFlag{ + Name: "repo", + Usage: "docker repository", + EnvVar: "PLUGIN_REPO", + }, + cli.BoolFlag{ + Name: "create-repository", + Usage: "create ACR repository", + EnvVar: "PLUGIN_CREATE_REPOSITORY", + }, + cli.StringSliceFlag{ + Name: "custom-labels", + Usage: "additional k=v labels", + EnvVar: "PLUGIN_CUSTOM_LABELS", + }, + cli.StringFlag{ + Name: "registry", + Usage: "ACR registry", + EnvVar: "PLUGIN_REGISTRY", + }, + cli.StringSliceFlag{ + Name: "registry-mirrors", + Usage: "docker registry mirrors", + EnvVar: "PLUGIN_REGISTRY_MIRRORS", + }, + cli.StringFlag{ + Name: "client-secret", + Usage: "Azure client secret", + EnvVar: "CLIENT_SECRET", + }, + cli.StringFlag{ + Name: "client-cert", + Usage: "Azure client certificate", + EnvVar: "CLIENT_CERTIFICATE", + }, + cli.StringFlag{ + Name: "tenant-id", + Usage: "Azure Tenant Id", + EnvVar: "TENANT_ID", + }, + cli.StringFlag{ + Name: "client-id", + Usage: "Azure Client Id", + EnvVar: "CLIENT_ID", + }, + cli.StringFlag{ + Name: "snapshot-mode", + Usage: "Specify one of full, redo or time as snapshot mode", + EnvVar: "PLUGIN_SNAPSHOT_MODE", + }, + cli.StringFlag{ + Name: "lifecycle-policy", + Usage: "Path to lifecycle policy file", + EnvVar: "PLUGIN_LIFECYCLE_POLICY", + }, + cli.StringFlag{ + Name: "repository-policy", + Usage: "Path to repository policy file", + EnvVar: "PLUGIN_REPOSITORY_POLICY", + }, + cli.BoolFlag{ + Name: "enable-cache", + Usage: "Set this flag to opt into caching with kaniko", + EnvVar: "PLUGIN_ENABLE_CACHE", + }, + cli.StringFlag{ + Name: "cache-repo", + Usage: "Remote repository that will be used to store cached layers. Cache repo should be present in specified registry. enable-cache needs to be set to use this flag", + EnvVar: "PLUGIN_CACHE_REPO", + }, + cli.IntFlag{ + Name: "cache-ttl", + Usage: "Cache timeout in hours. Defaults to two weeks.", + EnvVar: "PLUGIN_CACHE_TTL", + }, + cli.StringFlag{ + Name: "artifact-file", + Usage: "Artifact file location that will be generated by the plugin. This file will include information of docker images that are uploaded by the plugin.", + EnvVar: "PLUGIN_ARTIFACT_FILE", + }, + cli.BoolFlag{ + Name: "no-push", + Usage: "Set this flag if you only want to build the image, without pushing to a registry", + EnvVar: "PLUGIN_NO_PUSH", + }, + cli.StringFlag{ + Name: "verbosity", + Usage: "Set this flag with value as oneof to set the logging level for kaniko. Defaults to info.", + EnvVar: "PLUGIN_VERBOSITY", + }, + cli.StringFlag{ + Name: "platform", + Usage: "Allows to build with another default platform than the host, similarly to docker build --platform", + EnvVar: "PLUGIN_PLATFORM", + }, + cli.BoolFlag{ + Name: "skip-unused-stages", + Usage: "build only used stages", + EnvVar: "PLUGIN_SKIP_UNUSED_STAGES", + }, + } + + if err := app.Run(os.Args); err != nil { + logrus.Fatal(err) + } +} + +func run(c *cli.Context) error { + registry := c.String("registry") + noPush := c.Bool("no-push") + + err := createDockerConfig( + c.String("tenant-id"), + c.String("client-id"), + c.String("client-cert"), + c.String("client-secret"), + registry, + noPush, + ) + if err != nil { + return err + } + + plugin := kaniko.Plugin{ + Build: kaniko.Build{ + DroneCommitRef: c.String("drone-commit-ref"), + DroneRepoBranch: c.String("drone-repo-branch"), + Dockerfile: c.String("dockerfile"), + Context: c.String("context"), + Tags: c.StringSlice("tags"), + AutoTag: c.Bool("auto-tag"), + AutoTagSuffix: c.String("auto-tag-suffix"), + ExpandTag: c.Bool("expand-tag"), + Args: c.StringSlice("args"), + Target: c.String("target"), + Repo: c.String("repo"), + Mirrors: c.StringSlice("registry-mirrors"), + Labels: c.StringSlice("custom-labels"), + SnapshotMode: c.String("snapshot-mode"), + EnableCache: c.Bool("enable-cache"), + CacheRepo: fmt.Sprintf("%s/%s", c.String("registry"), c.String("cache-repo")), + CacheTTL: c.Int("cache-ttl"), + DigestFile: defaultDigestFile, + NoPush: noPush, + Verbosity: c.String("verbosity"), + Platform: c.String("platform"), + SkipUnusedStages: c.Bool("skip-unused-stages"), + }, + Artifact: kaniko.Artifact{ + Tags: c.StringSlice("tags"), + Repo: c.String("repo"), + Registry: c.String("registry"), + ArtifactFile: c.String("artifact-file"), + RegistryType: artifact.Docker, + }, + } + return plugin.Exec() +} + +func createDockerConfig(tenantId, clientId, cert, + clientSecret, registry string, noPush bool) error { + if registry == "" { + return fmt.Errorf("registry must be specified") + } + + if noPush { + return nil + } + + // case of client secret or cert based auth + if clientId != "" { + // only setup auth when pushing or credentials are defined + + token, err := getACRToken(tenantId, clientId, clientSecret, cert, registry) + if err != nil { + return errors.Wrap(err, "failed to fetch ACR Token") + } + err = docker.CreateDockerCfgFile(username, token, registry, dockerConfigPath) + if err != nil { + return errors.Wrap(err, "failed to create docker config") + } + } else { + return fmt.Errorf("managed authentication is not supported") + } + + return nil +} + +func getACRToken(tenantId, clientId, clientSecret, cert, registry string) (string, error) { + if tenantId == "" { + return "", fmt.Errorf("tenantId can't be empty for AAD authentication") + } + + if clientId == "" { + return "", fmt.Errorf("clientId can't be empty for AAD authentication") + } + + if clientSecret == "" && cert == "" { + return "", fmt.Errorf("one of client secert or cert should be defined") + } + + // in case of authentication via cert + if cert != "" { + err := setupACRCert(cert) + if err != nil { + errors.Wrap(err, "failed to push setup cert file") + } + } + + // TODO check for presence of file as well. + os.Setenv(clientIdEnv, clientId) + os.Setenv(clientSecretKeyEnv, clientSecret) + os.Setenv(tenantKeyEnv, tenantId) + env, err := azidentity.NewEnvironmentCredential(nil) + if err != nil { + return "", errors.Wrap(err, "failed to get env credentials from azure") + } + + policy := policy.TokenRequestOptions{ + Scopes: []string{"https://management.azure.com/.default"}, + } + os.Unsetenv(clientIdEnv) + os.Unsetenv(clientSecretKeyEnv) + os.Unsetenv(tenantKeyEnv) + os.Unsetenv(certPathEnv) + + azToken, err := env.GetToken(context.Background(), policy) + if err != nil { + return "", errors.Wrap(err, "failed to fetch access token") + } + + ACRToken, err := fetchACRToken(tenantId, azToken.Token, registry) + if err != nil { + return "", errors.Wrap(err, "failed to fetch ACR token") + } + return ACRToken, nil +} + +func fetchACRToken(tenantId, token, registry string) (string, error) { + formData := url.Values{ + "grant_type": {"access_token"}, + "service": {registry}, + "tenant": {tenantId}, + "access_token": {token}, + } + jsonResponse, err := http.PostForm(fmt.Sprintf("https://%s/oauth2/exchange", registry), formData) + if err != nil { + return "", errors.Wrap(err, "failed to fetch ACR token") + } + var response map[string]interface{} + err = json.NewDecoder(jsonResponse.Body).Decode(&response) + if err != nil { + return "", errors.Wrap(err, "failed to decode oauth exchange response") + } + + if x, found := response["refresh_token"]; found { + s, ok := x.(string) + if !ok { + errors.New("failed to cast refresh token from acr") + } else { + return s, nil + } + } else { + return "", errors.Wrap(err, "refresh token not found in response of oauth exchange call") + } + return "", errors.New("failed to get refresh token from acr") +} + +func setupACRCert(jsonKey string) error { + err := ioutil.WriteFile(ACRCertPath, []byte(jsonKey), 0644) + if err != nil { + return errors.Wrap(err, "failed to write ACR certificate") + } + err = os.Setenv(certPathEnv, ACRCertPath) + if err != nil { + return errors.Wrap(err, fmt.Sprintf("failed to set %s environment variable", certPathEnv)) + } + return nil +} diff --git a/docker/acr/Dockerfile.linux.amd64 b/docker/acr/Dockerfile.linux.amd64 new file mode 100644 index 0000000..4d39473 --- /dev/null +++ b/docker/acr/Dockerfile.linux.amd64 @@ -0,0 +1,5 @@ +FROM gcr.io/kaniko-project/executor + +ENV KANIKO_VERSION=1.8.1 +ADD release/linux/amd64/kaniko-acr /kaniko/ +ENTRYPOINT ["/kaniko/kaniko-acr"] diff --git a/docker/acr/Dockerfile.linux.arm64 b/docker/acr/Dockerfile.linux.arm64 new file mode 100644 index 0000000..6abdadc --- /dev/null +++ b/docker/acr/Dockerfile.linux.arm64 @@ -0,0 +1,8 @@ +FROM gcr.io/kaniko-project/executor:arm64-v1.8.1 + +ENV HOME /root +ENV USER root + +ENV KANIKO_VERSION=1.8.1 +ADD release/linux/arm64/kaniko-acr /kaniko/ +ENTRYPOINT ["/kaniko/kaniko-acr"] diff --git a/docker/acr/manifest.tmpl b/docker/acr/manifest.tmpl new file mode 100644 index 0000000..9545579 --- /dev/null +++ b/docker/acr/manifest.tmpl @@ -0,0 +1,13 @@ +image: plugins/kaniko:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}} +{{#if build.tags}} +tags: +{{#each build.tags}} + - {{this}} +{{/each}} +{{/if}} +manifests: + - + image: plugins/kaniko:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64 + platform: + architecture: amd64 + os: linux diff --git a/go.mod b/go.mod index d358923..42b1c7d 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,10 @@ require ( ) require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v0.5.3 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.12.9 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.8 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.14 // indirect @@ -27,9 +31,16 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.11.12 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.16.9 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/google/uuid v1.3.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e // indirect + golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect + golang.org/x/net v0.0.0-20220725212005-46097bf591d3 // indirect + golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/text v0.3.7 // indirect ) go 1.18 diff --git a/go.sum b/go.sum index 3ade02c..832c9ee 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,11 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.1 h1:tz19qLF65vuu2ibfTqGVJxG/zZAI27NEIIbvAOQwYbw= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.1/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/AzureAD/microsoft-authentication-library-for-go v0.5.3 h1:TsFCaaF5tR4XN8b4zLVl/J4qMb0nf80Q4CXcpXDNJDY= +github.com/AzureAD/microsoft-authentication-library-for-go v0.5.3/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aws/aws-sdk-go v1.44.52 h1:kHLbYJj59C7VrsLM4gm7pxsvaNIvhXCCIDYEFFoQ+VE= github.com/aws/aws-sdk-go v1.44.52/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= @@ -35,8 +43,14 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= @@ -45,6 +59,12 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -58,17 +78,27 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220725212005-46097bf591d3 h1:2yWTtPWWRcISTw3/o+s/Y4UOMnQL71DWyToOANFusCg= +golang.org/x/net v0.0.0-20220725212005-46097bf591d3/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e h1:NHvCuwuS43lGnYhten69ZWqi2QOj/CiDNcKbVqwVoew= golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/docker/docker_file.go b/pkg/docker/docker_file.go new file mode 100644 index 0000000..3a252a7 --- /dev/null +++ b/pkg/docker/docker_file.go @@ -0,0 +1,34 @@ +package docker + +import ( + "encoding/base64" + "fmt" + "io/ioutil" + "os" + + "github.com/pkg/errors" +) + +// Create the docker config file for authentication +func CreateDockerCfgFile(username, password, registry, path string) error { + if username == "" { + return fmt.Errorf("Username must be specified") + } + if password == "" { + return fmt.Errorf("Password must be specified") + } + + err := os.MkdirAll(path, 0600) + if err != nil { + return errors.Wrap(err, fmt.Sprintf("failed to create %s directory", path)) + } + + authBytes := []byte(fmt.Sprintf("%s:%s", username, password)) + encodedString := base64.StdEncoding.EncodeToString(authBytes) + jsonBytes := []byte(fmt.Sprintf(`{"auths": {"%s": {"auth": "%s"}}}`, "https://"+registry, encodedString)) + err = ioutil.WriteFile(path, jsonBytes, 0644) + if err != nil { + return errors.Wrap(err, "failed to create docker config file") + } + return nil +} diff --git a/scripts/build.sh b/scripts/build.sh index b850727..c5a6a70 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -11,13 +11,16 @@ set -x # linux GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-gcr ./cmd/kaniko-gcr +GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-acr ./cmd/kaniko-acr GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-ecr ./cmd/kaniko-ecr GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-docker ./cmd/kaniko-docker GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-gcr ./cmd/kaniko-gcr +GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-acr ./cmd/kaniko-acr GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-ecr ./cmd/kaniko-ecr GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-docker ./cmd/kaniko-docker GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-gcr ./cmd/kaniko-gcr +GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-acr ./cmd/kaniko-acr GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-ecr ./cmd/kaniko-ecr GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-docker ./cmd/kaniko-docker