ios_config_profile 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +9 -0
  3. data/.gitignore +35 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +602 -0
  6. data/.simplecov +4 -0
  7. data/CHANGELOG.md +67 -0
  8. data/CODE_OF_CONDUCT.md +13 -0
  9. data/Gemfile +5 -0
  10. data/LICENSE +661 -0
  11. data/README.md +15 -0
  12. data/Rakefile +5 -0
  13. data/ios_config_profile.gemspec +28 -0
  14. data/lib/ios_config_profile.rb +8 -0
  15. data/lib/ios_config_profile/basic_payload.rb +31 -0
  16. data/lib/ios_config_profile/command_payload.rb +24 -0
  17. data/lib/ios_config_profile/content/install_application_payload.rb +23 -0
  18. data/lib/ios_config_profile/content/install_book_payload.rb +23 -0
  19. data/lib/ios_config_profile/content/install_doc_payload.rb +27 -0
  20. data/lib/ios_config_profile/content/install_market_app_payload.rb +23 -0
  21. data/lib/ios_config_profile/content/installed_application_list_payload.rb +17 -0
  22. data/lib/ios_config_profile/content/remove_application_payload.rb +22 -0
  23. data/lib/ios_config_profile/content/remove_book_payload.rb +23 -0
  24. data/lib/ios_config_profile/content/remove_doc_payload.rb +23 -0
  25. data/lib/ios_config_profile/content/web_clip_payload.rb +38 -0
  26. data/lib/ios_config_profile/device/app_lock_payload.rb +33 -0
  27. data/lib/ios_config_profile/device/clear_passcode_payload.rb +24 -0
  28. data/lib/ios_config_profile/device/dep_payload.rb +40 -0
  29. data/lib/ios_config_profile/device/device_information_payload.rb +69 -0
  30. data/lib/ios_config_profile/device/enrollment_payload.rb +25 -0
  31. data/lib/ios_config_profile/device/erase_device_payload.rb +18 -0
  32. data/lib/ios_config_profile/device/install_profile_payload.rb +22 -0
  33. data/lib/ios_config_profile/device/lock_device_payload.rb +17 -0
  34. data/lib/ios_config_profile/device/mdm_payload.rb +40 -0
  35. data/lib/ios_config_profile/device/remove_profile_payload.rb +22 -0
  36. data/lib/ios_config_profile/device/restrictions_payload.rb +144 -0
  37. data/lib/ios_config_profile/device/scep_payload.rb +34 -0
  38. data/lib/ios_config_profile/device/security_payload.rb +32 -0
  39. data/lib/ios_config_profile/device/set_device_name_payload.rb +22 -0
  40. data/lib/ios_config_profile/device/vpn_payload.rb +86 -0
  41. data/lib/ios_config_profile/encrypted_payload.rb +14 -0
  42. data/lib/ios_config_profile/version.rb +4 -0
  43. data/spec/basic_payload_spec.rb +53 -0
  44. data/spec/command_payload_spec.rb +12 -0
  45. data/spec/content/install_application_payload_spec.rb +15 -0
  46. data/spec/content/install_book_payload_spec.rb +14 -0
  47. data/spec/content/install_doc_payload_spec.rb +16 -0
  48. data/spec/content/install_market_app_payload_spec.rb +15 -0
  49. data/spec/content/installed_application_list_payload_spec.rb +13 -0
  50. data/spec/content/remove_application_payoad_spec.rb +13 -0
  51. data/spec/content/remove_book_payload_spec.rb +14 -0
  52. data/spec/content/remove_doc_payload_spec.rb +18 -0
  53. data/spec/content/web_clip_payload_spec.rb +22 -0
  54. data/spec/device/app_lock_payload_spec.rb +23 -0
  55. data/spec/device/clear_passcode_payload_spec.rb +14 -0
  56. data/spec/device/dep_payload_spec.rb +18 -0
  57. data/spec/device/device_information_payload_spec.rb +28 -0
  58. data/spec/device/enrollment_payload_spec.rb +18 -0
  59. data/spec/device/erase_device_payload_spec.rb +11 -0
  60. data/spec/device/install_profile_payload_spec.rb +13 -0
  61. data/spec/device/lock_device_payload_spec.rb +11 -0
  62. data/spec/device/mdm_payload_spec.rb +41 -0
  63. data/spec/device/remove_profile_payload_spec.rb +14 -0
  64. data/spec/device/restrictions_payload_spec.rb +42 -0
  65. data/spec/device/scep_payload_spec.rb +14 -0
  66. data/spec/device/security_payload_spec.rb +29 -0
  67. data/spec/device/set_device_name_payload_spec.rb +14 -0
  68. data/spec/device/vpn_payload_spec.rb +75 -0
  69. data/spec/encrypted_payload_spec.rb +26 -0
  70. data/spec/spec_helper.rb +14 -0
  71. metadata +241 -0
