Skip to content

Commit

Permalink
chore: Replace with in unzipper on non-Windows platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
m8rmclaren committed Oct 6, 2023
1 parent 2aec4d7 commit 987b45e
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 13 deletions.
157 changes: 157 additions & 0 deletions .github/workflows/container.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Build and Release
on:
push:
branches:
- '*'
pull_request:
branches:
- 'v*'
types:
# action should run when the pull request is closed
# (regardless of whether it was merged or just closed)
- closed
# Make sure the action runs every time new commits are
# pushed to the pull request's branch
- synchronize

env:
REGISTRY: ghcr.io

jobs:
build:
name: Build Containers
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/arm64
- linux/amd64
- linux/s390x
- linux/ppc64le
- linux/386

permissions:
contents: read
packages: write

steps:

- name: Set IMAGE_NAME
run: |
echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
# Checkout code
# https://github.com/actions/checkout
- name: Checkout code
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0

# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

# Set up QEMU
# https://github.com/docker/setup-qemu-action
- name: Set up QEMU
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0

# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0

# Login to Docker registry
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Build and push Docker image with Buildx
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: .
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
push: ${{ github.event.pull_request.merged == true }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true

# Export digest
- name: Export digest
if: github.event.pull_request.merged == true
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
# Upload digest
- name: Upload digest
if: github.event.pull_request.merged == true
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: digests
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1

merge:
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true
needs:
- build
steps:
- name: Set IMAGE_NAME
run: |
echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
# Download digests
# https://github.com/actions/download-artifact
- name: Download digests
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
name: digests
path: /tmp/digests

# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0

# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

# Login to Docker registry
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Create manifest list and push
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ COPY pkg/ pkg/

# Build
# the GOARCH has a default value to allow the binary be built according to the host where the command
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
# was called. For example, if we build in a local env which has the Apple Silicon M1 chip,
# the docker BUILDPLATFORM arg will be linux/arm64, but for Apple x86 it will be linux/amd64. Therefore,
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o kfutil main.go
Expand All @@ -28,8 +28,8 @@ WORKDIR /
COPY --from=builder /workspace/kfutil /usr/local/bin/kfutil

# Install ca-certificates so that HTTPS works consistently
RUN apt update
RUN apt install ca-certificates -y
RUN apt-get update
RUN apt-get install ca-certificates -y

# Spin forever so that the container doesn't exit and the user can exec into it
ENTRYPOINT ["tail", "-f", "/dev/null"]
2 changes: 1 addition & 1 deletion cmd/orchs_ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (f *OrchsExtFlags) AddFlags(flags *pflag.FlagSet) {
flags.StringVarP(f.GithubToken, "token", "t", *f.GithubToken, "Token used for related authentication - required for private repositories")
flags.StringVarP(f.GithubOrg, "org", "", *f.GithubOrg, "Github organization to download extensions from. Default is keyfactor.")
flags.StringVarP(f.OutDir, "out", "o", *f.OutDir, "Path to the extensions directory to download extensions into. Default is ./extensions")
flags.StringSliceVarP(f.Extensions, "extensions", "e", *f.Extensions, "List of extensions to download. Should be in the format <extension name>:<version>. If no version is specified, the latest official version will be downloaded.")
flags.StringSliceVarP(f.Extensions, "extension", "e", *f.Extensions, "List of extensions to download. Should be in the format <extension name>@<version>. If no version is specified, the latest official version will be downloaded.")
flags.BoolVarP(f.AutoConfirm, "confirm", "y", *f.AutoConfirm, "Automatically confirm the download of extensions")
flags.BoolVarP(f.Upgrade, "update", "u", *f.Upgrade, "Update existing extensions if they are out of date.")
flags.BoolVarP(f.Prune, "prune", "P", *f.Prune, "Remove extensions from the extensions directory that are not in the extension configuration file or specified on the command line")
Expand Down
34 changes: 25 additions & 9 deletions pkg/cmdutil/extensions/extension_installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"log"
"os"
"path/filepath"
"runtime"
"sort"
"strings"
)
Expand Down Expand Up @@ -510,13 +509,22 @@ func (b *ExtensionInstaller) unzip(zipFilePath, destinationDirectory string) err
}(archive)

for _, f := range archive.File {
filePath := filepath.Join(destinationDirectory, f.Name)
log.Println("unzipping file", filePath)
rawPath := adjustFilePath(f.Name)
log.Println("unzipping file", rawPath)

// Remove the root directory from the path
pathComponents := strings.Split(rawPath, string(os.PathSeparator))
if len(pathComponents) > 1 {
pathComponents = pathComponents[1:] // remove the first directory
}
filePath := filepath.Join(destinationDirectory, filepath.Join(pathComponents...))

// Safety check for any malicious zip archives that might attempt to navigate to parent directories
if !strings.HasPrefix(filePath, filepath.Clean(destinationDirectory)+string(os.PathSeparator)) {
return fmt.Errorf("%s: illegal file path", filePath)
return fmt.Errorf("%s: illegal file path", rawPath)
}
if f.FileInfo().IsDir() {

if isDirectory(f) {
log.Println("creating directory...")
err = os.MkdirAll(filePath, os.ModePerm)
if err != nil {
Expand All @@ -525,10 +533,6 @@ func (b *ExtensionInstaller) unzip(zipFilePath, destinationDirectory string) err
continue
}

if strings.Contains(filePath, "\\") && runtime.GOOS != "windows" {
return fmt.Errorf("illegal file path: %s", filePath)
}

if err = os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
return fmt.Errorf("failed to create directory %s: %s", filepath.Dir(filePath), err)
}
Expand Down Expand Up @@ -560,6 +564,18 @@ func (b *ExtensionInstaller) unzip(zipFilePath, destinationDirectory string) err
return nil
}

func isDirectory(file *zip.File) bool {
return file.FileInfo().IsDir() || (strings.HasSuffix(adjustFilePath(file.Name), "/") && cmdutil.GetOs() != "windows")
}

func adjustFilePath(path string) string {
if strings.Contains(path, "\\") && cmdutil.GetOs() != "windows" {
path = strings.ReplaceAll(path, "\\", "/")
}

return path
}

func (b *ExtensionInstaller) PromptForExtensions() error {
extensionList, err := NewGithubReleaseFetcher(b.githubOrg, b.githubToken).GetExtensionList()
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions pkg/cmdutil/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package cmdutil

import (
"fmt"
"runtime"
)

func PrintError(err error) {
Expand All @@ -26,3 +27,7 @@ func PrintError(err error) {
fmt.Printf("\033[31m%s\u001B[0m\n", err)
}
}

func GetOs() string {
return runtime.GOOS
}

0 comments on commit 987b45e

Please sign in to comment.