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
309 changes: 309 additions & 0 deletions .github/workflows/publish.puppetforge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
name: Publish to Puppet Forge
on:
workflow_dispatch:

jobs:
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:
Comment on lines +7 to +78

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 3 months ago

To fix the problem, add a permissions block to the workflow file to explicitly set the minimum required permissions for the GITHUB_TOKEN. Since the workflow does not appear to require write access to repository contents or other resources, the minimal permission of contents: read is appropriate. This should be added at the top level of the workflow file (after the name and on keys), so it applies to all jobs unless overridden. No changes to the jobs themselves are necessary unless a job requires additional permissions.


Suggested changeset 1
.github/workflows/publish.puppetforge.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/publish.puppetforge.yml b/.github/workflows/publish.puppetforge.yml
--- a/.github/workflows/publish.puppetforge.yml
+++ b/.github/workflows/publish.puppetforge.yml
@@ -4,2 +4,5 @@
 
+permissions:
+  contents: read
+
 jobs:
EOF
@@ -4,2 +4,5 @@

permissions:
contents: read

jobs:
Copilot is powered by AI and may make mistakes. Always verify output.
needs: generate-sbom
environment: prod
runs-on: ubuntu-latest
timeout-minutes: 15

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

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

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

- 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: Get current version and validate
id: version
run: |
if [[ -f "metadata.json" ]]; then
VERSION=$(grep '"version"' metadata.json | cut -d'"' -f4)
echo "current_version=$VERSION" >> $GITHUB_OUTPUT
echo "Current version: $VERSION"
else
echo "Error: metadata.json not found"
exit 1
fi

- name: Check if version already exists on Puppet Forge
env:
VERSION: ${{ steps.version.outputs.current_version }}
run: |
echo "Checking if version $VERSION already exists on Puppet Forge..."
FORGE_CHECK=$(curl -s "https://forgeapi.puppet.com/v3/releases/keepersecurity-keeper_secrets_manager_puppet-$VERSION")

if echo "$FORGE_CHECK" | grep -q '"uri"'; then
echo "Error: Version $VERSION already exists on Puppet Forge!"
echo ""
echo "To publish a new release, you need to:"
echo "1. Bump the version in metadata.json"
echo " File: integration/keeper_secrets_manager_puppet/metadata.json"
echo " Current: \"version\": \"$VERSION\""
echo " Example: \"version\": \"1.0.3\" (for patch)"
echo " \"version\": \"1.1.0\" (for minor)"
echo " \"version\": \"2.0.0\" (for major)"
echo ""
echo "Version already published at: https://forge.puppet.com/modules/keepersecurity/keeper_secrets_manager_puppet"
exit 1
fi
echo "Version $VERSION is available for publishing"

- name: Validate API key format
env:
PUPPET_FORGE_API_KEY: ${{ steps.ksmsecrets.outputs.PUPPET_FORGE_API_KEY }}
run: |
if [[ ! "$PUPPET_FORGE_API_KEY" =~ ^[a-f0-9]{64}$ ]]; then
echo "Warning: API key format doesn't match expected pattern (64 hex characters)"
echo "Key length: ${#PUPPET_FORGE_API_KEY}"
echo "Continuing anyway, but check your key if publishing fails..."
else
echo "API key format looks correct"
fi

- name: Install dependencies
run: |
echo "Installing Ruby dependencies..."
if ! bundle install; then
echo "Failed to install dependencies"
echo "Gem versions installed:"
bundle list
exit 1
fi
echo "Dependencies installed successfully"

# Show key dependency versions
echo "Key dependency versions:"
bundle list | grep -E "(puppet|rake|puppet-lint)"

- name: Run comprehensive validation
run: |
echo "Running comprehensive validation..."

# Run lint with error handling
echo "Running puppet-lint..."
if ! bundle exec rake lint; then
echo "Lint failed"
exit 1
fi
echo "Lint passed"

# Run validation
echo "Running puppet validate..."
if ! bundle exec rake validate; then
echo "Validation failed"
exit 1
fi
echo "Validation passed"

# Run metadata lint
echo "Running metadata lint..."
if ! bundle exec metadata-json-lint metadata.json; then
echo "Metadata lint failed"
exit 1
fi
echo "Metadata validation passed"

- name: Run full test suite
run: |
echo "Running full test suite..."
if ! bundle exec rake spec; then
echo "Tests failed"
exit 1
fi
echo "All tests passed"

- name: Build module
run: |
echo "Building module..."
if ! bundle exec rake module:build; then
echo "Build failed"
exit 1
fi
echo "Module built successfully"

# Show built packages
echo "Built packages:"
ls -la pkg/ | grep '.tar.gz' || echo "No packages found"

- name: Publish to Puppet Forge with robust error handling
env:
PUPPET_FORGE_API_KEY: ${{ steps.ksmsecrets.outputs.PUPPET_FORGE_API_KEY }}
VERSION: ${{ steps.version.outputs.current_version }}
PDK_DISABLE_ANALYTICS: true
run: |
echo "Publishing to Puppet Forge..."

cd pkg
LATEST_FILE=$(ls -t keepersecurity-keeper_secrets_manager_puppet-*.tar.gz | head -1)

if [[ -z "$LATEST_FILE" ]]; then
echo "No package file found to publish"
exit 1
fi

