Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM alpine:3.19.1
FROM alpine:3.22.0

ARG USER=ext-installer
ENV HOME /home/$USER
Expand All @@ -9,6 +9,7 @@ RUN adduser -D $USER
USER $USER
WORKDIR $HOME

ADD install.sh .
COPY --chown=$USER:$USER install.sh .
RUN chmod +x install.sh

ENTRYPOINT ["./install.sh"]
50 changes: 48 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ list of all environment variables that can be configured:
| EXTENSION_CHECKSUM_URL | No | "" | Can be set to the file containing the checksum to validate the downloaded<br>extension. Will skip the checksum validation if not provided.<br>Argo CD API server needs to have network access to this URL. |
| MAX_DOWNLOAD_SEC | No | 30 | Total time in seconds allowed to download the extension. |
| EXTENSION_JS_VARS | No | "" | Export the variables to `extension-$EXTENSION_JS_VARS` in js file within the extension folder. These variables will be exported as env variables with key `${EXTENSION_NAME}_VARS`. <br/>The format should be `{key1=value1, key2=value2}`. |
| EXTENSION_GIT_TOKEN | No | "" | Token used for authentication when downloading the extension from a private Git repository. The token will be used in an `Authorization` header. |


# Examples
Expand All @@ -41,7 +42,7 @@ spec:
spec:
initContainers:
- name: extension-
image: quay.io/argoprojlabs/argocd-extension-installer:v0.0.5@sha256:27e72f047298188e2de1a73a1901013c274c4760c92f82e6e46cd5fbd0957c6b
image: quay.io/argoprojlabs/argocd-extension-installer:v0.0.9
env:
- name: EXTENSION_URL
value: https://github.com/some-org/somerepo/releases/download/v0.0.1/extension.tar
Expand All @@ -63,6 +64,51 @@ spec:
> The tag digest can be obtained in quay by clicking in the "fetch tag" icon and select "Docker Pull (by digest)":
> https://quay.io/repository/argoprojlabs/argocd-extension-installer?tab=tags

### Using private repositories

If your extension is hosted in a private Git repository, you can provide a Git access token using the `EXTENSION_GIT_TOKEN` environment variable. This token will be used to set an `Authorization` header when downloading the extension archive and optional checksum file.

The token can be injected either through a ConfigMap or a Secret. It is recommended to use a Kubernetes Secret to avoid exposing sensitive values in plain text.

Supported services include GitHub, GitLab, Bitbucket, and generic Git servers.

#### Example: Using a Kubernetes Secret

Create a Kubernetes Secret that holds your Git access token:

```yaml
apiVersion: v1
kind: Secret
metadata:
name: github-token-secret
namespace: argocd
type: Opaque
stringData:
EXTENSION_GIT_TOKEN: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```


Reference the token in your Argo CD server deployment:
```yaml
initContainers:
- name: extension-
image: quay.io/argoprojlabs/argocd-extension-installer:v0.0.9
env:
- name: EXTENSION_URL
value: https://github.com/some-org/somerepo/releases/download/v0.0.1/extension.tar
- name: EXTENSION_GIT_TOKEN
valueFrom:
secretKeyRef:
name: github-token-secret
key: EXTENSION_GIT_TOKEN
volumeMounts:
- name: extensions
mountPath: /tmp/extensions/
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
```

## Using ConfigMap

The example below demonstrates how to define all extension
Expand Down Expand Up @@ -99,7 +145,7 @@ spec:
spec:
initContainers:
- name: extension
image: quay.io/argoprojlabs/argocd-extension-installer:v0.0.5@sha256:27e72f047298188e2de1a73a1901013c274c4760c92f82e6e46cd5fbd0957c6b
image: quay.io/argoprojlabs/argocd-extension-installer:v0.0.9
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the sha256 for the new version. This is an important security measure to ensure that clients aren't fetching malicious images. The sha can be found in quay.io. We should probably clarify this in the doc somewhere.

env:
- name: EXTENSION_NAME
valueFrom:
Expand Down
92 changes: 88 additions & 4 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,94 @@ finalizer() {
}
trap finalizer EXIT

# detect if URL is a Git repository URL
is_git_url() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think that this Authorization should be git driven. We could have a private http server that requires authentication for providing extensions.

