Flex can not simply be acquired from the App Store and delivered to devices, there is a setup that needs to be completed and this must be done via your MDM.

Most Apps require the end user to configure the account to log into a server or perform an action. Flex is no different except it requires the administrator to configure the app. As you are the one holding the keys to your MDM server.

As the name suggests, Flex can be tailored to your needs. For example you can have the Flex app open and direct to the edit screen rather than the data review screen. So if you wanted end users to simply open the app, enter some data and save, this can be done.

Similarly you can also dictate which fields are visible and/or editable. This is critical as you only provide the fields that you want end users to see. Or you can also prevent editing all together, meaning you can present data to the end users as a kind of disclosure, useful in Europe if you need to disclose what data is collected.

One of key features of Flex is also the ability to display and/or edit Extension attributes, unlike previous apps that have done a similar process, Flex actually checks with the server to identify the field type and contents. If the field is a popup menu it will collect the values to present to the end user.

  • Only Text from your MDM Server is visible, this can be in your preferred language, but text gathered from your MDM will be in the language visible to the API of the MDM.
  • Edit Functionality can be revoked or delivered
  • Fields can be selected to be displayed
  •  Erase or remote wipe of a device can be disabled

The user account your create for your Jamf Api User Credentials should have limited permission within your Jamf PRO Server. To achieve this we have put together a list of value you will need for your API User. Also is a link to another You Tube video describing the permissions in more details.

Jamf PRO Server Objects

  • Buildings – Read Only
  • Departments – Read Only
  • Mobile Device Extension Attributes – Read Only
  • Mobile Devices – Create, Read, Write
  • Sites – Read Only
  • Users – Create Read Update

Jamf PRO Server Actions

  • Assign Users to Mobile Devices
  • Send Inventory Requests to Mobile Devices
  • Send Mobile Device Remote Wipe Command

Flex App Api Permissions

 

The credentials must be stored within the App Configuration in order to allow the device to communicate with your MDM. Secondly these credentials must be in base64 and the associated account must have the credentials to read, modify or delete a device based on the inventory fields and access your wish to provide.

 

Essentially Obfuscating Credentials (making them harder to read)

Basic Credentials include a username and password, we take these and encode them for obfuscating credentials, in other words they are not uncrackable, just not rememberable.

Below we will help you to obfuscate the credentials into base 64 encoded format.

Option 1 – App for macOS or EXE for Windows

Option 2 – Scripted

Simply open the Terminal.app on your Mac and run the following script. You can Choose Python or Bash.

Python Script
#!/usr/bin/env python3
import base64

client_id = 'myapiuser'
client_secret = 'Pang@l@ct1cG@rgl3Bl@5t3r'
encodedData = base64.b64encode(bytes(f'{client_id}:{client_secret}', 'ISO-8859-1')).decode('ascii')
print(authorization_header_string)
Bash or Shell Script
#!/bin/bash

## Edit here with your Jamf PRo API user
client_id='myapiuser'
client_secret='Pang@l@ct1cG@rgl3Bl@5t3r'
# Do not edit below here
echo "Encoded String"
printf "$client_id:$client_secret" | iconv -t ISO-8859-1 | base64 -i -

Example 1 – Core Functionality

  • Edit visible
  • Erase or wipe Device enabled
  • App Directed to Data View Screen
<dict>
	<key>serverURL</key>
	<string>$JPS_URL</string>
	<key>apiCredentials</key>
	<string>base64Credentials</string>
	<key>deviceID</key>
	<string>$JSSID</string>
	<key>submitText</key>
	<string>Submit</string>
	<key>forceDataEntry</key>
	<false/>
	<key>allowErase</key>
	<true/>
	<key>isEditable</key>
	<true/>
	<key>useLDAP</key>
	<false/>
	<key>enableAssetTag</key>
	<true/>
	<key>enableUsername</key>
	<true/>
	<key>enableFullname</key>
	<true/>
	<key>enableEmail</key>
	<true/>
	<key>enableDepartment</key>
	<true/>
	<key>enableBuilding</key>
	<true/>
	<key>enableSites</key>
	<true/>
	<key>labelUsername</key>
	<string>UserName:</string>
	<key>labelFullName</key>
	<string>Full Name:</string>
	<key>labelEmailAddress</key>
	<string>Email Address:</string>
	<key>labelSites</key>
	<string>Site:</string>
	<key>labelBuilding</key>
	<string>Building:</string>
	<key>labelDepartment</key>
	<string>Department:</string>
	<key>labelAssetTag</key>
	<string>Asset Tag:</string>
	<key>labelSerialNumber</key>
	<string>Serial Number:</string>
	<key>labelSupervised</key>
	<string>Supervised:</string>
	<key>labelIosVersion</key>
	<string>iOS Version:</string>
	<key>labelLastUpdate</key>
	<string>Last Update:</string>
	<key>labelSpaceUsed</key>
	<string>Space Used:</string>
	<key>labelImei</key>
	<string>IMEI Identifier:</string>
	<key>labelActivationLock</key>
	<string>Activation Lock:</string>
	<key>enabledEAs</key>
		<array/>
	<key>editableEAs</key>
		<array/>
