Skip to content

Commit

Permalink
Merge pull request #286 from cooktheryan/podman_secret
Browse files Browse the repository at this point in the history
podman secret usage
  • Loading branch information
sallyom committed Jan 6, 2023
2 parents 00fe573 + 28a9c45 commit 1ce4e7d
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 17 deletions.
176 changes: 174 additions & 2 deletions .github/workflows/docker-image.yml
Expand Up @@ -516,6 +516,178 @@ jobs:
echo 'Label was applied correctly'
fi
podman-secret-validate:
runs-on: ubuntu-latest
needs: [ build , pull-and-archive ]
steps:
- uses: actions/checkout@v2

- name: pull in podman
uses: actions/download-artifact@v1
with:
name: podman-bins
path: bin

- name: replace
run: |
chmod +x bin/podman
sudo mv bin/podman /usr/bin/podman
- name: Enable the podman socket
run: sudo systemctl enable --now podman.socket

- name: pull artifact
uses: actions/download-artifact@v1
with:
name: fetchit-image
path: /tmp

- name: Load the image
run: sudo podman load -i /tmp/fetchit.tar

- name: pull artifact
uses: actions/download-artifact@v1
with:
name: colors
path: /tmp

- name: Load the image
run: sudo podman load -i /tmp/colors.tar

- name: tag the image
run: sudo podman tag quay.io/fetchit/fetchit-amd:latest quay.io/fetchit/fetchit:latest

- name: generate podman secret
run: |
export GH_PAT=${{ secrets.GITHUB_TOKEN }}
podman secret create --env GH_PAT GH_PAT
- name: Start fetchit
run: sudo podman run -d --name fetchit -v fetchit-volume:/opt -v ./examples/podman-secret-raw.yaml:/opt/mount/config.yaml -v /run/podman/podman.sock:/run/podman/podman.sock --security-opt label=disable quay.io/fetchit/fetchit-amd:latest

- name: identify colors container
run: timeout 150 bash -c -- 'c=0 ; until [ $c -eq 2 ]; do c=$(sudo podman ps | grep colors | wc -l); done'

- name: Logs
if: always()
run: sudo podman logs fetchit

- name: verify container is running
run: if [[ $(sudo podman ps | grep -v CON= | grep colors | wc -l) = "2" ]] ; then echo "Container successfully launched"; else exit 1; fi

- name: Print the current running container
run: sudo podman ps

- name: Check the capabilities of cap1
run: if [[ $(sudo podman container inspect cap1 --format {{.EffectiveCaps}} | grep NET_ADMIN | wc -l) = "1" ]] ; then echo "Container successfully launched"; else exit 1; fi

- name: Check that no capabilities exist for cap2
run: if [[ $(sudo podman container inspect cap2 --format {{.EffectiveCaps}} | jq length) = "0" ]] ; then echo "Container successfully launched"; else exit 1; fi

- name: 'Check that the "owned-by:fetchit" label is applied'
run: |
declare -i numContainers=$(sudo podman ps --filter label=owned-by=fetchit | wc -l)
if (( numContainers > 1 )); then
echo 'Successfully applied labels'
else
exit 1
fi
# check against a garbage label
declare -i checkAgainst=$(sudo podman ps --filter label=owned-by=abcdefghijklmnopqrstuvwxyz | wc -l)
if (( checkAgainst == numContainers )); then
echo 'container amount with label cannot equal container amount with nonexistent label'
exit 1
else
echo 'Label was applied correctly'
fi
podman-config-secret-validate:
runs-on: ubuntu-latest
needs: [ build , pull-and-archive ]
steps:
- uses: actions/checkout@v2

- name: pull in podman
uses: actions/download-artifact@v1
with:
name: podman-bins
path: bin

- name: replace
run: |
chmod +x bin/podman
sudo mv bin/podman /usr/bin/podman
- name: Enable the podman socket
run: sudo systemctl enable --now podman.socket

- name: pull artifact
uses: actions/download-artifact@v1
with:
name: fetchit-image
path: /tmp

- name: Load the image
run: sudo podman load -i /tmp/fetchit.tar

- name: pull artifact
uses: actions/download-artifact@v1
with:
name: colors
path: /tmp

- name: Load the image
run: sudo podman load -i /tmp/colors.tar

- name: tag the image
run: sudo podman tag quay.io/fetchit/fetchit-amd:latest quay.io/fetchit/fetchit:latest

