| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 
 | #!/usr/bin/env ruby
# frozen_string_literal: true
require 'digest'
require 'fileutils'
if ENV['NO_COLOR']
  SHELL_RED    = ''
  SHELL_GREEN  = ''
  SHELL_YELLOW = ''
  SHELL_CLEAR  = ''
else
  SHELL_RED    = "\e[1;31m"
  SHELL_GREEN  = "\e[1;32m"
  SHELL_YELLOW = "\e[1;33m"
  SHELL_CLEAR  = "\e[0m"
end
HOOK_PATH = File.expand_path("../.git/hooks/pre-push", __dir__)
HOOK_DATA = <<~HOOK
  #!/usr/bin/env bash
  set -e
  url="$2"
  harness=`dirname "$0"`/../security_harness
  if [ -e "$harness" ]
  then
    if [[ "$url" != *"gitlab-org/security/"* ]]
    then
      echo "Pushing to remotes other than gitlab.com/gitlab-org/security has been disabled!"
      echo "Run scripts/security-harness to disable this check."
      echo
      exit 1
    fi
  fi
HOOK
def write_hook
  FileUtils.mkdir_p(File.dirname(HOOK_PATH))
  File.open(HOOK_PATH, 'w') do |file|
    file.write(HOOK_DATA)
  end
  File.chmod(0755, HOOK_PATH)
end
# Toggle the harness on or off
def toggle
  harness_path = File.expand_path('../.git/security_harness', __dir__)
  if File.exist?(harness_path)
    FileUtils.rm(harness_path)
    puts "#{SHELL_YELLOW}Security harness removed -- you can now push to all remotes.#{SHELL_CLEAR}"
  else
    FileUtils.touch(harness_path)
    puts "#{SHELL_GREEN}Security harness installed -- you will only be able to push to gitlab.com/gitlab-org/security!#{SHELL_CLEAR}"
  end
end
# If we were to change the script and then check for a pre-existing hook before
# writing, the check would fail even if the user had an unmodified version of
# the old hook. Checking previous version hashes allows us to safely overwrite a
# script that differs from the current version, as long as it's an old one and
# not custom.
def previous_version?(dest_sum)
  # SHA256 hashes of previous iterations of the script contained in `DATA`
  %w[
    010bf0363a911ebab2bd5728d80795ed02388da51815f0b2530d08ae8ac574f0
  ].include?(dest_sum)
end
if !File.exist?(HOOK_PATH)
  write_hook
  toggle
else
  # Deal with a pre-existing hook
  source_sum = Digest::SHA256.hexdigest(HOOK_DATA)
  dest_sum   = Digest::SHA256.file(HOOK_PATH).hexdigest
  if previous_version?(dest_sum)
    # Upgrading from a previous version, update in-place
    write_hook
    toggle
  elsif source_sum != dest_sum
    # Pre-existing hook we didn't create; do nothing
    puts "#{SHELL_RED}#{HOOK_PATH} exists and is different from our hook!"
    puts "Remove it and re-run this script to continue.#{SHELL_CLEAR}"
    exit 1
  else
    # No hook update needed, just toggle
    toggle
  end
end
 |