2014-09-19 4 views
11

Наши клиенты хотят использовать решение MDM (управление мобильными устройствами) (MobileIron) для установки клиентских сертификатов на корпоративные устройства iOS, чтобы ограничить доступ к определенным корпоративным веб-сервисам только на корпоративных устройствах.Клиентские сертификаты iOS и управление мобильными устройствами

MobileIron устанавливает сертификат клиента в Настройки> Общие> Профили, который является по умолчанию местом для сертификатов в iOS, и Safari может отвечать этим сертификатом, когда корпоративный веб-сервис бросает вызов ему на один.

Но мне нужно то же самое, что и в пользовательском приложении. Когда наше приложение получает вызов для сертификата, я должен иметь возможность ответить сертификатом от Настройки> Общие> Профили. У меня есть примеры ответов с сертификатом, который поставляется вместе с нашим приложением, и с сертификатом, который наше приложение хранит в своей собственной цепочке ключей, но у меня нет есть пример ответа с сертификатом, установленным на устройстве, в Настройки> Общие> Профили.

Может ли кто-нибудь объяснить мне более подробно о методе протокола NSURLAuthenticationChallengeSender-performDefaultHandlingForAuthenticationChallenge:? по умолчанию обработка означает, что iOS эффективно реагирует на вызов от имени приложения? Может ли этот ответ включать сертификат клиента, хранящийся в Настройки> Общие> Профили?

Update

Если MDM может установить сертификат клиента в приложение брелка, это было бы идеально.

ответ

1

Я только что вернулся с места на клиенте, который использовал MobileIron, и хотел сделать именно это. Поддержка разработки MobileIron предоставила нам этот фрагмент кода, который импортирует сертификат, предоставляемый AppConnect Wrapper, с помощью технологии Core Config от MobileIron.

Это некрасиво, но, поскольку оно было предоставлено ими, мне не разрешалось изменять его. Это работает! Вы вставляете это в вашем AppDelegate.h:

- (NSString *)appConnectConfigChangedTo:(NSDictionary *)newConfig; 

И это в свою AppDelegate.m, сразу после aforemention знака прагма:

#pragma mark UIApplicationDelegate implementation                                 
- (NSString *)appConnectConfigChangedTo:(NSDictionary *)newConfig{ 
        //NSLog(@"New config: %@", newConfig);                                          //unsecure 
        NSLog(@"New config retrieved");                                                 //confirm we got a new config 
        NSString *certStr       = [newConfig valueForKey:@"kUserCert"];                 //Store certificate as String 
        NSString *certPassword  = [newConfig valueForKey:@"kUserCert_MI_CERT_PW"];      //Store certificate password as string 
        NSData *cert = [[NSData alloc] initWithBase64EncodedString:certStr options:0];  //only for iOS7+, decodes base64 encoded certificate 
        CFDataRef pkcs12Data = (__bridge CFDataRef)cert;                                //Extract identity & certificate objects from 
        CFStringRef password = (__bridge CFStringRef)certPassword;                      //the cert data Identity 
        SecIdentityRef myIdentity = nil;                                                //Initialize variable for identity 
        SecCertificateRef myCertificate = nil;                                          //Initialize variable for certificate 
        OSStatus status = extractIdentityAndTrust(pkcs12Data, password, &myIdentity, nil); //Use Apple-provided method for extracting Identity and Trust 
        if (status != errSecSuccess || myIdentity == nil) { NSLog(@"Failed to extract identity and trust: %ld", status);} //Likely due to corruption 
        else { SecIdentityCopyCertificate(myIdentity, &myCertificate); }                //This method is supposed to store the Certificate, but Fiori doesn't see it here 
        const void *certs[] = { myCertificate };                                        //Initialize an array for one certificate 
        CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);                    //Make the array the way Apple wants it to be 
        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent];                                       //MobileIron's method of Credential storage 
        NSMutableDictionary *secIdentityParams = [[NSMutableDictionary alloc] init];    //Initialize Dictionary to store identity 
        [secIdentityParams setObject:(__bridge id)myIdentity forKey:(__bridge id)kSecValueRef]; //Build the secIdentityParams dictionary in the way the next method expects it to be 
        OSStatus certInstallStatus = SecItemAdd((__bridge CFDictionaryRef) secIdentityParams, NULL); //Add the identity to the keychain for Fiori consumption 
        if (myIdentity) CFRelease(myIdentity);                                          //Free 
        if (certsArray) CFRelease(certsArray);                                          //Up 
        if (myCertificate) CFRelease(myCertificate);                                    //Memory 
        return nil;                                                                     //Success 
}  
// Copied from Apple document on Certificates: 
// http://developer.apple.com/library/mac/documentation/security/conceptual/CertKeyTrustProgGuide/CertKeyTrustProgGuide.pdf 
OSStatus extractIdentityAndTrust(CFDataRef inP12data, CFStringRef password, SecIdentityRef *identity, SecTrustRef *trust){ 
        OSStatus securityError = errSecSuccess; 
        const void *keys[] = { kSecImportExportPassphrase }; 
        const void *values[] = { password }; 
        CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); 
        CFArrayRef items = nil; 
        securityError = SecPKCS12Import(inP12data, options, &items); 
        if (securityError == errSecSuccess) { 
             CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0); 
             if (identity && CFDictionaryGetValueIfPresent(myIdentityAndTrust, kSecImportItemIdentity, (const void **)identity)) { 
                  CFRetain(*identity); 
              } 
             if (trust && CFDictionaryGetValueIfPresent(myIdentityAndTrust, kSecImportItemTrust, (const void **)trust)) { 
                  CFRetain(*trust); 
              } 
         }   
        if (options) {CFRelease(options);} 
        if (items) {CFRelease(items);} 
        return securityError; 
} 

