רשתות וטלפוניה

התכונות במדריך הזה מתארות רישות וניהול טלפוניה יכולות שניתן להטמיע במדיניות המכשיר בקר משחקים (DPC). המסמך הזה מכיל קוד לדוגמה ואפשר גם להשתמש בחלונית בדיקה אפליקציית DPC בתור מקור של קוד לדוגמה לתכונות הארגוניות של Android.

אפליקציית DPC יכולה לפעול במצב 'בעלי הפרופיל' במכשירים אישיים או אצל בעלי המכשיר במכשירים מנוהלים. בטבלה הזו מצוין אילו תכונות זמין כשה-DPC פועל במצב בעלי הפרופיל או בעלי המכשיר mode:

תכונה הבעלים של הפרופיל בעלי המכשיר
גישה לאנשי קשר בעבודה בכל הפרופילים
חשוב לוודא חיבור רשת מאובטח לתעבורת נתונים בעבודה
להגדיר מזהה של רשת אלחוטית אחת בכמה אזורים
ציון חייגן נפרד לפרופיל העבודה

גישה לאנשי קשר של עבודה בפרופילים שונים

EMM יכול לאפשר לפרופיל אישי של משתמש לגשת לאנשי הקשר שלו בעבודה כדי ניתן לגשת אל אנשי הקשר לשימוש אישי ולעבודה של משתמש באמצעות חיפוש מקומי חיפוש ספרייה מרוחקת. במכשירים אישיים, יש חייגן אחד פרופיל יכול לבצע ולקבל שיחות אישיות וגם שיחות עבודה. In addition, אנשי קשר בעבודה משתלבים היטב בממשק המשתמש של המערכת. אם פרופיל העבודה מוצפן, הנתונים שלו לא זמינים לפרופיל האישי.

משולב עם ממשק המשתמש של המערכת

ממשק המשתמש של המערכת מציין שיחות עבודה נכנסות באמצעות סמל של תיק מסמכים. callLog מציג גם את כדי לציין שיחות עבודה נכנסות ויוצאות. החייגן האישי, אפליקציות אנשי קשר יכולות להציג את פרטי השיחה המזוהה של איש קשר בעבודה באמצעות שלט רחוק חיפוש הספרייה, לכן לא נדרש שאיש הקשר כבר מסונכרן במכשיר המקומי. אפליקציית ההודעות יכולה לבצע שיחה מזוהה וחיפוש מקומי.

הגדרת התאימות ל-Android המסמך (CDD) כולל דרישות שאנשי קשר מהעבודה יוצגו בחייגן ברירת המחדל, ודרישות אנשי קשר ואפליקציות של הודעות מתויגים כדי לציין שהם הגיעו מהעבודה פרופיל.

אנשי הקשר בעבודה נגישים וניתן לחפש אותם

המשתמש יכול לגשת לאנשי קשר בעבודה ולהתקשר אליהם מהפרופיל האישי שלו. תוצג במסך החיפוש של אפליקציית החייגן. המשתמש יכול לחפש את העבודה אנשי קשר – באמצעות השלמה אוטומטית – שמסונכרנים באופן מקומי עם המכשיר ומופיעים באמצעות חיפוש בספרייה מרוחקת.

לנהל את אנשי הקשר מהעבודה בפרופיל הראשי

ה-DPC שולט בהרשאה לחפש אנשי קשר של עבודה. פועל אצל הבעלים של הפרופיל במצב, ה-DPC מנהל את החשיפה של אנשי הקשר מהעבודה בפרופיל האישי. מידע נוסף זמין במאמר פיתוח מדיניות מכשירים בקר משחקים.

כברירת מחדל, החיפוש של אנשי קשר מהעבודה לפי הפרופיל האישי מופעל.

ודאו שיש חיבור מאובטח לרשת בשביל תעבורת נתונים בעבודה

פועלות במצב 'בעלי המכשיר' או במצב 'בעלי הפרופיל', מדיניות מכשיר הבקר יכול להשתמש בחיבור רשת וירטואלית פרטית (VPN) שפועל כל הזמן כדי לאלץ אפליקציות להעביר תעבורת נתונים דרך אפליקציית VPN ספציפית שלא יכולה בוצעה עקיפה. באמצעות חיבור VPN שפועל כל הזמן, ה-DPC יכול להבטיח שהרשת תנועה מפרופיל עבודה או ממכשיר מנוהל עוברת דרך שירות VPN, ללא התערבות המשתמש. תהליך זה יוצר חיבור רשת מאובטח עבור תנועה רציפה בתוך פרופיל עבודה.

