cocoapods-keys 0.9.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 54dc28574496b098df76d5fbb5fb61c09cb66839
4
- data.tar.gz: 6037257545de31f6c89d62b740732c8174cdf3d7
3
+ metadata.gz: 43e284067bd4672be8b813d0f5590572156eabda
4
+ data.tar.gz: 42960e0f836c6b72f6e8a34869346e0c1ada5b00
5
5
  SHA512:
6
- metadata.gz: 177cba97497cb4433c09e2606d2f1a9bdfb2af384bc0bd1d54f479927fcec670c26d7601fdc0c1decc56119443231b8c74d4582a6429665b1ae0ff8c8fda51a1
7
- data.tar.gz: 73b33ac99ab1fa60b8be9639bb922bc213e2b7190e6bcaa70b8bc470b01090eeb740eb872a9fb97321b972c6e14c438986da3a7e975701cd2660f23eff33a8ac
6
+ metadata.gz: f6de3d8e783506b471617ed1b67f385376734ce85f606996f1d11b17273513a77a0cff78992aace1501b38c3a419676b7e181bc1596dfac104badffa2fa0b758
7
+ data.tar.gz: ab271fdb4dc0027451ae75f3e36f9097a691c3b6a30020f0b1d21b01e40bf338c2897116cc32ad02bf5718a9ec1434409a0868b8cca27261febc832cca0acfec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cocoapods-keys (0.9.0)
4
+ cocoapods-keys (1.0.0)
5
5
  osx_keychain
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -14,7 +14,7 @@ Requires CocoaPods 0.34+.
14
14
 