echo "Publishing: $LATEST_FILE"

RESULT=$(curl -s -X POST \
-H "Authorization: Bearer $PUPPET_FORGE_API_KEY" \
-F "file=@$LATEST_FILE" \
https://forgeapi.puppet.com/v3/releases)

echo "$RESULT"

if echo "$RESULT" | grep -q '"uri"'; then
echo ""
echo "Successfully published to Puppet Forge!"
echo "Module available at: https://forge.puppet.com/modules/keepersecurity/keeper_secrets_manager_puppet"

# Extract and display the published version info
if echo "$RESULT" | grep -q '"version"'; then
PUBLISHED_VERSION=$(echo "$RESULT" | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
echo "Published version: $PUBLISHED_VERSION"
fi
else
echo ""
echo "Failed to publish. Check the error message above."

# Enhanced error handling with specific guidance
if echo "$RESULT" | grep -q 'cannot publish releases'; then
echo ""
echo "API Key Issue: Your API key may not have permission to publish to the keepersecurity namespace."
echo "Solutions:"
echo "1. Verify you are using the correct API key from the keepersecurity organization"
echo "2. Check that your API key has publish permissions"
echo "3. Regenerate your API key at: https://forge.puppet.com/organization/api-keys"
echo "4. Update the secret in GitHub: PUPPET_FORGE_API_KEY"
elif echo "$RESULT" | grep -q -i 'version.*already.*exists\|duplicate.*version\|version.*conflict'; then
echo ""
echo "Version Conflict: This version already exists on Puppet Forge."
echo ""
echo "To publish a new release:"
echo "1. Bump the version in metadata.json"
echo " File: integration/keeper_secrets_manager_puppet/metadata.json"
echo " Current: \"version\": \"$VERSION\""
echo " Example: \"version\": \"1.0.3\" (patch), \"1.1.0\" (minor), \"2.0.0\" (major)"
echo "2. Commit and push the version change"
echo "3. Re-run this workflow"
elif echo "$RESULT" | grep -q -i 'unauthorized\|authentication'; then
echo ""
echo "Authentication Error: API key is invalid or expired."
echo "Solutions:"
echo "1. Check that PUPPET_FORGE_API_KEY secret is set correctly"
echo "2. Regenerate API key at: https://forge.puppet.com/organization/api-keys"
echo "3. Update the GitHub secret with the new key"
else
echo ""
echo "Unknown error occurred. Please check the API response above."
echo "For help, visit: https://forge.puppet.com/docs/publish"
fi
exit 1
fi

- name: Create release summary
env:
VERSION: ${{ steps.version.outputs.current_version }}
run: |
echo "## Puppet Module Published Successfully!" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** $VERSION" >> $GITHUB_STEP_SUMMARY
echo "**Module:** keepersecurity-keeper_secrets_manager_puppet" >> $GITHUB_STEP_SUMMARY
echo "**Forge URL:** https://forge.puppet.com/modules/keepersecurity/keeper_secrets_manager_puppet" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Validation Results" >> $GITHUB_STEP_SUMMARY
echo "- Puppet Lint: Passed" >> $GITHUB_STEP_SUMMARY
echo "- Puppet Validate: Passed" >> $GITHUB_STEP_SUMMARY
echo "- Metadata Lint: Passed" >> $GITHUB_STEP_SUMMARY
echo "- Test Suite: Passed" >> $GITHUB_STEP_SUMMARY
echo "- Module Build: Successful" >> $GITHUB_STEP_SUMMARY
echo "- Forge Publish: Successful" >> $GITHUB_STEP_SUMMARY
Comment on lines +79 to +309

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 3 months ago

To fix the problem, add a permissions block to the workflow file. This can be done at the top level (applies to all jobs) or at the job level (applies to a specific job). Since neither job in this workflow appears to require write access to repository contents, the minimal and recommended fix is to add permissions: contents: read at the top level, just below the name and on keys. This will ensure that the GITHUB_TOKEN used in all jobs has only read access to repository contents, adhering to the principle of least privilege.

Suggested changeset 1
.github/workflows/publish.puppetforge.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/publish.puppetforge.yml b/.github/workflows/publish.puppetforge.yml
--- a/.github/workflows/publish.puppetforge.yml
+++ b/.github/workflows/publish.puppetforge.yml
@@ -4,2 +4,5 @@
 
+permissions:
+  contents: read
+
 jobs:
EOF
@@ -4,2 +4,5 @@

permissions:
contents: read

jobs:
Copilot is powered by AI and may make mistakes. Always verify output.
12 changes: 12 additions & 0 deletions integration/keeper_secrets_manager_puppet/.fixtures.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This file can be used to install module dependencies for unit testing
# See https://github.com/puppetlabs/puppetlabs_spec_helper#using-fixtures for details
---
fixtures:
forge_modules:
stdlib:
repo: "puppetlabs/stdlib"
ref: "9.2.0"
repositories:
stdlib:
repo: "https://github.com/puppetlabs/puppetlabs-stdlib.git"
ref: "v9.2.0"
5 changes: 5 additions & 0 deletions integration/keeper_secrets_manager_puppet/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*.rb eol=lf
*.erb eol=lf
*.pp eol=lf
*.sh eol=lf
*.epp eol=lf
Loading
Loading