После того, как вы создали приложение, обратитесь к администратору MobileIron «обернуть» приложение, чтобы он мог использовать AppConnect. Как только это будет сделано, и развернутое приложение будет развернуто для тестирования пользователей через MobileIron, настройте конфигурацию ядра, которая принимает пользовательский сертификат, специфичный для предоставленного пользователя, и подталкивает его к подготовленным устройствам под ключом Core Config «kUserCert».

+0

Очень интересно. Придется попробовать получить копию MobileIron, чтобы попробовать это. –

+0

Вам нужно интегрироваться с MobileIron SDK? – windfly2006

+0

Для этой функциональности не было традиционной библиотеки или SDK: MobileIron предоставил нам пример кода, и нам пришлось использовать их приложение Wrapper, чтобы обернуть приложение для работы AppConnect. –

1

Обновление MobileIron AppConnect 2.1 решает эту проблему, никакого специального кода не требуется. Сертификаты X.509 могут быть перенесены с помощью конфигурации AppConnect, а инфраструктура AppConnect перехватывает любой authentication challenges, когда он может ответить соответствующим сертификатом.Сертификаты могут быть созданы «на лету» при первом запуске, позже отменены, настроены для каждого пользователя или для каждого устройства, а разные URL-адреса могут использовать разные сертификаты.

Если кто-то использует фрагмент кода на этой странице, остановитесь, это не нужно. После переноса вашего немодифицированного приложения или связывания в инфраструктуре AppConnect добавьте ключ MI_AC_CLIENT_CERT_1 в конфигурацию AppConnect, указав конфигурацию регистрации сертификатов (например, SCEP, Entrust, Symantec PKI, PIV-D и т. Д.). Добавьте ключ MI_AC_CLIENT_1_RULE с URL-адресом (с дополнительным шаблоном). Нет шага 3. Теперь ваше приложение будет автоматически использовать сертификаты для аутентификации.

Подробная информация находится в . Руководство пользователя MobileConnect AppConnect и AppTunnel в разделе «Аутентификация сертификатов из приложений AppConnect для корпоративных служб».

+0

Итак, перейдя от проекта, который побудил меня задать этот вопрос, я не могу попробовать это. Похоже, что это обратилось бы к потребностям клиентов, и это упростило бы наше приложение. Тем не менее, проблема «перехват проверки подлинности» немного беспокоит меня. Означает ли это, что AppConnect становится конечной точкой HTTPS, а не приложением? Итак, AppConnect проксирует трафик? –

+0

Бретт, я не собираюсь разглашать наш «секретный соус» здесь, но ознакомьтесь с https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/AuthenticationChallenges.html и NSURLAuthenticationMethodClientCertificate. –

+0

Я возьму это как «да». –