</dict>

Example 2 – No Wipe and Change Default Display

  1. Edit visible
  2. Erase or wipe Device disabled
  3. App Directed to Data Entry Screen
<dict>
	<key>serverURL</key>
	<string>$JPS_URL</string>
	<key>apiCredentials</key>
	<string>base63Credentials</string>
	<key>deviceID</key>
	<string>$JSSID</string>
	<key>submitText</key>
	<string>Submit</string>
	<key>forceDataEntry</key>
	<true/>
	<key>allowErase</key>
	<false/>
	<key>isEditable</key>
	<true/>
	<key>useLDAP</key>
	<false/>
	<key>enableAssetTag</key>
	<true/>
	<key>enableUsername</key>
	<true/>
	<key>enableFullname</key>
	<true/>
	<key>enableEmail</key>
	<true/>
	<key>enableDepartment</key>
	<true/>
	<key>enableBuilding</key>
	<true/>
	<key>enableSites</key>
	<true/>
	<key>labelUsername</key>
	<string>UserName:</string>
	<key>labelFullName</key>
	<string>Full Name:</string>
	<key>labelEmailAddress</key>
	<string>Email Address:</string>
	<key>labelSites</key>
	<string>Site:</string>
	<key>labelBuilding</key>
	<string>Building:</string>
	<key>labelDepartment</key>
	<string>Department:</string>
	<key>labelAssetTag</key>
	<string>Asset Tag:</string>
	<key>labelSerialNumber</key>
	<string>Serial Number:</string>
	<key>labelSupervised</key>
	<string>Supervised:</string>
	<key>labelIosVersion</key>
	<string>iOS Version:</string>
	<key>labelLastUpdate</key>
	<string>Last Update:</string>
	<key>labelSpaceUsed</key>
	<string>Space Used:</string>
	<key>labelImei</key>
	<string>IMEI Identifier:</string>
	<key>labelActivationLock</key>
	<string>Activation Lock:</string>
	<key>enabledEAs</key>
	<array/>
	<key>editableEAs</key>
	<array/>
</dict>

Example 3 – No Edit

  1. Edit hidden
  2. Erase or wipe Device disabled
  3. App Directed to Data View Screen
<dict>
	<key>serverURL</key>
	<string>$JPS_URL</string>
	<key>apiCredentials</key>
	<string>base64Credentials</string>
	<key>deviceID</key>
	<string>$JSSID</string>
	<key>submitText</key>
	<string>Submit</string>
	<key>forceDataEntry</key>
	<false/>
	<key>allowErase</key>
	<false/>
	<key>isEditable</key>
	<false/>
	<key>useLDAP</key>
	<false/>
	<key>enableAssetTag</key>
	<true/>
	<key>enableUsername</key>
	<true/>
	<key>enableFullname</key>
	<true/>
	<key>enableEmail</key>
	<true/>
	<key>enableDepartment</key>
	<true/>
	<key>enableBuilding</key>
	<true/>
	<key>enableSites</key>
	<true/>
	<key>labelUsername</key>
	<string>UserName:</string>
	<key>labelFullName</key>
	<string>Full Name:</string>
	<key>labelEmailAddress</key>
	<string>Email Address:</string>
	<key>labelSites</key>
	<string>Site:</string>
	<key>labelBuilding</key>
	<string>Building:</string>
	<key>labelDepartment</key>
	<string>Department:</string>
	<key>labelAssetTag</key>
	<string>Asset Tag:</string>
	<key>labelSerialNumber</key>
	<string>Serial Number:</string>
	<key>labelSupervised</key>
	<string>Supervised:</string>
	<key>labelIosVersion</key>
	<string>iOS Version:</string>
	<key>labelLastUpdate</key>
	<string>Last Update:</string>
	<key>labelSpaceUsed</key>
	<string>Space Used:</string>
	<key>labelImei</key>
	<string>IMEI Identifier:</string>
	<key>labelActivationLock</key>
	<string>Activation Lock:</string>
	<key>enabledEAs</key>
	<array/>
	<key>editableEAs</key>
	<array/>
