Skip to content

Commit

Permalink
feat: support https URLs for digest-file (#2811)
Browse files Browse the repository at this point in the history
This feature allows one to specify an https URL for any of the
digest-file options, resulting in an HTTP PUT to the provided
URL. This could for example be a (pre-signed) URL to S3 or GCS.

Currently the final digest is only written to the local filesystem,
which disappears and is not accessible when Kaniko is run in a
managed container service like AWS ECS.

By supporting https a single implementation supports all storage
services, without the need for special code for S3, GCS, etc..
  • Loading branch information
lionello authored Nov 10, 2023
1 parent 5133ad8 commit e5395c7
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 0 deletions.
12 changes: 12 additions & 0 deletions pkg/executor/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package executor

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -136,6 +137,17 @@ func getDigest(image v1.Image) ([]byte, error) {
}

func writeDigestFile(path string, digestByteArray []byte) error {
if strings.HasPrefix(path, "https://") {
// Do a HTTP PUT to the URL; this could be a pre-signed URL to S3 or GCS or Azure
req, err := http.NewRequest("PUT", path, bytes.NewReader(digestByteArray)) //nolint:noctx
if err != nil {
return err
}
req.Header.Set("Content-Type", "text/plain")
_, err = http.DefaultClient.Do(req)
return err
}

parentDir := filepath.Dir(path)
if _, err := os.Stat(parentDir); os.IsNotExist(err) {
if err := os.MkdirAll(parentDir, 0700); err != nil {
Expand Down
30 changes: 30 additions & 0 deletions pkg/executor/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ package executor
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
Expand Down Expand Up @@ -475,4 +477,32 @@ func TestWriteDigestFile(t *testing.T) {
t.Errorf("expected file to be written successfully, but got error: %v", err)
}
})

t.Run("https PUT OK", func(t *testing.T) {
var uploadedContent []byte

// Start a test server that checks the PUT request.
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPut {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
uploadedContent, _ = io.ReadAll(r.Body)
w.WriteHeader(http.StatusNoContent)
}))
defer server.Close()

// Temporarily replace the default client with the test server client to avoid TLS verification errors.
oldClient := http.DefaultClient
defer func() { http.DefaultClient = oldClient }()
http.DefaultClient = server.Client()

err := writeDigestFile(server.URL+"/df?sig=1234", []byte("test"))
if err != nil {
t.Fatalf("expected file to be written successfully, but got error: %v", err)
}
if string(uploadedContent) != "test" {
t.Errorf("expected uploaded content to be 'test', but got '%s'", uploadedContent)
}
})
}

0 comments on commit e5395c7

Please sign in to comment.