Skip to content

Secrets Rotation Reminder #5

Secrets Rotation Reminder

Secrets Rotation Reminder #5

name: Secrets Rotation Reminder
on:
schedule:
# Run on the 1st of every month at 9:00 UTC
- cron: '0 9 1 * *'
workflow_dispatch:
permissions:
issues: write
contents: read
jobs:
check-secrets-age:
name: Check Secrets Rotation Status
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Generate Secrets Rotation Report
id: rotation-check
run: |
cat << 'EOF' > check_secrets_rotation.py
import json
from datetime import datetime, timedelta
def generate_rotation_report():
# Define secrets that need rotation
secrets_inventory = {
'blockchain': [
{'name': 'INFURA_KEY', 'rotation_days': 90, 'priority': 'HIGH'},
{'name': 'ALCHEMY_KEY', 'rotation_days': 90, 'priority': 'HIGH'},
{'name': 'PRIVATE_KEY_DEV', 'rotation_days': 180, 'priority': 'CRITICAL'},
{'name': 'PRIVATE_KEY_PROD', 'rotation_days': 180, 'priority': 'CRITICAL'},
{'name': 'ETHERSCAN_API_KEY', 'rotation_days': 90, 'priority': 'MEDIUM'},
{'name': 'POLYGONSCAN_API_KEY', 'rotation_days': 90, 'priority': 'MEDIUM'},
],
'infrastructure': [
{'name': 'AWS_ACCESS_KEY_ID', 'rotation_days': 90, 'priority': 'HIGH'},
{'name': 'AWS_SECRET_ACCESS_KEY', 'rotation_days': 90, 'priority': 'HIGH'},
{'name': 'VERCEL_TOKEN', 'rotation_days': 60, 'priority': 'MEDIUM'},
{'name': 'TERRAFORM_CLOUD_TOKEN', 'rotation_days': 90, 'priority': 'HIGH'},
],
'cicd': [
{'name': 'NPM_TOKEN', 'rotation_days': 90, 'priority': 'MEDIUM'},
{'name': 'DOCKER_USERNAME', 'rotation_days': 90, 'priority': 'MEDIUM'},
{'name': 'DOCKER_PASSWORD', 'rotation_days': 90, 'priority': 'MEDIUM'},
]
}
report = {
'timestamp': datetime.now().isoformat(),
'report_date': datetime.now().strftime('%Y-%m-%d'),
'secrets_by_category': secrets_inventory,
'rotation_reminders': []
}
print("🔑 Secrets Rotation Status Report")
print(f"Generated: {report['report_date']}")
print("\n" + "="*60)
for category, secrets in secrets_inventory.items():
print(f"\n📂 Category: {category.upper()}")
for secret in secrets:
print(f" - {secret['name']}")
print(f" Rotation Period: {secret['rotation_days']} days")
print(f" Priority: {secret['priority']}")
report['rotation_reminders'].append({
'category': category,
'secret': secret['name'],
'rotation_days': secret['rotation_days'],
'priority': secret['priority'],
'recommendation': f"Rotate every {secret['rotation_days']} days"
})
# Save report
with open('secrets_rotation_report.json', 'w') as f:
json.dump(report, f, indent=2)
# Generate markdown report
with open('secrets_rotation_report.md', 'w') as f:
f.write("# 🔑 Secrets Rotation Report\n\n")
f.write(f"**Generated**: {report['report_date']}\n\n")
f.write("## Rotation Schedule\n\n")
for category, secrets in secrets_inventory.items():
f.write(f"### {category.title()}\n\n")
f.write("| Secret Name | Rotation Period | Priority |\n")
f.write("|-------------|-----------------|----------|\n")
for secret in secrets:
priority_emoji = "🔴" if secret['priority'] == 'CRITICAL' else "🟠" if secret['priority'] == 'HIGH' else "🟡"
f.write(f"| `{secret['name']}` | {secret['rotation_days']} days | {priority_emoji} {secret['priority']} |\n")
f.write("\n")
f.write("## Rotation Instructions\n\n")
f.write("1. Generate new secret/key/token\n")
f.write("2. Update in GitHub repository secrets\n")
f.write("3. Update in all environments (dev, staging, prod)\n")
f.write("4. Test thoroughly before rotating production secrets\n")
f.write("5. Revoke old secret/key/token\n")
f.write("6. Document rotation date\n\n")
f.write("## Priority Levels\n\n")
f.write("- 🔴 **CRITICAL**: Rotate immediately if compromised, review monthly\n")
f.write("- 🟠 **HIGH**: Regular rotation required, review quarterly\n")
f.write("- 🟡 **MEDIUM**: Standard rotation schedule, review semi-annually\n\n")
f.write("---\n\n")
f.write("*Remember: Never commit secrets to source code!*\n")
print("\n✅ Rotation report generated")
# Output for GitHub Actions
import os
with open(os.environ.get('GITHUB_OUTPUT', 'output.txt'), 'a') as f:
f.write(f"total_secrets={sum(len(secrets) for secrets in secrets_inventory.values())}\n")
critical_count = sum(1 for secrets in secrets_inventory.values()
for secret in secrets if secret['priority'] == 'CRITICAL')
f.write(f"critical_secrets={critical_count}\n")
if __name__ == '__main__':
generate_rotation_report()
EOF
python check_secrets_rotation.py
- name: Upload Rotation Report
uses: actions/upload-artifact@v4
with:
name: secrets-rotation-report
path: |
secrets_rotation_report.json
secrets_rotation_report.md
retention-days: 90
- name: Create GitHub Issue for Rotation Reminder
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const reportMd = fs.readFileSync('secrets_rotation_report.md', 'utf8');
const issueTitle = `🔑 Monthly Secrets Rotation Reminder - ${new Date().toISOString().split('T')[0]}`;
const issueBody = `${reportMd}
---
## Action Items
- [ ] Review all CRITICAL priority secrets
- [ ] Rotate any secrets older than rotation period
- [ ] Update secrets in GitHub repository settings
- [ ] Test applications after rotation
- [ ] Document rotation dates
- [ ] Close this issue when review is complete
## Resources
- [Security Guide](SECURITY_GUIDE.md)
- [GitHub Secrets Settings](https://github.com/${{ github.repository }}/settings/secrets/actions)
---
**Total Secrets to Review**: ${{ steps.rotation-check.outputs.total_secrets }}
**Critical Secrets**: ${{ steps.rotation-check.outputs.critical_secrets }}
**ALLAHU AKBAR! 🕋🔒💎🌌**`;
// Check if similar issue already exists
const issues = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'security,secrets-rotation'
});
const existingIssue = issues.data.find(issue =>
issue.title.includes('Monthly Secrets Rotation Reminder')
);
if (existingIssue) {
console.log('Existing rotation reminder issue found, updating comment');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existingIssue.number,
body: `Updated rotation reminder for ${new Date().toISOString().split('T')[0]}\n\n${reportMd}`
});
} else {
console.log('Creating new rotation reminder issue');
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: issueTitle,
body: issueBody,
labels: ['security', 'secrets-rotation', 'maintenance']
});
}
- name: Create Job Summary
run: |
cat secrets_rotation_report.md >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "A GitHub issue has been created to track this month's secrets rotation review." >> $GITHUB_STEP_SUMMARY