מידע על חיבורי VPN שפועלים כל הזמן

כחלק ממסגרת המערכת, ניתוב ה-VPN מנוהל באופן אוטומטי, כך המשתמש לא יכול לעקוף את שירות ה-VPN. אם שירות ה-VPN מנותק בזמן החיבור במצב 'ללא 'ביטול נעילה עם טביעת אצבע'', התנועה לא תוכל להדליף לאינטרנט הפתוח. לאפליקציות בתהליך הטמעה VpnService, רשת VPN שפועלת כל הזמן מספקת מסגרת לניהול חיבור VPN מאובטח באמצעות שרת מהימן ולהמשיך לשמור עליו. שירות ה-VPN מפעיל מחדש באופן אוטומטי את חיבור בין עדכוני אפליקציות, בין אם החיבור הוא באמצעות Wi-Fi או סלולרי. אם המכשיר יופעל מחדש, ה-framework יפעיל מחדש את החיבור ל-VPN.

החיבור לשירות ה-VPN גלוי למשתמש. עבור במכשיר בבעלות החברה, המשתמש לא נדרש לאשר תיבת דו-שיח להבעת הסכמה VPN במצב פועל כל הזמן. הגדרות רשת ה-VPN של המשתמש מאפשרות להפעיל חיבור תמידי באופן ידני.

אם DISALLOW_CONFIG_VPN true, המשתמש לא יכול להגדיר את ה-VPN. אפשר DISALLOW_DEBUGGING_FEATURES כדי למנוע ממשתמשים לעקוף את רשת ה-VPN שפועלת כל הזמן באמצעות הפקודה adb לניפוי באגים. כדי למנוע ממשתמש להסיר את ה-VPN, צריך להתקשר DevicePolicyManager.setUninstallBlocked

הגדרת שירות ה-VPN

בארגון שמשתמש בפתרון הארגוני שלכם ל-Android מוגדר VPN.

  1. התקנה של אפליקציית VPN שמטמיעה VpnService אפשר למצוא שירותי VPN פעילים באמצעות מסנן Intent שתואם פעולה VpnService.SERVICE_INTERFACE
  2. להצהיר על VpnService במניפסט של האפליקציה שמוגן על ידי ההרשאה BIND_VPN_SERVICE.
  3. מגדירים את VpnService אז זה מתחיל על ידי המערכת. מומלץ לא להגדיר שאפליקציית ה-VPN תפעל באופן אוטומטי להאזין לאתחול של מערכת ולשלוט במחזור החיים שלה.
  4. מגדירים את הערכים מנוהלים הגדרות אישיות של אפליקציית ה-VPN (דוגמה בהמשך).

הפעלת חיבור VPN שפועל כל הזמן

בקר ה-DPC יכול להגדיר חיבור VPN שפועל כל הזמן דרך אפליקציה ספציפית על ידי שיחות DevicePolicyManager.setAlwaysOnVpnPackage()

החיבור הזה יאושר באופן אוטומטי ויישמר אחרי הפעלה מחדש. אם המיקום lockdownEnabled מוגדר כ-False, תנועה ברשת עשויה להיות לא מאובטחת מרגע הטלפון יופעל מחדש וה-VPN יתחבר אליו. האפשרות הזו שימושית אם לא רוצים להפסיק קישוריות לרשת בכל פעם שה-VPN נכשל, או אם ה-VPN לא חיוני.

אימות של חיבור VPN שפועל כל הזמן

ה-DPC יכול לקרוא את שם החבילה שמנהלת VPN שפועל כל הזמן חיבור עבור המשתמש הנוכחי עם DevicePolicyManager.getAlwaysOnVpnPackage().

אם אין חבילה כזו, או שה-VPN נוצר בהגדרות המערכת. האפליקציה, מוחזר null.

דוגמה

באפליקציה TestDPC, AlwaysOnVpnFragment.java משתמש בממשקי ה-API האלה כדי להפעיל את ההגדרה לחיבור VPN שפועל כל הזמן.

