Skip to main content

create-addon

Scaffold a new Dradis addon gem with the correct boilerplate structure. Ask questions to determine the addon type, name, description, and capabilities, then generate all required files in a new directory.

معلومات المصدر

المستودع
dradis/dradis-ce
آخر نشاط في المصدر
١٦ مارس ٢٠٢٦ في ١٦:٠٧
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٨٤٥
التفرعات
٢٢٨

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
create-addon
description
Scaffold a new Dradis addon gem with the correct boilerplate structure. Ask questions to determine the addon type, name, description, and capabilities, then generate all required files in a new directory.
You are scaffolding a new Dradis addon. Follow these steps exactly. ## Step 1 — Gather information Ask the user the following questions one group at a time. Keep the tone friendly and jargon-free. Wait for all answers in a group before moving to the next group. **Group 1 — The basics:** Ask these four questions together: 1. **What would you like to call your addon?** This can be a tool name, a product name, or just a short descriptive name. For example: "Custom Importer", "Custom Exporter", "ACME Risk Matrix". It will be used to name the addon directory and files. 2. **Describe what your addon does in one sentence.** For example: "Imports findings from our internal scanning tool into Dradis" or "Displays all project findings in a custom risk matrix table tailored to ACME's scoring methodology." 3. **Your name** — this will appear in the addon's metadata. 4. **Your email address** — also used in the addon's metadata. --- **Group 2 — What should your addon do?** Ask this as a simple choice. Frame it conversationally: > Dradis addons can do one or more of the following things. Which fits what you're building? > > **Option A — Import files** > Your addon will let users upload a file — any kind of file — and Dradis will read it and turn the contents into items in the project (like issues, notes, or evidence). Choose this if you have data in a file that you want to bring into Dradis automatically. > > **Option B — Export / generate reports** > Your addon will take the data already in a Dradis project and produce an output file from it — for example, a custom HTML report, a CSV export, or any other format your team needs. Choose this if you want to generate something *from* Dradis. > > **Option C — Add new pages to Dradis** > Your addon will add its own screens or interfaces inside the Dradis web app — for example, a custom risk matrix table, a team-specific findings view, or a bespoke workflow that only makes sense for your organisation. Choose this if you're building something that needs its own UI. > > **Option D — A combination** > Mix and match any of the above. Just tell us which ones apply. ## Step 2 — Confirm before creating Silently derive the following from the addon name: - `<slug>` — lowercase, hyphenated (e.g. `custom-importer`, `acme-risk-matrix`) - `<module_name>` — CamelCase (e.g. `CustomImporter`, `AcmeRiskMatrix`) - `<plugin_name>` — underscored (e.g. `custom_importer`, `acme_risk_matrix`) Then confirm with the user using only the details they gave you: > Here's what I'll create: > > - **Name:** <addon name they provided> > - **Description:** <description they provided> > - **Type:** <what they chose — Import, Export, Custom pages, or a combination> > - **Location:** `../plugins/dradis-<slug>/` > > Shall I go ahead? ## Step 3 — Generate files Create all files inside `../plugins/dradis-<slug>/` (a sibling directory to `dradis-ce`, under a `plugins/` folder). Generate every file listed below with correct content based on the answers. --- ### Files to generate #### `dradis-<slug>.gemspec` ```ruby $:.push File.expand_path('../lib', __FILE__) require 'dradis/plugins/<slug>/version' version = Dradis::Plugins::<module_name>::VERSION::STRING Gem::Specification.new do |spec| spec.platform = Gem::Platform::RUBY spec.name = 'dradis-<slug>' spec.version = version spec.summary = '<description>' spec.description = '<description>' spec.license = 'GPL-2' spec.authors = ['<author_name>'] spec.email = ['<author_email>'] spec.homepage = 'https://dradis.com' spec.files = `git ls-files`.split($\) spec.executables = spec.files.grep(%r{^bin/}).map { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ['lib'] spec.add_dependency 'dradis-plugins', '~> 4.0' spec.add_development_dependency 'bundler', '~> 2.0' spec.add_development_dependency 'combustion', '~> 1.3' spec.add_development_dependency 'rake' spec.add_development_dependency 'rspec-rails' end ``` #### `Gemfile` ```ruby source 'https://rubygems.org' gemspec ``` #### `Rakefile` ```ruby require 'bundler/gem_tasks' require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) task default: :spec ``` #### `lib/dradis-<slug>.rb` ```ruby require 'dradis-plugins' require 'dradis/plugins/<slug>' ``` #### `lib/dradis/plugins/<slug>.rb` ```ruby module Dradis::Plugins::<module_name> PLUGIN_NAME = :<plugin_name> end require 'dradis/plugins/<slug>/engine' require 'dradis/plugins/<slug>/gem_version' require 'dradis/plugins/<slug>/version' ``` If upload addon, also add: ```ruby require 'dradis/plugins/<slug>/field_processor' require 'dradis/plugins/<slug>/importer' require 'dradis/plugins/<slug>/mapping' ``` #### `lib/dradis/plugins/<slug>/engine.rb` The `provides` line reflects the user's chosen option(s): - Import only: `provides :upload` - Export only: `provides :export` - Custom pages only: `provides :addon` - Any combination: `provides :upload, :export` / `provides :upload, :addon` / etc. ```ruby module Dradis::Plugins::<module_name> class Engine < ::Rails::Engine isolate_namespace Dradis::Plugins::<module_name> include ::Dradis::Plugins::Base description '<description>' provides :<capability> # one or more of: :upload, :export, :addon end end ``` If `provides :addon` or `provides :export` is included, add an initializer block to mount the engine. Use `routes.append` (not `prepend`) so the engine never overrides the main app's routes: ```ruby initializer '<slug>.mount_engine' do Rails.application.routes.append do mount Dradis::Plugins::<module_name>::Engine => '/', as: :<plugin_name> end end ``` #### `lib/dradis/plugins/<slug>/version.rb` ```ruby require_relative 'gem_version' module Dradis module Plugins module <module_name> module VERSION MAJOR = 0 MINOR = 1 TINY = 0 PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') end end end end ``` #### `lib/dradis/plugins/<slug>/gem_version.rb` ```ruby module Dradis module Plugins module <module_name> def self.gem_version Gem::Version.new VERSION::STRING end end end end ``` #### `lib/dradis/plugins/<slug>/importer.rb` (upload addons only) ```ruby module Dradis::Plugins::<module_name> class Importer < Dradis::Plugins::Upload::Importer # Override the import method to process the uploaded file. # # The `params` hash includes: # params[:file] - path to the uploaded file (a Tempfile or String path) # params[:project] - the current Dradis project # # Use content_service to create nodes, issues, and evidence: # content_service.create_node(label: 'hostname') # content_service.create_note(node: node, text: '#[Title]#\nValue') # content_service.create_issue(text: '#[Title]#\nValue') # content_service.create_evidence(issue: issue, node: node, content: '#[Port]#\n443') # # Use mapping_service to apply field mappings from templates: # mapping_service.apply_mapping(source: :<entity>, data: object) def import(params = {}) file_content = File.read(params[:file]) # TODO: parse file_content and iterate over findings logger.info { 'Done.' } end end end ``` #### `lib/dradis/plugins/<slug>/field_processor.rb` (upload addons only) ```ruby module Dradis::Plugins::<module_name> class FieldProcessor < Dradis::Plugins::Upload::FieldProcessor # Map a Liquid template field name to a value from the source data object. # # `params[:data]` is the object you passed to mapping_service.apply_mapping. # `params[:field]` is the field name from the template (e.g. '<plugin_name>[entity.attribute]'). # # Example: # when '<plugin_name>[finding.title]' then object.title def value(params = {}) _object = params[:data] _field = params[:field] case params[:field] # TODO: add field mappings here # when '<plugin_name>[finding.title]' then object.title end end end end ``` #### `lib/dradis/plugins/<slug>/mapping.rb` (upload addons only) ```ruby module Dradis::Plugins::<module_name> module Mapping # DEFAULT_MAPPING defines the default Liquid templates used when importing. # Keys are entity types (matching your importer), values are field-to-template maps. # Template variables use the syntax: {{ <plugin_name>[entity.attribute] }} DEFAULT_MAPPING = { issue: { 'Title' => '{{ <plugin_name>[issue.title] }}', 'Description' => '{{ <plugin_name>[issue.description] }}' }, evidence: { 'Output' => '{{ <plugin_name>[evidence.output] }}' } }.freeze SOURCE_FIELDS = { issue: %w[ issue.title issue.description ], evidence: %w[ evidence.output ] }.freeze end end ``` Adjust entity names and fields based on the user's answers about their data model. #### `templates/` (upload addons only) Create both sample files. Use the Dradis `#[FieldName]#` syntax. **`templates/issue.sample`:** ``` #[Title]# {{ <plugin_name>[issue.title] }} #[Description]# {{ <plugin_name>[issue.description] }} ``` **`templates/evidence.sample`:** ``` #[Output]# {{ <plugin_name>[evidence.output] }} ``` #### `spec/spec_helper.rb` ```ruby ENV['RAILS_ENV'] ||= 'test' require 'combustion' Combustion.initialize! :all require 'rspec/rails' RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true end config.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end config.shared_context_metadata_behavior = :apply_to_host_groups end ``` #### `spec/dradis/plugins/<slug>/importer_spec.rb` (upload addons only) ```ruby require 'spec_helper' describe Dradis::Plugins::<module_name>::Importer do pending 'add importer specs here' end ``` #### `spec/fixtures/files/.gitkeep` Empty placeholder file so the fixtures directory is tracked. #### `.gitignore` ``` *.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc/ coverage/ doc/ lib/bundler/man/ pkg/ rdoc/ spec/reports/ test/tmp/ test/version_tmp/ tmp/ ``` #### `LICENSE` ``` Copyright (c) <year> <author_name> This software is open source and available under the GNU General Public License version 2 (GPL-2). See https://www.gnu.org/licenses/old-licenses/gpl-2.0.html ``` #### `CHANGELOG.md` ```markdown # Changelog ## [Unreleased] ### Added - Initial release ``` #### `README.md` ```markdown # dradis-<slug> <description> ## Installation Add to your Dradis `Gemfile`: ```ruby gem 'dradis-<slug>' ``` Then run: ``` bundle install ``` ## Usage <!-- TODO: describe how to use this addon -->
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub