axm 0.1.1 → 1.0.0
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 +4 -4
- data/CHANGELOG.md +31 -2
- data/README.md +12 -2
- data/lib/axm/client/mdm_servers.rb +31 -0
- data/lib/axm/client/organization_device_activities.rb +74 -0
- data/lib/axm/client/organization_devices.rb +57 -1
- data/lib/axm/client.rb +53 -18
- data/lib/axm/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0d2f95c8bc2de0f7a2c7ea620d2f301980eb6c5a21243bc8ee878b0ae4ebb351
|
|
4
|
+
data.tar.gz: 59c698eebe7dbe7baf4b1378ca5a66b0045334a2d69c3441b0300ca5dc3de6a4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8e3fc06e2e51475d49a6d5612700046e9003967200d1234ca3aa52d4ead5f08827d8f4eb432a512af127cb01920befab0a3f4dd9f354a6705a4f3ca8d1d5d781
|
|
7
|
+
data.tar.gz: dac8b555c797f8b773de5c58cc0de9b35128df4251a5cfbe9c3260160c11f5b2178e010f3fe9d8126a63ad144c0db71e9abd452b020488bb6440bb239e1875fe
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
|
-
##
|
|
1
|
+
## 1.0.0 - 2025-11-08
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
- List all MDM servers in an organisation
|
|
6
|
+
- Show all device IDs assigned to a specific MDM server
|
|
7
|
+
- Show which MDM server a device is assigned to
|
|
8
|
+
- Show the ID of the MDM server a device is assigned to
|
|
9
|
+
- Show information about the MDM server a device is assigned to
|
|
10
|
+
- Assign and unassign devices to MDM servers
|
|
11
|
+
- Show AppleCare coverage information for devices
|
|
12
|
+
|
|
13
|
+
## 0.1.2 - 2025-07-14
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Get information about a specific device
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Fixed issue with incorrect endpoints being included
|
|
22
|
+
|
|
23
|
+
## [0.1.1] - 2025-07-14
|
|
24
|
+
|
|
25
|
+
- Updated README with more detailed usage instructions
|
|
26
|
+
|
|
27
|
+
## [0.1.0] - 2025-07-14
|
|
4
28
|
|
|
5
29
|
- Initial release
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Exchange credentials for an access token
|
|
34
|
+
- List all devices in an organisation
|
data/README.md
CHANGED
|
@@ -26,10 +26,10 @@ With the credentials handy, you can create an instance of the client:
|
|
|
26
26
|
|
|
27
27
|
```ruby
|
|
28
28
|
private_key = File.read('path/to/your/private_key.pem')
|
|
29
|
-
|
|
29
|
+
client_id = 'your_client_id'
|
|
30
30
|
key_id = 'your_key_id'
|
|
31
31
|
|
|
32
|
-
client = Axm::Client.new(private_key:,
|
|
32
|
+
client = Axm::Client.new(private_key:, client_id:, key_id:)
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
You're now ready to make API requests.
|
|
@@ -48,6 +48,16 @@ client.get('/v1/some/endpoint', { limit: 10 })
|
|
|
48
48
|
|
|
49
49
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
50
50
|
|
|
51
|
+
If the credentials are stored in the `secrets/` directory, you can use the `Secret.read` method to load them:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
private_key = Secret.read('private_key.pem')
|
|
55
|
+
client_id = Secret.read('client_id')
|
|
56
|
+
key_id = Secret.read('key_id')
|
|
57
|
+
|
|
58
|
+
client = Axm::Client.new(private_key:, client_id:, key_id:)
|
|
59
|
+
```
|
|
60
|
+
|
|
51
61
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
52
62
|
|
|
53
63
|
## Contributing
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Axm
|
|
2
|
+
class Client
|
|
3
|
+
module MdmServers
|
|
4
|
+
# Retrieves a list of MDM servers associated with the organization.
|
|
5
|
+
#
|
|
6
|
+
# @param options [Hash] Optional query parameters to filter fields or paginate results.
|
|
7
|
+
# - fields: (Array) Array of fields to include in the response.
|
|
8
|
+
# - limit: (Integer) Maximum number of devices to return per page (default: 100, maximum: 1000).
|
|
9
|
+
# @return [Array<Hash>] An array of MDM servers.
|
|
10
|
+
#
|
|
11
|
+
# See: https://developer.apple.com/documentation/applebusinessmanagerapi/get-mdm-servers
|
|
12
|
+
# See: https://developer.apple.com/documentation/appleschoolmanagerapi/get-mdm-servers
|
|
13
|
+
def list_mdm_servers(options = {})
|
|
14
|
+
get("v1/mdmServers", options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Retrieves a list of IDs for the devices assigned to a specific MDM server.
|
|
18
|
+
#
|
|
19
|
+
# @param mdm_server_id [String] The unique identifier of the MDM server.
|
|
20
|
+
# @param options [Hash] Optional query parameters to paginate results or increase number of returned results.
|
|
21
|
+
# - limit: (Integer) Maximum number of devices to return per page (default: 100, maximum: 1000).
|
|
22
|
+
# @return [Array<Hash>] An array of device IDs assigned to the specified MDM server.
|
|
23
|
+
#
|
|
24
|
+
# See: https://developer.apple.com/documentation/applebusinessmanagerapi/get-all-device-ids-for-a-mdmserver
|
|
25
|
+
# See: https://developer.apple.com/documentation/appleschoolmanagerapi/get-all-device-ids-for-a-mdmserver
|
|
26
|
+
def devices_assigned_to_mdm_server(mdm_server_id, options = {})
|
|
27
|
+
get("v1/mdmServers/#{mdm_server_id}/relationships/devices", options)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module Axm
|
|
2
|
+
class Client
|
|
3
|
+
module OrganizationDeviceActivities
|
|
4
|
+
# Get information for an organization device activity that a device management action, such as assign or unassign, creates.
|
|
5
|
+
#
|
|
6
|
+
# @param options [Hash] Optional query parameters to filter returned attributes.
|
|
7
|
+
# - fields: (Array) Array of fields to include in the response.
|
|
8
|
+
# @return [<Hash>] A single organization device activity resource.
|
|
9
|
+
#
|
|
10
|
+
# See: https://developer.apple.com/documentation/applebusinessmanagerapi/get-orgdeviceactivity-information
|
|
11
|
+
# See: https://developer.apple.com/documentation/appleschoolmanagerapi/get-orgdeviceactivity-information
|
|
12
|
+
def org_device_activity(activity_id, options = {})
|
|
13
|
+
get("v1/orgDeviceActivities/#{activity_id}", options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Assigns a device to an MDM server.
|
|
17
|
+
#
|
|
18
|
+
# @param device_ids [Array<String>] Array of device IDs to be assigned.
|
|
19
|
+
# @param mdm_server_id [String] The unique identifier of the MDM server to which the device will be assigned.
|
|
20
|
+
# @return [Hash, Integer] The response from the POST method, containing details of the assignment and status code.
|
|
21
|
+
def assign(device_id, mdm_server_id)
|
|
22
|
+
assignment_change(device_id, mdm_server_id, "ASSIGN_DEVICES")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Unassigns a device from an MDM server.
|
|
26
|
+
#
|
|
27
|
+
# @param device_ids [Array<String>] Array of device IDs to be unassigned.
|
|
28
|
+
# @param mdm_server_id [String] The unique identifier of the MDM server to which the device will be assigned.
|
|
29
|
+
# @return [Hash, Integer] The response from the POST method, containing details of the assignment and status code.
|
|
30
|
+
def unassign(device_id, mdm_server_id)
|
|
31
|
+
assignment_change(device_id, mdm_server_id, "UNASSIGN_DEVICES")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# Sends a request to change the assignment of a device to an MDM server.
|
|
37
|
+
#
|
|
38
|
+
# @param device_ids [Array<String>] Array of IDs of devices to be assigned or unassigned.
|
|
39
|
+
# @param mdm_server_id [String] The unique identifier of the MDM server.
|
|
40
|
+
# @param activity_type [String] The type of activity being performed ("ASSIGN_DEVICES" or "UNASSIGN_DEVICES").
|
|
41
|
+
# @return [Hash, Integer] The response from the POST request, containing details of the operation and status code.
|
|
42
|
+
def assignment_change(device_ids, mdm_server_id, activity_type)
|
|
43
|
+
devices = device_ids.map do |device_id|
|
|
44
|
+
{
|
|
45
|
+
type: "orgDevices",
|
|
46
|
+
id: device_id
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
request_body = {
|
|
51
|
+
data: {
|
|
52
|
+
type: "orgDeviceActivities",
|
|
53
|
+
attributes: {
|
|
54
|
+
activityType: activity_type
|
|
55
|
+
},
|
|
56
|
+
relationships: {
|
|
57
|
+
mdmServer: {
|
|
58
|
+
data: {
|
|
59
|
+
type: "mdmServers",
|
|
60
|
+
id: mdm_server_id
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
devices: {
|
|
64
|
+
data: devices
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
post("v1/orgDeviceActivities", request_body)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -11,7 +11,63 @@ module Axm
|
|
|
11
11
|
# See: https://developer.apple.com/documentation/applebusinessmanagerapi/get-org-devices
|
|
12
12
|
# See: https://developer.apple.com/documentation/appleschoolmanagerapi/get-org-devices
|
|
13
13
|
def list_org_devices(options = {})
|
|
14
|
-
get(
|
|
14
|
+
get("v1/orgDevices", options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Retrieves information about a specific device in the organization.
|
|
18
|
+
#
|
|
19
|
+
# @param options [Hash] Optional query parameters to filter or paginate results.
|
|
20
|
+
# - fields: (Array) Array of fields to include in the response.
|
|
21
|
+
# @return [<Hash>] A device and its selected attributes.
|
|
22
|
+
#
|
|
23
|
+
# See: https://developer.apple.com/documentation/applebusinessmanagerapi/get-orgdevice-information
|
|
24
|
+
# See: https://developer.apple.com/documentation/appleschoolmanagerapi/get-orgdevice-information
|
|
25
|
+
def device(id, options = {})
|
|
26
|
+
get("/v1/orgDevices/#{id}", options)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Fetch the assigned device management service ID for a device.
|
|
30
|
+
#
|
|
31
|
+
# @param device_id [String] The unique identifier of the device.
|
|
32
|
+
# @param options [Hash] Optional query parameters to filter or paginate results.
|
|
33
|
+
# @return [<Hash>] Identifier of the device's assigned MDM server.
|
|
34
|
+
#
|
|
35
|
+
# See: https://developer.apple.com/documentation/applebusinessmanagerapi/get-the-assigned-server-id-for-an-orgdevice
|
|
36
|
+
# See: https://developer.apple.com/documentation/appleschoolmanagerapi/get-the-assigned-server-id-for-an-orgdevice
|
|
37
|
+
def assigned_mdm_server_id(device_id, options = {})
|
|
38
|
+
get("v1/orgDevices/#{device_id}/relationships/assignedServer", options)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Fetch the assigned device management service information for a device.
|
|
42
|
+
#
|
|
43
|
+
# @param device_id [String] The unique identifier of the device.
|
|
44
|
+
# @param options [Hash] Optional query parameters to filter or paginate results.
|
|
45
|
+
# - id: (String) The unique identifier of the device.
|
|
46
|
+
# - fields: (Array) Array of fields to include in the response.
|
|
47
|
+
# @return [<Hash>] A hash containing the identifier of the device's assigned MDM server.
|
|
48
|
+
#
|
|
49
|
+
# See: https://developer.apple.com/documentation/applebusinessmanagerapi/get-the-assigned-server-information-for-an-orgdevice
|
|
50
|
+
# See: https://developer.apple.com/documentation/appleschoolmanagerapi/get-the-assigned-server-information-for-an-orgdevice
|
|
51
|
+
def assigned_mdm_server(device_id, options = {})
|
|
52
|
+
options[:fields_key] = "mdmServers"
|
|
53
|
+
|
|
54
|
+
get("v1/orgDevices/#{device_id}/assignedServer", options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Fetch the AppleCare coverage information for a device.
|
|
58
|
+
#
|
|
59
|
+
# @param device_id [String] The unique identifier of the device.
|
|
60
|
+
# @param options [Hash] Optional query parameters to filter or paginate results.
|
|
61
|
+
# - fields: (Array) Array of fields to include in the response.
|
|
62
|
+
# - limit: (Integer) The number of included related resources to return (default: 100, maximum: 1000).
|
|
63
|
+
# @return [<Hash>] A hash containing the identifier of the device's assigned MDM server.
|
|
64
|
+
#
|
|
65
|
+
# See: https://developer.apple.com/documentation/applebusinessmanagerapi/get-all-apple-care-coverage-for-an-orgdevice
|
|
66
|
+
# See: https://developer.apple.com/documentation/appleschoolmanagerapi/get-all-apple-care-coverage-for-an-orgdevice
|
|
67
|
+
def applecare_coverage(device_id, options = {})
|
|
68
|
+
options[:fields_key] = "appleCareCoverage"
|
|
69
|
+
|
|
70
|
+
get("v1/orgDevices/#{device_id}/appleCareCoverage", options)
|
|
15
71
|
end
|
|
16
72
|
end
|
|
17
73
|
end
|
data/lib/axm/client.rb
CHANGED
|
@@ -4,10 +4,16 @@ require 'net/http'
|
|
|
4
4
|
require 'securerandom'
|
|
5
5
|
require 'time'
|
|
6
6
|
|
|
7
|
+
require 'axm/client/mdm_servers'
|
|
8
|
+
require 'axm/client/organization_device_activities'
|
|
7
9
|
require 'axm/client/organization_devices'
|
|
8
10
|
|
|
9
11
|
module Axm
|
|
10
12
|
class Client
|
|
13
|
+
include MdmServers
|
|
14
|
+
include OrganizationDeviceActivities
|
|
15
|
+
include OrganizationDevices
|
|
16
|
+
|
|
11
17
|
# Initializes a new instance of the AXM client.
|
|
12
18
|
#
|
|
13
19
|
# @param private_key [String] The private key used for authentication.
|
|
@@ -83,15 +89,7 @@ module Axm
|
|
|
83
89
|
return cached_access_token unless token_expired
|
|
84
90
|
end
|
|
85
91
|
|
|
86
|
-
|
|
87
|
-
grant_type: 'client_credentials',
|
|
88
|
-
client_id: @client_id,
|
|
89
|
-
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
|
|
90
|
-
client_assertion: client_assertion,
|
|
91
|
-
scope: "#{scope}.api"
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
response = post('https://account.apple.com/auth/oauth2/v2/token', params)
|
|
92
|
+
response = exchange_access_token_request
|
|
95
93
|
|
|
96
94
|
response_body = response.first if response.last.to_i == 200
|
|
97
95
|
|
|
@@ -112,10 +110,14 @@ module Axm
|
|
|
112
110
|
def get(path, options = {})
|
|
113
111
|
options = options.dup
|
|
114
112
|
|
|
115
|
-
endpoint
|
|
113
|
+
# API endpoints are prefixed with 'v1', so we can extract the endpoint from the path.
|
|
114
|
+
endpoint = path.split('/')[1]
|
|
115
|
+
|
|
116
|
+
# For the cases where the fields_key is different to the path component, it can be overriden as an option.
|
|
117
|
+
fields_key = options.delete(:fields_key) || endpoint
|
|
116
118
|
|
|
117
119
|
fields = options.delete(:fields)
|
|
118
|
-
options["fields[#{
|
|
120
|
+
options["fields[#{fields_key}]"] = fields.join(',') if fields
|
|
119
121
|
|
|
120
122
|
uri = URI("https://#{api_domain}/#{path}")
|
|
121
123
|
uri.query = URI.encode_www_form(options) unless options.empty?
|
|
@@ -131,20 +133,27 @@ module Axm
|
|
|
131
133
|
JSON.parse(res.body)
|
|
132
134
|
end
|
|
133
135
|
|
|
134
|
-
# Sends a POST request to the
|
|
136
|
+
# Sends a POST request to exchange the credentials for an access token.
|
|
135
137
|
#
|
|
136
|
-
# @
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
# @return [Net::HTTPResponse, integer] The HTTP response object and status code.
|
|
139
|
+
def exchange_access_token_request
|
|
140
|
+
uri = URI('https://account.apple.com/auth/oauth2/v2/token')
|
|
141
|
+
|
|
142
|
+
request_body = {
|
|
143
|
+
grant_type: 'client_credentials',
|
|
144
|
+
client_id: @client_id,
|
|
145
|
+
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
|
|
146
|
+
client_assertion: client_assertion,
|
|
147
|
+
scope: "#{scope}.api"
|
|
148
|
+
}
|
|
149
|
+
|
|
141
150
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
142
151
|
http.use_ssl = uri.scheme == 'https'
|
|
143
152
|
|
|
144
153
|
request = Net::HTTP::Post.new(uri)
|
|
145
154
|
request['Host'] = uri.host
|
|
146
155
|
request['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
147
|
-
request.body = URI.encode_www_form(
|
|
156
|
+
request.body = URI.encode_www_form(request_body)
|
|
148
157
|
|
|
149
158
|
response = http.request(request)
|
|
150
159
|
|
|
@@ -153,8 +162,34 @@ module Axm
|
|
|
153
162
|
response_json = JSON.parse(response.body)
|
|
154
163
|
|
|
155
164
|
raise 'Invalid request' if response_json['error'] == 'invalid_request'
|
|
165
|
+
raise 'Invalid client ID or key ID' if response_json['error'] == 'invalid_client'
|
|
156
166
|
|
|
157
167
|
[response_json, response.code]
|
|
158
168
|
end
|
|
169
|
+
|
|
170
|
+
# Sends a POST request to the specified URI with given parameters.
|
|
171
|
+
#
|
|
172
|
+
# @param uri [String, URI] The endpoint URI.
|
|
173
|
+
# @param request_body [Hash] Parameters to include in the request body.
|
|
174
|
+
# @return [Hash, Integer] The HTTP response object and status code.
|
|
175
|
+
def post(path, request_body = {})
|
|
176
|
+
uri = URI("https://#{api_domain}/#{path}")
|
|
177
|
+
|
|
178
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
179
|
+
http.use_ssl = uri.scheme == 'https'
|
|
180
|
+
|
|
181
|
+
request = Net::HTTP::Post.new(uri)
|
|
182
|
+
request['Host'] = uri.host
|
|
183
|
+
request['Content-Type'] = 'application/json'
|
|
184
|
+
request['Authorization'] = "Bearer #{access_token['access_token']}"
|
|
185
|
+
|
|
186
|
+
request.body = request_body.to_json unless request_body.empty?
|
|
187
|
+
|
|
188
|
+
response = http.request(request)
|
|
189
|
+
|
|
190
|
+
response_body = JSON.parse(response.body)
|
|
191
|
+
|
|
192
|
+
[response_body, response.code]
|
|
193
|
+
end
|
|
159
194
|
end
|
|
160
195
|
end
|
data/lib/axm/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: axm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nick-f
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-11-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jwt
|
|
@@ -40,6 +40,8 @@ files:
|
|
|
40
40
|
- Rakefile
|
|
41
41
|
- lib/axm.rb
|
|
42
42
|
- lib/axm/client.rb
|
|
43
|
+
- lib/axm/client/mdm_servers.rb
|
|
44
|
+
- lib/axm/client/organization_device_activities.rb
|
|
43
45
|
- lib/axm/client/organization_devices.rb
|
|
44
46
|
- lib/axm/secret.rb
|
|
45
47
|
- lib/axm/version.rb
|
|
@@ -66,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
66
68
|
- !ruby/object:Gem::Version
|
|
67
69
|
version: '0'
|
|
68
70
|
requirements: []
|
|
69
|
-
rubygems_version: 3.
|
|
71
|
+
rubygems_version: 3.5.22
|
|
70
72
|
signing_key:
|
|
71
73
|
specification_version: 4
|
|
72
74
|
summary: Gem to interact with the Apple Business Manager/Apple School Manager API
|