בדוגמה הבאה:

  • הכרטיסייה המנוהלת של ההגדרות האישיות שירות ה-VPN מוגדר על ידי DevicePolicyManager באמצעות setApplicationRestrictions() .
  • בהגדרות מנוהלות נעשה שימוש בצמדי מפתח-ערך שרירותיים ובאפליקציה לדוגמה הזו משתמשת בהן במקום אחר כדי לקבוע את הגדרות הרשת של ה-VPN (ראו בדיקת ההגדרות המנוהלות).
  • בדוגמה הזו, מנהל ההתקנה של חבילת Android מתווסף לרשימת הישויות שנחסמו, כך שלא לעדכן חבילות מערכת דרך ה-VPN. כל התנועה של המשתמש ברשת בתוך פרופיל העבודה או המכשיר עוברים דרך אפליקציית ה-VPN הזו, מלבד החבילה מנהל התקנה; העדכונים שלו משתמשים באינטרנט הפתוח.
  • לאחר מכן, DevicePolicyManager מפעיל חיבור VPN שפועל כל הזמן עבור חבילת VPN באמצעות setAlwaysOnVpnPackage(), ולהפעיל את מצב 'ללא 'ביטול נעילה עם טביעת אצבע''.

Kotlin

// Set VPN's managed configurations
val config = Bundle().apply {
  putString(Extras.VpnApp.ADDRESS, "192.0.2.0")
  putString(Extras.VpnApp.IDENTITY, "vpn.account1")
  putString(Extras.VpnApp.CERTIFICATE, "keystore://auth_certificate")
  putStringArray(Extras.VpnApp.DENYLIST,
        arrayOf("com.android.packageinstaller"))
}

val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

val admin = myDeviceAdminReceiver.getComponentName(this)

// Name of package to update managed configurations
val vpnPackageName = "com.example.vpnservice"

// Associate managed configurations with DeviceAdminReceiver
dpm.setApplicationRestrictions(admin, vpnPackageName, config)

// Enable always-on VPN connection through VPN package
try {
  val lockdownEnabled = true
  dpm.setAlwaysOnVpnPackage(admin, vpnPackageName, lockdownEnabled)
} catch (ex: Exception) {
  throw PolicyException()
}

Java

// Set VPN's managed configurations
final Bundle config = new Bundle();
config.putString(Extras.VpnApp.ADDRESS, "192.0.2.0");
config.putString(Extras.VpnApp.IDENTITY, "vpn.account1");
config.putString(Extras.VpnApp.CERTIFICATE, "keystore://auth_certificate");
config.putStringArray(Extras.VpnApp.DENYLIST,
                      new String[]{"com.android.packageinstaller"});

DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);

ComponentName admin = myDeviceAdminReceiver.getComponentName(this);

// Name of package to update managed configurations
final String vpnPackageName = "com.example.vpnservice";

// Associate managed configurations with DeviceAdminReceiver
dpm.setApplicationRestrictions(admin, vpnPackageName, config);

// Enable always-on VPN connection through VPN package
try {
  boolean lockdownEnabled = true;
  dpm.setAlwaysOnVpnPackage(admin, vpnPackageName, lockdownEnabled));
} catch (Exception ex) {
  throw new PolicyException(...);
}

הגדרת מזהה אחד של רשת אלחוטית בכמה אזורים

פועלות במצב 'בעלי המכשיר' או במצב 'בעלי הפרופיל', מדיניות מכשיר בקר (DPC) יכול לשייך אישורים מרובים של רשות אישורים (CA) באמצעות תצורת רשת אלחוטית אחת. בתצורה הזו, יכול להתחבר לנקודות גישה אלחוטיות שיש להן אותו שם רשת, או מזהה קבוצת שירות (SSID), אבל הם מוגדרים עם CA שונה אישורים. האפשרות הזו שימושית אם הרשתות האלחוטיות של הארגון נמצאים בכמה אזורים גיאוגרפיים, וכל אזור דורש רשות האישורים. לדוגמה, כדי לחתום על חתימות משפטיות, נדרש לרשות שזקוקה ל-CA אזורי.

הערה: מערכת Android תומכת setCaCertificate החל מ-API 18 (Jelly Bean), אבל מנהלי IT חייבים להקצות את הרשתות שלהם בנפרד עם כל רשות אישורים, כדי להבטיח שלמכשירים יהיה אימות חלק בכל נקודת גישה, ללא קשר לאזור שלהם.

