Skip to content
Merged
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
171 changes: 88 additions & 83 deletions .github/workflows/publish.puppetforge.yml
Original file line number Diff line number Diff line change
@@ -1,136 +1,141 @@
name: Publish to Puppet Forge

on:
workflow_dispatch:
release:
types: [published]

jobs:
security-scan:
name: Security Scan
generate-sbom:
runs-on: ubuntu-latest

steps:
- name: Get the source code
uses: actions/checkout@v3

- name: Install Syft
run: |
echo "Installing Syft v1.18.1..."
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /tmp/bin v1.18.1
echo "/tmp/bin" >> $GITHUB_PATH

- name: Install Manifest CLI
run: |
echo "Installing Manifest CLI v0.18.3..."
curl -sSfL https://raw.githubusercontent.com/manifest-cyber/cli/main/install.sh | sh -s -- -b /tmp/bin v0.18.3

- name: Create Syft configuration
run: |
cat > syft-config.yaml << 'EOF'
package:
search:
scope: all-layers
exclude:
- "**/spec/**"
- "**/examples/**"
- "**/tests/**"
cataloger:
enabled: true
ruby:
enabled: true
search-gems: true
java:
enabled: false
python:
enabled: false
nodejs:
enabled: false
EOF

- name: Generate and upload SBOM
env:
MANIFEST_API_KEY: ${{ secrets.MANIFEST_TOKEN }}
run: |
PUPPET_MODULE_DIR="./integration/keeper_secrets_manager_puppet"

# Get version from metadata.json
echo "Detecting Puppet module version..."
if [ -f "${PUPPET_MODULE_DIR}/metadata.json" ]; then
VERSION=$(cat "${PUPPET_MODULE_DIR}/metadata.json" | jq -r .version)
echo "Detected version: ${VERSION}"
else
VERSION="1.0.0"
echo "Could not detect version, using default: ${VERSION}"
fi

echo "Generating SBOM with Manifest CLI..."
/tmp/bin/manifest sbom "${PUPPET_MODULE_DIR}" \
--generator=syft \
--name=keeper-secrets-manager-puppet \
--version=${VERSION} \
--output=spdx-json \
--file=puppet-module-sbom.json \
--api-key=${MANIFEST_API_KEY} \
--publish=true \
--asset-label=application,sbom-generated,ruby,puppet \
--generator-config=syft-config.yaml

echo "SBOM generated and uploaded successfully: puppet-module-sbom.json"
echo "---------- SBOM Preview (first 20 lines) ----------"
head -n 20 puppet-module-sbom.json

publish-puppet-forge:
needs: generate-sbom
environment: prod
runs-on: ubuntu-latest
timeout-minutes: 10

defaults:
run:
working-directory: ./integration/keeper_secrets_manager_puppet

steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Get the source code
uses: actions/checkout@v3

- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
working-directory: ./integration/keeper_secrets_manager_puppet

- name: Install dependencies
run: |
bundle install

- name: Retrieve secrets from KSM
id: ksmsecrets
uses: Keeper-Security/ksm-action@master
with:
keeper-secret-config: ${{ secrets.KSM_KSM_CONFIG }}
secrets: |
_gC1qMMHRcD6Fztyd692kw/field/password > PUPPET_FORGE_API_KEY

- name: Run Puppet Lint
run: |
bundle exec puppet-lint \
--no-140chars-check \
--no-autoloader_layout-check \
--no-documentation-check \
--no-class_inherits_from_params_class-check \
manifests/

- name: Validate Puppet manifests
run: |
bundle exec puppet parser validate manifests/*.pp

- name: Run metadata lint
run: |
bundle exec metadata-json-lint metadata.json

- name: Security scan for Ruby dependencies
run: |
gem install bundler-audit
bundle audit check --update

- name: Check for hardcoded secrets
run: |
# Check for potential secrets in manifests
echo "Checking for hardcoded secrets..."
! grep -rE "(password|secret|token|key)\s*=\s*['\"][^'\"]+['\"]" manifests/ || {
echo "::error::Found potential hardcoded secrets in manifests"
exit 1
}

- name: Run RSpec tests
run: |
bundle exec rake spec

publish:
name: Build and Publish to Puppet Forge
needs: security-scan
environment: prod
runs-on: ubuntu-latest

defaults:
run:
working-directory: ./integration/keeper_secrets_manager_puppet

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
working-directory: ./integration/keeper_secrets_manager_puppet

- name: Install dependencies
run: |
bundle install

- name: Retrieve secrets from KSM
id: ksmsecrets
uses: Keeper-Security/ksm-action@master
with:
keeper-secret-config: ${{ secrets.KSM_PUPPET_FORGE_CONFIG }}
secrets: |
_gC1qMMHRcD6Fztyd692kw/field/password > PUPPET_FORGE_API_KEY

- name: Build module
run: |
bundle exec pdk build

- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
path: ./integration/keeper_secrets_manager_puppet
format: cyclonedx-json
output-file: puppet-module-sbom.json

- name: Upload SBOM
uses: actions/upload-artifact@v4
with:
name: puppet-module-sbom
path: puppet-module-sbom.json
retention-days: 90

- name: Publish to Puppet Forge
env:
PDK_DISABLE_ANALYTICS: true
run: |
# Use PDK to publish with API key
bundle exec pdk release publish --forge-token=${{ steps.ksmsecrets.outputs.PUPPET_FORGE_API_KEY }} --force

- name: Create GitHub Release Assets
if: github.event_name == 'release'
run: |
# Find the built module
MODULE_FILE=$(find pkg -name "*.tar.gz" | head -1)

# Upload to GitHub release
gh release upload ${{ github.event.release.tag_name }} \
"${MODULE_FILE}" \
--clobber
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
bundle exec pdk release publish --forge-token=${{ secrets.PUPPET_FORGE_API_KEY }} --force