data/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # ios_config_profile
2
+
3
+ [ ![Codeship Status for cellabus/ios_config_profile](https://codeship.com/projects/78639f70-c12a-0132-6290-3eb2295b72b3/status?branch=master)](https://codeship.com/projects/73471)
4
+ [![Dependency Status](https://gemnasium.com/cellabus/ios_config_profile.svg)](https://gemnasium.com/cellabus/ios_config_profile)
5
+ [![Code Climate](https://codeclimate.com/github/cellabus/ios_config_profile/badges/gpa.svg)](https://codeclimate.com/github/cellabus/ios_config_profile)
6
+ [![Test Coverage](https://codeclimate.com/github/cellabus/ios_config_profile/badges/coverage.svg)](https://codeclimate.com/github/cellabus/ios_config_profile/coverage)
7
+
8
+ Gem for creating and manipulating Apple Configuration Profiles and Mobile
9
+ Device Management (MDM) Protocols
10
+
11
+ # Usage
12
+ TODO
13
+
14
+ # Development
15
+ To run tests - `bundle exec rspec`
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rspec/core/rake_task"
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task default: :spec
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "ios_config_profile/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ios_config_profile"
8
+ spec.version = IOSConfigProfile::VERSION
9
+ spec.authors = ["Albert Wang"]
10
+ spec.email = ["albert@cellabus.com"]
11
+ spec.description = "Generate Apple iOS configuration profiles and payloads"
12
+ spec.summary = "This gem provides an easy way to generate configuration profiles for use with Apple iOS devices. These profiles and payloads can be delivered via Apple MDM, Apple's Configurator, or the iPhone Configuration Utility (IPCU)."
13
+ spec.homepage = "https://github.com/cellabus/ios_config_profile"
14
+ spec.license = "AGPL-3.0"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "CFPropertyList", "~> 2.2"
22
+ spec.add_dependency "plist", "~> 3.1"
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake", "~> 10.4"
25
+ spec.add_development_dependency "rspec", "~> 3.4"
26
+ spec.add_development_dependency "rspec-its", "~> 1.2"
27
+ spec.add_development_dependency "codeclimate-test-reporter", "~> 0.4"
28
+ end
@@ -0,0 +1,8 @@
1
+ require "ios-cert-enrollment"
2
+ require "ios_config_profile/version"
3
+ require "ios_config_profile/basic_payload"
4
+ require "ios_config_profile/command_payload"
5
+ require "ios_config_profile/encrypted_payload"
6
+ project_root = File.dirname(File.absolute_path(__FILE__))
7
+ Dir.glob(project_root + "/ios_config_profile/device/*.rb", &method(:require))
8
+ Dir.glob(project_root + "/ios_config_profile/content/*.rb", &method(:require))
@@ -0,0 +1,31 @@
1
+ module IOSConfigProfile
2
+ module BasicPayload
3
+ def uuid
4
+ # Note that this should be cached so that external code can read the
5
+ # uuid of a given payload without having to parse the payload itself
6
+ @uuid ||= random_uuid
7
+ end
8
+
9
+ def to_command_payload
10
+ CommandPayload.new(self)
11
+ end
12
+
13
+ def to_encrypted_payload
14
+ EncryptedPayload.new(self)
15
+ end
16
+
17
+ private
18
+
19
+ def random_uuid
20
+ SecureRandom.uuid
21
+ end
22
+
23
+ def require_attributes(*names)
24
+ names.each { |name| require_attribute name }
25
+ end
26
+
27
+ def require_attribute(name)
28
+ send(name) || raise(%{Required attribute "#{name}" is not present})
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ require "ios_config_profile"
2
+
3
+ module IOSConfigProfile
4
+ class CommandPayload < Hash
5
+ include IOSConfigProfile::BasicPayload
6
+
7
+ attr_reader :command
8
+
9
+ def initialize(command)
10
+ @command = command
11
+ require_attributes :command
12
+ merge! command_payload
13
+ end
14
+
15
+ private
16
+
17
+ def command_payload
18
+ {
19
+ "Command" => command,
20
+ "CommandUUID" => uuid,
21
+ }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ module IOSConfigProfile
2
+ class InstallApplicationPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_accessor :itunes_store_id
6
+
7
+ def initialize(itunes_store_id)
8
+ self.itunes_store_id = itunes_store_id
9
+ require_attributes :itunes_store_id
10
+ merge! install_application_payload
11
+ end
12
+
13
+ private
14
+
15
+ def install_application_payload
16
+ {
17
+ "RequestType" => "InstallApplication",
18
+ "iTunesStoreID" => itunes_store_id,
19
+ "ManagementFlags" => 1,
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module IOSConfigProfile
2
+ class InstallBookPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_accessor :itunes_store_id
6
+
7
+ def initialize(itunes_store_id)
8
+ self.itunes_store_id = itunes_store_id
9
+ require_attributes :itunes_store_id
10
+ merge! install_book_payload
11
+ end
12
+
13
+ private
14
+
15
+ def install_book_payload
16
+ {
17
+ "RequestType" => "InstallMedia",
18
+ "iTunesStoreID" => itunes_store_id,
19
+ "MediaType" => "Book",
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ module IOSConfigProfile
2
+ class InstallDocPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_accessor :filepicker_url, :name
6
+
7
+ def initialize(filepicker_url, name)
8
+ @filepicker_url = filepicker_url
9
+ @name = name
10
+ require_attributes :filepicker_url, :name
11
+ merge! install_doc_payload
12
+ end
13
+
14
+ private
15
+
16
+ def install_doc_payload
17
+ {
18
+ "RequestType" => "InstallMedia",
19
+ "MediaURL" => filepicker_url,
20
+ "MediaType" => "Book",
21
+ "Kind" => "pdf",
22
+ "Title" => name,
23
+ "PersistentID" => "com.cellabus.files.#{filepicker_url}",
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ module IOSConfigProfile
2
+ class InstallMarketAppPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_accessor :manifest_url
6
+
7
+ def initialize(manifest_url)
8
+ self.manifest_url = manifest_url
9
+ require_attributes :manifest_url
10
+ merge! install_market_app_payload
11
+ end
12
+
13
+ private
14
+
15
+ def install_market_app_payload
16
+ {
17
+ "RequestType" => "InstallApplication",
18
+ "ManifestURL" => manifest_url,
19
+ "ManagementFlags" => 1,
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module IOSConfigProfile
2
+ class InstalledApplicationListPayload < Hash
3
+ include BasicPayload
4
+
5
+ def initialize
6
+ merge! installed_application_list_request_payload
7
+ end
8
+
9
+ private
10
+
11
+ def installed_application_list_request_payload
12
+ {
13
+ "RequestType" => "InstalledApplicationList",
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ module IOSConfigProfile
2
+ class RemoveApplicationPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_accessor :bundle_id
6
+
7
+ def initialize(bundle_id)
8
+ self.bundle_id = bundle_id
9
+ require_attributes :bundle_id
10
+ merge! remove_application_payload
11
+ end
12
+
13
+ private
14
+
15
+ def remove_application_payload
16
+ {
17
+ "RequestType" => "RemoveApplication",
18
+ "Identifier" => bundle_id,
19
+ }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ module IOSConfigProfile
2
+ class RemoveBookPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_accessor :itunes_store_id
6
+
7
+ def initialize(itunes_store_id)
8
+ self.itunes_store_id = itunes_store_id
9
+ require_attributes :itunes_store_id
10
+ merge! remove_book_payload
11
+ end
12
+
13
+ private
14
+
15
+ def remove_book_payload
16
+ {
17
+ "RequestType" => "RemoveMedia",
18
+ "MediaType" => "Book",
19
+ "iTunesStoreID" => itunes_store_id,
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module IOSConfigProfile
2
+ class RemoveDocPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_accessor :doc_url
6
+
7
+ def initialize(doc_url)
8
+ @doc_url = doc_url
9
+ require_attributes :doc_url
10
+ merge! install_doc_payload
11
+ end
12
+
13
+ private
14
+
15
+ def install_doc_payload
16
+ {
17
+ "RequestType" => "RemoveMedia",
18
+ "MediaType" => "Book",
19
+ "PersistentID" => "com.cellabus.files.#{doc_url}",
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ module IOSConfigProfile
2
+ class WebClipPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_accessor :url, :label, :icon
6
+
7
+ def initialize(url, label, icon)
8
+ self.url = url
9
+ self.label = label
10
+ self.icon = icon
11
+ require_attributes :url, :label
12
+ merge! web_clip_payload
13
+ end
14
+
15
+ private
16
+
17
+ def web_clip_payload
18
+ {
19
+ "PayloadContent" => [{
20
+ "URL" => url,
21
+ "Label" => label,
22
+ "Icon" => StringIO.new(icon),
23
+ "IsRemovable" => false,
24
+ "PayloadType" => "com.apple.webClip.managed",
25
+ "PayloadIdentifier" => "com.cellabus.webclip",
26
+ "PayloadDescription" => "Add home screen website bookmark",
27
+ "PayloadUUID" => uuid,
28
+ "PayloadVersion" => 1,
29
+ }],
30
+ "PayloadType" => "Configuration",
31
+ "PayloadDisplayName" => "Cellabus Web Clip",
32
+ "PayloadIdentifier" => "com.cellabus.config.mdm.#{SecureRandom.urlsafe_base64}",
33
+ "PayloadUUID" => uuid,
34
+ "PayloadVersion" => 1,
35
+ }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ module IOSConfigProfile
2
+ class AppLockPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_accessor :app_bundle_id
6
+
7
+ def initialize(app_bundle_id)
8
+ self.app_bundle_id = app_bundle_id
9
+ require_attributes :app_bundle_id
10
+ merge! app_lock_payload
11
+ end
12
+
13
+ private
14
+
15
+ def app_lock_payload
16
+ {
17
+ "PayloadContent" => [{
18
+ "App" => { "Identifier" => app_bundle_id },
19
+ "PayloadType" => "com.apple.app.lock",
20
+ "PayloadIdentifier" => "com.cellabusapplock.profile.mdm",
21
+ "PayloadDescription" => "Lock device to an app",
22
+ "PayloadUUID" => uuid,
23
+ "PayloadVersion" => 1,
24
+ }],
25
+ "PayloadType" => "Configuration",
26
+ "PayloadDisplayName" => "Cellabus App Lock",
27
+ "PayloadIdentifier" => "com.cellabusapplock.profile.mdm",
28
+ "PayloadUUID" => uuid,
29
+ "PayloadVersion" => 1,
30
+ }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ require "stringio"
2
+
3
+ module IOSConfigProfile
4
+ class ClearPasscodePayload < Hash
5
+ include IOSConfigProfile::BasicPayload
6
+
7
+ attr_accessor :unlock_token
8
+
9
+ def initialize(unlock_token)
10
+ self.unlock_token = unlock_token
11
+ require_attributes :unlock_token
12
+ merge! clear_passcode_payload
13
+ end
14
+
15
+ private
16
+
17
+ def clear_passcode_payload
18
+ {
19
+ "RequestType" => "ClearPasscode",
20
+ "UnlockToken" => StringIO.new(unlock_token),
21
+ }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ module IOSConfigProfile
2
+ class DEPPayload < Hash
3
+ include IOSConfigProfile::BasicPayload
4
+
5
+ attr_reader :url, :topic, :identity_cert, :identity_cert_password
6
+
7
+ def initialize(url, topic, identity_cert, identity_cert_password)
8
+ @url = url
9
+ @topic = topic
10
+ @identity_cert = identity_cert
11
+ @identity_cert_password = identity_cert_password
12
+ require_attributes :url, :topic, :identity_cert, :identity_cert_password
13
+ merge! dep_payload
14
+ end
15
+
16
+ private
17
+
18
+ def dep_payload
19
+ {
20
+ "PayloadContent" => [mdm_payload, security_payload],
21
+ "PayloadDescription" => "Cellabus MDM Enrollment Profile",
22
+ "PayloadDisplayName" => "Cellabus MDM Enrollment Profile",
23
+ "PayloadIdentifier" => "com.cellabus.mdm.enrollment.profile",
24
+ "PayloadOrganization" => "Cellabus, Inc.",
25
+ "PayloadRemovalDisallowed" => false,
26
+ "PayloadType" => "Configuration",
27
+ "PayloadUUID" => uuid,
28
+ "PayloadVersion" => 1,
29
+ }
30
+ end
31
+
32
+ def mdm_payload
33
+ @mdm_payload ||= IOSConfigProfile::MDMPayload.new(url, security_payload, topic)
34
+ end
35
+
36
+ def security_payload
37
+ @security_payload ||= IOSConfigProfile::SecurityPayload.new(identity_cert, identity_cert_password)
38
+ end
39
+ end
40
+ end