Compare commits

...

6 Commits

Author SHA1 Message Date
ebtasam-faridy 16758bd8cc fix: [CI-20436] adding fallback in case of del con (#164)
* fix: [CI-20436] adding fallback in case of del con

* fix: [CI-20436] adding fallback in case of del con testcase

* fix: [CI-20436] adding fallback in case of del con testcase

* fix: [CI-20436] adding fallback in case of del con testcase

* fix: [CI-20436] adding fallback in case of del con testcase

* fix: [CI-20436] adding fallback in case of del con testcase

* fix: [CI-20436] reverting some changes
2026-02-07 12:55:04 +05:30
Chirag S dd3c29c971 fix: [CI-14073]: Print absolute lookup path incase dockerfile not present (#163) 2026-01-29 14:01:55 +05:30
tapankarangiya c06fde824e fix: [CI-20230]: Updated go version (#160) 2026-01-20 18:03:38 +05:30
tapankarangiya 5bbe6ba026 Update pipeline drone-kaniko-harness (#161) 2026-01-20 13:43:16 +05:30
Abhay 9491e6b36f fix: [CI-19670]: fix vulnerabilty fron kaniko (#159)
* fix: [CI-19670]: fix vulnerabilty fron kaniko

* Update docker/gcr/Dockerfile.linux.amd64

* Update docker/gcr/Dockerfile.linux.arm64

---------

Co-authored-by: OP (oppenheimer) <21008429+Ompragash@users.noreply.github.com>
2025-11-26 11:39:40 +05:30
OP (oppenheimer) 594f1e2f23 fix: Consolidate platform flags to use --custom-platform and eliminate deprecation warning (#158) 2025-11-21 11:25:52 +05:30
13 changed files with 239 additions and 69 deletions
+2 -2
View File
@@ -37,7 +37,7 @@ pipeline:
identifier: Build
spec:
connectorRef: Plugins_Docker_Hub_Connector
image: golang:1.23.0
image: golang:1.24.11
shell: Sh
command: |-
go test ./...
@@ -322,7 +322,7 @@ pipeline:
identifier: Build_and_Test
spec:
connectorRef: Plugins_Docker_Hub_Connector
image: golang:1.23.0
image: golang:1.24.11
shell: Sh
command: |-
go test ./...
+59 -24
View File
@@ -254,7 +254,7 @@ func main() {
cli.StringFlag{
Name: "platform",
Usage: "Allows to build with another default platform than the host, similarly to docker build --platform",
EnvVar: "PLUGIN_PLATFORM",
EnvVar: "PLUGIN_PLATFORM,PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "skip-unused-stages",
@@ -292,11 +292,6 @@ func main() {
Usage: "Sub-path within the context to build.",
EnvVar: "PLUGIN_CONTEXT_SUB_PATH",
},
cli.StringFlag{
Name: "custom-platform",
Usage: "Platform to use for building.",
EnvVar: "PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "force",
Usage: "Force building the image even if it already exists.",
@@ -477,14 +472,13 @@ func run(c *cli.Context) error {
DigestFile: defaultDigestFile,
NoPush: noPush,
Verbosity: c.String("verbosity"),
Platform: c.String("platform"),
CustomPlatform: c.String("platform"),
SkipUnusedStages: c.Bool("skip-unused-stages"),
CacheDir: c.String("cache-dir"),
CacheCopyLayers: c.Bool("cache-copy-layers"),
CacheRunLayers: c.Bool("cache-run-layers"),
Cleanup: c.Bool("cleanup"),
ContextSubPath: c.String("context-sub-path"),
CustomPlatform: c.String("custom-platform"),
Force: c.Bool("force"),
ImageNameWithDigestFile: c.String("image-name-with-digest-file"),
ImageNameTagWithDigestFile: c.String("image-name-tag-with-digest-file"),
@@ -542,21 +536,21 @@ func setupAuth(tenantId, clientId, oidcIdToken, cert,
return "", fmt.Errorf("registry must be specified")
}
// Determine auth path: OIDC or Service Principal (secret/cert)
if tenantId == "" || clientId == "" {
if noPush {
logrus.Warnf("NO_PUSH mode: tenantId or clientId not provided")
return "", nil
}
return "", fmt.Errorf("tenantId and clientId must be provided")
}
var aadAccessToken string
var acrToken string
var publicUrl string
var err error
if oidcIdToken != "" {
// OIDC authentication flow requires tenantId and clientId
if tenantId == "" || clientId == "" {
if noPush {
logrus.Warnf("NO_PUSH mode: tenantId or clientId not provided for OIDC")
return "", nil
}
return "", fmt.Errorf("tenantId and clientId must be provided for OIDC authentication")
}
logrus.Debug("Using OIDC authentication flow")
// Exchange OIDC ID token for AAD access token via client_assertion
aadAccessToken, err = azureutil.GetAADAccessTokenViaClientAssertion(context.Background(), tenantId, clientId, oidcIdToken, authorityHost)
if err != nil {
@@ -571,16 +565,21 @@ func setupAuth(tenantId, clientId, oidcIdToken, cert,
if err != nil {
return handleError(noPush, err, "failed to fetch ACR token")
}
} else if clientSecret != "" || cert != "" {
} else {
logrus.Debug("Using traditional Azure AD authentication flow")
// Validate that if tenantId is provided, clientId must also be provided
// (unless using managed identity with no explicit tenantId)
if tenantId != "" && clientId == "" && clientSecret == "" && cert == "" {
if noPush {
logrus.Warnf("NO_PUSH mode: tenantId provided but clientId is missing")
return "", nil
}
return "", fmt.Errorf("tenantId and clientId must be provided")
}
acrToken, publicUrl, err = getACRToken(subscriptionId, tenantId, clientId, clientSecret, cert, registry)
if err != nil {
return handleError(noPush, err, "failed to fetch ACR Token")
}
} else {
if noPush {
return "", nil
}
return "", fmt.Errorf("managed authentication is not supported")
}
if err := setDockerAuth(username, acrToken, registry, dockerUsername, dockerPassword, dockerRegistry); err != nil {
@@ -599,10 +598,46 @@ func handleError(noPush bool, err error, msg string) (string, error) {
}
func getACRToken(subscriptionId, tenantId, clientId, clientSecret, cert, registry string) (string, string, error) {
// Handle managed identity (when no clientSecret or cert provided)
if clientSecret == "" && cert == "" {
if tenantId == "" {
tenantId = os.Getenv("AZURE_TENANT_ID")
if tenantId == "" {
tenantId = os.Getenv("TENANT_ID")
}
}
opts := &azidentity.DefaultAzureCredentialOptions{}
if tenantId != "" {
opts.TenantID = tenantId
}
cred, err := azidentity.NewDefaultAzureCredential(opts)
if err != nil {
return "", "", errors.Wrap(err, "failed to get credentials")
}
policy := policy.TokenRequestOptions{
Scopes: []string{"https://management.azure.com/.default"},
}
azToken, err := cred.GetToken(context.Background(), policy)
if err != nil {
return "", "", errors.Wrap(err, "failed to fetch access token")
}
publicUrl, err := getPublicUrl(azToken.Token, registry, subscriptionId)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to get public url with error: %s\n", err)
}
if tenantId == "" {
return "", "", fmt.Errorf("tenantId cannot be empty for ACR token exchange")
}
ACRToken, err := fetchACRToken(tenantId, azToken.Token, registry)
if err != nil {
return "", "", errors.Wrap(err, "failed to fetch ACR token")
}
return ACRToken, publicUrl, nil
}
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")
}
+49
View File
@@ -387,3 +387,52 @@ func TestSetupAuth_NoCreds_NoPushTrue(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "", pub)
}
// Test cases for managed identity support
func TestSetupAuth_ManagedIdentity_NoPush_Positive(t *testing.T) {
// Positive test: Managed identity flow with noPush=true should succeed
// This tests the new managed identity support when no credentials are provided
pub, err := setupAuth("tenant123", "", "", "", "", "sub", "myregistry.azurecr.io", "", "", "", "", true)
assert.NoError(t, err)
assert.Equal(t, "", pub)
}
func TestSetupAuth_TenantIdButNoClientId_ManagedIdentity(t *testing.T) {
// Negative test: When tenantId is provided but clientId is missing for managed identity,
// it should fail (unless noPush is true)
pub, err := setupAuth("tenant123", "", "", "", "", "sub", "myregistry.azurecr.io", "", "", "", "", false)
assert.Error(t, err)
assert.Contains(t, err.Error(), "tenantId and clientId must be provided")
assert.Equal(t, "", pub)
}
func TestGetACRToken_ManagedIdentity_NoTenantId(t *testing.T) {
// Negative test: Managed identity requires tenantId for ACR token exchange
// Clear environment variables to ensure tenantId is not available
originalTenantId := os.Getenv("AZURE_TENANT_ID")
originalTenantId2 := os.Getenv("TENANT_ID")
defer func() {
if originalTenantId != "" {
os.Setenv("AZURE_TENANT_ID", originalTenantId)
} else {
os.Unsetenv("AZURE_TENANT_ID")
}
if originalTenantId2 != "" {
os.Setenv("TENANT_ID", originalTenantId2)
} else {
os.Unsetenv("TENANT_ID")
}
}()
os.Unsetenv("AZURE_TENANT_ID")
os.Unsetenv("TENANT_ID")
// Managed identity path without tenantId should fail
// The failure occurs when DefaultAzureCredential tries to acquire a token
// since tenantId is required for ACR token exchange but not available
_, _, err := getACRToken("sub", "", "", "", "", "myregistry.azurecr.io")
assert.Error(t, err)
// The error will be from DefaultAzureCredential failing to acquire a token
// because tenantId is missing and no credentials are available
assert.Contains(t, err.Error(), "failed to fetch access token")
}
+2 -8
View File
@@ -213,7 +213,7 @@ func main() {
cli.StringFlag{
Name: "platform",
Usage: "Allows to build with another default platform than the host, similarly to docker build --platform",
EnvVar: "PLUGIN_PLATFORM",
EnvVar: "PLUGIN_PLATFORM,PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "skip-unused-stages",
@@ -257,11 +257,6 @@ func main() {
Usage: "Sub-path within the context to build.",
EnvVar: "PLUGIN_CONTEXT_SUB_PATH",
},
cli.StringFlag{
Name: "custom-platform",
Usage: "Platform to use for building.",
EnvVar: "PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "force",
Usage: "Force building the image even if it already exists.",
@@ -449,7 +444,7 @@ func run(c *cli.Context) error {
NoPush: noPush,
TarPath: c.String("tar-path"),
Verbosity: c.String("verbosity"),
Platform: c.String("platform"),
CustomPlatform: c.String("platform"),
PushOnly: c.Bool("push-only"),
SkipUnusedStages: c.Bool("skip-unused-stages"),
CacheDir: c.String("cache-dir"),
@@ -457,7 +452,6 @@ func run(c *cli.Context) error {
CacheRunLayers: c.Bool("cache-run-layers"),
Cleanup: c.Bool("cleanup"),
ContextSubPath: c.String("context-sub-path"),
CustomPlatform: c.String("custom-platform"),
Force: c.Bool("force"),
ImageNameWithDigestFile: c.String("image-name-with-digest-file"),
ImageNameTagWithDigestFile: c.String("image-name-tag-with-digest-file"),
+58
View File
@@ -206,6 +206,64 @@ func TestDockerBuildArgsProcessing(t *testing.T) {
}
}
func TestPlatformEnvVarMapping(t *testing.T) {
tests := []struct {
name string
envVar string
envValue string
expectedValue string
}{
{
name: "PLUGIN_PLATFORM env var",
envVar: "PLUGIN_PLATFORM",
envValue: "linux/amd64",
expectedValue: "linux/amd64",
},
{
name: "PLUGIN_CUSTOM_PLATFORM env var",
envVar: "PLUGIN_CUSTOM_PLATFORM",
envValue: "linux/arm64",
expectedValue: "linux/arm64",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Set the environment variable
os.Setenv(tt.envVar, tt.envValue)
defer os.Unsetenv(tt.envVar)
app := cli.NewApp()
app.Name = "kaniko-docker-test"
var capturedPlatform string
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "platform",
Usage: "Allows to build with another default platform than the host",
EnvVar: "PLUGIN_PLATFORM,PLUGIN_CUSTOM_PLATFORM",
},
}
app.Action = func(c *cli.Context) error {
capturedPlatform = c.String("platform")
return nil
}
err := app.Run([]string{"kaniko-docker-test"})
if err != nil {
t.Errorf("CLI run error = %v, want nil", err)
return
}
if capturedPlatform != tt.expectedValue {
t.Errorf("Got platform = %v, want %v", capturedPlatform, tt.expectedValue)
}
})
}
}
func TestCreateDockerConfig(t *testing.T) {
config := docker.NewConfig()
tempDir, err := ioutil.TempDir("", "docker-config-test")
+2 -8
View File
@@ -244,7 +244,7 @@ func main() {
cli.StringFlag{
Name: "platform",
Usage: "Allows to build with another default platform than the host, similarly to docker build --platform",
EnvVar: "PLUGIN_PLATFORM",
EnvVar: "PLUGIN_PLATFORM,PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "skip-unused-stages",
@@ -282,11 +282,6 @@ func main() {
Usage: "Sub-path within the context to build.",
EnvVar: "PLUGIN_CONTEXT_SUB_PATH",
},
cli.StringFlag{
Name: "custom-platform",
Usage: "Platform to use for building.",
EnvVar: "PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "force",
Usage: "Force building the image even if it already exists.",
@@ -518,14 +513,13 @@ func run(c *cli.Context) error {
DigestFile: defaultDigestFile,
NoPush: noPush,
Verbosity: c.String("verbosity"),
Platform: c.String("platform"),
CustomPlatform: c.String("platform"),
SkipUnusedStages: c.Bool("skip-unused-stages"),
CacheDir: c.String("cache-dir"),
CacheCopyLayers: c.Bool("cache-copy-layers"),
CacheRunLayers: c.Bool("cache-run-layers"),
Cleanup: c.Bool("cleanup"),
ContextSubPath: c.String("context-sub-path"),
CustomPlatform: c.String("custom-platform"),
Force: c.Bool("force"),
ImageNameWithDigestFile: c.String("image-name-with-digest-file"),
ImageNameTagWithDigestFile: c.String("image-name-tag-with-digest-file"),
+2 -8
View File
@@ -207,7 +207,7 @@ func main() {
cli.StringFlag{
Name: "platform",
Usage: "Allows to build with another default platform than the host, similarly to docker build --platform",
EnvVar: "PLUGIN_PLATFORM",
EnvVar: "PLUGIN_PLATFORM,PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "skip-unused-stages",
@@ -245,11 +245,6 @@ func main() {
Usage: "Sub-path within the context to build.",
EnvVar: "PLUGIN_CONTEXT_SUB_PATH",
},
cli.StringFlag{
Name: "custom-platform",
Usage: "Platform to use for building.",
EnvVar: "PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "force",
Usage: "Force building the image even if it already exists.",
@@ -430,14 +425,13 @@ func run(c *cli.Context) error {
SourceTarPath: c.String("source-tar-path"),
TarPath: c.String("tar-path"),
Verbosity: c.String("verbosity"),
Platform: c.String("platform"),
CustomPlatform: c.String("platform"),
SkipUnusedStages: c.Bool("skip-unused-stages"),
CacheDir: c.String("cache-dir"),
CacheCopyLayers: c.Bool("cache-copy-layers"),
CacheRunLayers: c.Bool("cache-run-layers"),
Cleanup: c.Bool("cleanup"),
ContextSubPath: c.String("context-sub-path"),
CustomPlatform: c.String("custom-platform"),
Force: c.Bool("force"),
ImageNameWithDigestFile: c.String("image-name-with-digest-file"),
ImageNameTagWithDigestFile: c.String("image-name-tag-with-digest-file"),
+2 -8
View File
@@ -176,7 +176,7 @@ func main() {
cli.StringFlag{
Name: "platform",
Usage: "Allows to build with another default platform than the host, similarly to docker build --platform",
EnvVar: "PLUGIN_PLATFORM",
EnvVar: "PLUGIN_PLATFORM,PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "skip-unused-stages",
@@ -214,11 +214,6 @@ func main() {
Usage: "Sub-path within the context to build.",
EnvVar: "PLUGIN_CONTEXT_SUB_PATH",
},
cli.StringFlag{
Name: "custom-platform",
Usage: "Platform to use for building.",
EnvVar: "PLUGIN_CUSTOM_PLATFORM",
},
cli.BoolFlag{
Name: "force",
Usage: "Force building the image even if it already exists.",
@@ -404,14 +399,13 @@ func run(c *cli.Context) error {
DigestFile: defaultDigestFile,
NoPush: noPush,
Verbosity: c.String("verbosity"),
Platform: c.String("platform"),
CustomPlatform: c.String("platform"),
SkipUnusedStages: c.Bool("skip-unused-stages"),
CacheDir: c.String("cache-dir"),
CacheCopyLayers: c.Bool("cache-copy-layers"),
CacheRunLayers: c.Bool("cache-run-layers"),
Cleanup: c.Bool("cleanup"),
ContextSubPath: c.String("context-sub-path"),
CustomPlatform: c.String("custom-platform"),
Force: c.Bool("force"),
ImageNameWithDigestFile: c.String("image-name-with-digest-file"),
ImageNameTagWithDigestFile: c.String("image-name-tag-with-digest-file"),
+1 -1
View File
@@ -1,4 +1,4 @@
FROM gcr.io/kaniko-project/executor:v1.23.2
FROM harnesscommunity/kaniko-executor:1.25.0-linux-amd64
ENV KANIKO_VERSION=1.23.2
ADD release/linux/amd64/kaniko-gcr /kaniko/
+1 -1
View File
@@ -1,4 +1,4 @@
FROM gcr.io/kaniko-project/executor:v1.23.2
FROM harnesscommunity/kaniko-executor:1.25.0-linux-arm64
ENV HOME /root
ENV USER root
+1 -3
View File
@@ -58,6 +58,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)
go 1.23.0
toolchain go1.23.8
go 1.24.11
+9 -6
View File
@@ -37,7 +37,6 @@ type (
Labels []string // Label map
Mirrors []string // Docker repository mirrors
NoPush bool // Set this flag if you only want to build the image, without pushing to a registry
Platform string // Allows to build with another default platform than the host, similarly to docker build --platform
PushOnly bool // Specify if the operation is push-only.
Repo string // Docker build repository
SkipTlsVerify bool // Docker skip tls certificate verify for registry
@@ -228,7 +227,15 @@ func (p Plugin) Exec() error {
}
if _, err := os.Stat(p.Build.Dockerfile); os.IsNotExist(err) {
return fmt.Errorf("dockerfile does not exist at path: %s", p.Build.Dockerfile)
// Get absolute path for better error message. If path is empty, this will
// return the current working directory, showing where the plugin looked.
absPath, absErr := filepath.Abs(p.Build.Dockerfile)
if absErr != nil {
absPath = p.Build.Dockerfile
}
return fmt.Errorf("dockerfile does not exist at path: %s", absPath)
}
var tags = p.Build.Tags
@@ -311,10 +318,6 @@ func (p Plugin) Exec() error {
cmdArgs = append(cmdArgs, fmt.Sprintf("--verbosity=%s", p.Build.Verbosity))
}
if p.Build.Platform != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--customPlatform=%s", p.Build.Platform))
}
if p.Build.SkipUnusedStages {
cmdArgs = append(cmdArgs, "--skip-unused-stages")
}
+51
View File
@@ -283,6 +283,57 @@ func TestTarPathValidation(t *testing.T) {
}
}
func TestCustomPlatformFlag(t *testing.T) {
tests := []struct {
name string
customPlatform string
expectFlag bool
}{
{
name: "with_custom_platform",
customPlatform: "linux/amd64",
expectFlag: true,
},
{
name: "with_custom_platform_arm",
customPlatform: "linux/arm64",
expectFlag: true,
},
{
name: "empty_custom_platform",
customPlatform: "",
expectFlag: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := Plugin{
Build: Build{
Dockerfile: "Dockerfile",
Context: ".",
Repo: "test/repo",
Tags: []string{"latest"},
CustomPlatform: tt.customPlatform,
NoPush: true, // Don't actually push
},
}
// We can't actually run Exec() without kaniko installed,
// but we can verify the logic by checking the field is set correctly
if tt.expectFlag && p.Build.CustomPlatform == "" {
t.Errorf("Expected CustomPlatform to be set to %q, but got empty string", tt.customPlatform)
}
if !tt.expectFlag && p.Build.CustomPlatform != "" {
t.Errorf("Expected CustomPlatform to be empty, but got %q", p.Build.CustomPlatform)
}
if tt.expectFlag && p.Build.CustomPlatform != tt.customPlatform {
t.Errorf("Expected CustomPlatform to be %q, but got %q", tt.customPlatform, p.Build.CustomPlatform)
}
})
}
}
func TestSourceTarballPush(t *testing.T) {
tests := []struct {
name string