local url="$1"
case "$url" in
https://github.com/*|https://gitlab.com/*|https://bitbucket.org/*|*.git|*git*)
return 0
;;
*)
return 1
;;
esac
}

# construct authorization header for Git API
get_git_auth_header() {
local url="$1"
local token="$2"

if [ -z "$token" ]; then
echo ""
return
fi

case "$url" in
https://github.com/*)
echo "Authorization: token $token"
;;
https://gitlab.com/*)
echo "Authorization: Bearer $token"
;;
https://bitbucket.org/*)
echo "Authorization: Bearer $token"
;;
*)
# Generic Git token format
echo "Authorization: Bearer $token"
;;
esac
}

# will download the extension respecting the max download
# duration setting
download_extension() {
mkdir -p $download_dir
echo "Downloading the UI extension..."
curl -Lf --max-time $download_max_sec $ext_url -o $ext_file

# Check if this is a Git repository URL and token is provided
if is_git_url "$ext_url" && [ -n "$git_token" ]; then
echo "Detected Git repository URL with authentication token"
auth_header=$(get_git_auth_header "$ext_url" "$git_token")

if [ -n "$auth_header" ]; then
echo "Using authenticated download for private repository"
curl -Lf --max-time $download_max_sec -H "$auth_header" "$ext_url" -o "$ext_file"
else
curl -Lf --max-time $download_max_sec "$ext_url" -o "$ext_file"
fi
elif is_git_url "$ext_url" && [ -z "$git_token" ]; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Public extensions can be published in github and won't require token. Example:
https://github.com/argoproj-labs/argocd-ephemeral-access/releases/download/v1.0.0-rc2/extension.tar.gz

not sure if this elif and the else below is required.

echo "WARNING: Git repository URL detected but no EXTENSION_GIT_TOKEN provided"
echo "This may fail if the repository is private"
Comment on lines +89 to +90
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the majority of the extensions are going to be public. That being said, I am not sure if it is a good idea to display this warning message every time.

curl -Lf --max-time $download_max_sec "$ext_url" -o "$ext_file"
else
# Non-Git URL, use standard download
curl -Lf --max-time $download_max_sec "$ext_url" -o "$ext_file"
fi

# Validate checksum if provided
if [ "$checksum_url" != "" ]; then
echo "Validating the UI extension checksum..."
expected_sha=$(curl -Lf $checksum_url | grep "$ext_filename" | awk '{print $1;}')

# Apply same authentication logic for checksum URL if it's also a Git URL
if is_git_url "$checksum_url" && [ -n "$git_token" ]; then
auth_header=$(get_git_auth_header "$checksum_url" "$git_token")

if [ -n "$auth_header" ]; then
expected_sha=$(curl -Lf -H "$auth_header" "$checksum_url" | grep "$ext_filename" | awk '{print $1;}')
else
expected_sha=$(curl -Lf "$checksum_url" | grep "$ext_filename" | awk '{print $1;}')
fi
else
expected_sha=$(curl -Lf "$checksum_url" | grep "$ext_filename" | awk '{print $1;}')
fi

current_sha=$(sha256sum $ext_file | awk '{print $1;}')
if [ "$expected_sha" != "$current_sha" ]; then
echo "ERROR: extension checksum mismatch"
echo "Expected: $expected_sha"
echo "Current: $current_sha"
exit 1
fi
fi
Expand Down Expand Up @@ -69,7 +145,6 @@ install_extension() {
fi

echo "UI extension installed successfully"

}

create_extension_js_file_with_vars() {
Expand Down Expand Up @@ -103,6 +178,10 @@ if [ "$ext_url" = "" ]; then
echo "error: the env var EXTENSION_URL must be provided"
exit 1
fi

# Git token for private repository access
git_token="${EXTENSION_GIT_TOKEN:-}"

checksum_url="${EXTENSION_CHECKSUM_URL:-}"
download_max_sec="${MAX_DOWNLOAD_SEC:-30}"

Expand All @@ -118,7 +197,12 @@ if [ -n "${ext_vars}" ]; then
ext_vars=$(echo "$ext_vars" | jq -c '.')
fi

# Log authentication status (without exposing token)
if [ -n "$git_token" ]; then
echo "Git authentication token detected for private repository access"
else
echo "No Git authentication token provided - public repositories only"
fi

download_extension
install_extension