Class: Fastlane::Actions::VerifyXcodeAction

Inherits:
Fastlane::Action show all
Defined in:
lib/fastlane/actions/verify_xcode.rb

Documentation collapse

Class Method Summary collapse

Methods inherited from Fastlane::Action

action_name, author, output, return_value, sh, step_text

Class Method Details

.authorsObject



98
99
100
# File 'lib/fastlane/actions/verify_xcode.rb', line 98

def self.authors
  ["KrauseFx"]
end

.available_optionsObject



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/fastlane/actions/verify_xcode.rb', line 86

def self.available_options
  [
    FastlaneCore::ConfigItem.new(key: :xcode_path,
                                 env_name: "FL_VERIFY_XCODE_XCODE_PATH",
                                 description: "The path to the Xcode installation to test",
                                 default_value: File.expand_path('../../', FastlaneCore::Helper.xcode_path),
                                 verify_block: proc do |value|
                                   UI.user_error!("Couldn't find Xcode at path '#{value}'") unless File.exist?(value)
                                 end)
  ]
end

.descriptionObject



74
75
76
# File 'lib/fastlane/actions/verify_xcode.rb', line 74

def self.description
  "Verifies that the Xcode installation is properly signed by Apple"
end

.detailsObject



78
79
80
81
82
83
84
# File 'lib/fastlane/actions/verify_xcode.rb', line 78

def self.details
  [
    "This action was implemented after the recent Xcode attacked to make sure",
    "you're not using a hacked Xcode installation.",
    "http://researchcenter.paloaltonetworks.com/2015/09/novel-malware-xcodeghost-modifies-xcode-infects-apple-ios-apps-and-hits-app-store/"
  ].join("\n")
end

.is_supported?(platform) ⇒ Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/fastlane/actions/verify_xcode.rb', line 102

def self.is_supported?(platform)
  [:ios, :mac].include?(platform)
end

.run(params) ⇒ Object



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
# File 'lib/fastlane/actions/verify_xcode.rb', line 7

def self.run(params)
  UI.success("Verifying your Xcode installation at path '#{params[:xcode_path]}'...")

  # Check 1/2

  UI.success("Verifying Xcode was signed by Apple Inc.")
  command = "codesign --display --verbose=4 '#{params[:xcode_path]}'"

  must_includes = [
    "Identifier=com.apple.dt.Xcode",
    "Authority=Apple Mac OS Application Signing",
    "Authority=Apple Worldwide Developer Relations Certification Authority",
    "Authority=Apple Root CA",
    "TeamIdentifier=59GAB85EFG"
  ]

  verify(command: command, must_includes: must_includes, params: params)

  UI.success("Successfully verified the code signature")

  # Check 2/2
  # More information https://developer.apple.com/news/?id=09222015a
  UI.message("Verifying Xcode using GateKeeper...")
  UI.success("This will take up to a few minutes, now is a great time to go for a coffee ☕...")

  command = "/usr/sbin/spctl --assess --verbose '#{params[:xcode_path]}'"
  must_includes = ['accepted']

  output = verify(command: command, must_includes: must_includes, params: params)

  if output.include?("source=Mac App Store") or output.include?("source=Apple") or output.include?("source=Apple System")
    UI.success("Successfully verified Xcode installation at path '#{params[:xcode_path]}' 🎧")
  else
    show_and_raise_error("Invalid Download Source of Xcode: #{output}", params[:xcode_path])
  end

  true
end

.show_and_raise_error(error, xcode_path) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/fastlane/actions/verify_xcode.rb', line 62

def self.show_and_raise_error(error, xcode_path)
  UI.error("Attention: Your Xcode Installation might be hacked.")
  UI.error("This might be a false alarm, if so, please submit an issue on GitHub")
  UI.error("The following information couldn't be found:")
  UI.error(error)
  UI.user_error!("The Xcode installation at path '#{xcode_path}' might be compromised.")
end

.verify(command: nil, must_includes: nil, params: nil) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/fastlane/actions/verify_xcode.rb', line 46

def self.verify(command: nil, must_includes: nil, params: nil)
  output = Actions.sh(command)

  errors = []
  must_includes.each do |current|
    next if output.include?(current)
    errors << current
  end

  if errors.count > 0
    show_and_raise_error(errors.join("\n"), params[:xcode_path])
  end

  return output
end