File Coverage

blib/lib/Config/Apple/Profile.pm
Criterion Covered Total %
statement 30 34 88.2
branch n/a
condition n/a
subroutine 10 11 90.9
pod 1 1 100.0
total 41 46 89.1


line stmt bran cond sub pod time code
1             package Config::Apple::Profile;
2              
3 1     1   14733 use 5.10.1;
  1         3  
  1         41  
4 1     1   5 use strict;
  1         5  
  1         28  
5 1     1   4 use warnings FATAL => 'all';
  1         1  
  1         39  
6 1     1   4 use base qw(Config::Apple::Profile::Payload::Common);
  1         1  
  1         431  
7              
8 1     1   681 use Exporter::Easiest q(OK => $VERSION);
  1         820  
  1         9  
9 1     1   210 use Mac::PropertyList;
  1         2  
  1         55  
10 1     1   6 use Readonly;
  1         2  
  1         59  
11 1     1   7 use Config::Apple::Profile::Payload::Common;
  1         2  
  1         34  
12 1     1   5 use Config::Apple::Profile::Payload::Types qw(:all);
  1         3  
  1         258  
13 1     1   8 use Config::Apple::Profile::Targets qw(:all);
  1         2  
  1         669  
14              
15             our $VERSION = '0.87';
16              
17              
18             =encoding utf8
19              
20             =head1 NAME
21              
22             Config::Apple::Profile - An OO interface to Apple Configuration Profiles.
23              
24              
25             =head1 SYNOPSIS
26              
27             use File::Temp;
28             use Config::Apple::Profile;
29             use Config::Apple::Profile::Payload::Certificate::PEM;
30             use Config::Apple::Profile::Payload::Wireless;
31              
32             my $cert = new Config::Apple::Profile::Payload::Certificate::PEM;
33             my $cert_payload = $cert->payload;
34             $cert_payload->{PayloadIdentifier} = 'com.example.group15.payload.cert';
35             $cert_payload->{PayloadCertificateFileName} = 'myCA.pem';
36             $cert_payload->{PayloadContent} = <
37             ----- BEGIN CERTIFICATE -----
38             dsfkldfsbnjksjkgnndbfjkdgnjdfkgjkndfg
39             # snip
40             dgkdfgldmklbgklmd==
41             ----- END CERTIFICATE -----
42             ENDCERT
43              
44             my $wifi = new Config::Apple::Profile::Payload::Wireless;
45             my $wifi_payload = $wifi->payload;
46             $wifi_payload->{PayloadIdentifier} = 'com.example.group15.payload.wireless';
47             $wifi_payload->{SSID_STR} = 'CorpNet Public';
48             $wifi_payload->{EncryptionType} = 'None';
49              
50             my $profile = new Config::Apple::Profile;
51             my $profile_payload = $profile->payload;
52             $profile_payload->{PayloadIdentifier} = 'com.example.group15.payload';
53             $profile_payload->{PayloadDisplayName} = "My Group's Profile";
54             push @{$profile_payload->{PayloadContent}}, $cert_payload, $wireless_payload;
55              
56             my ($fh, $file) = tempfile('CorpConfig',
57             SUFFIX => '.mobileconfig', UNLINK => 0);
58             print $fh $profile->export;
59             close $fh;
60             print "Configuration Profile written to $file\n";
61              
62              
63             =head1 DESCRIPTION
64              
65             Apple provides users with a way to configure Apple devices (running iOS or Mac
66             OS X) using ready-made configuration files, which Apple calls
67             B. This suite of Perl modules is intended to aid
68             people who would like to generate their own configuration profiles, without
69             having to mess around with the XML themselves.
70              
71             Configuration profiles can be used by iOS and Mac OS X to set a number of
72             general and user-specific items. Examples include:
73              
74             =over 4
75              
76             =item *
77              
78             Configuring an LDAP server, for directory search in Mail and Contacts.
79              
80             =item *
81              
82             Specifying password requirements to match company policy (and common sense).
83              
84             =item *
85              
86             Configuring an email account, with or without a user's credentials.
87              
88             =item *
89              
90             Adding new certificate authorities.
91              
92             =back
93              
94             Configuration profiles can be pre-made static files, or they can be
95             dynamically-generated with configurations (such as usernames and passwords)
96             that are specific to a user. Configuration profiles may be encrypted (so they
97             may only be read on a specific device) and signed (to verify that they have not
98             been modified by anyone other than the profile's creator).
99              
100             A configuration profile contains one or more B, in addition to some
101             header information. In Perl terms, a payload can be thought of as a Hash.
102             There are some keys of the "hash" that are common to all types of payloads,
103             and of course other keys that are payload-specific. Some keys are optinal,
104             and some keys are only optional on one platform or the other (iOS or Mac OS X).
105             In addition, there are some payloads that are only valid on one platform. For
106             example, the C payload can only be
107             used with a Mac OS X configuration profile.
108              
109             For a list of all payloads that Apple currently recognizes, refer to the
110             I linked below. Not all payloads are
111             implemented in this release. If you are interested in seeing more payloads
112             supported, please contribute! See the L section below for more info.
113              
114              
115             =head1 CLASS HIERARCHY
116              
117             Classes are laid out in the following hierarchy:
118              
119             Config::Apple::
120             Profile <-- This file
121             Profile::
122             Payload:: <-- All payload-related classes are in here
123             Common.pm <-- Common payload elements are here
124             Certificate.pm <-- The Certificate payload type
125             Certificate:: <-- Certificate sub-types are here
126             Email.pm <-- The Email payload type
127             Tie:: <-- Internal support code
128             Encryption.pm <-- Profile encryption (TBI)
129             Signing.pm <-- Profile signing (TBI)
130              
131             Clients need only C the modules that directly provide the functionality
132             they are looking for.
133              
134             As an example, if you want to create a configuration profile that configures an
135             IMAP email account, an LDAP server, and a passcode policy, you would need the
136             following modules:
137              
138             =over 4
139              
140             =item * L would configure the email account.
141              
142             =item * L would configure the LDAP server.
143              
144             =item * L would configure the passcode
145             policy.
146              
147             =item * This module would put everything together, and give you the final profile.
148              
149             =back
150              
151             =cut
152              
153              
154             =head1 CLASS METHODS
155              
156             =head2 new()
157              
158             Returns a new object.
159              
160             =cut
161              
162             # This call automatically goes up to Config::Apple::Profile::Payload::Common
163              
164              
165             =head1 INSTANCE METHODS
166              
167             =head2 INHERITED METHODS
168              
169             Most of the methods, including critical ones such as C and C,
170             are implemented in the module C,
171             and are not reimplemented here. See L.
172              
173              
174             =head2 export()
175              
176             export([C => C, ...])
177              
178             Return a string containing the profile, serialized as XML. The entire string
179             will already be encoded as UTF-8. If any UUID or Identifier keys have not been
180             filled in, they are filled in with random values.
181              
182             This method is used when it is time to output a profile.
183              
184             Several parameters can be provided, which will influence how this method runs.
185              
186             =over 4
187              
188             =item target
189              
190             If C (a value from L) is provided,
191             then this will be taken into account when exporting. Only payload keys that
192             are used on the specified target will be included in the output.
193              
194             The C option controls what happens if keys are excluded.
195              
196             =item version
197              
198             If C (a version string) is provided, then only payload keys that work
199             on the specified version will be included in the output.
200              
201             If C is provided, then C must also be set, but C can
202             be set without setting C.
203              
204             The C option controls what happens if keys are excluded.
205              
206             =item completeness
207              
208             If C is set to a true value, and keys are excluded because of
209             C or C, then C will throw an exception. If set to a
210             false value, or if not set at all, then no exceptions will be thrown, and a
211             less-than-complete (but still valid) plist will be returned.
212              
213             =back
214              
215             The following exceptions may be thrown:
216              
217             =over 4
218              
219             =item Config::Apple::Profile::Exception::KeyRequired
220              
221             Thrown if a required key has not been set.
222              
223             =item Config::Apple::Profile::Exception::Incomplete
224              
225             Thrown if payload keys are being excluded from the output because of C
226             or C.
227              
228             =back
229              
230             =cut
231              
232             sub export {
233 0     0 1   my $self = shift @_;
234            
235             # Fill in identifiers/UUIDs, then convert to plist, and export
236 0           $self->populate_id;
237 0           my $plist = $self->plist(@_);
238 0           return Mac::PropertyList::plist_as_string($plist);
239             }
240              
241              
242             =head1 PAYLOAD KEYS
243              
244             Payload keys are the keys that you can use when manipulating the hash returned
245             by C.
246              
247             All of the payload keys defined in L
248             are used by this payload.
249              
250             This payload has the following additional keys:
251              
252             =head2 C
253              
254             I
255              
256             An array of C objects.
257              
258             =head2 C
259              
260             I
261              
262             Payload contents that are encrypted, such that only a single device may decrypt
263             and read it. This is a Data type, which is formed by first taking the contents
264             of C, and serializing them as a plist with an array as the root
265             element. Next, the contents are CMS-encrypted as enveloped data, then finally
266             DER-encoded.
267              
268             Until C is implemented, the following
269             OpenSSL command can be used to encrypt the plist.
270              
271             openssl cms -encrypt -in your.mobileconfig_fragment
272             -out your.mobileconfig_fragment.encrypted -outform der -cmsout
273             your_recipients_cert.pem
274              
275             OpenSSL 1 or later is required for the C command.
276              
277             =head2 C
278              
279             I
280              
281             Applies to Mac OS X only.
282              
283             Can be set to "System", in which case the profile will apply system-wide,
284             or "User", in which case the profile will only apply to the user installing
285             the profile.
286              
287             If not set, the default is "User".
288              
289             =head2 C
290              
291             I
292              
293             A dictionary of strings. The keys are locale identifiers, specifically
294             canonicalized IETF BCP 47 locale strings. Each value is a localized text string
295             containing a message that the user will see when installing the profile. This
296             is a place to put warnings, agreements, etc..
297              
298             An extra pair, with the key "default", may be included to provide a default
299             consent message. If no default is set, the "en" localization will be used as a
300             last resort.
301              
302             =head2 C
303              
304             I
305              
306             A boolean. If set to C, then the profile may only be removed if a
307             profile removal password is provided. To set such a password, include an object
308             from L as part of
309             C.
310              
311             =head2 C
312              
313             I
314              
315             A floating-point number, the number of seconds that the profile will remain on
316             the device before it is automatically removed.
317              
318             If C is set, this value will be ignored.
319              
320             =head2 C
321              
322             I
323              
324             A date. Once past, the profile will be automatically removed from the device.
325              
326             This value overrides C.
327              
328             =head2 C
329              
330             I
331              
332             A date. This only applies to payloads delivered over-the-air, using a mobile
333             device management (MDM) solution. Once past, this profile will be marked as
334             "expired", and will be eligible for updating over-the-air.
335              
336             =cut
337              
338             Readonly our %payloadKeys => (
339             # Bring in the common keys...
340             %Config::Apple::Profile::Payload::Common::payloadKeys,
341            
342             #... and define our own!
343             'PayloadContent' => {
344             type => $ProfileArray,
345             subtype => $ProfileClass,
346             description => 'The payloads to be delivered in this profile.',
347             targets => {
348             $TargetIOS => '5.0',
349             $TargetMACOSX => '10.7',
350             },
351             optional => 1,
352             },
353             'EncryptedPayloadContent' => {
354             type => $ProfileData,
355             description => 'Payload content that has been encrypted to a specific '
356             . 'user. The contents of "PayloadContent" must be serialized as '
357             . 'an array plist, then CMS-encrypted (as enveloped data), and '
358             . 'finally serialized in DER format.',
359             targets => {
360             $TargetIOS => '5.0',
361             $TargetMACOSX => '10.7',
362             },
363             optional => 1,
364             },
365             'PayloadExpirationDate' => {
366             type => $ProfileDate,
367             description => 'For profiles delivered via OTA, the date when the '
368             . 'profile has expired and can be updated (again via OTA).',
369             targets => {
370             $TargetIOS => '5.0',
371             $TargetMACOSX => '10.7',
372             },
373             optional => 1,
374             },
375             'PayloadRemovalDisallowed' => {
376             type => $ProfileBool,
377             description => 'If true, the profile may only be removed if a profile-'
378             . 'removal password has been set, and the password is provided '
379             . 'by the user.',
380             targets => {
381             $TargetIOS => '5.0',
382             $TargetMACOSX => '10.7',
383             },
384             optional => 1,
385             },
386             'PayloadScope' => {
387             type => $ProfileString,
388             description => 'Controls if the profile applies to the entire "System",'
389             . ' or if just to the specific "User". If one of those two values '
390             . 'is not provided, "User" will be used as the default.',
391             targets => {
392             # Desktop only, not for iOS
393             $TargetMACOSX => '10.7',
394             },
395             optional => 1,
396             },
397             'RemovalDate' => {
398             type => $ProfileDate,
399             description => 'The date when the profile will be automatically removed'
400             . ' from the device. Overrides DurationUntilRemoval.',
401             targets => {
402             $TargetIOS => '5.0',
403             $TargetMACOSX => '10.7',
404             },
405             optional => 1,
406             },
407             'DurationUntilRemoval' => {
408             type => $ProfileReal,
409             description => 'The number of seconds until the profile is '
410             . 'automatically removed from the device. The RemovalDate profile '
411             . 'key overrides this one.',
412             targets => {
413             $TargetIOS => '5.0',
414             $TargetMACOSX => '10.7',
415             },
416             optional => 1,
417             },
418             'ConsentText' => {
419             type => $ProfileDict,
420             subtype => $ProfileString,
421             description => 'A dictionary where the keys are canonicalized IETF BCP '
422             . '47 locale strings. The key "default" may be used as the '
423             . 'default entry. The values are localized messages that the user '
424             . 'must accept before the profile is installed.',
425             targets => {
426             $TargetIOS => '5.0',
427             $TargetMACOSX => '10.7',
428             },
429             optional => 1,
430             },
431             'PayloadType' => {
432             type => $ProfileString,
433             targets => {
434             $TargetIOS => '5.0',
435             $TargetMACOSX => '10.7',
436             },
437             value => 'Configuration',
438             },
439             'PayloadVersion' => {
440             type => $ProfileNumber,
441             value => 1,
442             },
443             ); # End of %payloadKeys
444              
445              
446             =head1 SEE ALSO
447              
448             =over 4
449              
450             =item * Apple's "Configuration Profile Reference".
451              
452             L
453              
454             =item * Apple's "Over-the-Air Profile Delivery and Configuration" document.
455              
456             L.
457              
458             =back
459              
460              
461             =head1 SUPPORT
462              
463             You can find documentation for this module with the perldoc command.
464              
465             perldoc Config::Apple::Profile
466              
467             All modules have some POD inside them. If you're not interested in using the
468             command-line, your IDE may have PerlDoc support, or you can go here:
469              
470             =over 4
471              
472             =item * MetaCPAN
473              
474             L
475              
476             =item * search.cpan.org
477              
478             L
479              
480             =item * AnnoCPAN: Annotated CPAN documentation
481              
482             L
483              
484             =back
485              
486             If you have found a bug, or want to request an enhancement of some sort, you
487             may do so here:
488              
489             =over 4
490              
491             =item * Github's issue section
492              
493             https://github.com/akkornel/Config-Apple-Profile/issues
494              
495             =item * RT: CPAN's request tracker (for people who don't use Github)
496              
497             L
498              
499             =back
500              
501             Finally, feel free to rate the release!
502              
503             =over 4
504              
505             =item * CPAN Ratings
506              
507             L
508              
509             =back
510              
511              
512             =head1 SOURCE
513              
514             This project is on GitHub:
515              
516             L
517              
518             The web site linked above has the most recently-pushed code, along with
519             information on how to get a copy to your computer.
520              
521             If you are interested in making a contribution, please make it in the form
522             of a GitHub pull request.
523              
524              
525             =head1 ACKNOWLEDGEMENTS
526              
527             Thanks are due to B (C) for the L
528             module, which is relied on heavily by this code!
529              
530              
531             =head1 AUTHOR
532              
533             A. Karl Kornel, C<< >>
534              
535              
536             =head1 COPYRIGHT AND LICENSE
537              
538             Copyright 2014 A. Karl Kornel.
539              
540             This program is free software; you can redistribute it and/or modify it
541             under the terms of either: the GNU General Public License as published
542             by the Free Software Foundation; or the Artistic License.
543              
544             See L for more information.
545              
546             =cut
547              
548             1;