From fcd5ac933a091d85f222d8b4524887b724df9a8b Mon Sep 17 00:00:00 2001 From: Russell Hancox Date: Mon, 3 May 2021 13:22:04 -0400 Subject: [PATCH] Sort certificates by most-recently issued (#20) This commit also adds a _very_ basic test that the filtering and sorting is working and updates the used apple_rules to the latest version, which requires bazel 4.0 --- BUILD | 8 ++- .../MOLAuthenticatingURLSession.m | 70 ++++++++++++------- Tests/MOLAuthenticatingURLSessionTest.m | 60 ++++++++++++++++ Tests/MOLDERDecoderTest.m | 9 +-- Tests/example_org_client_cert.pem | 33 +++++++++ Tests/example_org_client_cert_old.pem | 35 ++++++++++ Tests/internet_widgits_client_cert.pem | 35 ++++++++++ WORKSPACE | 2 +- 8 files changed, 216 insertions(+), 36 deletions(-) create mode 100644 Tests/MOLAuthenticatingURLSessionTest.m create mode 100644 Tests/example_org_client_cert.pem create mode 100644 Tests/example_org_client_cert_old.pem create mode 100644 Tests/internet_widgits_client_cert.pem diff --git a/BUILD b/BUILD index e2bd0c5..e2dea70 100644 --- a/BUILD +++ b/BUILD @@ -23,9 +23,15 @@ objc_library( testonly = 1, srcs = [ "Source/MOLAuthenticatingURLSession/MOLDERDecoder.h", + "Tests/MOLAuthenticatingURLSessionTest.m", "Tests/MOLDERDecoderTest.m", ], - data = ["Tests/dn.plist"], + data = [ + "Tests/dn.plist", + "Tests/example_org_client_cert.pem", + "Tests/example_org_client_cert_old.pem", + "Tests/internet_widgits_client_cert.pem", + ], deps = [":MOLAuthenticatingURLSession"], ) diff --git a/Source/MOLAuthenticatingURLSession/MOLAuthenticatingURLSession.m b/Source/MOLAuthenticatingURLSession/MOLAuthenticatingURLSession.m index d1c54ad..01d2950 100644 --- a/Source/MOLAuthenticatingURLSession/MOLAuthenticatingURLSession.m +++ b/Source/MOLAuthenticatingURLSession/MOLAuthenticatingURLSession.m @@ -336,7 +336,45 @@ - (SecIdentityRef)identityByFilteringArray:(NSArray *)array issuerCountryName:(NSString *)issuerCountryName issuerOrgName:(NSString *)issuerOrgName issuerOrgUnit:(NSString *)issuerOrgUnit { - NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:4]; + NSArray *sortedCerts = [self filterAndSortArray:array + commonName:commonName + issuerCommonName:issuerCommonName + issuerCountryName:issuerCountryName + issuerOrgName:issuerOrgName + issuerOrgUnit:issuerOrgUnit]; + for (MOLCertificate *cert in sortedCerts) { + SecIdentityRef identityRef = NULL; + OSStatus status = SecIdentityCreateWithCertificate(NULL, cert.certRef, &identityRef); + if (status == errSecSuccess) { + return identityRef; + } else { + // Avoid infinite recursion from self-signed certs + if ((!cert.commonName || [cert.commonName isEqual:cert.issuerCommonName]) && + (!cert.countryName || [cert.countryName isEqual:cert.issuerCountryName]) && + (!cert.orgName || [cert.orgName isEqual:cert.issuerOrgName]) && + (!cert.orgUnit || [cert.orgUnit isEqual:cert.issuerOrgUnit])) { + continue; + } + + // cert is an intermediate, recurse to find the leaf. + return [self identityByFilteringArray:array + commonName:nil + issuerCommonName:cert.commonName + issuerCountryName:cert.countryName + issuerOrgName:cert.orgName + issuerOrgUnit:cert.orgUnit]; + } + } + return NULL; +} + +- (NSArray *)filterAndSortArray:(NSArray *)array + commonName:(NSString *)commonName + issuerCommonName:(NSString *)issuerCommonName + issuerCountryName:(NSString *)issuerCountryName + issuerOrgName:(NSString *)issuerOrgName + issuerOrgUnit:(NSString *)issuerOrgUnit { + NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:5]; if (commonName) { [predicates addObject:[NSPredicate predicateWithFormat:@"SELF.commonName == %@", @@ -361,32 +399,12 @@ - (SecIdentityRef)identityByFilteringArray:(NSArray *)array NSCompoundPredicate *andPreds = [NSCompoundPredicate andPredicateWithSubpredicates:predicates]; - NSArray *filteredCerts = [array filteredArrayUsingPredicate:andPreds]; - if (!filteredCerts.count) return NULL; + NSArray *filteredCerts = [array filteredArrayUsingPredicate:andPreds]; + if (!filteredCerts.count) return nil; - for (MOLCertificate *cert in filteredCerts) { - SecIdentityRef identityRef = NULL; - OSStatus status = SecIdentityCreateWithCertificate(NULL, cert.certRef, &identityRef); - if (status == errSecSuccess) { - return identityRef; - } else { - // Avoid infinite recursion from self-signed certs - if ((!cert.commonName || [cert.commonName isEqual:cert.issuerCommonName]) && - (!cert.countryName || [cert.countryName isEqual:cert.issuerCountryName]) && - (!cert.orgName || [cert.orgName isEqual:cert.issuerOrgName]) && - (!cert.orgUnit || [cert.orgUnit isEqual:cert.issuerOrgUnit])) { - continue; - } - - return [self identityByFilteringArray:array - commonName:nil - issuerCommonName:cert.commonName - issuerCountryName:cert.countryName - issuerOrgName:cert.orgName - issuerOrgUnit:cert.orgUnit]; - } - } - return NULL; + return [filteredCerts sortedArrayUsingComparator:^(MOLCertificate *obj1, MOLCertificate *obj2) { + return [obj2.validFrom compare:obj1.validFrom]; + }]; } - (SecIdentityRef)identityFromFile:(NSString *)file password:(NSString *)password { diff --git a/Tests/MOLAuthenticatingURLSessionTest.m b/Tests/MOLAuthenticatingURLSessionTest.m new file mode 100644 index 0000000..86ae762 --- /dev/null +++ b/Tests/MOLAuthenticatingURLSessionTest.m @@ -0,0 +1,60 @@ +/// Copyright 2021 Google Inc. All rights reserved. +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. + +#import + +#import + +#import "Source/MOLAuthenticatingURLSession/MOLAuthenticatingURLSession.h" + +@interface MOLAuthenticatingURLSession (Testing) +- (NSArray *)filterAndSortArray:(NSArray *)array + commonName:(NSString *)commonName + issuerCommonName:(NSString *)issuerCommonName + issuerCountryName:(NSString *)issuerCountryName + issuerOrgName:(NSString *)issuerOrgName + issuerOrgUnit:(NSString *)issuerOrgUnit; +@end + +@interface MOLAuthenticatingURLSessionTest : XCTestCase +@end + +@implementation MOLAuthenticatingURLSessionTest + +- (MOLCertificate *)certFromFilename:(NSString *)filename { + NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:filename ofType:@"pem"]; + NSString *data = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; + return [[MOLCertificate alloc] initWithCertificateDataPEM:data]; +} + +- (void)testFilterAndSortArray { + MOLCertificate *c1 = [self certFromFilename:@"example_org_client_cert_old"]; + MOLCertificate *c2 = [self certFromFilename:@"internet_widgits_client_cert"]; + MOLCertificate *c3 = [self certFromFilename:@"example_org_client_cert"]; + + MOLAuthenticatingURLSession *s = [[MOLAuthenticatingURLSession alloc] init]; + + NSArray *got = [s filterAndSortArray:@[ c1, c2, c3 ] + commonName:@"Example Organization Client Certificate" + issuerCommonName:nil + issuerCountryName:nil + issuerOrgName:nil + issuerOrgUnit:nil]; + + + NSArray *want = @[ c3, c1 ]; + XCTAssertEqualObjects(got, want, @""); +} + +@end diff --git a/Tests/MOLDERDecoderTest.m b/Tests/MOLDERDecoderTest.m index c5ac9c4..5bf3615 100644 --- a/Tests/MOLDERDecoderTest.m +++ b/Tests/MOLDERDecoderTest.m @@ -15,6 +15,7 @@ #import #import +#import @interface MOLDERDecoder (Testing) + (NSString *)decodeOIDWithBytes:(unsigned char *)bytes length:(NSUInteger)length; @@ -25,14 +26,6 @@ @interface MOLDERDecoderTest : XCTestCase @implementation MOLDERDecoderTest -- (void)setUp { - [super setUp]; -} - -- (void)tearDown { - [super tearDown]; -} - - (void)testAllFields { NSString *file = [[NSBundle bundleForClass:[self class]] pathForResource:@"dn" ofType:@"plist"]; NSArray *distinguishedNames = [NSArray arrayWithContentsOfFile:file]; diff --git a/Tests/example_org_client_cert.pem b/Tests/example_org_client_cert.pem new file mode 100644 index 0000000..4a289c8 --- /dev/null +++ b/Tests/example_org_client_cert.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFwDCCA6gCCQD0lJTYOlYnGDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcx +HTAbBgNVBAoMFEV4YW1wbGUgT3JnYW5pemF0aW9uMRQwEgYDVQQLDAtFbmdpbmVl +cmluZzEwMC4GA1UEAwwnRXhhbXBsZSBPcmdhbml6YXRpb24gQ2xpZW50IENlcnRp +ZmljYXRlMB4XDTIxMDUwMzE2MDgxM1oXDTMyMDcyMDE2MDgxM1owgaExCzAJBgNV +BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW +aWV3MR0wGwYDVQQKDBRFeGFtcGxlIE9yZ2FuaXphdGlvbjEUMBIGA1UECwwLRW5n +aW5lZXJpbmcxMDAuBgNVBAMMJ0V4YW1wbGUgT3JnYW5pemF0aW9uIENsaWVudCBD +ZXJ0aWZpY2F0ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO7maT3z +hupTcFlm3sCJmPNCgn0LZqi0AWkht7ygYzxbWH1GI1A3chPTjM0gUNz0Q9RMdST8 +aQ8CvpfLXuO+vWtny1s2MPtcnz7kfbB64ez03J1RLVVc8bIbwt5mfucU+fzF+Qvj +9Jkhvngz2GiLbkt8K9XJKeWOmLqBqTLuJhPrWXEU55tMTRwFeW48fJ5Av/Ls5FU1 +lG5/gGc/ZfY9EZi4daTT/ePkwJa4OgM/ceY/E+MR+bqvYX91NQoAtjxdKRZ/c+JZ +JyHSpj36FjyPaQ5sEFZMdV2Guji162E4Nu3xXRoR4EpAe7BSBBZJMgUgzkmJgYOa +jqK3O9sw26Mcydk8o1yHKjRiM99QVWmM6LDvQLs4q0Oh80xkyezsnSwh8gMFTw0N +48DnvyxAuk1rYcIM7ytXZrmFZFqrXEaoiPJuvjFEyFsaXdY25PMIdvKP83dx/SDb +wpMlaEdg2yec9asqKwpBiFR9Pd0geFXvdXBhs0QyyTlyjz7xYbsJsl1JbK73zd8B +kH9A48pYHzYaR2xiCk/WRoMgtKif3DNZvmVHW3ux8QMTRQdPaIsUB21SNSd+7IBX +B25+w12guX0ozQ5/atPUkwNInC3QuLZH9+VFhJFDjhkcPhMAhRGEL0XMV2bWJBqg +cfF3i6aXUKMFVHGjnclYG75lHh6pdb28xqzhAgMBAAEwDQYJKoZIhvcNAQELBQAD +ggIBAKv27/iGhHwDS34Jq9qjBb4a63ZDYAwVNgepymqjGsYuL3sYyVMUTHdfboPw +a51Jabh+lG7YBJt6+PZzP8tcpjL0II4ysR7LWGnHii6Un6M0Ds1BtnDjiE0J6TwP +XJtsROPys6/aBEnUIiSPtF/TNHiDDcNgvZD9wi/3pv3zIRhoS/slOCf+AQhw5ccj +o2Sf113zuGtvvYvQVp1m1eo9+/P9r7CHdhFMJ1oVayzbIabQe8v0OnUTT0TyUbBR +9OrtuOx3fE02i2JfOVVEbtnIbQI3QK19joVqajjvIkvbiq4PNbfFkw7e4FO4XKmv +1P0wnwRMtHNWCkXLZefbv+PYQBnDcEzUj6tIlJCreuX0TTUlhV2LcH6XzY1Dw98t +wiB9clvzv3yjpIsZy6wY1/1iZ39AVSsKfE4nDA7ja2tqMXl8HI5kMpMOqaZi0AWw +LBheth0x1DC5nATp5HUh34ul2jZ4oAguzCGq8CxLXf8x5v00633ur7IpmDpe3bQx +oo8wia6rXjq4XAsCvtT36hEoxdL1GV3Q4Sp4z6DYqL7rc7lVecn5q//dyjBDGrSA +S6SZ8w850L87vp03QrXzxIbpQL++kIl45jalW+KU37/JvEm/fZ0GT3sqk4nKSexs +Ns3XBynypa52RZcmuFQkjdiUkkjWPZmkoVCv8satfdWimBsK +-----END CERTIFICATE----- diff --git a/Tests/example_org_client_cert_old.pem b/Tests/example_org_client_cert_old.pem new file mode 100644 index 0000000..3f08c80 --- /dev/null +++ b/Tests/example_org_client_cert_old.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGJTCCBA2gAwIBAgIUIEt2zigMYKVdwxwE4W5zDtB43k0wDQYJKoZIhvcNAQEL +BQAwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH +DA1Nb3VudGFpbiBWaWV3MR0wGwYDVQQKDBRFeGFtcGxlIE9yZ2FuaXphdGlvbjEU +MBIGA1UECwwLRW5naW5lZXJpbmcxMDAuBgNVBAMMJ0V4YW1wbGUgT3JnYW5pemF0 +aW9uIENsaWVudCBDZXJ0aWZpY2F0ZTAeFw0yMTA0MTkxNjM0MTBaFw0zMjA3MDYx +NjM0MTBaMIGhMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG +A1UEBwwNTW91bnRhaW4gVmlldzEdMBsGA1UECgwURXhhbXBsZSBPcmdhbml6YXRp +b24xFDASBgNVBAsMC0VuZ2luZWVyaW5nMTAwLgYDVQQDDCdFeGFtcGxlIE9yZ2Fu +aXphdGlvbiBDbGllbnQgQ2VydGlmaWNhdGUwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQC72no9kT68zvguv3xv/BcFgHodpWlEueSSoSdPHVIvWR9QSO2J +FsUalWsfCa1rzCkl455PgOOmEs3zPIx9u8k2D1HVh7MvsP/QXDkSFrO+xtySXMSZ +/7FtHW5TOzDgHAj6AOycNUjTiLbjkOTjqay42gFZpynEnMlCXBeqljCn/ZserFYB +4Fh29oFuVTiRz/VnqKIku4QKI9SYN4trahX2D94jNXu/OoZWV4PODKLzU3yL8giv +GkjdLSHjIjXTpX37FIUvMfQ6/ra/Jg4QZ3GKBW+V8a/Y2isvyigNcOLJjAjSnmgz +34786YYdyY0tH6MmFaMFWrAerv+4NPNC2SCRy5t/gAPT6djZmyOrcvoUkotVyODL +WRXOQkzIWbAaAp0WoBqRVLr+2SImKLp92UHPLRSe8Y6uwK2/zM85RocjjNu0N7zC +paOdqBH6cZWEa5kU55S9G8Bm12c+HvPK8KOnLlT8mC0ixYNMb8+5/f9MQCEWUa4C +FWRxzk7/IKu0zAOcdyKoDkiDPVQ7YXrBVBZzeobW/cOYwsx3+RlFahMLnEFsw1Lo +WUCrNTi8wa77LeVFoiz2h/yNzpxhiK9wjkO2I/yxZFwYrFIS22lqmrXxVg9sPeqL +5koS9YUawF6HKHtQFcLl44OZv4wr8Y03Mj8STrujSFt2Cp4c3YYLackEywIDAQAB +o1MwUTAdBgNVHQ4EFgQUrpVGjLUBdpjszUQZsdpRkCNcZIIwHwYDVR0jBBgwFoAU +rpVGjLUBdpjszUQZsdpRkCNcZIIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQsFAAOCAgEAUDkCqO2MInuUjk0LvhtK+yvBU5m4LGm/nqYY6jGzA7QLC1cxREPw +tEG1LVQ0fghPx1xzZKCCfAxObaNeVIgDkaekhLyvGwM1UBwpBJzGqiIOSv8MMD2L +9jMxawUdhLdH7EWZ1Oz+uR75pdAiBjCk8p0rcxSrlbH4/wpry+EdfQrKQlgCogi5 +EA8Z2sznHi0vQh7awj7zq0/Tr6KOC/oW5hI8LE1IYenQf427oHqtDo1WRLTdHtgi +PJQswa8tYREmgvtMDAJZ4UV3wwcbrtSWiNJdmDwLfs4uoiEMzF+nlVA9p9pVYSBl +FmohyT61oNLq5kPZ6M0sjp32+HVnbjFUNqMEJneep350Y9j+HvH0La/Jj84pIWvD +/IrEXO/UqMBhUT6wBNLWcOFaSkjBLA0aQgdmZ+Dfd6iA+Sk8jLfnEew/5dDku6IY +s8Htwuu/zJKedsIK/ikG1BynFJwM26hwqza2OeEp8dZWUeq6LUKprFMgDrz1lqJH +YyrsWViZS3Lj0IkS1bvb9Un5Hq6ACFYpGtapHL9RMPUj3fZ2aaWnziO4jEGVf9AC +qePhthh2+O5sdP+8Y/EjYgNXfPI68AF8A42ZKx0JhfusbweH6sccrMm26Ng15+va +5Oy2LOm3iA71Taa6g1SRDy933sa8tsERqjNjUkm9s+8NNH7raKmhEpk= +-----END CERTIFICATE----- diff --git a/Tests/internet_widgits_client_cert.pem b/Tests/internet_widgits_client_cert.pem new file mode 100644 index 0000000..0d6e4d5 --- /dev/null +++ b/Tests/internet_widgits_client_cert.pem @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGBzCCA++gAwIBAgIUUeR6m7gHvzGcU7UUoVnFMohnURYwDQYJKoZIhvcNAQEL +BQAwgZIxCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQH +DAVQYXJpczEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRQwEgYD +VQQLDAtFbmdpbmVlcmluZzElMCMGA1UEAwwcSW50ZXJuZXQgV2lkZ2l0cyBDbGll +bnQgQ2VydDAeFw0yMTA0MTkxNjEzMjJaFw0zMjA3MDYxNjEzMjJaMIGSMQswCQYD +VQQGEwJGUjETMBEGA1UECAwKU29tZS1TdGF0ZTEOMAwGA1UEBwwFUGFyaXMxITAf +BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UECwwLRW5naW5l +ZXJpbmcxJTAjBgNVBAMMHEludGVybmV0IFdpZGdpdHMgQ2xpZW50IENlcnQwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnjIiDnzosJi/70gUsW5UNlx+0 +x5o1F69M68BjD6JPfjv2mMHbK1a5CkagwrCsjwFe1nBma+vvbhV51PxV/snteo/7 +surEd+oJ1jbAGe2E1qURkEeM3Z915zg+CmDlWJsiIvfsYmKAwjfb0KCebioBUM9p +GR+sAKZiQq8w4dZahf7bsLevDettN426LmKnaAj+LCzOZb3ih00ecWN9/SQVh/S1 +q2fDDIxkr5d7orjVdBr8ecoiYkXzGKVccOKwHtnL94tvp3vRSMdhNSuiabae9N+i +XVc4mnILRrvGE8hrEy9et4EJHbRKNvypz+yD1ktoLNYN5fVilB4Nxxe9Rdo3MfNx +SiA4r7HwYWUAxHlxX0U9TYiLHMk/4WSdCThLVXrxQHtfZ+se2ZDdmQhNn3Vf6L/C +Srj0eZjeCRGflwEyJnqVziJOVbcnKqX+hfYfsPdFdJrcVEcKRYK7Xog74inePPUl +WxrbIa19ZLS/wgXIEsVtSdoYTCwLLZtfJ02RtSojVr3FxS8/e0tOkCCRK00o54b9 +d9qxvjSJI/0O+OcuVAwTFJl9jN0s0zmRjN6rFlxmjjYoF6nyBMvPhRsYcAq0Uk4u +Qi/3zPZvMwkqRneNYv9zsn1tcd4udcSp9gkmy+6oeGK6+LL/OMMGn9ZXVCd43gJy +UBEfJoN+ufCnnFdm2QIDAQABo1MwUTAdBgNVHQ4EFgQUNVH/caHIQb05OJKjWOn5 +makZ4WYwHwYDVR0jBBgwFoAUNVH/caHIQb05OJKjWOn5makZ4WYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEANAYHuXn8PGjY/0lj5tQltSpAiF1z +T/vurp/kVUt5HSCm3A/2OyxP4eFzAAlyfLvxTSx7nacqxHpZC0f+wCUpBU03zzmQ +UmMYVfu9wD6Kf9y6RBVcOc7mafHSTHhPu00vdbeZAtkB5qiZpZqmhNzZqQH3bBK5 +g3K7akDk4cENwcoTIctSSHeuZzvqLWK3KfNHNmAvCfWZDb2WJKNP3Xt7imCoYtLF +0f89XmV3ygS7Sc/1B3Ji2uBT9Lxxb4vziOXMlB9KPrFu0K7IhGO8gVeMmi+OWAC4 +aaiixFUVm6jhH/nn/IOnkjwKuNCaHZuCf9Lvn9aFEKfTLhgMBpQhBP8cpx/6/RIp +rzBRC1QU+K8LoKpue/5+U7soHIyLNPDYxWHyjxghHE/8bI9nnGf/wC6MnOhiRtFq +/HRK/EfyPkjOphQ+rv/O325b1E2A0HOf3NC3Ktgel729aKyzY5GCg2k/42dn9mkj +jivEMjcs4vl/wh6TIaTNDvvTqUhdIsjVP3ZtdFLNmVwble6LMKezMEzEp7GmiPcZ +kSIskyYjfoMpdbZGSinQ0Z2aaKvfM6HD7+7NN0vSu+L0KY7Kc/Cc3Xj61CSYgV1G +FJpNa5chaDM6+4XcWZuXo+jRghVi04dxd2r2l8GCESe/3B2OspcqSLHyVnH9IL+Y ++zF36y3iF/eBeAI= +-----END CERTIFICATE----- diff --git a/WORKSPACE b/WORKSPACE index 5030e95..1d6584b 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -3,7 +3,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") git_repository( name = "build_bazel_rules_apple", remote = "https://github.com/bazelbuild/rules_apple.git", - tag = "0.17.2", + tag = "0.31.1", ) load(