From f7e94fea1e75d7b5e4f0470614f2b0c4c81082ba Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Tue, 30 Aug 2016 13:08:50 -0300 Subject: [PATCH] WIP --- app/models/custom_rule.rb | 15 ++++++ app/models/push_rule.rb | 1 + .../20160830160157_create_custom_rules.rb | 12 +++++ db/schema.rb | 53 ++++++++++++------- lib/gitlab/checks/change_access.rb | 20 ++++++- 5 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 app/models/custom_rule.rb create mode 100644 db/migrate/20160830160157_create_custom_rules.rb diff --git a/app/models/custom_rule.rb b/app/models/custom_rule.rb new file mode 100644 index 00000000000000..604b766e0db92e --- /dev/null +++ b/app/models/custom_rule.rb @@ -0,0 +1,15 @@ +# Custom rules which will be checked on each file content +# present on commit. +# +# This rules are written especially to prevent secrets like +# private keys to be pushed accidentaly into a repository. +# +# Any file content into the commit which matches the ruby regular expression +# will prevent the push to happen. + +class CustomRule < ActiveRecord::Base + belongs_to :push_rule + validates :push_rule_id, :title, :regex, presence: true + + scope :enabled_rules, -> { where(enabled: true) } +end diff --git a/app/models/push_rule.rb b/app/models/push_rule.rb index b76774b75e497a..f2ba5dbaab6bde 100644 --- a/app/models/push_rule.rb +++ b/app/models/push_rule.rb @@ -1,5 +1,6 @@ class PushRule < ActiveRecord::Base belongs_to :project + has_many :custom_rules validates :project, presence: true, unless: "is_sample?" validates :max_file_size, numericality: { greater_than_or_equal_to: 0, only_integer: true } diff --git a/db/migrate/20160830160157_create_custom_rules.rb b/db/migrate/20160830160157_create_custom_rules.rb new file mode 100644 index 00000000000000..6701a5509cf3b6 --- /dev/null +++ b/db/migrate/20160830160157_create_custom_rules.rb @@ -0,0 +1,12 @@ +class CreateCustomRules < ActiveRecord::Migration + DOWNTIME = false + + def change + create_table :custom_rules do |t| + t.belongs_to :push_rule, index: true + t.string :title + t.string :regex + t.boolean :enabled + end + end +end diff --git a/db/schema.rb b/db/schema.rb index cd2a87cdd80223..641e58125ea2b7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160831223750) do +ActiveRecord::Schema.define(version: 20160830160157) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -321,6 +321,16 @@ add_index "ci_runners", ["locked"], name: "index_ci_runners_on_locked", using: :btree add_index "ci_runners", ["token"], name: "index_ci_runners_on_token", using: :btree + create_table "ci_services", force: :cascade do |t| + t.string "type" + t.string "title" + t.integer "project_id", null: false + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "active", default: false, null: false + t.text "properties" + end + create_table "ci_sessions", force: :cascade do |t| t.string "session_id", null: false t.text "data" @@ -376,6 +386,22 @@ add_index "ci_variables", ["gl_project_id"], name: "index_ci_variables_on_gl_project_id", using: :btree + create_table "ci_web_hooks", force: :cascade do |t| + t.string "url", null: false + t.integer "project_id", null: false + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "custom_rules", force: :cascade do |t| + t.integer "push_rule_id" + t.string "title" + t.string "regex" + t.boolean "enabled" + end + + add_index "custom_rules", ["push_rule_id"], name: "index_custom_rules_on_push_rule_id", using: :btree + create_table "deploy_keys_projects", force: :cascade do |t| t.integer "deploy_key_id", null: false t.integer "project_id", null: false @@ -727,12 +753,12 @@ t.boolean "share_with_group_lock", default: false t.integer "visibility_level", default: 20, null: false t.boolean "request_access_enabled", default: true, null: false - t.datetime "deleted_at" t.string "ldap_sync_status", default: "ready", null: false t.string "ldap_sync_error" t.datetime "ldap_sync_last_update_at" t.datetime "ldap_sync_last_successful_update_at" t.datetime "ldap_sync_last_sync_at" + t.datetime "deleted_at" end add_index "namespaces", ["created_at"], name: "index_namespaces_on_created_at", using: :btree @@ -874,19 +900,6 @@ add_index "personal_access_tokens", ["token"], name: "index_personal_access_tokens_on_token", unique: true, using: :btree add_index "personal_access_tokens", ["user_id"], name: "index_personal_access_tokens_on_user_id", using: :btree - create_table "project_features", force: :cascade do |t| - t.integer "project_id" - t.integer "merge_requests_access_level" - t.integer "issues_access_level" - t.integer "wiki_access_level" - t.integer "snippets_access_level" - t.integer "builds_access_level" - t.datetime "created_at" - t.datetime "updated_at" - end - - add_index "project_features", ["project_id"], name: "index_project_features_on_project_id", using: :btree - create_table "project_group_links", force: :cascade do |t| t.integer "project_id", null: false t.integer "group_id", null: false @@ -911,7 +924,11 @@ t.datetime "created_at" t.datetime "updated_at" t.integer "creator_id" + t.boolean "issues_enabled", default: true, null: false + t.boolean "merge_requests_enabled", default: true, null: false + t.boolean "wiki_enabled", default: true, null: false t.integer "namespace_id" + t.boolean "snippets_enabled", default: true, null: false t.datetime "last_activity_at" t.string "import_url" t.integer "visibility_level", default: 0, null: false @@ -935,6 +952,7 @@ t.integer "mirror_user_id" t.text "import_error" t.integer "ci_id" + t.boolean "builds_enabled", default: true, null: false t.boolean "shared_runners_enabled", default: true, null: false t.string "runners_token" t.string "build_coverage_regex" @@ -950,10 +968,9 @@ t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false t.boolean "has_external_issue_tracker" t.string "repository_storage", default: "default", null: false + t.boolean "repository_read_only" t.boolean "request_access_enabled", default: true, null: false t.boolean "has_external_wiki" - t.boolean "repository_read_only" - t.boolean "lfs_enabled" end add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree @@ -1295,8 +1312,8 @@ t.boolean "note_events", default: false, null: false t.boolean "enable_ssl_verification", default: true t.boolean "build_events", default: false, null: false - t.string "token" t.boolean "wiki_page_events", default: false, null: false + t.string "token" t.boolean "pipeline_events", default: false, null: false end diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb index 923eacedeca119..e880e7cbadc688 100644 --- a/lib/gitlab/checks/change_access.rb +++ b/lib/gitlab/checks/change_access.rb @@ -146,7 +146,7 @@ def check_commit_diff(commit, push_rule) return if validations.empty? - commit.raw_diffs(deltas_only: true).each do |diff| + commit.raw_diffs.each do |diff| validations.each do |validation| if error = validation.call(diff) return error @@ -170,6 +170,12 @@ def validations_for_commit(commit, push_rule) validations << file_size_validation(commit, push_rule.max_file_size) end + custom_rules = push_rule.custom_rules.enabled_rules + + if custom_rules.any? + validations << diff_content_validation(custom_rules) + end + validations end @@ -216,6 +222,18 @@ def file_size_validation(commit, max_file_size) end end + def diff_content_validation(rules) + lambda do |diff| + return if diff.deleted_file || diff.renamed_file + + forbidden_rules = rules.select { |rule| (diff.diff =~ Regexp.new(rule.regex)).present? } + + if forbidden_rules.any? + forbidden_rules.map { |rule| "Commit files contains forbidden content especified in #{rule.title}." }.join('/n') + end + end + end + def commits project.repository.new_commits(@newrev) end -- GitLab