From 60b967ee3a9689518d181bc28d7feabd09731e96 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Fri, 24 May 2019 19:02:58 +0200 Subject: [PATCH] Make provisioning ids dynamic via .xcconfig --- Passepartout-iOS-Tunnel/Tunnel.entitlements | 2 +- Passepartout-iOS/Config.xcconfig | 32 +++++++++++++++++++ Passepartout-iOS/Info.plist | 7 ++++ Passepartout-iOS/Passepartout.entitlements | 2 +- .../Organizer/OrganizerViewController.swift | 2 +- Passepartout.xcodeproj/project.pbxproj | 12 ++++--- Passepartout/Sources/AppConstants.swift | 16 ++++++++++ Passepartout/Sources/GroupConstants.swift | 26 +++++++-------- .../Sources/Model/ConnectionService.swift | 2 +- .../Sources/Model/TransientStore.swift | 2 +- Passepartout/Sources/VPN/VPN.swift | 2 +- README.md | 10 +++--- 12 files changed, 87 insertions(+), 28 deletions(-) create mode 100644 Passepartout-iOS/Config.xcconfig diff --git a/Passepartout-iOS-Tunnel/Tunnel.entitlements b/Passepartout-iOS-Tunnel/Tunnel.entitlements index ad9e428b..c2da4ee5 100644 --- a/Passepartout-iOS-Tunnel/Tunnel.entitlements +++ b/Passepartout-iOS-Tunnel/Tunnel.entitlements @@ -8,7 +8,7 @@ com.apple.security.application-groups - group.com.algoritmico.Passepartout + group.$(CFG_GROUP_ID) diff --git a/Passepartout-iOS/Config.xcconfig b/Passepartout-iOS/Config.xcconfig new file mode 100644 index 00000000..6b0607df --- /dev/null +++ b/Passepartout-iOS/Config.xcconfig @@ -0,0 +1,32 @@ +// +// Config.xcconfig +// Passepartout +// +// Created by Davide De Rosa on 5/24/19. +// Copyright (c) 2019 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +CFG_TEAM_ID = DTDYD63ZX9 +CFG_APP_ID = com.algoritmico.ios.Passepartout +CFG_GROUP_ID = com.algoritmico.Passepartout +CFG_APPSTORE_ID = 1433648537 diff --git a/Passepartout-iOS/Info.plist b/Passepartout-iOS/Info.plist index d521790a..a930e4a9 100644 --- a/Passepartout-iOS/Info.plist +++ b/Passepartout-iOS/Info.plist @@ -105,5 +105,12 @@ + com.algoritmico.Passepartout.config + + group_id + group.$(CFG_GROUP_ID) + appstore_id + $(CFG_APPSTORE_ID) + diff --git a/Passepartout-iOS/Passepartout.entitlements b/Passepartout-iOS/Passepartout.entitlements index 20e38ffd..25d1fc93 100644 --- a/Passepartout-iOS/Passepartout.entitlements +++ b/Passepartout-iOS/Passepartout.entitlements @@ -12,7 +12,7 @@ com.apple.security.application-groups - group.com.algoritmico.Passepartout + group.$(CFG_GROUP_ID) diff --git a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift index 79bdc85e..e3371a90 100644 --- a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift +++ b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift @@ -319,7 +319,7 @@ class OrganizerViewController: UITableViewController, TableModelHost { } private func writeReview() { - let url = AppConstants.URLs.review(withId: GroupConstants.App.appId) + let url = AppConstants.URLs.review(withId: AppConstants.App.appStoreId) UIApplication.shared.open(url, options: [:], completionHandler: nil) } diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj index 0f71b737..f706b326 100644 --- a/Passepartout.xcodeproj/project.pbxproj +++ b/Passepartout.xcodeproj/project.pbxproj @@ -185,6 +185,7 @@ 0E158AD920E11B0B00C85A82 /* EndpointViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndpointViewController.swift; sourceTree = ""; }; 0E1D72B1213BFFCF00BA1586 /* ProviderPresetViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProviderPresetViewController.swift; sourceTree = ""; }; 0E1D72B3213C118500BA1586 /* ConfigurationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationViewController.swift; sourceTree = ""; }; + 0E23B4A12298559800304C30 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = ""; }; 0E242735225944060064A1A3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intents.strings; sourceTree = ""; }; 0E24273B225950450064A1A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/About.storyboard; sourceTree = ""; }; 0E24273F225951B00064A1A3 /* InApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InApp.swift; sourceTree = ""; }; @@ -461,6 +462,7 @@ 0E1066CA20E0F85C004F98B7 /* Cells */, 0ECEE44C20E1120F00A6BB43 /* Tables */, 0EDE8DF120C93ED8004C739C /* Scenes */, + 0E23B4A12298559800304C30 /* Config.xcconfig */, 0EDE8DE220C86A13004C739C /* Passepartout.entitlements */, 0E57F63B20C83FC5008323CF /* AppDelegate.swift */, 0E24273C225950450064A1A3 /* About.storyboard */, @@ -1341,6 +1343,7 @@ }; 0E57F65320C83FC7008323CF /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 0E23B4A12298559800304C30 /* Config.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; @@ -1407,6 +1410,7 @@ }; 0E57F65420C83FC7008323CF /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 0E23B4A12298559800304C30 /* Config.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; @@ -1480,7 +1484,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID)"; PRODUCT_NAME = Passepartout; PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -1504,7 +1508,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID)"; PRODUCT_NAME = Passepartout; PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout"; SWIFT_VERSION = 5.0; @@ -1527,7 +1531,7 @@ "@executable_path/../../Frameworks", ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout.Tunnel; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID).Tunnel"; PRODUCT_NAME = "Passepartout-Tunnel"; PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout.Tunnel"; SKIP_INSTALL = YES; @@ -1550,7 +1554,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout.Tunnel; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID).Tunnel"; PRODUCT_NAME = "Passepartout-Tunnel"; PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout.Tunnel"; SKIP_INSTALL = YES; diff --git a/Passepartout/Sources/AppConstants.swift b/Passepartout/Sources/AppConstants.swift index 2ecdc4e7..1312436d 100644 --- a/Passepartout/Sources/AppConstants.swift +++ b/Passepartout/Sources/AppConstants.swift @@ -28,6 +28,22 @@ import TunnelKit import SwiftyBeaver public class AppConstants { + public class App { + public static let appStoreId: String = { + guard let identifier = GroupConstants.App.config["appstore_id"] as? String else { + fatalError("Missing appstore_id from Info.plist config") + } + return identifier + }() + + public static let tunnelBundleId: String = { + guard let identifier = Bundle.main.infoDictionary?[kCFBundleIdentifierKey as String] as? String else { + fatalError("Missing kCFBundleIdentifierKey from Info.plist") + } + return "\(identifier).Tunnel" + }() + } + public class Flags { public static let isBeta = false } diff --git a/Passepartout/Sources/GroupConstants.swift b/Passepartout/Sources/GroupConstants.swift index a6120a51..4061ce1a 100644 --- a/Passepartout/Sources/GroupConstants.swift +++ b/Passepartout/Sources/GroupConstants.swift @@ -39,23 +39,23 @@ public class GroupConstants { public static let buildNumber = Int(Bundle.main.infoDictionary![kCFBundleVersionKey as String] as! String)! public static let versionString = "\(versionNumber) (\(buildNumber))" - - public static let teamId = "DTDYD63ZX9" - public static let appId = "1433648537" + public static let config: [String: Any] = { + guard let cfg = Bundle.main.infoDictionary?["com.algoritmico.Passepartout.config"] as? [String: Any] else { + fatalError("Missing app config from Info.plist") + } + return cfg + }() - #if os(iOS) - public static let appGroup = "group.com.algoritmico.Passepartout" - - public static let tunnelIdentifier = "com.algoritmico.ios.Passepartout.Tunnel" - #else - public static let appGroup = "\(teamId).group.com.algoritmico.Passepartout" - - public static let tunnelIdentifier = "com.algoritmico.macos.Passepartout.Tunnel" - #endif + public static let groupId: String = { + guard let identifier = config["group_id"] as? String else { + fatalError("Missing group_id from Info.plist config") + } + return identifier + }() private static var containerURL: URL { - guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup) else { + guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupId) else { print("Unable to access App Group container") return FileManager.default.userURL(for: .documentDirectory, appending: nil) } diff --git a/Passepartout/Sources/Model/ConnectionService.swift b/Passepartout/Sources/Model/ConnectionService.swift index 5f553c34..c1c52761 100644 --- a/Passepartout/Sources/Model/ConnectionService.swift +++ b/Passepartout/Sources/Model/ConnectionService.swift @@ -539,7 +539,7 @@ public class ConnectionService: Codable { } let protocolConfiguration = try cfg.generatedTunnelProtocol( - withBundleIdentifier: GroupConstants.App.tunnelIdentifier, + withBundleIdentifier: AppConstants.App.tunnelBundleId, appGroup: appGroup, credentials: creds ) diff --git a/Passepartout/Sources/Model/TransientStore.swift b/Passepartout/Sources/Model/TransientStore.swift index 3ec4c3cc..afda9a0e 100644 --- a/Passepartout/Sources/Model/TransientStore.swift +++ b/Passepartout/Sources/Model/TransientStore.swift @@ -119,7 +119,7 @@ public class TransientStore { } catch let e { log.error("Could not decode service: \(e)") service = ConnectionService( - withAppGroup: GroupConstants.App.appGroup, + withAppGroup: GroupConstants.App.groupId, baseConfiguration: cfg ) diff --git a/Passepartout/Sources/VPN/VPN.swift b/Passepartout/Sources/VPN/VPN.swift index 184cca7b..443494c2 100644 --- a/Passepartout/Sources/VPN/VPN.swift +++ b/Passepartout/Sources/VPN/VPN.swift @@ -29,6 +29,6 @@ public class VPN { #if targetEnvironment(simulator) public static let shared = MockVPNProvider() #else - public static let shared = StandardVPNProvider(bundleIdentifier: GroupConstants.App.tunnelIdentifier) + public static let shared = StandardVPNProvider(bundleIdentifier: AppConstants.App.tunnelBundleId) #endif } diff --git a/README.md b/README.md index 300c37a3..7a79138e 100644 --- a/README.md +++ b/README.md @@ -108,12 +108,12 @@ For the VPN to work properly, the app requires: both in the main app and the tunnel extension target. -Make sure to also update the following constants in `Passepartout/Sources/GroupConstants.swift` according to your developer account and your target bundle identifiers: +Make sure to update `Passepartout-iOS/Config.xcconfig` according to your developer account and your identifiers: - public static let teamId - public static let appId - public static let appGroup - public static let tunnelIdentifier + CFG_TEAM_ID = A1B2C3D4E5 + CFG_APP_ID = com.example.ios.MyApp + CFG_GROUP_ID = com.example.MyAppGroup // omit the "group." prefix + CFG_APPSTORE_ID = 1234567890 ## License