- name: generate podman secret
run: |
export GH_PAT=${{ secrets.GITHUB_TOKEN }}
podman secret create --env GH_PAT GH_PAT
- name: Start fetchit
run: sudo podman run -d --name fetchit -v fetchit-volume:/opt -v ./examples/podman-secret-raw-config.yaml:/opt/mount/config.yaml -v /run/podman/podman.sock:/run/podman/podman.sock --security-opt label=disable quay.io/fetchit/fetchit-amd:latest

- name: identify colors container
run: timeout 150 bash -c -- 'c=0 ; until [ $c -eq 2 ]; do c=$(sudo podman ps | grep colors | wc -l); done'

- name: Logs
if: always()
run: sudo podman logs fetchit

- name: verify container is running
run: if [[ $(sudo podman ps | grep -v CON= | grep colors | wc -l) = "2" ]] ; then echo "Container successfully launched"; else exit 1; fi

- name: Print the current running container
run: sudo podman ps

- name: Check the capabilities of cap1
run: if [[ $(sudo podman container inspect cap1 --format {{.EffectiveCaps}} | grep NET_ADMIN | wc -l) = "1" ]] ; then echo "Container successfully launched"; else exit 1; fi

- name: Check that no capabilities exist for cap2
run: if [[ $(sudo podman container inspect cap2 --format {{.EffectiveCaps}} | jq length) = "0" ]] ; then echo "Container successfully launched"; else exit 1; fi

- name: 'Check that the "owned-by:fetchit" label is applied'
run: |
declare -i numContainers=$(sudo podman ps --filter label=owned-by=fetchit | wc -l)
if (( numContainers > 1 )); then
echo 'Successfully applied labels'
else
exit 1
fi
# check against a garbage label
declare -i checkAgainst=$(sudo podman ps --filter label=owned-by=abcdefghijklmnopqrstuvwxyz | wc -l)
if (( checkAgainst == numContainers )); then
echo 'container amount with label cannot equal container amount with nonexistent label'
exit 1
else
echo 'Label was applied correctly'
fi
config-env-raw-validate:
runs-on: ubuntu-latest
needs: [ build , pull-and-archive ]
Expand Down Expand Up @@ -1703,7 +1875,7 @@ jobs:

push-amd-image-to-registry:
runs-on: ubuntu-latest
needs: [ build, raw-validate, fetchit-config-target-no-config-validate, fetchit-config-reload-validate, clean-validate, kube-validate, systemd-validate, systemd-enable-validate, systemd-user-enable-validate, systemd-autoupdate-validate, systemd-restart-validate, systemd-validate-exact-file, multi-engine-validate, make-change-to-repo, filetransfer-validate, filetransfer-validate-exact-file, ansible-validate, loader-validate, disconnected-validate ]
needs: [ build, raw-validate, podman-secret-validate, podman-config-secret-validate, fetchit-config-target-no-config-validate, fetchit-config-reload-validate, clean-validate, kube-validate, systemd-validate, systemd-enable-validate, systemd-user-enable-validate, systemd-autoupdate-validate, systemd-restart-validate, systemd-validate-exact-file, multi-engine-validate, make-change-to-repo, filetransfer-validate, filetransfer-validate-exact-file, ansible-validate, loader-validate, disconnected-validate ]
if: >
(github.event_name == 'push' || github.event_name == 'schedule') &&
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
Expand All @@ -1730,7 +1902,7 @@ jobs:

build-arm-and-manifest-list:
runs-on: ubuntu-latest
needs: [ build, raw-validate, fetchit-config-target-no-config-validate, fetchit-config-reload-validate, clean-validate, kube-validate, systemd-validate, systemd-enable-validate, systemd-user-enable-validate, systemd-autoupdate-validate, systemd-restart-validate, systemd-validate-exact-file, multi-engine-validate, make-change-to-repo, filetransfer-validate, filetransfer-validate-exact-file, ansible-validate, loader-validate, disconnected-validate ]
needs: [ build, raw-validate, podman-secret-validate, podman-config-secret-validate, fetchit-config-target-no-config-validate, fetchit-config-reload-validate, clean-validate, kube-validate, systemd-validate, systemd-enable-validate, systemd-user-enable-validate, systemd-autoupdate-validate, systemd-restart-validate, systemd-validate-exact-file, multi-engine-validate, make-change-to-repo, filetransfer-validate, filetransfer-validate-exact-file, ansible-validate, loader-validate, disconnected-validate ]
if: >
(github.event_name == 'push' || github.event_name == 'schedule') &&
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
Expand Down
30 changes: 25 additions & 5 deletions docs/methods.rst
Expand Up @@ -48,15 +48,25 @@ When using basic authentication the config.yaml will need to include the followi

