Administrative tasks

Relution is executing several automatic background tasks, which are scheduled as one time jobs or recurring jobs. For example, these tasks can be used to handle the system maintenance or create various reports or notifications.

Creating organizations

You are logged in as system administrator.

To create a new organization, you need to log in to the web portal as the administrator of the system organization.

  • Navigate to Settings > Organizations

  • Click on Add and provide the required attributes in the sections

    • Organization

    • Organization Administrator

  • Click Save to save your changes

After the organization is created, you can now sign in as the organization administrator you created in the previous step. Either click on the Login as organization administrator button or sign out and sign in with the credentials you provided.

Certificate expiration notifications

Certificate expiration is executed for all system keystores (see Relution Configuration > Security > Keysore) and all organization APNS certificates (see Relution Portal > Settings > Organization > Certificates).

For any of the above mentioned certificates a notification e-mail is created:

  • 30 days before expiration

  • 7 days before expiration

  • on the day of the expiration

  • repeatedly each 30 days after expiration

Certificate notification types:

  • System keystores are reported to the Keystore Notification Recipients (see Relution Configuration > Other > Common Relution Configuration), because system keystores are used globally and Relution support should be notified

  • APNS certificates with following UIDs com.mwaysolutions.enterprise.mway.relutionclient, com.mwaysolutions.store.relution, com.apple.mgmt.mway.mwaysolutions are reported to the Keystore Notification Recipients. Additionally Relution support should be notified

  • Custom APNS certificates are reported to the organization administrators, because these certificates are organization specific and the organization needs to take action

If the Keystore Notification Recipients are not defined, then a log entry is created instead of the e-mail.

Notes:

  • Relution System Portal can be called by logging in as System Administrator and Clicking "System Portal" on the help menu on the top right corner

  • Relution Portal can be found at https://[relutionURL]/relution/portal/

Using the Relution REST API (Application Programming Interface)

All functionality in Relution is available through an extensive REST API. You can use this API to call Relution from any other application or script.

Creating API Access Tokens

You need an API Access Token to access Relution through third party systems or scripts. You can create an access token by clicking on the user name in the top right corner of the Relution portal. Then click "Profile", "Access tokens", "Add".

For system admins, the Profile menu is not shown. Should you want to use APIs that require System Admin rights, log in as System Admin and type in this URL: https://<server>/relution/portal/#/profile to set the API key.

Sample Scripts

Here are some sample scripts that show how to use the API:

Uploading users via CSV import

To create users in Relution based on a .csv file you need to create 2 files. The first one is the users.csv file which needs to have one line for each user in the following format:

userid,email,first name,last name,password,phone number

You can copy the following example and replace the attributes with your values:

user1,user1@company.com,Heinz,Ketchup,p4ssw0rd,+49234346345
user2,user2@company.com,Heinz,Ketchup,p4ssw0rd,+49234346345
user3,user3@company.com,Heinz,Ketchup,p4ssw0rd,+49234346345
user4,user4@company.com,Heinz,Ketchup,p4ssw0rd,+49234346345
user5,user5@company.com,Heinz,Ketchup,p4ssw0rd,+49234346345
user6,user6@company.com,Heinz,Ketchup,p4ssw0rd,+49234346345

The second file you need is a bash script file (.sh). Copy the following example and replace following attributes with your values:

  • <valid_Relution_API_Key>

  • <relution_URL>

Save both files. Additionally the script has to be made executable:

chmod +x ./relutionCSVupload.sh

Execute it in your terminal as follows:

./relutionCSVupload.sh -f users.csv
#!/bin/bash
#--------------------------------------------------------------------------------

# Headers

ACCESS_TOKEN="<valid_Relution_API_Key>"

while getopts "a:h:f:r:" opt; do
  case $opt in
    a) # apikey
    APIKEY="$OPTARG"
    ;;

    h) # host
    HOST="$OPTARG"
    ;;

    f) # File
    FILE="$OPTARG"
    ;;

    r) # Role
    ROLE="$OPTARG"
    ;;

    \?)
    echo "Unknown option -$OPTARG" >&2
    ;;
  esac
done

APIKEY=$ACCESS_TOKEN
HOST='https://<relution_URL>'
# Remember to avoid the last backslash
echo $HOST

if [[ -z $APIKEY ]]; then
  echo "Please specify an API Key (-a)"
  exit 1
fi

if [[ -z $HOST ]]; then
  echo "Please specify a Host URL (-h)"
  exit 1
fi

if [[ ! -f $FILE ]]; then
  echo "Please specify an existing csv file (-f)"
  exit 1
fi

if [[ -z $ROLE ]]; then
  ROLE=Organame%20Device%20User
fi

ERRORS=0