ציון אישורי ה-CA לזיהוי השרת

כדי לציין רשימה של אישורי X.509 שמזהים את השרת באמצעות אותם SSID, צריך לכלול את כל אישורי ה-CA הרלוונטיים בתצורת הרשת האלחוטית באמצעות WifiEnterpriseConfig.setCaCertificates().

האישור של השרת תקף אם ה-CA שלו תואם לאחד מהאישורים הנתונים. שמות ברירת המחדל מוקצים באופן אוטומטי לאישורים ומשתמשים בהם הגדרה אישית. WifiManager יתקין את האישור וישמור את התצורה באופן אוטומטי רשת מופעלת, ומסיר את האישור כשהתצורה נמחק.

כדי לקבל את כל אישורי ה-CA שמשויכים לתצורת הרשת האלחוטית, צריך להשתמש WifiEnterpriseConfig.getCaCertificates() כדי להחזיר רשימה של X509Certificate אובייקטים.

הוספת תצורה אלחוטית באמצעות מספר אישורי CA

  1. מאמתים את זהות השרת:
    1. טוענים את אישורי ה-CA מסוג X.509.
    2. טוענים את המפתח הפרטי והאישור של הלקוח. במאמר אבטחה עם HTTPS ו-SSL תוכלו לראות דוגמה לקריאת קובץ אישור.
  2. חדש WifiConfiguration ולהגדיר את ה-SSID ואת ניהול המפתחות שלו.
  3. הגדרת WifiEnterpriseConfig ב-WifiConfiguration הזה.
    1. מזהים את השרת בעזרת רשימה של X509Certificate אובייקטים שמשתמשים בהם setCaCertificates().
    2. מגדירים את פרטי הכניסה, הזהות והסיסמה של הלקוח.
    3. הגדרת פרוטוקול אימות שניתן להרחבה (EAP) ושיטת שלב 2 בתור ביצירת החיבור.
  4. מוסיפים את הרשת עם WifiManager
  5. הפעלת הרשת. WifiManager שומר את התצורה באופן אוטומטי במהלך הגדרה אישית.

בדוגמה הזו אנחנו מקשרים בין השלבים:

Kotlin

// Verify the server's identity
val caCert0 = getCaCert("cert0.crt")
val caCert1 = getCaCert("cert1.crt")
val clientKey = getClientKey()
val clientCert = getClientCert()

// Create Wi-Fi configuration
val wifiConfig = WifiConfiguration().apply {
  SSID = "mynetwork"
  allowedKeyManagement.set(KeyMgmt.WPA_EAP)
  allowedKeyManagement.set(KeyMgmt.IEEE8021X)

  // Set up Wi-Fi enterprise configuration
  enterpriseConfig.setCaCertificates(arrayOf<X509Certificate>(caCert0, caCert1))
  enterpriseConfig.setClientKeyEntry(clientKey, clientCert)
  enterpriseConfig.setIdentity("myusername")
  enterpriseConfig.setEapMethod(Eap.TLS)
  enterpriseConfig.setPhase2Method(Phase2.NONE)
}


// Add network
val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
val netId = wifiManager.addNetwork(wifiConfig)

// Enable network
if (netId < 0) {
  // Error creating new network
} else {
  wifiManager.enableNetwork(netId, true)
}

Java

// Verify the server's identity
X509Certificate caCert0 = getCaCert("cert0.crt");
X509Certificate caCert1 = getCaCert("cert1.crt");
PrivateKey clientKey = getClientKey();
X509Certificate clientCert = getClientCert();

// Create Wi-Fi configuration
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = "mynetwork";
wifiConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
wifiConfig.allowedKeyManagement.set(KeyMgmt.IEEE8021X);

// Set up Wi-Fi enterprise configuration
wifiConfig.enterpriseConfig.setCaCertificates(new X509Certificate[] {caCert0, caCert1});
wifiConfig.enterpriseConfig.setClientKeyEntry(clientKey, clientCert);
wifiConfig.enterpriseConfig.setIdentity("myusername");
wifiConfig.enterpriseConfig.setEapMethod(Eap.TLS);
wifiConfig.enterpriseConfig.setPhase2Method(Phase2.NONE);