.. code-block:: yaml
gitAuth:
username: bob
password: bobpassword
configReload:
schedule: "*/5 * * * *"
username: bob
passwords: bobpassword
configUrl: https://raw.githubusercontent.com/containers/fetchit/main/examples/config-reload.yaml
NOTE: This is not recommended for public repositories. As your credentials will need to be in clear text in the config.yaml.

PAT is the preferred method of authentication when available as the credentials can be reissued or locked.
PAT is the preferred method of authentication when available as the credentials can be reissued or locked. The PAT will be used both for the configuration file and the repo

.. code-block:: yaml
gitAuth:
pat: github-alphanumeric-token
configReload:
schedule: "*/5 * * * *"
configUrl: https://raw.githubusercontent.com/containers/fetchit/main/examples/config-reload.yaml
Configuring FetchIt Using Environment Variables
-----------------------------------------------
Expand Down Expand Up @@ -92,17 +102,27 @@ An example of using username/password is shown below.

.. code-block:: yaml
gitAuth:
username: bob
password: bobpassword
targetConfigs:
- url: http://github.com/containers/fetchit
username: bob
password: bobpassword
branch: main
ansible:
- name: ans-ex
targetPath: examples/ansible
sshDirectory: /root/.ssh
schedule: "*/5 * * * *"
Podman secrets can also be used but FetchIt must be started with the secret defined as an environment variable.
This variable is defined as `--secret GH_PAT,type=env` in the `podman run` command.

.. code-block:: bash
export GH_PAT_TOKEN=CHANGEME
podman secret create --env GH_PAT GH_PAT_TOKEN
podman run -d --name fetchit -v fetchit-volume:/opt -v $HOME/.fetchit:/opt/mount -v /run/user/1000/podman/podman.sock:/run/podman/podman.sock --secret GH_PAT,type=env --security-opt label=disable --secret GH_PAT,type=env quay.io/fetchit/fetchit:latest
Ansible
-------
The AnsibleTarget method allows for an Ansible playbook to be run on the host. A container is created containing the Ansible playbook, and the container will run the playbook. This playbook can be used to install software, configure the host, or perform other tasks.
Expand Down
1 change: 0 additions & 1 deletion examples/pat-testing-config.yaml
Expand Up @@ -5,7 +5,6 @@
configReload:
configURL: https://raw.githubusercontent.com/containers/fetchit/main/examples/config-reload.yaml
schedule: "*/2 * * * *"
pat: CHANGEME
gitAuth:
pat: CHANGEME
targetConfigs:
Expand Down
17 changes: 17 additions & 0 deletions examples/podman-secret-raw-config.yaml
@@ -0,0 +1,17 @@
# for this test, start with this config, Using a podman secret
# then wait to be sure the
# targetConfigs from .fetchit/config.yaml are populated
# and for follow-up test, push a change to the config and confirm
# new targetConfigs are fetched & run
configReload:
configURL: https://raw.githubusercontent.com/containers/fetchit/main/examples/config-reload.yaml
schedule: "*/2 * * * *"
gitAuth:
envSecret: GH_PAT
targetConfigs:
- url: https://github.com/containers/fetchit
raw:
- name: raw
targetPath: examples/raw
schedule: "*/1 * * * *"
branch: main
10 changes: 10 additions & 0 deletions examples/podman-secret-raw.yaml
@@ -0,0 +1,10 @@
# for this test, use of a podman secret with a raw target
gitAuth:
envSecret: GH_PAT
targetConfigs:
- url: https://github.com/containers/fetchit
raw:
- name: raw
targetPath: examples/raw
schedule: "*/1 * * * *"
branch: main
6 changes: 5 additions & 1 deletion pkg/engine/apply.go
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"os"
"path/filepath"
"strings"