</dict>

Example 4 – Display Language (Korean)

  1. Edit enabled
  2. Erase or wipe Device enabled
  3. App Directed to Data View Screen
<dict>
	<key>serverURL</key>
	<string>$JPS_URL</string>
	<key>apiCredentials</key>
	<string>base64Encoded</string>
	<key>deviceID</key>
	<string>$JSSID</string>
	<key>submitText</key>
	<string>제출</string>
	<key>forceDataEntry</key>
	<true/>
	<key>allowErase</key>
	<true/>
	<key>isEditable</key>
	<true/>
	<key>useLDAP</key>
	<false/>
	<key>enableAssetTag</key>
	<true/>
	<key>enableUsername</key>
	<true/>
	<key>enableFullname</key>
	<true/>
	<key>enableEmail</key>
	<true/>
	<key>enableDepartment</key>
	<true/>
	<key>enableBuilding</key>
	<true/>
	<key>enableSites</key>
	<true/>
	<key>labelUsername</key>
	<string>사용자 이름:</string>
	<key>labelFullName</key>
	<string>전체 이름:</string>
	<key>labelEmailAddress</key>
	<string>이메일 주소:</string>
	<key>labelSite</key>
	<string>사이트:</string>
	<key>labelBuilding</key>
	<string>건물:</string>
	<key>labelDepartment</key>
	<string>부서:</string>
	<key>labelAssetTag</key>
	<string>자산 태그:</string>
	<key>labelSerialNumber</key>
	<string>일련 번호:</string>
	<key>labelSupervised</key>
	<string>감독 대상:</string>
	<key>labelIosVersion</key>
	<string>iOS 버전:</string>
	<key>labelLastUpdate</key>
	<string>최종 업데이트:</string>
	<key>labelSpaceUsed</key>
	<string>사용된 공간:</string>
	<key>labelImei</key>
	<string>IMEI 식별자:</string>
	<key>labelActivationLock</key>
	<string>활성화 잠금:</string>
	<key>enabledEAs</key>
	<array>
		<string>사용자 정의 자산 태그</string>
	</array>
	<key>editableEAs</key>
	<array>
		<string>사용자 정의 자산 태그</string>
	</array>
</dict>

Extension Attributes offer a huge flexibility option within the Flex ecosystem. Here you can add up to 4 Extension Attributes to allow end users to populate via a popup or  standard text field to allow end users to populate information manually.

 

Example:

  • Field Name in Jamf: “Aircraft_Type”
  • Field Name in Jamf: “Department OG”
  • Field Name in Jamf: “Reason for Return”

 

To enter these details into the app configuration web form please use the name from the Jamf Extension attribute as the Title and configure its edit-ability via the radio buttons. An example of the code is below;

<key>enabledEAs</key>
<array>
    <string>Aircraft_Type</string>
    <string>Department OG</string>
    <string>On Loan Device</string>
    <string>Reason for Return</string>
</array>
<key>editableEAs</key>
<array>
	<string>Aircraft_Type</string>
	<string>Department OG</string>
	<string>On Loan Device</string>
	<string>Reason for Return</string>
</array>

Example Full App Config with Extension Attributes