echo -n "Importing users from $FILE to Relution server ${HOST} as '${ROLE//%20/ }'... "
echo
echo
# On missing errors information, you can try to run the following curl expression directly to see the full output
# curl -X POST -H "Accept: application/json" -H "X-User-Access-Token: $APIKEY" -F "file=@$FILE" "$HOST/gofer/security/user/import?overwrite&role=$ROLE"
HTTP_ERROR=$(curl -X POST -H "Accept: application/json" -H "X-User-Access-Token: $APIKEY" -F "file=@$FILE" -sw "%{http_code}" "$HOST/gofer/security/user/import?overwrite&role=$ROLE")
echo $HTTP_ERROR
HTTP_ERROR=${HTTP_ERROR: -6}
HTTP_ERROR=${HTTP_ERROR: 3}

if [[ $HTTP_ERROR -ne 200 ]]; then
  ERRORS=$((ERRORS + 1))
  echo "$HTTP_ERROR"
  else
    echo "Done. No Errors."
fi

if [[ $ERRORS -gt 0 ]]; then
  echo "Error(s) during upload: ($ERRORS)"
  exit $ERRORS
fi

echo "All done."
echo

Creating a new Relution organization

#!/bin/bash
#--------------------------------------------------------------------------------

# Web service URL, change the server name as needed
SVR_URL="https://<myserver>/relution/api/v1/wizard"

# Access token of System Admin, create it by opening https://<server>/relution/portal/#/profile
# Open this URL in your browser while logged in as System Administrator.
# NOTE: This is not an URL you can reach through clicking through the portal!
ACCESS_TOKEN="<sysadmin_api_token>"

# HTTP Headers
ACCEPT="application/json"
ACCEPT_CHARSET="UTF-8"

# Input JSON, change values as needed
read -r -d '' JSON_BODY << 'EOF'
{
  "name": "My Orga",
  "uniqueName": "myorga",
  "orgaMailReplyTo": [],
  "passwordPolicy": {
    "allowSimplePassword": false,
    "maximumPasswordAge": 0,
    "minimumNumbersOfDigits": 0,
    "minimumNumbersOfLowerCaseLetters": 0,
    "minimumNumbersOfUpperCaseLetters": 0,
    "minimumPasswordLength": 8,
    "requiredNumbersOfSymbols": 0
  },
  "orgaName": "myorga",
  "orgaFullName": "My Orga",
  "orgaContactName": "MyOrga Admin",
  "orgaContactEMail": "myorgaadmin@mail.de",
  "orgaAdminUser": "myorgaadmin",
  "orgaAdminGivenName": "MyOrga",
  "orgaAdminSurName": "Admin",
  "orgaAdminPwd": "myorgaadminpw",
  "orgaAdminEmail": "myorgaadmin@mail.de"
}
EOF

echo "Creating new Relution Organization at $SVR_URL..."
echo

# No changes should be required beyond this line...

RESPONSE=$(curl -X POST \
  ${SVR_URL} \
  -H "X-User-Access-Token: $ACCESS_TOKEN" \
  -H "Accept: $ACCEPT" \
  -H "Accept-Charset: $ACCEPT_CHARSET" \
  -H "Content-Type: $ACCEPT" \
  --write-out " HTTP_STATUS=%{http_code}" \
  --silent \
  -d "$JSON_BODY")
if [[ $RESPONSE =~ HTTP_STATUS=([0-9]+) ]]; then
  HTTP_STATUS=${BASH_REMATCH[1]}
fi

if [[ $HTTP_STATUS -lt 200 || $HTTP_STATUS -gt 299 ]]; then
  echo " HTTP status: $HTTP_STATUS"
else
    echo "Done. No Errors."
fi
echo

Querying the devices enrolled in a specific organization

#!/bin/bash
#--------------------------------------------------------------------------------

# Web service URL, change the server name as needed
SVR_URL="https://<myserver>/relution/api/v1/devices/baseInfo"

# Query filter, set to COMPLIANT (also possible: INACTIVE, NONCOMPUIANT, ...)
FILTER="?filter=%7B%22type%22:%22logOp%22,%22operation%22:%22AND%22,%22filters%22:%5B%7B%22type%22:%22stringEnum%22,%22fieldName%22:%22status%22,%22values%22:%5B%22COMPLIANT%22%5D%7D,%7B%22type%22:%22logOp%22,%22operation%22:%22NAND%22,%22filters%22:%5B%7B%22type%22:%22stringEnum%22,%22fieldName%22:%22status%22,%22values%22:%5B%22DELETED%22%5D%7D%5D%7D%5D%7DgetItems=true&getNonpagedCount=false"

# Access token of an Orga Admin, create it by clicking on the user name in the top right corner of the portal.
# Then click "Profile", "Access tokens", "Add".
ACCESS_TOKEN="<orga_admin_access_token>"

