A simple module to delete specific files.
\n\nIt allows you to specify a list of files you want deleted on hosts in your infrastructure. When this module is deployed as part of your policy set, every time CFEngine runs, it will check if those files exist, and delete them if they do.
\n\nRecommendation: Enforce the removal of files known to be malicious or indicating insecure configuration.\nExamples of such files are `~/.shosts` files, `/etc/cron.deny`, etc.
\n\nThis module accepts input.\nBoth the cfbs CLI and Mission Portal (3.21 and beyond) allow you to specify the files you want deleted.\nHere is an example of what it looks like in Mission Portal:
\n\n
delete_files:delete_files.files\nArray of dicts having path and why keys.
path must be a regular expression matching the fully qualified path to a filewhy should explain why the file being absent is important {\n \"variables\": {\n \"delete_files:delete_files.files\": {\n \"comment\": \"Files and their required permissions\",\n \"value\": [\n {\n \"why\": \"The file lists remote hosts and users that are trusted by the local system when using the rshd daemon and can allow unauthenticated access to the system. Reccomended by CIS CCE-84145-2.\",\n \"path\": \"/etc/hosts.equiv\"\n },\n {\n \"why\": \"The file lists remote hosts and users that are trusted by the local system when using the rshd daemon and can allow unauthenticated access to the system. Reccomended by CIS CCE-84145-2.\",\n \"path\": \"/home/.*/.rhosts\"\n },\n {\n \"why\": \"The file lists remote hosts and users that are trusted by the local system when using the rshd daemon and can allow unauthenticated access to the system. Reccomended by CIS CCE-84145-2.\",\n \"path\": \"/root/.rhosts\"\n }\n ]\n }\n }\n }\nNotes:
\ndelete_files:DEBUG or default:DEBUG define results in DEBUG reports from policy.path and why keys is supported.why key is supported.why key added in version 2.0.0.CFEngine build module that installs ClamAV from upstream packages, keeps its signatures fresh, runs periodic scans, and reports the results as CFEngine Enterprise inventory.
\n
.deb/.rpm from clamav.net (Debian/Ubuntu and RHEL-family, x86_64/aarch64) and creates the clamav user.freshclam when signatures are older than 2 days (configurable).clamscan over /home, /root, /tmp, /var/tmp when the last report is older than 3 days (configurable).Only Linux is supported. Windows support is coming soon.
\ncfbs add clamav\ncfbs build\nScan intervals, scan targets, and excluded directories can be set interactively with cfbs input clamav. Any default can also be overridden via augments, e.g.:
{\n \"variables\": {\n \"clamav:globals.clamav_version\": \"1.5.4\",\n \"clamav:globals.max_age_days\": \"1\",\n \"clamav:globals.signature_max_age_days\": \"1\",\n \"clamav:globals.scan_target\": [\"/home\", \"/srv\"],\n \"clamav:globals.exclude_dirs\": [\"/proc\", \"/sys\", \"/dev\", \"/run\", \"/srv/backup\"]\n }\n}\nEntries in exclude_dirs are directory paths without a trailing slash. The module anchors each one and passes it to clamscan --exclude-dir, which matches it as a path prefix, so /dev also covers /dev/shm. Setting the list replaces the built-in one (/proc, /sys, /dev, /run, /var/lib/clamav, /var/cfengine), so include any of those you still want.
Trigger actions immediately:
\ncf-agent -KI --define clamav:want_scan_now # force a scan\ncf-agent -KI --define clamav:want_freshen_now # force a signature update\nThis module contains a ready-made Mission Portal compliance report covering infections, scan recency, and signature freshness - see compliance-report/README.md.
\nclamscan and freshclam load the full signature database into memory, ensure at least ~2 GB of available RAM on scanned hosts. On hosts with less memory, add a swap file with the manage-swap module.clamav-freshclam daemon locks the signature database while running, which causes the module\u2019s freshclam runs to fail. Disable it with systemctl disable --now clamav-freshclam if CFEngine should manage updates.The git promise type enables writing concise policy for cloning a git repo and keeping it updated.
| Name | \n\t\t\t\t\tType | \n\t\t\t\t\tDescription | \n\t\t\t\t\tMandatory | \n\t\t\t\t\tDefault | \n\t\t\t
|---|---|---|---|---|
destination | \n\t\t\t\t\tstring | \n\t\t\t\t\tDestination path | \n\t\t\t\t\tNo | \n\t\t\t\t\tPromiser | \n\t\t\t
repository | \n\t\t\t\t\tstring | \n\t\t\t\t\tGit repository URL | \n\t\t\t\t\tYes | \n\t\t\t\t\t- | \n\t\t\t
bare | \n\t\t\t\t\tboolean | \n\t\t\t\t\tIf true, clones the repository as bare repository | \n\t\t\t\t\tNo | \n\t\t\t\t\t- | \n\t\t\t
clone | \n\t\t\t\t\tboolean | \n\t\t\t\t\tIf true, clones the repository if it doesn\u2019t exist at the destination path | \n\t\t\t\t\tNo | \n\t\t\t\t\t- | \n\t\t\t
depth | \n\t\t\t\t\tinteger | \n\t\t\t\t\tCreate a shallow clone with a history truncated to the specified number or revisions. Set to 0 to perform a full clone. | \n\t\t\t\t\tNo | \n\t\t\t\t\t0 | \n\t\t\t
executable | \n\t\t\t\t\tstring | \n\t\t\t\t\tPath to the git executable | \n\t\t\t\t\tNo | \n\t\t\t\t\tgit | \n\t\t\t
force | \n\t\t\t\t\tboolean | \n\t\t\t\t\tIf true, discard any local changes to the repository before updating it | \n\t\t\t\t\tNo | \n\t\t\t\t\t- | \n\t\t\t
recursive | \n\t\t\t\t\tboolean | \n\t\t\t\t\tIf true, use the --recursive git option | \n\t\t\t\t\tNo | \n\t\t\t\t\tyes | \n\t\t\t
reference | \n\t\t\t\t\tstring | \n\t\t\t\t\tIf set, use the --reference git option with the given value | \n\t\t\t\t\tNo | \n\t\t\t\t\t- | \n\t\t\t
remote | \n\t\t\t\t\tstring | \n\t\t\t\t\tName of the git remote | \n\t\t\t\t\tNo | \n\t\t\t\t\torigin | \n\t\t\t
ssh_executable | \n\t\t\t\t\tstring | \n\t\t\t\t\tPath to the ssh executable | \n\t\t\t\t\tNo | \n\t\t\t\t\tssh | \n\t\t\t
ssh_options | \n\t\t\t\t\tstring | \n\t\t\t\t\tAdditional options for the git command, e.g. -o StrictHostKeyChecking=no | \n\t\t\t\t\tNo | \n\t\t\t\t\t- | \n\t\t\t
update | \n\t\t\t\t\tboolean | \n\t\t\t\t\tIf true, updates the repository if it already exists at the destination path | \n\t\t\t\t\tNo | \n\t\t\t\t\t- | \n\t\t\t
version | \n\t\t\t\t\tstring | \n\t\t\t\t\tThe version of the repository to checkout. It can be a branch name, a tag name or a SHA-1 hash. | \n\t\t\t\t\tNo | \n\t\t\t\t\tHEAD | \n\t\t\t
Check out a git repository in a given destination path:
\nbundle agent main\n{\n git:\n \"starter_pack_repo\"\n repository => \"https://github.com/cfengine/starter_pack\",\n destination => \"/northern.tech/cfengine/starter-pack\",\n version => \"master\";\n}\nFull example with almost all the attributes:
\nbundle agent main\n{\n git:\n \"starter_pack_repo\"\n destination => \"/northern.tech/cfengine/starter_pack\",\n repository => \"https://github.com/cfengine/starter_pack\",\n bare => \"true\",\n clone => \"true\",\n depth => \"1\",\n executable => \"/bin/git\",\n force => \"true\",\n recursive => \"true\",\n remote => \"origin\",\n ssh_options => \"UserKnownHostsFile=/dev/null\",\n update => \"true\",\n version => \"master\";\n}\nThis module will set the HOME environment variable if it is not set already based on the user running cf-agent, typically root.
In order to add authentication you can use gitcredentials.
\nAn example of this usage would be to have two files in $HOME: .gitconfig and .git-credentials.
.gitconfig[credential]\n helper = store\n.git-credentialsUsing the store helper places the username and password in plaintext in $HOME/.git-credentials.
Here is an explanation of that file storage format:
\n\n\nThe
\n.git-credentialsfile is stored in plaintext. Each credential is stored on its own line as a URL like:
https://user:pass@example.com\n\n\nNo other kinds of lines (e.g. empty lines or comment lines) are allowed in the file, even though some may be silently ignored. Do not view or edit the file with editors.
\n
This software was created by the team at Northern.tech, with many contributions from the community.\nThanks everyone!
\nFeel free to open pull requests to expand this documentation, add features or fix problems.\nYou can also pick up an existing task or file an issue in our bug tracker.
\nThis software is licensed under the MIT License. See LICENSE in the root of the repository for the full license text.
\n" + } + }, + "library-for-promise-types-in-python": { + "0.3.1": { + "author": { + "image": "https://avatars.githubusercontent.com/u/1239823?v=4", + "name": "CFEngine", + "url": "https://github.com/cfengine" + }, + "versions": { + "0.1.0": { + "date": "Oct 26, 2021", + "latest": false + }, + "0.1.1": { + "date": "Nov 1, 2021", + "latest": false + }, + "0.2.1": { + "date": "Feb 8, 2023", + "latest": false + }, + "0.2.2": { + "date": "Mar 5, 2024", + "latest": false + }, + "0.2.3": { + "date": "Jun 19, 2024", + "latest": false + }, + "0.3.0": { + "date": "Jul 15, 2025", + "latest": false + }, + "0.3.1": { + "date": "Apr 1, 2026", + "latest": true + } + }, + "updated": "Apr 1, 2026", + "downloads": 9072, + "repo": "https://github.com/cfengine/modules", + "documentation": null, + "website": null, + "commit": "679c6c0b18cdb517c7595b1701c3707f47106da5", + "discussion": "https://github.com/cfengine/core/discussions/new?category=modules&title=library-for-promise-types-in-python&body=I+have+a+question+regarding...", + "discussionSearch": "https://github.com/cfengine/core/discussions/categories/modules?discussions_q=is%3Aopen+category%3AModules+library-for-promise-types-in-python", + "version": "0.3.1", + "readme": "A library for CFEngine custom promise types implemented in Python.\nIt provides the PromiseModule base class and many helper values and mechanisms that facilitates creation of custom promises.
If you\u2019d like to develop new promise types (or other modules) for CFEngine, we recommend finishing our getting started tutorial:
\nhttps://docs.cfengine.com/docs/3.21/getting-started.html
\n(The last part shows implementing your first module).
\nIf you feel comfortable with using CFEngine and writing Python code already, there is a template project you can just copy and start editing:
\nhttps://github.com/cfengine/promise-type-template
\nFor more detailed information about how custom promise types work, see our documentation:
\nhttps://docs.cfengine.com/docs/3.21/reference-promise-types-custom.html
\n" + } + } +} \ No newline at end of file diff --git a/e2e/modules/index.json b/e2e/modules/index.json new file mode 100644 index 0000000..249811d --- /dev/null +++ b/e2e/modules/index.json @@ -0,0 +1,156 @@ +{ + "name": "index", + "type": "index", + "index": { + "delete-files": { + "description": "Allows you to specify a list of files you want deleted on hosts in your infrastructure. When this module is deployed as part of your policy set, every time CFEngine runs, it will check if those files exist, and delete them if they do.", + "tags": [ + "supported", + "management" + ], + "repo": "https://github.com/nickanderson/cfengine-delete-files", + "by": "https://github.com/nickanderson", + "version": "2.0.0", + "commit": "84cce7c5653b6a5f2b5a28ebb33c697ffc676dd4", + "steps": [ + "copy delete-files.cf services/cfbs/modules/delete-files/delete-files.cf", + "input delete-files/input.json def.json", + "bundles delete_files:delete_files", + "policy_files services/cfbs/modules/delete-files/delete-files.cf" + ], + "input": [ + { + "type": "list", + "variable": "files", + "namespace": "delete_files", + "bundle": "delete_files", + "label": "Files", + "subtype": [ + { + "key": "path", + "type": "string", + "label": "Path", + "question": "Path to file" + }, + { + "key": "why", + "type": "string", + "label": "Why", + "question": "Why should this file be deleted?", + "default": "Unknown" + } + ], + "while": "Specify another file you want deleted on your hosts?" + } + ] + }, + "clamav": { + "description": "Automates the installation, scanning, and reporting of ClamAV antivirus software.", + "tags": [ + "compliance", + "experimental", + "inventory", + "security" + ], + "repo": "https://github.com/aleksandrychev/cfengine-clamav", + "by": "https://github.com/aleksandrychev", + "version": "0.1.0", + "commit": "6ebb89d7d54966b4a8cdbe8d68e510e47086fba8", + "dependencies": [ + "compliance-report-imports" + ], + "steps": [ + "copy policy/main.cf services/cfbs/modules/clamav/main.cf", + "json cfbs/def.json def.json", + "input ./input.json def.json", + "copy ./compliance-report/compliance_report_clamav.json .no-distrib/compliance-report-definitions/compliance_report_clamav.json" + ], + "input": [ + { + "type": "string", + "variable": "max_age_days", + "namespace": "clamav", + "bundle": "globals", + "label": "Scan interval (days)", + "question": "How many days may an existing scan report age before a new clamscan run is forced?", + "default": "3" + }, + { + "type": "string", + "variable": "signature_max_age_days", + "namespace": "clamav", + "bundle": "globals", + "label": "Signature update interval (days)", + "question": "How many days may pass between freshclam signature updates?", + "default": "2" + }, + { + "type": "list", + "variable": "scan_target", + "namespace": "clamav", + "bundle": "globals", + "label": "Scan targets", + "subtype": { + "type": "string", + "label": "Directory", + "question": "Directory for clamscan to scan recursively (defaults: /home /root /tmp /var/tmp)" + }, + "while": "Add another directory to scan?" + }, + { + "type": "list", + "variable": "exclude_dirs", + "namespace": "clamav", + "bundle": "globals", + "label": "Excluded directories", + "subtype": { + "type": "string", + "label": "Directory", + "question": "Directory clamscan should skip, without trailing slash. Answering replaces the whole default list (/proc /sys /dev /run /var/lib/clamav /var/cfengine), so re-add any you want to keep" + }, + "while": "Add another exclusion?" + } + ] + }, + "promise-type-git": { + "description": "Promise type to manage git repos.", + "tags": [ + "supported", + "promise-type" + ], + "repo": "https://github.com/cfengine/modules", + "by": "https://github.com/tranchitella", + "version": "0.2.6", + "commit": "3055538003b5dc88c80547703368da33fd43a5a9", + "subdirectory": "promise-types/git", + "dependencies": [ + "library-for-promise-types-in-python" + ], + "steps": [ + "copy git.py modules/promises/", + "append enable.cf services/init.cf" + ] + }, + "library-for-promise-types-in-python": { + "description": "Library enabling promise types implemented in python.", + "tags": [ + "supported", + "library" + ], + "repo": "https://github.com/cfengine/modules", + "by": "https://github.com/cfengine", + "version": "0.3.1", + "commit": "679c6c0b18cdb517c7595b1701c3707f47106da5", + "subdirectory": "libraries/python", + "steps": [ + "copy cfengine_module_library.py modules/promises/cfengine_module_library.py", + "replace_version 2 0.0.0 modules/promises/cfengine_module_library.py", + "copy cfengine_module_library.py modules/promises/cfengine.py", + "replace_version 2 0.0.0 modules/promises/cfengine.py" + ] + }, + "git": { + "alias": "promise-type-git" + } + } +} \ No newline at end of file diff --git a/e2e/test-environments.spec.ts b/e2e/test-environments.spec.ts index 25fe134..f988056 100644 --- a/e2e/test-environments.spec.ts +++ b/e2e/test-environments.spec.ts @@ -110,6 +110,10 @@ test.describe('with Docker', () => { const response = await fetch('http://localhost:8080/'); expect(response.status).toBe(200); expect(await response.text()).toContain('CFEngine Policy Builder demo project'); + // The logo the http promise downloaded (promise-type-http, added with its block). + const logo = await fetch('http://localhost:8080/cfengine-logo.svg'); + expect(logo.status).toBe(200); + expect(await logo.text()).toContain('