15
15
  Key names are stored in `~/cocoapods/keys/` and key values in the OS X keychain. When you run `pod install` or `pod update`, an Objective-C class is created with scrambled versions of the keys, making it difficult to just [dump](https://github.com/stefanesser/dumpdecrypted) the contents of the decrypted binary and extract the keys. At runtime, the keys are unscrambled for use in your app.
16
16
 
17
- The generated Objective-C classes are stored in the `Pods/Keys` directory, so if you're checking in your [Pods folder](http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control), just add `Pods/Keys` to your `.gitignore` file.
17
+ The generated Objective-C classes are stored in the `Pods/Keys` directory, so if you're checking in your [Pods folder](http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control), just add `Pods/Keys` to your `.gitignore` file. CocoaPods-Keys supports integration in Swift or Objective-C projects.
18
18
 
19
19
  ## Usage
20
20
 
@@ -45,12 +45,12 @@ For example:
45
45
  └ redditAPIToken & mixpanelAPIToken
46
46
  ```
47
47
 
48
- After the next `pod install` or `pod update` keys will add a new Objective-C class to your Pods xcworkspace. This provides an API to your keys from Cocoa code. For example the application code above would look like:
48
+ After the next `pod install` or `pod update` keys will add a new `Keys` framework to your Pods project. This provides an API to your keys from Cocoa code. For example the application code above would look like:
49
49
 
50
50
  ``` objc
51
51
 
52
52
  #import "ORAppDelegate.h"
53
- #import <CocoaPods-Keys/MyApplicationKeys.h>
53
+ #import <Keys/MyApplicationKeys.h>
54
54
  #import <ARAnalytics/ARAnalytics.h>
55
55
 
56
56
  @implementation ORAppDelegate
@@ -67,6 +67,38 @@ After the next `pod install` or `pod update` keys will add a new Objective-C cla
67
67
 
68
68
  ```
69
69
 
70
+ ## Usage via CocoaPods 0.36
71
+
72
+ Using the new Plugin API in CocoaPods we can automate a lot of the fiddly bits away. You define what keys you want inside your [Podfile](https://github.com/artsy/eidolon/blob/0a9f5947914eb637fd4abf364fa3532b56da3c52/Podfile#L6-L21) and Keys will detect what keys are not yet set. If you need to specify a different project name from the target name, use the key `:target` to specify it.
73
+
74
+ ```
75
+ plugin 'cocoapods-keys', {
76
+ :project => "Eidolon",
77
+ :keys => [
78
+ "ArtsyAPIClientSecret",
79
+ "ArtsyAPIClientKey",
80
+ "HockeyProductionSecret",
81
+ "HockeyBetaSecret",
82
+ "MixpanelProductionAPIClientKey",
83
+ ...
84
+ ]}
85
+ ```
86
+
87
+ Then running `pod install` will prompt for the keys not yet set and you can ensure everyone has the same setup.
88
+
89
+ #### Other commands
90
+
91
+ CocoaPods-keys has 3 other commands:
92
+
93
+ * `pod keys get [key] [optional project]`
94
+ Which will output the value of the key to STDOUT, useful for scripting.
95
+
96
+ * `pod keys rm [key] [optional project]`
97
+ Will remove a key from a project.
98
+
99
+ * `pod keys generate [optional project]`
100
+ Will generate the obfuscated Objective-C keys class (mainly used internally).
101
+
70
102
  #### Security
71
103
 
72
104
  Key security is difficult. Right now even the biggest apps get their keys [leaked](https://threatpost.com/twitter-oauth-api-keys-leaked-030713/77597). This is neatly summed up by John Adams of the Twitter Security Team on [Quora](http://www.quora.com/Twitter-1/How-were-the-Twitter-iPhone-and-Android-OAuth-keys-leaked).
@@ -1,3 +1,3 @@
1
1
  module CocoaPodsKeys
2
- VERSION = "0.9.5"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -21,7 +21,8 @@ module CocoaPodsKeys
21
21
 
22
22
  @data_length = @keys.values.map(&:length).reduce(:+) * (20 + rand(10))
23
23
  data = `head -c #{@data_length} /dev/random | base64 | head -c #{@data_length}`
24
- length = data.length
24
+ data = data + '\\"'
25
+ @data_length = data.length
25
26
 
26
27
  # Swap the characters within the hashed string with the characters from
27
28
  # the keyring values. Then store that index in a index-ed copy of the values.
@@ -32,15 +33,20 @@ module CocoaPodsKeys
32
33
  value.chars.each_with_index do |char, char_index|
33
34
  loop do
34
35
 
35
- index = rand data.length
36
- unless @used_indexes.include?(index)
37
- data[index] = char
38
-
39
- @used_indexes << index
36
+ if char == '"'
37
+ index = data.delete('\\').length - 1
40
38
  @indexed_keys[key][char_index] = index
41
39
  break
40
+ else
41
+ index = rand data.length
42
+ unless @used_indexes.include?(index)
43
+ data[index] = char
44
+
45
+ @used_indexes << index
46
+ @indexed_keys[key][char_index] = index
47
+ break
48
+ end
42
49
  end
43
-
44
50
  end
45
51
  end
46
52
  end
@@ -79,6 +85,7 @@ SOURCE
79
85
  //
80
86
 
81
87
  #import <objc/runtime.h>
88
+ #import <Foundation/NSDictionary.h>
82
89
  #import "<%= @name %>.h"
83
90
 
84
91
  #pragma clang diagnostic push
@@ -121,6 +128,20 @@ static NSString *_podKeys<%= Digest::MD5.hexdigest(key) %>(<%= name %> *self, SE
121
128
 
122
129
  static char <%= name %>Data[<%= @data_length %>] = "<%= @data %>";
123
130
 
131
+ - (NSString *)description
132
+ {
133
+ return [@{
134
+ <%- @keys.each do |key, value| -%>
135
+ @"<%= key %>": self.<%= key %>,
136
+ <%- end -%>
137
+ } description];
138
+ }
139
+
140
+ - (id)debugQuickLookObject
141
+ {
142
+ return [self description];
143
+ }
144
+
124
145
  @end
125
146
  SOURCE
126
147
 
@@ -131,7 +152,7 @@ SOURCE
131
152
 
132
153
  def render_erb(erb)
133
154
  require 'erb'
134
- ERB.new(erb).result(binding)
155
+ ERB.new(erb, nil, '-').result(binding)
135
156
  end
136
157
 
137
158
  def key_data_arrays
@@ -22,21 +22,21 @@ module CocoaPodsKeys
22
22
  name.split(/[^a-zA-Z0-9_]/).map { |s| s[0].upcase + s[1..-1] }.join('')
23
23
  end
24
24
 
25
+ def self.keychain_prefix
26
+ "cocoapods-keys-"
27
+ end
28
+
25
29
  def save(key, value)
26
30
  keychain = OSXKeychain.new
27
- keychain[keychain_prefix + name, key] = value
31
+ keychain[self.class.keychain_prefix + name, key] = value
28
32
  end
29
33
 
30
34
  def keychain_data
31
35
  keychain = OSXKeychain.new
32
36
  Hash[
33
- @keys.map { |key| [key, keychain[keychain_prefix + name, key]] }
37
+ @keys.map { |key| [key, keychain[self.class.keychain_prefix + name, key]] }
34
38
  ]
35
39
  end
36
40
 
37
- def keychain_prefix
38
- "cocoapods-keys-"
39
- end
40
-
41
41
  end
42
42
  end
@@ -20,6 +20,10 @@ module CocoaPodsKeys
20
20
  def self.get_keyring(path)
21
21
  get_keyring_at_path(yaml_path_for_path(path))
22
22
  end
23
+
24
+ def self.get_keyring_named(name)
25
+ self.get_all_keyrings.find { |k| k.name == name }
26
+ end
23
27
 
24
28
  def self.save_keyring(keyring)
25
29
  `mkdir -p #{keys_dir}`
@@ -1,8 +1,72 @@
1
+ require 'cocoapods-core'
2
+
1
3
  module CocoaPodsKeys
4
+ class << self
5
+ def podspec_for_current_project(spec_contents)
6
+ keyring = KeyringLiberator.get_keyring_named(user_options["project"]) || KeyringLiberator.get_keyring(Dir.getwd)
7
+ raise Informative, "Could not load keyring" unless keyring
8
+ key_master = KeyMaster.new(keyring)
9
+
10
+ spec_contents.gsub!(/%%SOURCE_FILES%%/, "#{key_master.name}.{h,m}")
11
+ spec_contents.gsub!(/%%PROJECT_NAME%%/, user_options["project"])
12
+ end
13
+
14
+ def setup
15
+ require 'preinstaller'
16
+
17
+ PreInstaller.new(user_options).setup
18
+ # Add our template podspec (needs to be remote, not local).
19
+ podfile.pod 'Keys', :git => 'https://github.com/ashfurrow/empty-podspec.git'
20
+ end
21
+
22
+ private
23
+
24
+ def podfile
25
+ Pod::Config.instance.podfile
26
+ end
27
+
28
+ def user_options
29
+ podfile.plugins["cocoapods-keys"]
30
+ end
31
+ end
32
+ end
33
+
34
+ module Pod
35
+ class Installer
36
+ alias_method :install_before_cocoapods_keys!, :install!
37
+
38
+ def install!
39
+ CocoaPodsKeys.setup
40
+ install_before_cocoapods_keys!
41
+ end
42
+
43
+ class Analyzer
44
+ class SandboxAnalyzer
45
+ alias_method :pod_state_before_cocoapods_keys, :pod_state
46
+
47
+ def pod_state(pod)
48
+ if pod == 'Keys'
49
+ # return :added if we were, otherwise assume the Keys have :changed since last install, following my mother's "Better Safe than Sorry" principle.
50
+ return :added if pod_added?(pod)
51
+ :changed
52
+ else
53
+ pod_state_before_cocoapods_keys(pod)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
2
59
 
3
- Pod::HooksManager.register(:post_install) do |options|
4
- require 'installer'
60
+ class Specification
61
+ class << self
62
+ alias_method :from_string_before_cocoapods_keys, :from_string
5
63
 
6
- Installer.new(options.sandbox_root).install!
64
+ def from_string(spec_contents, path, subspec_name = nil)
65
+ if path.to_s.include? "Keys.podspec"
66
+ CocoaPodsKeys.podspec_for_current_project(spec_contents)
67
+ end
68
+ from_string_before_cocoapods_keys(spec_contents, path, subspec_name)
69
+ end
70
+ end
7
71
  end
8
72
  end
@@ -4,6 +4,9 @@ module Pod
4
4
  class Keys < Command
5
5
  require 'pod/command/keys/list'
6
6
  require 'pod/command/keys/set'
7
+ require 'pod/command/keys/get'
8
+ require 'pod/command/keys/rm'
9
+ require 'pod/command/keys/generate'
7
10
 
8
11
  self.summary = "A key value store for environment settings in Cocoa Apps."
9
12
 
@@ -0,0 +1,43 @@
1
+ require 'keyring_liberator'
2
+ require 'key_master'
3
+
4
+ module Pod
5
+ class Command
6
+ class Keys
7
+ class Generate < Keys
8
+ include CocoaPodsKeys
9
+
10
+ self.summary = "Generates the .h and .m files representing the keys."
11
+
12
+ self.description = <<-DESC
13
+ Generates the Objective-C class containing obfuscated keys for the project
14
+ in the current working directory (if it exists). The .h and .m files are
15
+ generated in the current working directory.
16
+ DESC
17
+
18
+ def initialize(argv)
19
+ @project_name = argv.shift_argument
20
+ super
21
+ end
22
+
23
+ def run
24
+ key_master = KeyMaster.new(@keyring)
25
+
26
+ interface_file = key_master.name + '.h'
27
+ implementation_file = key_master.name + '.m'
28
+
29
+ File.write(interface_file, key_master.interface)
30
+ File.write(implementation_file, key_master.implementation)
31
+ end
32
+
33
+ def validate!
34
+ super
35
+ verify_podfile_exists!
36
+
37
+ @keyring = KeyringLiberator.get_keyring_named(@project_name) || KeyringLiberator.get_keyring(Dir.getwd)
38
+ help! "No keys associated with this directory or project name." unless @keyring
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,59 @@
1
+ require "keyring_liberator"
2
+ require "name_whisperer"
3
+
4
+ module Pod
5
+ class Command
6
+ class Keys
7
+
8
+ class Get < Keys
9
+ self.summary = "Print a values of a key."
10
+
11
+ self.description = <<-DESC
12
+ Outputs the value of a key to SDTOUT
13
+
14
+ A second optional operator can be done to force a project name.
15
+ DESC
16
+
17
+ self.arguments = [CLAide::Argument.new('key', true),
18
+ CLAide::Argument.new('project_name', false)]
19
+
20
+ def initialize(argv)
21
+ @key_name = argv.shift_argument
22
+ @project_name = argv.shift_argument
23
+ super
24
+ end
25
+
26
+ def validate!
27
+ super
28
+ verify_podfile_exists!
29
+ help! "A key name is required for lookup." unless @key_name
30
+ end
31
+
32
+ def run
33
+ keyring = get_current_keyring
34
+ if !keyring
35
+ $stderr.puts "Could not find a project for this folder"
36
+ return
37
+ end
38
+
39
+ if keyring.keys.include? @key_name
40
+ data = keyring.keychain_data
41
+ $stderr.puts data[@key_name]
42
+ else
43
+ $stderr.puts "Could not find value"
44
+ end
45
+ end
46
+
47
+ def get_current_keyring
48
+ current_dir = Dir.getwd
49
+ keyring = CocoaPodsKeys::KeyringLiberator.get_keyring current_dir
50
+ if !keyring && @project_name
51
+ return CocoaPodsKeys::KeyringLiberator.get_keyring_named @project_name
52
+ end
53
+ keyring
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,71 @@
1
+ require "keyring_liberator"
2
+ require "keyring"
3
+ require "name_whisperer"
4
+
5
+ module Pod
6
+ class Command
7
+ class Keys
8
+
9
+ class Rm < Keys
10
+ self.summary = "Remove a key-value pair from a project."
11
+
12
+ self.description = <<-DESC
13
+ Remove a key, and it's value from a project
14
+
15
+ A second optional operator can be done to force a project name.
16
+ DESC
17
+
18
+ self.arguments = [CLAide::Argument.new('key', true), CLAide::Argument.new('project_name', false)]
19
+
20
+ def initialize(argv)
21
+ @key_name = argv.shift_argument
22
+ @project_name = argv.shift_argument
23
+ super
24
+ end
25
+
26
+ def validate!
27
+ super
28
+ verify_podfile_exists!
29
+ help! "A key name is required for lookup." unless @key_name
30
+ end
31
+
32
+ def run
33
+ keyring = get_current_keyring
34
+ if !keyring
35
+ $stderr.puts "Could not find a project to remove the key from."
36
+ return
37
+ end
38
+
39
+ if keyring.keys.include? @key_name
40
+ keyring.save(@key_name, "")
41
+ keyring.keys.delete @key_name
42
+ CocoaPodsKeys::KeyringLiberator.save_keyring(keyring)
43
+
44
+ prefix = CocoaPodsKeys::Keyring.keychain_prefix
45
+ delete_generic = `security delete-generic-password -a #{@key_name} -l #{prefix+keyring.name} 2>&1`
46
+
47
+ if delete_generic.include? "security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain."
48
+ $stderr.puts "Removed value for #{@key_name}, but could not delete from Keychain."
49
+ elsif delete_generic.include? "password has been deleted."
50
+ $stderr.puts "Removed value for #{@key_name}, and deleted associated key in Keychain."
51
+ else
52
+ $stderr.puts "Removed value for #{@key_name}."
53
+ end
54
+ else
55
+ $stderr.puts "Could not find key named #{@key_name}."
56
+ end
57
+ end
58
+
59
+ def get_current_keyring
60
+ current_dir = Dir.getwd
61
+ keyring = CocoaPodsKeys::KeyringLiberator.get_keyring current_dir
62
+ if !keyring && @project_name
63
+ return CocoaPodsKeys::KeyringLiberator.get_keyring_named @project_name
64
+ end
65
+ keyring
66
+ end
67
+
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,47 @@
1
+ module CocoaPodsKeys
2
+ class PreInstaller
3
+ def initialize(user_options)
4
+ @options = user_options
5
+ end
6
+
7
+ def setup
8
+ require 'key_master'
9
+ require 'keyring_liberator'
10
+ require 'pod/command/keys/set'
11
+
12
+ current_dir = Dir.getwd
13
+ keyring = KeyringLiberator.get_keyring_named(@options["project"]) || KeyringLiberator.get_keyring(current_dir)
14
+ unless keyring
15
+ name = @options["project"] || CocoaPodsKeys::NameWhisperer.get_project_name
16
+ keyring = CocoaPodsKeys::Keyring.new(name, current_dir, [])
17
+ end
18
+
19
+ data = keyring.keychain_data
20
+ has_shown_intro = false
21
+ @options["keys"].each do |key|
22
+ unless data.keys.include? key
23
+
24
+ unless has_shown_intro
25
+ puts "\n CocoaPods-Keys has detected a keys mismatch for your setup."
26
+ has_shown_intro = true
27
+ end
28
+
29
+ puts " What is the key for " + key.green
30
+ answer = ""
31
+ loop do
32
+ print " > "
33
+ answer = STDIN.gets.chomp
34
+ break if answer.length > 0
35
+ end
36
+
37
+ puts ""
38
+ args = CLAide::ARGV.new([key, answer, keyring.name])
39
+ setter = Pod::Command::Keys::Set.new(args)
40
+ setter.run
41
+
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-keys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Orta Therox
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-11-17 00:00:00.000000000 Z
12
+ date: 2015-02-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: osx_keychain
@@ -70,15 +70,18 @@ files:
70
70
  - cocoapods_keys.gemspec
71
71
  - lib/cocoapods_keys.rb
72
72
  - lib/cocoapods_plugin.rb
73
- - lib/installer.rb
74
73
  - lib/key_master.rb
75
74
  - lib/keyring.rb
76
75
  - lib/keyring_liberator.rb
77
76
  - lib/name_whisperer.rb
78
77
  - lib/plugin.rb
79
78
  - lib/pod/command/keys.rb
79
+ - lib/pod/command/keys/generate.rb
80
+ - lib/pod/command/keys/get.rb
80
81
  - lib/pod/command/keys/list.rb
82
+ - lib/pod/command/keys/rm.rb
81
83
  - lib/pod/command/keys/set.rb
84
+ - lib/preinstaller.rb
82
85
  homepage: https://github.com/cocoapods/cocoapods-keys
83
86
  licenses:
84
87
  - MIT
@@ -1,53 +0,0 @@
1
- module CocoaPodsKeys
2
- class Installer
3
- def initialize(sandbox_root)
4
- @sandbox_root = sandbox_root
5
- end
6
-
7
- def install!
8
- require 'key_master'
9
- require 'keyring_liberator'
10
-
11
- keyring = KeyringLiberator.get_keyring(Dir.getwd)
12
-
13
- return unless keyring
14
-
15
- Pod::UI.section 'Adding keys' do
16
- key_master = KeyMaster.new(keyring)
17
-
18
- keys_folder = File.join(@sandbox_root, 'Keys')
19
- keys_headers_folder = File.join(@sandbox_root, 'Headers', 'Public', 'CocoaPods-Keys')
20
- interface_name = key_master.name + '.h'
21
- interface_file = File.join(keys_headers_folder, interface_name)
22
- implementation_file = File.join(keys_folder, key_master.name + '.m')
23
-
24
- Dir.mkdir keys_folder unless Dir.exists? keys_folder
25
- Dir.mkdir keys_headers_folder unless Dir.exists? keys_headers_folder
26
- File.open(interface_file, 'w') { |f| f.write(key_master.interface) }
27
- File.open(implementation_file, 'w') { |f| f.write(key_master.implementation) }
28
-
29
- project = Xcodeproj::Project.open File.join(@sandbox_root, 'Pods.xcodeproj')
30
-
31
- group = project.new_group('Keys')
32
- interface = group.new_file(interface_file)
33
- implementation = group.new_file(implementation_file)
34
-
35
- pods_target = project.targets.detect { |t| t.name == 'Pods' }
36
- unless pods_target
37
- pods_target = project.targets.detect { |t| t.name == 'Pods-' + keyring.name }
38
- end
39
-
40
- pods_target.add_file_references [implementation]
41
-
42
- # Swift Pod support
43
- if pods_target.product_type == "com.apple.product-type.framework"
44
- pods_target.add_file_references [interface]
45
- header_ref = pods_target.headers_build_phase.files[-1]
46
- header_ref.settings = { "ATTRIBUTES" => ["Public"] }
47
- end
48
-
49
- project.save
50
- end
51
- end
52
- end
53
- end