<dict>
	<key>serverURL</key>
	<string>$JPS_URL</string>
	<key>apiCredentials</key>
	<string>base64Credentials</string>
	<key>deviceID</key>
	<string>$JSSID</string>
	<key>submitText</key>
	<string>Submit</string>
	<key>forceDataEntry</key>
	<false/>
	<key>allowErase</key>
	<true/>
	<key>isEditable</key>
	<true/>
	<key>useLDAP</key>
	<false/>
	<key>enableAssetTag</key>
	<true/>
	<key>enableUsername</key>
	<true/>
	<key>enableFullname</key>
	<true/>
	<key>enableEmail</key>
	<true/>
	<key>enableDepartment</key>
	<true/>
	<key>enableBuilding</key>
	<true/>
	<key>enableSites</key>
	<true/>
	<key>labelUsername</key>
	<string>UserName:</string>
	<key>labelFullName</key>
	<string>Full Name:</string>
	<key>labelEmailAddress</key>
	<string>Email Address:</string>
	<key>labelSites</key>
	<string>Site:</string>
	<key>labelBuilding</key>
	<string>Building:</string>
	<key>labelDepartment</key>
	<string>Department:</string>
	<key>labelAssetTag</key>
	<string>Asset Tag:</string>
	<key>labelSerialNumber</key>
	<string>Serial Number:</string>
	<key>labelSupervised</key>
	<string>Supervised:</string>
	<key>labelIosVersion</key>
	<string>iOS Version:</string>
	<key>labelLastUpdate</key>
	<string>Last Update:</string>
	<key>labelSpaceUsed</key>
	<string>Space Used:</string>
	<key>labelImei</key>
	<string>IMEI Identifier:</string>
	<key>labelActivationLock</key>
	<string>Activation Lock:</string>
	<key>enabledEAs</key>
	<array>
		<string>Aircraft_Type</string>
		<string>Department OG</string>
		<string>On Loan Device</string>
		<string>Reason for Return</string>
	</array>
	<key>editableEAs</key>
	<array>
		<string>Aircraft_Type</string>
		<string>Department OG</string>
		<string>On Loan Device</string>
		<string>Reason for Return</string>
	</array>
</dict>

Designed for the company or organisation that wants to use Flex and force users to enter their data.

Imagine your site needs to deploy mail settings and custom lock screen message. We need their username, email address and possibly which department and building they are in.

 

The end result of this demo is to

have an automated solution to ensure end users enter their data. If they do not, then the iPad or iPhone remains locked to Flex, waiting for the data to be entered… forever! Who said the days of evil IT admins were over?

If you want the Flex app to ‘first’ launch directly to the edit interface on the initial launch then this option is for you.

Step 1 Smart Group – group our target audience

Lets start with a smart group to identify the devices. And lets say our company name in the example below is D8Flex, obviously you will change this on your site.

Smart Group Name

Flex-Device information Missing

Criteria

If we enter “blank” below then do not enter anything  for the value, when in doubt have a look at our screen shot below. Think of a smart group as an automated search by Jamf.

Modifier

 

or

or

or

Criteria

Username

Email Address

Department

Building

Operator

is

is

is

is

Value

blank

blank

blank

blank

User details missing
Smart Group Criteria

Step 2 Lock the device to Flex

Configuration Profile (before data entered)

So once we have the smart group created and we have confirmed its correct operation (please always check your smart groups are correct), i.e. edit the user details to see if the smartgroup responds correctly once you enter some information.

 

Navigate to:

Jamf Dashboard > Mobile Devices > Configuration Profiles

 

Next we want to lock the device to the Flex app. So for devices with missing information we deploy a configuration profile to only allow Flex.

Name

auto – Device info missing

Payload

Single App Mode App Name: FlexMDM

Scope

Flex-Device information Missing

bundle identifier is com.d8services.flex

So far we have created one smart group and one configuration profile. The result on the device is that at any time the user information is removed the profile to apply “Single App Mode” is re-applied.

 

If the device is to remain on a shelf until it is assigned it can be powered down. The next user who received the device then submits their details and once complete single app mode will be disabled.

Step 3 Data Entered – what now?

I’m glad you asked, well now we have our devices with all the information we want or need, so now we will simply deploy our configurations. Targeting All devices while excluding the smart group we created earlier. In the scope pane of a configuration profile you will see three tabs across the top of the screen. The first is the target, i.e. the main body of devices you want to deploy to, the second is the limitation of the target group, and lastly there is the exclusion group. As we created a smart group for information missing, we can simply add that group here.

Name

auto – Exchange Configuration

Payload

Exchange ActiveSync

Scope

Target: All devices

Limitation: none

Exclusion: Flex-Device information Missing

Payload Value

Account Name: D8Flex

Exchange ActiveSync Host: outlook.office365.com

Domain: blank

User: $EMAIL

Email Address: $EMAIL

Password: blank

Exchange information inside configuration profile
Target All Devices
Target devices for the profile
Excluded devices, we selected the group from step 1
Excluded devices, we selected the group from step 1

Step 4 Lock Screen details

Lock Screen Message and gocha’s

