mdm 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +37 -0
  5. data/app/controllers/mdm/application_controller.rb +4 -0
  6. data/app/controllers/mdm/commands_controller.rb +60 -0
  7. data/app/controllers/mdm/enrollment/enrollment_controller.rb +47 -0
  8. data/app/controllers/mdm/management/accounts_controller.rb +15 -0
  9. data/app/controllers/mdm/management/devices_controller.rb +35 -0
  10. data/app/controllers/mdm/management/profiles_controller.rb +35 -0
  11. data/app/controllers/mdm/management/services_controller.rb +13 -0
  12. data/app/controllers/mdm/server_controller.rb +44 -0
  13. data/app/helpers/mdm/application_helper.rb +4 -0
  14. data/app/models/mdm/command.rb +23 -0
  15. data/app/models/mdm/cursor.rb +11 -0
  16. data/app/models/mdm/device.rb +39 -0
  17. data/app/models/mdm/payload.rb +158 -0
  18. data/app/models/mdm/profile.rb +14 -0
  19. data/app/views/layouts/mdm/application.html.erb +14 -0
  20. data/config/routes.rb +18 -0
  21. data/db/migrate/20150816150227_create_mdm_commands.rb +12 -0
  22. data/db/migrate/20150816150732_create_mdm_devices.rb +34 -0
  23. data/db/migrate/20150823153933_create_mdm_cursors.rb +10 -0
  24. data/db/migrate/20150827082737_create_mdm_profiles.rb +24 -0
  25. data/lib/mdm.rb +21 -0
  26. data/lib/mdm/configuration.rb +14 -0
  27. data/lib/mdm/engine.rb +5 -0
  28. data/lib/mdm/enrollment/client.rb +47 -0
  29. data/lib/mdm/enrollment/service/account.rb +32 -0
  30. data/lib/mdm/enrollment/service/assign_profile.rb +35 -0
  31. data/lib/mdm/enrollment/service/auth.rb +100 -0
  32. data/lib/mdm/enrollment/service/base.rb +67 -0
  33. data/lib/mdm/enrollment/service/create_profile.rb +69 -0
  34. data/lib/mdm/enrollment/service/devices.rb +92 -0
  35. data/lib/mdm/enrollment/service/profile.rb +62 -0
  36. data/lib/mdm/enrollment/service/sync.rb +43 -0
  37. data/lib/mdm/railtie.rb +22 -0
  38. data/lib/mdm/version.rb +3 -0
  39. data/lib/tasks/mdm_tasks.rake +4 -0
  40. data/test/controllers/mdm/commands_controller_test.rb +13 -0
  41. data/test/controllers/mdm/enrollment/accounts_controller_test.rb +13 -0
  42. data/test/controllers/mdm/enrollment/devices_controller_test.rb +13 -0
  43. data/test/controllers/mdm/enrollment/enrollment_controller_test.rb +13 -0
  44. data/test/controllers/mdm/enrollment/profiles_controller_test.rb +13 -0
  45. data/test/controllers/mdm/services_controller_test.rb +13 -0
  46. data/test/dummy/README.rdoc +28 -0
  47. data/test/dummy/Rakefile +6 -0
  48. data/test/dummy/app/assets/javascripts/application.js +13 -0
  49. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  50. data/test/dummy/app/controllers/application_controller.rb +5 -0
  51. data/test/dummy/app/helpers/application_helper.rb +2 -0
  52. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  53. data/test/dummy/bin/bundle +3 -0
  54. data/test/dummy/bin/rails +4 -0
  55. data/test/dummy/bin/rake +4 -0
  56. data/test/dummy/bin/setup +29 -0
  57. data/test/dummy/config.ru +4 -0
  58. data/test/dummy/config/application.rb +26 -0
  59. data/test/dummy/config/boot.rb +5 -0
  60. data/test/dummy/config/database.yml +25 -0
  61. data/test/dummy/config/environment.rb +5 -0
  62. data/test/dummy/config/environments/development.rb +41 -0
  63. data/test/dummy/config/environments/production.rb +79 -0
  64. data/test/dummy/config/environments/test.rb +42 -0
  65. data/test/dummy/config/initializers/assets.rb +11 -0
  66. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  67. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  68. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  69. data/test/dummy/config/initializers/inflections.rb +16 -0
  70. data/test/dummy/config/initializers/mime_types.rb +4 -0
  71. data/test/dummy/config/initializers/session_store.rb +3 -0
  72. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  73. data/test/dummy/config/locales/en.yml +23 -0
  74. data/test/dummy/config/routes.rb +4 -0
  75. data/test/dummy/config/secrets.yml +22 -0
  76. data/test/dummy/public/404.html +67 -0
  77. data/test/dummy/public/422.html +67 -0
  78. data/test/dummy/public/500.html +66 -0
  79. data/test/dummy/public/favicon.ico +0 -0
  80. data/test/fixtures/mdm/commands.yml +11 -0
  81. data/test/fixtures/mdm/cursors.yml +9 -0
  82. data/test/fixtures/mdm/devices.yml +25 -0
  83. data/test/fixtures/mdm/profiles.yml +35 -0
  84. data/test/integration/navigation_test.rb +9 -0
  85. data/test/mdm_test.rb +7 -0
  86. data/test/models/mdm/command_test.rb +9 -0
  87. data/test/models/mdm/cursor_test.rb +9 -0
  88. data/test/models/mdm/device_test.rb +9 -0
  89. data/test/models/mdm/profile_test.rb +9 -0
  90. data/test/test_helper.rb +20 -0
  91. metadata +254 -0