Expand Down Expand Up @@ -61,7 +62,10 @@ func getLatest(target *Target) (plumbing.Hash, error) {
if err != nil {
return plumbing.Hash{}, utils.WrapErr(err, "Error opening repository %s to fetch latest commit", directory)
}

if target.envSecret != "" {
logger.Infof("Using the envSecret %s", target.envSecret)
target.pat = os.Getenv(target.envSecret)
}
if target.pat != "" {
target.username = "fetchit"
target.password = target.pat
Expand Down
9 changes: 7 additions & 2 deletions pkg/engine/config.go
Expand Up @@ -48,15 +48,20 @@ func (c *ConfigReload) Process(ctx, conn context.Context, skew int) {
if c.ConfigURL != "" {
envURL = c.ConfigURL
}
os.Setenv("FETCHIT_CONFIG_URL", envURL)
pat := fetchit.pat
if fetchit.envSecret != "" {
pat = os.Getenv(fetchit.envSecret)
}
username := fetchit.username
password := fetchit.password
// If ConfigURL is not populated, warn and leave
if envURL == "" && c.Device == "" {
logger.Debugf("Fetchit ConfigReload found, but neither $FETCHIT_CONFIG_URL on system nor ConfigReload.ConfigURL are set, exiting without updating the config.")
}
// CheckForConfigUpdates downloads & places config file in defaultConfigPath
// if the downloaded config file differs from what's currently on the system.
if envURL != "" {
restart := checkForConfigUpdates(envURL, true, false, c.PAT, c.Username, c.Password)
restart := checkForConfigUpdates(envURL, true, false, pat, username, password)
if !restart {
return
}
Expand Down
21 changes: 15 additions & 6 deletions pkg/engine/fetchit.go
Expand Up @@ -42,6 +42,7 @@ type Fetchit struct {
username string
password string
pat string
envSecret string
restartFetchit bool
scheduler *gocron.Scheduler
methodTargetScheds map[Method]SchedInfo
Expand Down Expand Up @@ -146,9 +147,9 @@ func (fc *FetchitConfig) populateFetchit(config *FetchitConfig) *Fetchit {
if config.GitAuth != nil {
// Check for SSH usage
if config.GitAuth.SSH {
if err := os.Setenv("SSH_KNOWN_HOSTS", "/opt/mount/.ssh/known_hosts"); err != nil {
cobra.CheckErr(err)
}
if err := os.Setenv("SSH_KNOWN_HOSTS", "/opt/mount/.ssh/known_hosts"); err != nil {
cobra.CheckErr(err)
}
keyPath := defaultSSHKey
// Check for unique ssh key file
if config.GitAuth.SSHKeyFile != "" {
Expand All @@ -163,6 +164,7 @@ func (fc *FetchitConfig) populateFetchit(config *FetchitConfig) *Fetchit {
fetchit.username = config.GitAuth.Username
fetchit.password = config.GitAuth.Password
fetchit.pat = config.GitAuth.PAT
fetchit.envSecret = config.GitAuth.EnvSecret
}

if config.Prune != nil {
Expand Down Expand Up @@ -261,9 +263,11 @@ func getMethodTargetScheds(targetConfigs []*TargetConfig, fetchit *Fetchit) *Fet
tc.mu.Lock()
defer tc.mu.Unlock()
internalTarget := &Target{
url: tc.Url,
device: tc.Device,
pat: fetchit.pat,
url: tc.Url,
device: tc.Device,
pat: fetchit.pat,
// define the environment variable for envSecret
envSecret: fetchit.envSecret,
ssh: fetchit.ssh,
sshKey: fetchit.sshKey,
username: fetchit.username,
Expand Down Expand Up @@ -399,6 +403,11 @@ func getClone(target *Target) error {
}
if !exists {
logger.Infof("git clone %s %s --recursive", target.url, target.branch)
// if the envSecret is set, use it as variable target.PAT
if target.envSecret != "" {
target.pat = os.Getenv(target.envSecret)
logger.Infof("Using the envSecret %s", target.envSecret)
}
if target.pat != "" {
target.username = "fetchit"
target.password = target.pat
Expand Down
1 change: 1 addition & 0 deletions pkg/engine/gitauth.go
Expand Up @@ -14,6 +14,7 @@ type GitAuth struct {
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
PAT string `mapstructure:"pat"`
EnvSecret string `mapstructure:"envSecret"`
}

// Checks to see if private key exists on given path
Expand Down

0 comments on commit 1ce4e7d

Please sign in to comment.