Compare commits

...

3 Commits

Author SHA1 Message Date
ompragash.viswanathan@harness.io 474a6a8d28 Update pipeline drone-kaniko-harness 2025-04-09 19:19:27 +05:30
OP (oppenheimer) 58bd727c07 feat: [CI-16588]: Add support to PLUGIN_TAR_PATH, PLUGIN_SOURCE_TAR_PATH and PLUGIN_PUSH_ONLY to kaniko-ecr (#141)
* Add support for tar-path, source-tar-path and push-only operations

* Updated cmd/kaniko-ecr/main.go

* Updated cmd/kaniko-ecr/main.go

* Update cmd/kaniko-ecr/main.go
2025-03-24 21:31:18 +05:30
ci-reporunner a73b8ee28d Update pipeline drone-kaniko-harness (#142)
Co-authored-by: ompragash.viswanathan@harness.io <ompragash.viswanathan@harness.io>
2025-03-20 19:10:13 +05:30
2 changed files with 130 additions and 28 deletions
+3 -28
View File
@@ -12,32 +12,6 @@ pipeline:
build: <+input>
sparseCheckout: []
stages:
- stage:
name: Manager Approval
identifier: Manager_Approval
description: ""
type: Approval
spec:
execution:
steps:
- step:
name: CI Manager Approval
identifier: CI_Manager_Approval
type: HarnessApproval
timeout: 1d
spec:
approvalMessage: |-
Please review the following information
and approve the pipeline progression
includePipelineExecutionHistory: true
approvers:
minimumCount: 1
disallowPipelineExecutor: false
userGroups:
- CI_Manager
isAutoRejectEnabled: false
approverInputs: []
tags: {}
- parallel:
- stage:
name: linux-amd64
@@ -655,13 +629,13 @@ pipeline:
nodeName: manifest_<+matrix.repo>
- step:
type: Plugin
name: Manifest_kaniko
name: Manifest_kaniko191
identifier: Manifest_kaniko
spec:
connectorRef: Plugins_Docker_Hub_Connector
image: plugins/manifest
settings:
auto_tag: "true"
auto_tag: "false"
spec: docker/<+matrix.repo>/manifest-kaniko1.9.1.tmpl
username: drone
password: <+secrets.getValue("Plugins_Docker_Hub_Pat")>
@@ -679,3 +653,4 @@ pipeline:
nodeName: manifest_<+matrix.repo>
when:
pipelineStatus: Success
allowStageExecutions: true
+127
View File
@@ -14,6 +14,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/ecr"
"github.com/aws/aws-sdk-go-v2/service/ecrpublic"
awsv1 "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/session"
ecrv1 "github.com/aws/aws-sdk-go/service/ecr"
@@ -29,6 +30,8 @@ import (
kaniko "github.com/drone/drone-kaniko"
"github.com/drone/drone-kaniko/pkg/artifact"
"github.com/drone/drone-kaniko/pkg/docker"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/crane"
)
const (
@@ -403,6 +406,21 @@ func main() {
Usage: "OIDC token for assuming role via web identity",
EnvVar: "PLUGIN_OIDC_TOKEN_ID",
},
cli.StringFlag{
Name: "tar-path",
Usage: "Set this flag to save the image as a tarball at path",
EnvVar: "PLUGIN_TAR_PATH, PLUGIN_DESTINATION_TAR_PATH",
},
cli.StringFlag{
Name: "source-tar-path",
Usage: "Set this flag for the source tarball during push operations.",
EnvVar: "PLUGIN_SOURCE_TAR_PATH",
},
cli.BoolFlag{
Name: "push-only",
Usage: "Specify if the operation is push-only",
EnvVar: "PLUGIN_PUSH_ONLY",
},
}
if err := app.Run(os.Args); err != nil {
@@ -415,10 +433,21 @@ func run(c *cli.Context) error {
registry := c.String("registry")
region := c.String("region")
noPush := c.Bool("no-push")
pushOnly := c.Bool("push-only")
assumeRole := c.String("assume-role")
externalId := c.String("external-id")
oidcToken := c.String("oidc-token-id")
// Validate flags
if noPush && pushOnly {
return fmt.Errorf("no-push and push-only flags cannot be used together")
}
// Handle push-only operation
if pushOnly {
return handlePushOnly(c)
}
// setup docker config for azure registry and base image docker registry
err := setDockerAuth(
c.String("docker-registry"),
@@ -521,6 +550,9 @@ func run(c *cli.Context) error {
IgnorePaths: c.StringSlice("ignore-paths"),
ImageFSExtractRetry: c.Int("image-fs-extract-retry"),
ImageDownloadRetry: c.Int("image-download-retry"),
TarPath: c.String("tar-path"),
SourceTarPath: c.String("source-tar-path"),
PushOnly: c.Bool("push-only"),
},
Artifact: kaniko.Artifact{
Tags: c.StringSlice("tags"),
@@ -846,3 +878,98 @@ func getOidcCreds(oidcToken, assumeRole string) (string, string, string, error)
// Return the credentials
return *result.Credentials.AccessKeyId, *result.Credentials.SecretAccessKey, *result.Credentials.SessionToken, nil
}
func createECRSession(region, accessKey, secretKey, sessionToken string) *ecrv1.ECR {
sess := session.Must(session.NewSession(&awsv1.Config{
Region: awsv1.String(region),
Credentials: credentials.NewStaticCredentials(
accessKey,
secretKey,
sessionToken,
),
}))
return ecrv1.New(sess)
}
func handlePushOnly(c *cli.Context) error {
sourceTarPath := c.String("source-tar-path")
if sourceTarPath == "" {
return fmt.Errorf("source_tar_path is required when push_only is set")
}
if _, err := os.Stat(sourceTarPath); os.IsNotExist(err) {
return fmt.Errorf("image tarball does not exist at path: %s", sourceTarPath)
}
repo := c.String("repo")
registry := c.String("registry")
if repo == "" || registry == "" {
return fmt.Errorf("repository and registry must be specified for push-only operation")
}
// Load the image from the tarball
img, err := crane.Load(sourceTarPath)
if err != nil {
return fmt.Errorf("failed to load image from tarball: %v", err)
}
// Get ECR credentials using existing auth methods
var username, password string
var svc *ecrv1.ECR
if oidcToken := c.String("oidc-token-id"); oidcToken != "" && c.String("assume-role") != "" {
accessKey, secretKey, sessionToken, err := getOidcCreds(oidcToken, c.String("assume-role"))
if err != nil {
return fmt.Errorf("failed to get OIDC credentials: %v", err)
}
svc = createECRSession(c.String("region"), accessKey, secretKey, sessionToken)
} else if assumeRole := c.String("assume-role"); assumeRole != "" {
accessKey, secretKey, sessionToken, err := getAssumeRoleCreds(c.String("region"), assumeRole, c.String("external-id"), "")
if err != nil {
return fmt.Errorf("failed to get assume role credentials: %v", err)
}
svc = createECRSession(c.String("region"), accessKey, secretKey, sessionToken)
} else {
// Use direct credentials or IAM role
sess := session.Must(session.NewSession(&awsv1.Config{
Region: awsv1.String(c.String("region")),
Credentials: credentials.NewStaticCredentials(
c.String("access-key"),
c.String("secret-key"),
"",
),
}))
svc = ecrv1.New(sess)
}
// Get ECR auth token using the configured session
username, password, _, err = getAuthInfo(svc)
if err != nil {
return fmt.Errorf("failed to get ECR credentials: %v", err)
}
// Setup crane auth
opts := []crane.Option{
crane.WithAuth(&authn.Basic{
Username: username,
Password: password,
}),
}
// Push for each tag
tags := c.StringSlice("tags")
if len(tags) == 0 {
tags = []string{"latest"}
}
for _, tag := range tags {
dest := fmt.Sprintf("%s/%s:%s", registry, repo, tag)
if err := crane.Push(img, dest, opts...); err != nil {
return fmt.Errorf("failed to push image to %s: %v", dest, err)
}
fmt.Printf("Successfully pushed image to %s\n", dest)
}
return nil
}