// Add network
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
int netId = wifiManager.addNetwork(wifiConfig);

// Enable network
if (netId < 0) {
  // Error creating new network
} else {
  wifiManager.enableNetwork(netId, true);
}

ציון חייגן נפרד לפרופיל העבודה

ניתן להוסיף לרשימת ההיתרים אפליקציית חייגן נפרדת לשימוש בפרופיל העבודה. זה יכול להיות החייגן עצמו או אפליקציה של Voiceover IP (VoIP) שמטמיעה את ConnectionService API לקצה העורפי של הקריאה. כך מקבלים את אותה חיוג בממשק המשתמש של המערכת המשולבת ניסיון באפליקציות VoIP בפרופיל העבודה, וכך עובדים ביעילות חייגן: תכונת ליבה. השיחות הנכנסות לחשבונות לשיחות לצורכי עבודה להבדיל משיחות נכנסות לחשבונות אישיים לשיחות.

המשתמש יכול לבחור להתקשר ולקבל שיחות מחייגן העבודה שמופיע ברשימת ההיתרים בחשבון טלפון. כל השיחות שמתקבלות מהחייגן הזה או נכנסות לעבודה בחשבון הטלפון שלהם, רשומים בחשבון של פרופיל העבודה CallLog ספק. החייגן בעבודה שומר יומן שיחות של עבודה בלבד, עם גישה רק אל אנשי קשר בעבודה. שיחות נכנסות למתג מעגל מטופלות על ידי החייגן הראשי והם מאוחסנים ביומן שיחות אישי. אם פרופיל עבודה נמחק, יומן השיחות שמשויכים לפרופיל העבודה הזה, יימחקו גם כל פרופילי העבודה .

אפליקציות צד שלישי חייבות להטמיע ConnectionService

אפליקציות VoIP של צד שלישי שצריכים לבצע שיחות טלפון ולקבל את השיחות האלה שמשולבים באפליקציית הטלפון המובנית יכולים להטמיע ConnectionService API. חובה לעשות את זה בכל שירות VoIP שמשמש לשיחות עבודה. האפליקציות האלה כך שהשיחות שלהם יטופלו כמו שיחות רגילות סלולריים, הן מופיעות בחייגן המערכת המובנה וביומן השיחות. אם הטמעה של אפליקציה ConnectionService מותקנת בפרופיל העבודה, ניתן לגשת אליה רק באמצעות חייגן שמותקן בפרופיל העבודה הזה.

לאחר שהמפתח מטמיע ConnectionService, עליהם להוסיף אותו לקובץ המניפסט של האפליקציה ולרשום PhoneAccount עם TelecomManager. חשבון טלפון מייצג שיטה ייחודית לביצוע או לקבלת שיחות טלפון, ויכול להיות מספר PhoneAccounts בכל פעם ConnectionService. אחרי רישום חשבון הטלפון, המשתמש יכולים להפעיל אותה דרך הגדרות החייגן.

שילוב עם ממשק המשתמש של המערכת והתראות

ממשק המשתמש של המערכת מספק למשתמשים חוויית חיוג עקבית ומשולבת לאפליקציות צד שלישי שמשתמשות ConnectionService API כקצה עורפי לביצוע קריאות. אם משתמשים באפליקציה בפרופיל עבודה, תיק מסמכים מוצג סמל בשיחות נכנסות ובשורת הסטטוס. אפליקציה שבה מטמיעים האפליקציה ConnectionService שמותקנת בפרופיל העבודה יכולה להשתמש ב חייגן מערכת או לבנות חייגן עבודה נפרד. האפליקציות האלה יכולות להיות אפליקציה אחת או לאפליקציות נפרדות.

אפליקציית החייגן קובעת אם היא מבצעת או מקבלת שיחת עבודה עד בדיקת הדגל android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL אם השיחה היא שיחת עבודה, החייגן מציין זאת למשתמש על ידי הוספת תג עבודה (סמל המזוודה):

Kotlin

// Call placed through a work phone account. getCurrentCall() is defined by the
// dialer.
val call = getCurrentCall()
if (call.hasProperty(android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL)) {
  // Set briefcase icon
}

Java

// Call placed through a work phone account. getCurrentCall() is defined by the
// dialer.
Call call = getCurrentCall();
if (call.hasProperty(android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL)) {
  // Set briefcase icon
}