Skip to content
Merged
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
4 changes: 3 additions & 1 deletion Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
---
apiVersion: v2
description: A Helm chart to build and deploy secrets using external-secrets for ansible-edge-gitops
home: https://github.com/validatedpatterns/aap-config-chart.git
keywords:
- pattern
name: aap-config
version: 0.2.0
version: 0.2.1
dependencies:
- name: vp-rbac
version: '0.1.*'
Expand Down
50 changes: 49 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# aap-config

![Version: 0.2.0](https://img.shields.io/badge/Version-0.2.0-informational?style=flat-square)
![Version: 0.2.1](https://img.shields.io/badge/Version-0.2.1-informational?style=flat-square)

A Helm chart to build and deploy secrets using external-secrets for ansible-edge-gitops

Expand All @@ -27,6 +27,51 @@ namespaces from external secrets validation.
To use this version, you will also need to update your pattern to use the
`openshift-external-secrets-operator` and `openshift-external-secrets` helm chart.

* v0.2.1: Support credential (HTTPS or SSH) injection for git client in AGOF config
jobs.

### VP-Secrets-v2

```yaml
---
# NEVER COMMIT THESE VALUES TO GIT
version: "2.0"
secrets:
- name: aap-manifest
fields:
- name: b64content
path: 'full pathname of file containing Satellite Manifest for entitling Ansible Automation Platform'
base64: true

- name: automation-hub-token
fields:
- name: token
value: 'An automation hub token for retrieving Certified and Validated Ansible content'

# Optional
- name: agof-vault-file
fields:
- name: agof-vault-file
path: 'full pathname of a valid agof_vault file for secrets to overlay the iac config'
base64: true

# Optional, if git auth is needed
- name: git-auth-secret
fields:
# HTTPS auth
- name: username
value: "Username to authenticate with"
- value: password
value: "Password to authenticate with"
# SSH auth
- name: .git-credentials
value: "git credentials"
- name: ssh-privatekey
value: "An ssh private key"
- name: known_hosts
value: "SSH known hosts for SSH authentication"
```

## Requirements

| Repository | Name | Version |
Expand All @@ -42,6 +87,9 @@ To use this version, you will also need to update your pattern to use the
| agof.agof_revision | string | `"v2"` | |
| agof.automationHubTokenKey | string | `"secret/data/hub/automation-hub-token"` | |
| agof.extraPlaybookOpts | string | `""` | |
| agof.gitAuthHttpsStyle | string | `"auto"` | |
| agof.gitAuthSecret | string | `""` | |
| agof.gitAuthVaultKey | string | `""` | |
| agof.iac_repo | string | `"https://github.com/validatedpatterns-demos/ansible-edge-gitops-hmi-config-as-code.git"` | |
| agof.iac_revision | string | `"main"` | |
| agof.vaultFileKey | string | `"secret/data/hub/agof-vault-file"` | |
Expand Down
45 changes: 45 additions & 0 deletions README.md.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,51 @@ namespaces from external secrets validation.
To use this version, you will also need to update your pattern to use the
`openshift-external-secrets-operator` and `openshift-external-secrets` helm chart.

* v0.2.1: Support credential (HTTPS or SSH) injection for git client in AGOF config
jobs.

### VP-Secrets-v2

```yaml
---
# NEVER COMMIT THESE VALUES TO GIT
version: "2.0"
secrets:
- name: aap-manifest
fields:
- name: b64content
path: 'full pathname of file containing Satellite Manifest for entitling Ansible Automation Platform'
base64: true

- name: automation-hub-token
fields:
- name: token
value: 'An automation hub token for retrieving Certified and Validated Ansible content'

# Optional
- name: agof-vault-file
fields:
- name: agof-vault-file
path: 'full pathname of a valid agof_vault file for secrets to overlay the iac config'
base64: true

# Optional, if git auth is needed
- name: git-auth-secret
fields:
# HTTPS auth
- name: username
value: "Username to authenticate with"
- value: password
value: "Password to authenticate with"
# SSH auth
- name: .git-credentials
value: "git credentials"
- name: ssh-privatekey
value: "An ssh private key"
- name: known_hosts
value: "SSH known hosts for SSH authentication"
```

{{ template "chart.homepageLine" . }}

{{ template "chart.maintainersSection" . }}
Expand Down
117 changes: 113 additions & 4 deletions templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ volumes:
- name: agof-vault-file
secret:
secretName: agof-vault-file
{{- if $.Values.agof.gitAuthSecret }}
- name: agof-git-auth
secret:
secretName: {{ $.Values.agof.gitAuthSecret | quote }}
{{- end }}
initContainers:
- name: agof-init
image: {{ .Values.configJob.image }}
Expand All @@ -19,15 +24,119 @@ initContainers:
command:
- /bin/bash
- -c
- >
base64 -d /pattern-home/agof-vault-file/agof-vault-file > ~/agof_vault.yml &&
git clone --recurse-submodules --single-branch --branch "{{ .Values.agof.agof_revision }}"
-- "{{ .Values.agof.agof_repo }}" /pattern-home/agof_repo
- |
set -euo pipefail
export GIT_TERMINAL_PROMPT=0
agof_repo_url={{ $.Values.agof.agof_repo | quote }}
iac_repo_url={{ $.Values.agof.iac_repo | quote }}
base64 -d /pattern-home/agof-vault-file/agof-vault-file > ~/agof_vault.yml
{{- if $.Values.agof.gitAuthSecret }}
GIT_AUTH_DIR=/pattern-home/git-auth
if [[ -f "$GIT_AUTH_DIR/.git-credentials" ]]; then
cp "$GIT_AUTH_DIR/.git-credentials" ~/.git-credentials
chmod 600 ~/.git-credentials
git config --global credential.helper store
elif [[ -f "$GIT_AUTH_DIR/ssh-privatekey" ]]; then
mkdir -p ~/.ssh
cp "$GIT_AUTH_DIR/ssh-privatekey" ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
if [[ -f "$GIT_AUTH_DIR/known_hosts" ]]; then
cp "$GIT_AUTH_DIR/known_hosts" ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
export GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes'
else
export GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new'
fi
else
agof_git_host_from_url() {
local u="$1"
if [[ "$u" =~ ^https?://([^/@]+) ]]; then
echo "${BASH_REMATCH[1]}"
elif [[ "$u" =~ ^https?://[^@]+@([^/]+) ]]; then
echo "${BASH_REMATCH[1]}"
elif [[ "$u" =~ ^git@([^:]+): ]]; then
echo "${BASH_REMATCH[1]}"
elif [[ "$u" =~ ^ssh://[^@]+@([^/:]+) ]]; then
echo "${BASH_REMATCH[1]}"
fi
}
agof_unique_git_hosts() {
local url h
for url in "$@"; do
[[ -z "$url" ]] && continue
h=$(agof_git_host_from_url "$url") || true
[[ -n "$h" ]] && printf '%s\n' "$h"
done | awk '!x[$0]++'
}
agof_https_store_credential() {
local host="$1" user="$2" pass="$3"
git config --global credential.helper store
printf 'protocol=https\nhost=%s\nusername=%s\npassword=%s\n\n' "$host" "$user" "$pass" | git credential approve
}
agof_https_user_for_style() {
local host_lc style
host_lc=$(echo "$1" | tr '[:upper:]' '[:lower:]')
style="$2"
case "$style" in
github) printf '%s' 'git' ;;
gitlab) printf '%s' 'oauth2' ;;
gitea) printf '%s' 'oauth2' ;;
auto)
if [[ "$host_lc" == *"github.com"* ]]; then printf '%s' 'git'
elif [[ "$host_lc" == *"gitlab"* ]]; then printf '%s' 'oauth2'
elif [[ "$host_lc" == *"gitea"* ]] || [[ "$host_lc" == *"forgejo"* ]] || [[ "$host_lc" == *"codeberg"* ]]; then printf '%s' 'oauth2'
else printf '%s' 'git'
fi
;;
*) printf '%s' 'git' ;;
esac
}
https_style={{ default "auto" $.Values.agof.gitAuthHttpsStyle | quote }}
if [[ -f "$GIT_AUTH_DIR/username" ]] && { [[ -f "$GIT_AUTH_DIR/password" ]] || [[ -f "$GIT_AUTH_DIR/token" ]]; }; then
u=$(cat "$GIT_AUTH_DIR/username")
if [[ -f "$GIT_AUTH_DIR/token" ]]; then
p=$(cat "$GIT_AUTH_DIR/token")
else
p=$(cat "$GIT_AUTH_DIR/password")
fi
host_any=""
while IFS= read -r host; do
[[ -z "$host" ]] && continue
host_any=1
agof_https_store_credential "$host" "$u" "$p"
done < <(agof_unique_git_hosts "$agof_repo_url" "$iac_repo_url")
if [[ -z "$host_any" ]]; then
echo "agof.gitAuthSecret: could not parse git host from agof_repo or iac_repo for HTTPS credentials" >&2
exit 1
fi
elif [[ -f "$GIT_AUTH_DIR/token" ]] && [[ ! -f "$GIT_AUTH_DIR/username" ]]; then
p=$(cat "$GIT_AUTH_DIR/token")
host_any=""
while IFS= read -r host; do
[[ -z "$host" ]] && continue
host_any=1
u="$(agof_https_user_for_style "$host" "$https_style")"
agof_https_store_credential "$host" "$u" "$p"
done < <(agof_unique_git_hosts "$agof_repo_url" "$iac_repo_url")
if [[ -z "$host_any" ]]; then
echo "agof.gitAuthSecret: could not parse git host from agof_repo or iac_repo for HTTPS token" >&2
exit 1
fi
fi
fi
{{- end }}
git clone --recurse-submodules --single-branch --branch "{{ $.Values.agof.agof_revision }}" \
-- "$agof_repo_url" /pattern-home/agof_repo
volumeMounts:
- name: agof-scratch-space
mountPath: /pattern-home
- name: agof-vault-file
mountPath: /pattern-home/agof-vault-file
{{- if $.Values.agof.gitAuthSecret }}
- name: agof-git-auth
mountPath: /pattern-home/git-auth
readOnly: true
{{- end }}
containers:
- name: agof-config
image: {{ .Values.configJob.image }}
Expand Down
3 changes: 3 additions & 0 deletions templates/external-secrets-validation-job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ spec:
"aap-manifest"
"agof-vault-file"
"automation-hub-token"
{{- if and $.Values.agof.gitAuthSecret $.Values.agof.gitAuthVaultKey }}
"{{ $.Values.agof.gitAuthSecret }}"
{{- end }}
)

# Function to check if a secret exists and has data
Expand Down
22 changes: 22 additions & 0 deletions templates/secret-agof-gitauth.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{- if and $.Values.agof.gitAuthVaultKey (not $.Values.agof.gitAuthSecret) -}}
{{- fail "agof.gitAuthVaultKey requires agof.gitAuthSecret (Kubernetes Secret / ExternalSecret name)" -}}
{{- end }}
{{- if and $.Values.agof.gitAuthSecret $.Values.agof.gitAuthVaultKey }}
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: {{ $.Values.agof.gitAuthSecret }}
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
refreshInterval: 15s
secretStoreRef:
name: {{ $.Values.secretStore.name }}
kind: {{ $.Values.secretStore.kind }}
target:
name: {{ $.Values.agof.gitAuthSecret }}
dataFrom:
- extract:
key: {{ $.Values.agof.gitAuthVaultKey }}
{{- end }}
15 changes: 15 additions & 0 deletions values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ agof:

agof_repo: https://github.com/validatedpatterns/agof.git
agof_revision: v2
# Optional: name of an existing Secret (same namespace) whose keys are mounted for
# git in the agof-init container (clone agof_repo) and the agof-config container
# (e.g. clone/fetch iac_repo during make). Use one of:
# - .git-credentials: full git-credential-store line(s) for HTTPS
# - ssh-privatekey (+ optional known_hosts): SSH private key (e.g. kubernetes.io/ssh-auth)
# - HTTPS: username + (password or token), or token-only with gitAuthHttpsStyle below
gitAuthSecret: ''
# Optional Vault path: when set (with gitAuthSecret), an ExternalSecret is created that uses
# dataFrom.extract to copy all fields from that Vault secret into the Kubernetes Secret named
# gitAuthSecret (same pattern as vaultFileKey / agof-vault-file).
gitAuthVaultKey: ''
# When the Secret has only a "token" key: how to pick the HTTPS username (PAT / OAuth).
# auto: from each repo URL host (github.com -> git; gitlab / gitea / forgejo / codeberg -> oauth2)
# github|gitlab|gitea: force that platform's usual clone user (git / oauth2 / oauth2)
gitAuthHttpsStyle: auto

iac_repo: https://github.com/validatedpatterns-demos/ansible-edge-gitops-hmi-config-as-code.git
iac_revision: main
Expand Down