Now you might ask why we need a discussion on this, but the lock screen is only deployed when either we manually modify the Configuration Profile and re-push this to “All Devices”, or when you fall in and out of the scope, maybe via smart group (I’m glad we created one earlier, arn’t you?).

 

So if you deploy a lockscreen screen payload to the device before all user data is available, then the Jamf server sends out a configuration profile without any user information included. It will not resend if the user data is updated, either manually or via Jamf, it must be resent to the device one information is present.

 

Now this said you could choose to simply contain Building or Department information and nothing about the end user. If this is the case simply assign it to the Building or Department. If you assign a configuration profile to the scope of a Building and Department then the profile might be installed when only one is set, meaning the result in the “LockScreen” will simply display the variable name i.e. $DEPARTMENTNAME instead of the actual department name. To correct this you will have to redeploy the profile. A way around this is to make a smart group for the Building and Department, then scope to this, ensuring both are set prior to assignment.

Name

auto – Notification Screen

Payload

Lock Screen Message

Scope

Target: All Devices

Limitations: none

Exclusions: Flex-Device information Missing

Payload Value

Asset Tag Information: | $EMAIL | D8Flex | $DEPARTMENTNAME | $BUILDINGNAME |

LockScreen Message
Lock Screen Message inside the Configuration Profile

I realise that the Asset Tag Information payload above might appear a bit odd looking, but the end result we want is as follows:

 

| [email protected] | D8Flex | Development | Bangkok Soi 105 |

 

A quick screen shot from the device after deployment is below. When a configuration profile contains variables it means we do not need multiple profiles for each device. One will surfice, but Jamf populates this variable with the device information at the time of deployment. So each device receives its very own profile.

Asset Tag information displayed on a device after deployment

For more variables you can use with Jamf configuration profiles please have a look at Jamf’s Administrator Guide 

serverURL

this “should be set to $JPS_URL, this is the URL to connect to your Jamf PRO Server, by using the Jamf variable the URL is submitted by Jamf during deployment

string

apiCredentials

Credentials for the Jamf Pro service account you will be using with Flex, we have created both an App and demonstrated the raw code for you to choose. see under credentials on this page https://flex.d8services.com/flex-app-config-examples/

string

deviceID

device ID with in your Jamf PRO Server, this value must be set to the Jamf variable $JSSID. If you enter a value manually here flex will show you another devices inventory record. DO NOT CHANGE THIS

string

frontPageGraphic

Currently not in use, but if we receive feedback we can start work on this. It is the URL for the graphic you may want to have as the loading screen

string

submitText

Text used by Flex to display the submission button after editing, allows for folk from other countries to use their language. Flex will default to “Submit” if this value does not exist, but you could have “enter”, or whatever you like.

string

forceDataEntry

optional to force Flex to the edit screen on initial launch.

Boolean true/false

isEditable

Does Flex allow the end user to edit the user data? If you disable this then you could simply use Flex for showing your users their “collected” data on your server. And also allow end users to update inventory etc.

Boolean true/false

enableAssetTag

Will the Asset Tag field visible in both the edit and display only pane.

Boolean true/false

enableUsername

Will the username field visible in both the edit and display only pane.

Boolean true/false

enableFullname

Will the Full Name field visible in both the edit and display only pane.

Boolean true/false

enableEmail

Will the Email field visible in both the edit and display only pane.

Boolean true/false

enableDepartment

Will the Department field visible in both the edit and display only pane.

Boolean true/false

enableBuilding

Will the Building field visible in both the edit and display only pane.

Boolean true/false

enableSites

Will the Sites field visible in both the edit and display only pane.

Boolean true/false

labelUsername

Text used to describe the Username field, also can be another language, based on your preference

string

labelSites

Text used to describe the sites from Jamf PRO, also can be another language, based on your preference

string

labelBuilding

Text used to describe the Building field, also can be another language, based on your preference

string

labelDepartment

Text used to describe the Department field, also can be another language, based on your preference

string

allowErase

Will Flex allow end users to wipe their device? The erase option will be greyed out if false

Boolean true/false

enabledEAs

Extension Attribute names allowed for viewing (enter these in your language in Jamf, and then enter the same string of characters in this field) upto 4 individual EA’s are allowed

Array of strings

editableEAs

 

Extension Attribute names used in the edit screen (enter these in your language in Jamf, and then enter the same string of characters in this field) upto 4 individual EA’s are allowed

Array of strings

If you need to send us a message, please feel free to use the form below. Do not forget that we have a Github page for issues.

get in touch