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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +37 -0
- data/app/controllers/mdm/application_controller.rb +4 -0
- data/app/controllers/mdm/commands_controller.rb +60 -0
- data/app/controllers/mdm/enrollment/enrollment_controller.rb +47 -0
- data/app/controllers/mdm/management/accounts_controller.rb +15 -0
- data/app/controllers/mdm/management/devices_controller.rb +35 -0
- data/app/controllers/mdm/management/profiles_controller.rb +35 -0
- data/app/controllers/mdm/management/services_controller.rb +13 -0
- data/app/controllers/mdm/server_controller.rb +44 -0
- data/app/helpers/mdm/application_helper.rb +4 -0
- data/app/models/mdm/command.rb +23 -0
- data/app/models/mdm/cursor.rb +11 -0
- data/app/models/mdm/device.rb +39 -0
- data/app/models/mdm/payload.rb +158 -0
- data/app/models/mdm/profile.rb +14 -0
- data/app/views/layouts/mdm/application.html.erb +14 -0
- data/config/routes.rb +18 -0
- data/db/migrate/20150816150227_create_mdm_commands.rb +12 -0
- data/db/migrate/20150816150732_create_mdm_devices.rb +34 -0
- data/db/migrate/20150823153933_create_mdm_cursors.rb +10 -0
- data/db/migrate/20150827082737_create_mdm_profiles.rb +24 -0
- data/lib/mdm.rb +21 -0
- data/lib/mdm/configuration.rb +14 -0
- data/lib/mdm/engine.rb +5 -0
- data/lib/mdm/enrollment/client.rb +47 -0
- data/lib/mdm/enrollment/service/account.rb +32 -0
- data/lib/mdm/enrollment/service/assign_profile.rb +35 -0
- data/lib/mdm/enrollment/service/auth.rb +100 -0
- data/lib/mdm/enrollment/service/base.rb +67 -0
- data/lib/mdm/enrollment/service/create_profile.rb +69 -0
- data/lib/mdm/enrollment/service/devices.rb +92 -0
- data/lib/mdm/enrollment/service/profile.rb +62 -0
- data/lib/mdm/enrollment/service/sync.rb +43 -0
- data/lib/mdm/railtie.rb +22 -0
- data/lib/mdm/version.rb +3 -0
- data/lib/tasks/mdm_tasks.rake +4 -0
- data/test/controllers/mdm/commands_controller_test.rb +13 -0
- data/test/controllers/mdm/enrollment/accounts_controller_test.rb +13 -0
- data/test/controllers/mdm/enrollment/devices_controller_test.rb +13 -0
- data/test/controllers/mdm/enrollment/enrollment_controller_test.rb +13 -0
- data/test/controllers/mdm/enrollment/profiles_controller_test.rb +13 -0
- data/test/controllers/mdm/services_controller_test.rb +13 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fixtures/mdm/commands.yml +11 -0
- data/test/fixtures/mdm/cursors.yml +9 -0
- data/test/fixtures/mdm/devices.yml +25 -0
- data/test/fixtures/mdm/profiles.yml +35 -0
- data/test/integration/navigation_test.rb +9 -0
- data/test/mdm_test.rb +7 -0
- data/test/models/mdm/command_test.rb +9 -0
- data/test/models/mdm/cursor_test.rb +9 -0
- data/test/models/mdm/device_test.rb +9 -0
- data/test/models/mdm/profile_test.rb +9 -0
- data/test/test_helper.rb +20 -0
- 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
|
data/config/routes.rb
ADDED
|
@@ -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,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,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
|
data/lib/mdm.rb
ADDED
|
@@ -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
|
data/lib/mdm/engine.rb
ADDED
|
@@ -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
|