@@ -0,0 +1,14 @@
1
+ module Mdm
2
+ class Profile < ActiveRecord::Base
3
+
4
+ serialize :anchor_certs, Array
5
+ serialize :supervising_host_certs, Array
6
+ serialize :skip_setup_items, Array
7
+ serialize :devices, Array # Array of serial numbers
8
+
9
+ def devices
10
+ @devices ||= Mdm::Device.where(
11
+ serial_number: super)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Mdm</title>
5
+ <%= stylesheet_link_tag "mdm/application", media: "all" %>
6
+ <%= javascript_include_tag "mdm/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,18 @@
1
+ Mdm::Engine.routes.draw do
2
+
3
+ namespace :management do
4
+ resource :account, only: [:show]
5
+ resources :services, only: [:index]
6
+ resources :devices, only: [:index, :show]
7
+ resources :profiles, except: [:delete]
8
+ resources :commands, only: [:index, :create]
9
+ end
10
+
11
+ namespace :enrollment do
12
+ get 'enroll', to: 'enrollment#enroll'
13
+ put 'checkin', to: 'enrollment#checkin'
14
+ end
15
+
16
+ put '/', to: 'server#server'
17
+
18
+ end
@@ -0,0 +1,12 @@
1
+ class CreateMdmCommands < ActiveRecord::Migration
2
+ def change
3
+ create_table :mdm_commands do |t|
4
+ t.string :uuid
5
+ t.string :status
6
+ t.references :mdm_device
7
+ t.text :payload
8
+
9
+ t.timestamps null: false
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,34 @@
1
+ class CreateMdmDevices < ActiveRecord::Migration
2
+ def change
3
+ create_table :mdm_devices do |t|
4
+ t.string :name
5
+ t.binary :unlock_token
6
+ t.string :push_token
7
+ t.string :push_magic
8
+ t.string :udid
9
+ t.string :serial_number
10
+ t.string :device_model
11
+ t.string :device_model_name
12
+ t.string :description
13
+ t.string :color
14
+ t.string :asset_tag
15
+ t.string :profile_status
16
+ t.string :profile_uuid
17
+ t.integer :profile_assign_time
18
+ t.integer :profile_push_time
19
+ t.string :op_type
20
+ t.integer :op_date
21
+ t.string :device_assigned_by
22
+ t.integer :device_assigned_date
23
+ t.boolean :is_supervised
24
+ t.integer :available_capacity
25
+ t.integer :device_capacity
26
+ t.string :os_version
27
+ t.string :build_version
28
+ t.string :imei
29
+ t.boolean :is_roaming
30
+
31
+ t.timestamps null: false
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,10 @@
1
+ class CreateMdmCursors < ActiveRecord::Migration
2
+ def change
3
+ create_table :mdm_cursors do |t|
4
+ t.string :service
5
+ t.string :content
6
+
7
+ t.timestamps null: false
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ class CreateMdmProfiles < ActiveRecord::Migration
2
+ def change
3
+ create_table :mdm_profiles do |t|
4
+ t.string :profile_uuid
5
+ t.string :profile_name
6
+ t.string :url
7
+ t.integer :is_supervised
8
+ t.integer :allow_pairing
9
+ t.integer :is_mandatory
10
+ t.integer :await_device_configured
11
+ t.integer :is_mdm_removable
12
+ t.string :department
13
+ t.string :org_magic
14
+ t.string :support_phone_number
15
+ t.string :support_email_address
16
+ t.text :anchor_certs
17
+ t.text :supervising_host_certs
18
+ t.text :skip_setup_items
19
+ t.text :devices
20
+
21
+ t.timestamps null: false
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ require "mdm/engine"
2
+
3
+ require 'mdm/configuration'
4
+
5
+ require 'mdm/enrollment/client'
6
+
7
+ require 'mdm/enrollment/service/base'
8
+ require 'mdm/enrollment/service/auth'
9
+ require 'mdm/enrollment/service/account'
10
+ require 'mdm/enrollment/service/devices'
11
+ require 'mdm/enrollment/service/sync'
12
+ require 'mdm/enrollment/service/profile'
13
+ require 'mdm/enrollment/service/create_profile'
14
+ require 'mdm/enrollment/service/assign_profile'
15
+
16
+ require 'mdm/railtie' if defined?(Rails)
17
+
18
+ require 'houston'
19
+
20
+ module Mdm
21
+ end
@@ -0,0 +1,14 @@
1
+ require 'confiture'
2
+
3
+ module Mdm
4
+
5
+ class Configuration
6
+ include ::Confiture::Configuration
7
+
8
+ confiture_allowed_keys(
9
+ :configuration_profile,
10
+ :apn_certificate
11
+ )
12
+ end
13
+
14
+ end
@@ -0,0 +1,5 @@
1
+ module Mdm
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Mdm
4
+ end
5
+ end
@@ -0,0 +1,47 @@
1
+ module Mdm
2
+
3
+ module Enrollment
4
+
5
+ class Client
6
+
7
+ include HTTParty
8
+
9
+ attr_reader :authenticated, :response
10
+
11
+ base_uri 'https://mdmenrollment.apple.com'
12
+ format :json
13
+ headers 'X-Server-Protocol-Version' => '2',
14
+ 'Content-Type' => 'application/json;charset=UTF8'
15
+
16
+ %w(get post put delete).each { |method|
17
+ define_method(method) { |path, options = {}|
18
+ inject_auth_token_if_authenticated(options)
19
+ @response = self.class.send(method, path, options)
20
+ Auth.update_token_from_response(@response)
21
+ @response
22
+ }
23
+ }
24
+
25
+ def authenticate!
26
+ @authenticated = true
27
+ end
28
+
29
+ def extract_from_response(*attributes)
30
+ return [] if response.nil?
31
+ attributes.map { |attribute|
32
+ response[attribute] }
33
+ end
34
+
35
+ private
36
+
37
+ def inject_auth_token_if_authenticated(options = {})
38
+ if authenticated
39
+ (options[:headers] ||= {})
40
+ .merge!('X-ADM-Auth-Session' => Auth.token)
41
+ end
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,32 @@
1
+ module Mdm
2
+
3
+ module Enrollment
4
+
5
+ class Account < Service::Base
6
+
7
+ def path
8
+ '/account'
9
+ end
10
+
11
+ def method
12
+ :get
13
+ end
14
+
15
+ def result
16
+ {
17
+ server_name: client.response['server_name'],
18
+ server_uuid: client.response['server_uuid'],
19
+ facilitator_id: client.response['facilitator_id'],
20
+ admin_id: client.response['admin_id'],
21
+ org_name: client.response['org_name'],
22
+ org_email: client.response['org_email'],
23
+ org_phone: client.response['org_phone'],
24
+ org_address: client.response['org_address'],
25
+ }
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,35 @@
1
+ module Mdm
2
+
3
+ module Enrollment
4
+
5
+ class AssignProfile < Service::Base
6
+
7
+ attr_accessor :devices
8
+ attr_accessor :profile
9
+
10
+ def start
11
+ params[:profile_uuid] = profile.profile_uuid
12
+ params[:devices] = devices.map(&:serial_number)
13
+ super
14
+ end
15
+
16
+ def path
17
+ '/profile/devices'
18
+ end
19
+
20
+ def method
21
+ :put
22
+ end
23
+
24
+ def result
25
+ {
26
+ profile_uuid: client.response['profile_uuid'],
27
+ devices: client.response['devices']
28
+ }
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,100 @@
1
+ module Mdm
2
+
3
+ module Enrollment
4
+
5
+ class Auth < Service::Base
6
+
7
+ cattr_accessor :consumer_key,
8
+ :consumer_secret,
9
+ :access_token,
10
+ :access_secret
11
+
12
+ # Debug purpose only
13
+ self.consumer_key = "CK_974972d3a9acf95666e6c0cf4ae026f3d3ca6109b8582d95f3b7171f1f033749f66d8fa299202cf2cf616f7cbbc5fbb8"
14
+ self.consumer_secret = "CS_f7a9a4bbcee4bfbf1e449a218bb74377c139f25e"
15
+ self.access_token = "AT_O8413116053O51d9691b9ff836ea72c731723efa2105710e1862O1438344338000"
16
+ self.access_secret = "AS_6eb94db58653f61ec3808f4051937f12e478948f"
17
+
18
+ class << self
19
+
20
+ def token
21
+ @@token ||= new.obtain_token
22
+ end
23
+
24
+ def update_token_from_response(response)
25
+ if response && token = response.headers['x-adm-auth-session']
26
+ @@token = token
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ def obtain_token
33
+ client.get '/session',
34
+ headers: {
35
+ 'Authorization' => authorization_header
36
+ }
37
+ client.response['auth_session_token']
38
+ end
39
+
40
+ def params
41
+ @params ||= {
42
+ oauth_consumer_key: consumer_key,
43
+ oauth_token: access_token,
44
+ oauth_nonce: nonce,
45
+ oauth_timestamp: Time.now.getutc.to_i.to_s,
46
+ oauth_version: '1.0',
47
+ oauth_signature_method: 'HMAC-SHA1'
48
+ }
49
+ end
50
+
51
+ private
52
+
53
+ def authorization_header
54
+ params_with_signature = params.merge(
55
+ realm: 'MDM',
56
+ oauth_signature: sign(base_str)
57
+ )
58
+
59
+ 'OAuth ' + params_with_signature.map { |key, value|
60
+ "#{key}=\"#{value}\""
61
+ }.join(', ')
62
+ end
63
+
64
+ def base_str
65
+ # Encode, sort and join params
66
+ params_encoded = params.inject({}) { |hash, (key, value)|
67
+ hash[CGI::escape(key.to_s)] = CGI::escape(value)
68
+ hash
69
+ }.sort.map { |key, value|
70
+ "#{key}=#{value}"
71
+ }.join('&')
72
+
73
+ # Request method + url with path + params, escaped and joined by &
74
+ [
75
+ 'GET',
76
+ "https://mdmenrollment.apple.com/session",
77
+ params_encoded
78
+ ].map { |str|
79
+ CGI::escape(str)
80
+ }.join('&')
81
+ end
82
+
83
+ def sign(base_str)
84
+ key = "#{CGI::escape(consumer_secret)}&#{CGI::escape(access_secret)}"
85
+ digest = OpenSSL::Digest.new('sha1')
86
+ hmac = OpenSSL::HMAC.digest(digest, key, base_str)
87
+ CGI::escape(Base64.encode64(hmac).chomp.gsub(/\n/, ''))
88
+ end
89
+
90
+ def nonce
91
+ @nonce ||= Base64.encode64(
92
+ OpenSSL::Random.random_bytes(7)
93
+ ).gsub(/\W/, '')
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+
100
+ end
@@ -0,0 +1,67 @@
1
+ module Mdm
2
+
3
+ module Enrollment
4
+
5
+ module Service
6
+
7
+ class Base
8
+
9
+ def self.available_services
10
+ [:account]
11
+ end
12
+
13
+ def self.accepted_params
14
+ []
15
+ end
16
+
17
+ def start
18
+ if authenticate?
19
+ client.authenticate!
20
+ end
21
+
22
+ options = if [:post, :put].include? method
23
+ { body: params.to_json }
24
+ else
25
+ { query: params }
26
+ end
27
+
28
+ client.send(method, path, options)
29
+ end
30
+
31
+ def result
32
+ raise 'Subclasses must implement this method'
33
+ end
34
+
35
+ def method
36
+ raise 'Subclasses must implement this method'
37
+ end
38
+
39
+ def path
40
+ raise 'Subclasses must implement this method'
41
+ end
42
+
43
+ def authenticate?
44
+ true
45
+ end
46
+
47
+ def params
48
+ @params ||= {}
49
+ end
50
+
51
+ def params=(params)
52
+ @params = params.permit(self.class.accepted_params)
53
+ end
54
+
55
+ protected
56
+
57
+ def client
58
+ @client ||= Enrollment::Client.new
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end