# HTTP Headers
ACCEPT="application/json"
ACCEPT_CHARSET="UTF-8"

function parse_json()
{
    echo $1 | \
    sed -e 's/[{}]/''/g' | \
    sed -e 's/", "/'\",\"'/g' | \
    sed -e 's/" ,"/'\",\"'/g' | \
    sed -e 's/" , "/'\",\"'/g' | \
    sed -e 's/","/'\"---SEPERATOR---\"'/g' | \
    awk -F=':' -v RS='---SEPERATOR---' "\$1~/\"$2\"/ {print}" | \
    sed -e "s/\"$2\"://" | \
    tr -d "\n\t" | \
    sed -e 's/\\"/"/g' | \
    sed -e 's/\\\\/\\/g' | \
    sed -e 's/^[ \t]*//g' | \
    sed -e 's/^"//'  -e 's/"$//'
}

# Output JSON - not used in the script, just for reference
read -r -d '' JSON_BODY << 'EOF'
{
  "errors": {
    "additionalProp1": {},
    "additionalProp2": {},
    "additionalProp3": {}
  },
  "extras": {
    "additionalProp1": {},
    "additionalProp2": {},
    "additionalProp3": {}
  },
  "message": "string",
  "results": [
    {
      "complianceNoticeCount": 0,
      "complianceViolatedCount": 0,
      "deviceId": "string",
      "enrollmentDate": 0,
      "enrollmentType": "UNKNOWN",
      "executedPolicy": {
        "name": "string",
        "policyUuid": "string",
        "policyVersionUuid": "string",
        "state": "ACTIVE",
        "version": 0
      },
      "iosAvailableUpdates": [
        {
          "downloadPercentComplete": 0,
          "downloaded": true,
          "errorChain": [
            {
              "errorCode": 0,
              "errorDomain": "string",
              "localizedDescription": "string",
              "usEnglishDescription": "string"
            }
          ],
          "installAction": "DEFAULT",
          "isDownloaded": true,
          "lastUpdateStatusTime": 0,
          "productKey": "string",
          "productVersion": {
            "majorVersion": 0,
            "minorVersion": 0,
            "patchVersion": 0
          },
          "updateStatus": "IDLE"
        }
      ],
      "iosCurrentOSUpdate": {
        "downloadPercentComplete": 0,
        "downloaded": true,
        "errorChain": [
          {
            "errorCode": 0,
            "errorDomain": "string",
            "localizedDescription": "string",
            "usEnglishDescription": "string"
          }
        ],
        "installAction": "DEFAULT",
        "isDownloaded": true,
        "lastUpdateStatusTime": 0,
        "productKey": "string",
        "productVersion": {
          "majorVersion": 0,
          "minorVersion": 0,
          "patchVersion": 0
        },
        "updateStatus": "IDLE"
      },
      "isDep": true,
      "isSupervised": true,
      "lastConnectionDate": 0,
      "manufacturer": "string",
      "model": "string",
      "msisdn": "string",
      "name": "string",
      "openActions": 0,
      "osVersion": "string",
      "ownership": "COD",
      "platform": "UNKNOWN",
      "policy": {
        "name": "string",
        "policyUuid": "string",
        "policyVersionUuid": "string",
        "state": "ACTIVE",
        "version": 0
      },
      "ruleset": {
        "name": "string",
        "rulesetUuid": "string",
        "rulesetVersionUuid": "string",
        "version": 0
      },
      "serialNumber": "string",
      "status": "COMPLIANT",
      "supervised": true,
      "userName": "string",
      "uuid": "string",
      "wifiMac": "string"
    }
  ],
  "status": "string",
  "total": 0
}
EOF

echo "Querying devices at $SVR_URL..."
echo

# No changes should be required beyond this line...

RESPONSE=$(curl -X GET \
  ${SVR_URL}${FILTER} \
  -H "X-User-Access-Token: $ACCESS_TOKEN" \
  -H "Accept: $ACCEPT" \
  -H "Accept-Charset: $ACCEPT_CHARSET" \
  -H "Content-Type: $ACCEPT" \
  --write-out " HTTP_STATUS=%{http_code}" \
  --silent \
  )
if [[ $RESPONSE =~ HTTP_STATUS=([0-9]+) ]]; then
  HTTP_STATUS=${BASH_REMATCH[1]}
fi

if [[ $HTTP_STATUS -lt 200 || $HTTP_STATUS -gt 299 ]]; then
  echo " HTTP status: $HTTP_STATUS"
else
    echo "Done. Parsing ouput..."
    echo ${RESPONSE%HTTP_STATUS*} | jq '.results[].name'
fi
echo