motion-provisioning 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -0
- data/bin/console +7 -0
- data/bin/export_private_key +0 -0
- data/bin/setup +9 -0
- data/export_private_key/export_private_key.c +144 -0
- data/lib/motion-provisioning/certificate.rb +46 -17
- data/lib/motion-provisioning/provisioning_profile.rb +2 -2
- data/lib/motion-provisioning/spaceship/free_portal_client.rb +1 -1
- data/lib/motion-provisioning/tasks.rb +1 -0
- data/lib/motion-provisioning/version.rb +1 -1
- data/lib/motion-provisioning.rb +0 -1
- metadata +16 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48e42fb68d7a25eb15c82c1aa8a5b3a1c6e228ced5d59682f75a4c115a30fcae
|
4
|
+
data.tar.gz: 88e05257a72160fb218b36780c16ce6c9a93094a2121820f3294a80f7a7c79e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd5e4c1d65e25e5d9ec9defb1b93a33296e09a7ee94aa1545430f387558089dc7e95da007ff87a9522ca5bca1534355cae5d3aa51c4b96b10b3767396895e58a
|
7
|
+
data.tar.gz: '0238f533575b8bb4f52d8ef38cfd6ce1480b3b11cd10018d5839d9bc04b5a0d0b5f75e3017051d2dfb6d9f747190e919dca3d51d788b65b48722c22fbdb86a5e'
|
data/README.md
CHANGED
@@ -170,6 +170,10 @@ After you create a new distribution certificate, share the
|
|
170
170
|
corresponding `.cer` and `.p12` files located in the `provisioning`
|
171
171
|
folder with your team members.
|
172
172
|
|
173
|
+
After copying the files to the team member's `provisioning` directory,
|
174
|
+
drag and drop the certificate file into the Keychain Access app's login
|
175
|
+
keychain in order to install the certificate.
|
176
|
+
|
173
177
|
## Recreate certificates and profiles
|
174
178
|
|
175
179
|
Once the certificates and profiles are cached in the `provisioning`
|
@@ -184,6 +188,9 @@ Or to recreate the development certificate:
|
|
184
188
|
|
185
189
|
rake device recreate_certificate=1
|
186
190
|
|
191
|
+
Or to recreate the distribution certificate:
|
192
|
+
|
193
|
+
rake archive:distribution recreate_certificate=1
|
187
194
|
|
188
195
|
## Entitlements and App Services
|
189
196
|
|
data/bin/console
ADDED
data/bin/export_private_key
CHANGED
Binary file
|
data/bin/setup
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
/*
|
2
|
+
* This file contains modified code with copyright:
|
3
|
+
*
|
4
|
+
* Copyright (c) 2003-2010,2012,2014 Apple Inc. All Rights Reserved.
|
5
|
+
*
|
6
|
+
* Covered by the APPLE PUBLIC SOURCE LICENSE
|
7
|
+
* (http://opensource.apple.com/license/apsl/)
|
8
|
+
*/
|
9
|
+
|
10
|
+
#import <CoreFoundation/CoreFoundation.h>
|
11
|
+
#import <Security/Security.h>
|
12
|
+
|
13
|
+
#define DEBUG 0
|
14
|
+
|
15
|
+
unsigned char
|
16
|
+
hexValue(char c)
|
17
|
+
{
|
18
|
+
static const char digits[] = "0123456789abcdef";
|
19
|
+
char *p;
|
20
|
+
if (p = strchr(digits, tolower(c)))
|
21
|
+
return p - digits;
|
22
|
+
else
|
23
|
+
return 0;
|
24
|
+
}
|
25
|
+
|
26
|
+
void
|
27
|
+
fromHex(const char *hexDigits, CSSM_DATA *data)
|
28
|
+
{
|
29
|
+
size_t bytes = strlen(hexDigits) / 2; // (discards malformed odd end)
|
30
|
+
if (bytes > data->Length)
|
31
|
+
return;
|
32
|
+
// length(bytes); // (will assert if we try to grow it)
|
33
|
+
size_t n;
|
34
|
+
for (n = 0; n < bytes; n++) {
|
35
|
+
data->Data[n] = (uint8)(hexValue(hexDigits[2*n]) << 4 | hexValue(hexDigits[2*n+1]));
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
int main(int argc, char *argv[]) {
|
40
|
+
|
41
|
+
if (argc != 4) {
|
42
|
+
exit(1);
|
43
|
+
}
|
44
|
+
|
45
|
+
char* identity_name = argv[1];
|
46
|
+
char* hash = argv[2];
|
47
|
+
char* key_password = argv[3];
|
48
|
+
|
49
|
+
// First get a list of Identities matching the specified name
|
50
|
+
const void* values[] = {
|
51
|
+
kSecClassIdentity,
|
52
|
+
kCFBooleanTrue,
|
53
|
+
CFStringCreateWithCString(NULL, identity_name, kCFStringEncodingUTF8),
|
54
|
+
kSecMatchLimitAll
|
55
|
+
};
|
56
|
+
const void* keys[] = {
|
57
|
+
kSecClass,
|
58
|
+
kSecReturnRef,
|
59
|
+
kSecMatchSubjectContains,
|
60
|
+
kSecMatchLimit
|
61
|
+
};
|
62
|
+
CFIndex numValues = sizeof(keys)/sizeof(void*);
|
63
|
+
CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, numValues, NULL, NULL);
|
64
|
+
|
65
|
+
CFTypeRef results;
|
66
|
+
if (SecItemCopyMatching(query, &results) != noErr) {
|
67
|
+
exit(1);
|
68
|
+
}
|
69
|
+
|
70
|
+
// Prepare the Identity hash
|
71
|
+
CSSM_DATA hashData = { 0, NULL };
|
72
|
+
CSSM_SIZE len = strlen(hash)/2;
|
73
|
+
hashData.Length = len;
|
74
|
+
hashData.Data = (uint8 *)malloc(hashData.Length);
|
75
|
+
fromHex(hash, &hashData);
|
76
|
+
|
77
|
+
SecIdentityRef item;
|
78
|
+
CSSM_DATA certData = { 0, NULL };
|
79
|
+
SecCertificateRef cert = NULL;
|
80
|
+
Boolean found = FALSE;
|
81
|
+
|
82
|
+
// Check all found identitied, looking for one whose certificate matches the
|
83
|
+
// specified hash
|
84
|
+
CFIndex count = CFArrayGetCount(results);
|
85
|
+
for (int i = 0; i < count; i++) {
|
86
|
+
item = CFArrayGetValueAtIndex(results, i);
|
87
|
+
|
88
|
+
if (SecIdentityCopyCertificate(item, &cert) != noErr) {
|
89
|
+
CFRelease(&item);
|
90
|
+
continue;
|
91
|
+
}
|
92
|
+
|
93
|
+
if (SecCertificateGetData(cert, &certData) != noErr) {
|
94
|
+
CFRelease(&cert);
|
95
|
+
CFRelease(&item);
|
96
|
+
continue;
|
97
|
+
}
|
98
|
+
|
99
|
+
uint8 candidate_sha1_hash[20];
|
100
|
+
CSSM_DATA digest;
|
101
|
+
digest.Length = sizeof(candidate_sha1_hash);
|
102
|
+
digest.Data = candidate_sha1_hash;
|
103
|
+
if ((SecDigestGetData(CSSM_ALGID_SHA1, &digest, &certData) == CSSM_OK) &&
|
104
|
+
(hashData.Length == digest.Length) &&
|
105
|
+
(!memcmp(hashData.Data, digest.Data, digest.Length))) {
|
106
|
+
found = TRUE;
|
107
|
+
break;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
if (found) {
|
112
|
+
#if DEBUG
|
113
|
+
CFStringRef nameRef = NULL;
|
114
|
+
if (SecCertificateCopyCommonName(cert, &nameRef) != noErr) {
|
115
|
+
exit(1);
|
116
|
+
}
|
117
|
+
|
118
|
+
char *cert_name = CFStringGetCStringPtr(nameRef, kCFStringEncodingUTF8);
|
119
|
+
printf("%s\n", cert_name);
|
120
|
+
#endif
|
121
|
+
|
122
|
+
// Finally, get the encrypted private key using the specified password
|
123
|
+
// and print it to stdout in PEM format
|
124
|
+
SecKeyRef key = NULL;
|
125
|
+
if (SecIdentityCopyPrivateKey(item, &key) != noErr) {
|
126
|
+
exit(1);
|
127
|
+
}
|
128
|
+
|
129
|
+
SecKeyImportExportParameters keyParams;
|
130
|
+
keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
|
131
|
+
keyParams.flags = 0;
|
132
|
+
keyParams.passphrase = CFDataCreate(NULL, key_password, 5);
|
133
|
+
keyParams.alertTitle = 0;
|
134
|
+
keyParams.alertPrompt = 0;
|
135
|
+
|
136
|
+
CFDataRef key_data;
|
137
|
+
OSStatus status = SecKeychainItemExport(key, kSecFormatWrappedPKCS8,
|
138
|
+
kSecItemPemArmour, &keyParams, &key_data);
|
139
|
+
|
140
|
+
if(status == noErr) {
|
141
|
+
write(fileno(stdout), CFDataGetBytePtr(key_data), CFDataGetLength(key_data));
|
142
|
+
}
|
143
|
+
}
|
144
|
+
}
|
@@ -24,14 +24,13 @@ module MotionProvisioning
|
|
24
24
|
installed_cert = identities.detect { |e| e[:fingerprint] == fingerprint }
|
25
25
|
if installed_cert
|
26
26
|
Utils.log("Info", "Using certificate '#{installed_cert[:name]}'.")
|
27
|
-
return installed_cert[:
|
27
|
+
return installed_cert[:fingerprint]
|
28
28
|
else
|
29
29
|
# The certificate is not installed, so we install the cert and the key
|
30
30
|
import_file(private_key_path)
|
31
31
|
import_file(certificate_path)
|
32
|
-
|
33
|
-
|
34
|
-
return name
|
32
|
+
Utils.log("Info", "Using certificate '#{common_name(certificate_path)}'.")
|
33
|
+
return sha1_fingerprint(certificate_path)
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
@@ -48,23 +47,23 @@ module MotionProvisioning
|
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
51
|
-
# There are no certificates in the server so we create a new one
|
52
50
|
if certificates.empty?
|
53
|
-
|
51
|
+
# There are no certificates in the server so we create a new one
|
52
|
+
Utils.log("Warning", "Couldn't find any existing certificates. Creating a new certificate...")
|
54
53
|
if certificate = create_certificate
|
55
|
-
return
|
54
|
+
return sha1_fingerprint(certificate)
|
56
55
|
else
|
57
56
|
Utils.log("Error", "Something went wrong when trying to create a new certificate.")
|
58
57
|
abort
|
59
58
|
end
|
60
|
-
# There are certificates in the server, but none is installed locally. Revoke all and create a new one.
|
61
59
|
elsif installed_certificate.nil?
|
62
|
-
|
60
|
+
# There are certificates in the server, but none are installed locally. Revoke all and create a new one.
|
61
|
+
Utils.log("Error", "None of the available certificates (#{certificates.count}) are installed locally. Revoking...")
|
63
62
|
|
64
63
|
# For distribution, ask before revoking
|
65
64
|
if self.type == :distribution
|
66
|
-
answer = Utils.ask("Info", "There are #{certificates.count} distribution
|
67
|
-
"Before revoking and creating a new
|
65
|
+
answer = Utils.ask("Info", "There #{certificates.count == 1 ? 'is 1' : "are #{certificates.count}"} distribution certificate(s) in your account, but none installed locally.\n" \
|
66
|
+
"Before revoking and creating a new certificate, ask other team members who might have them installed to share them with you.\n" \
|
68
67
|
"Do you want to continue revoking the certificates? (Y/n):")
|
69
68
|
abort if answer.no?
|
70
69
|
end
|
@@ -79,13 +78,43 @@ module MotionProvisioning
|
|
79
78
|
end
|
80
79
|
|
81
80
|
if certificate = create_certificate
|
82
|
-
return
|
81
|
+
return sha1_fingerprint(certificate)
|
83
82
|
else
|
84
83
|
Utils.log("Error", "Something went wrong when trying to create a new certificate...")
|
85
84
|
abort
|
86
85
|
end
|
87
|
-
|
86
|
+
elsif ENV['recreate_certificate'] != nil
|
87
|
+
# Force recreate certificate, even though a valid certificate is already installed locally
|
88
|
+
|
89
|
+
if self.type == :distribution
|
90
|
+
answer = Utils.ask("Info", "There are #{certificates.count} distribution certificates in your account.\n" \
|
91
|
+
"Before revoking and creating a new one, ask other team members who might have them installed to share them with you.\n" \
|
92
|
+
"Do you want to revoke the existing certificates? (Y/n):")
|
93
|
+
if answer.yes?
|
94
|
+
certificates.each(&:revoke!)
|
95
|
+
end
|
96
|
+
else
|
97
|
+
answer = Utils.ask("Info", "You have #{certificates.count} development certificates in your account.\n" \
|
98
|
+
"Do you want to revoke your existing certificates? (Y/n):")
|
99
|
+
if answer.yes?
|
100
|
+
if MotionProvisioning.free
|
101
|
+
certificates.each do |certificate|
|
102
|
+
client.revoke_development_certificate(certificate.motionprovisioning_serialNumber)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
certificates.each(&:revoke!)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
if certificate = create_certificate
|
111
|
+
return sha1_fingerprint(certificate)
|
112
|
+
else
|
113
|
+
Utils.log("Error", "Something went wrong when trying to create a new certificate.")
|
114
|
+
abort
|
115
|
+
end
|
88
116
|
else
|
117
|
+
# There are certificates on the server, and one of them is installed locally.
|
89
118
|
Utils.log("Info", "Found certificate '#{installed_certificate.name}' which is installed in the local machine.")
|
90
119
|
|
91
120
|
path = store_certificate_raw(installed_certificate.motionprovisioning_certContent || installed_certificate.download_raw)
|
@@ -97,7 +126,7 @@ module MotionProvisioning
|
|
97
126
|
# This certificate is installed on the local machine
|
98
127
|
Utils.log("Info", "Using certificate '#{installed_certificate.name}'.")
|
99
128
|
|
100
|
-
|
129
|
+
sha1_fingerprint(path)
|
101
130
|
end
|
102
131
|
end
|
103
132
|
|
@@ -134,7 +163,7 @@ module MotionProvisioning
|
|
134
163
|
when :mac
|
135
164
|
cert_type = Spaceship.certificate.mac_development
|
136
165
|
cert_type = Spaceship.certificate.mac_app_distribution if self.type == :distribution
|
137
|
-
cert_type = Spaceship.certificate.
|
166
|
+
cert_type = Spaceship.certificate.developer_id_application if self.type == :developer_id
|
138
167
|
end
|
139
168
|
cert_type
|
140
169
|
end
|
@@ -191,9 +220,9 @@ module MotionProvisioning
|
|
191
220
|
Utils.log("Info", "Successfully installed certificate.")
|
192
221
|
|
193
222
|
if self.type == :distribution
|
194
|
-
Utils.log("Warning", "You have just created a distribution certificate. These certificates must be shared with other team members by sending them the private key (.p12) and certificate (.cer) files in your
|
223
|
+
Utils.log("Warning", "You have just created a distribution certificate. These certificates must be shared with other team members by sending them the private key (.p12) and certificate (.cer) files in your 'provisioning' folder and install them in the keychain.")
|
195
224
|
else
|
196
|
-
Utils.log("Warning", "You have just created a development certificate. If you want to use this certificate on another machine, transfer the private key (.p12) and certificate (.cer) files in your
|
225
|
+
Utils.log("Warning", "You have just created a development certificate. If you want to use this certificate on another machine, transfer the private key (.p12) and certificate (.cer) files in your 'provisioning' folder and install them in the keychain.")
|
197
226
|
end
|
198
227
|
Utils.ask("Info", "Press any key to continue...")
|
199
228
|
|
@@ -30,8 +30,7 @@ module MotionProvisioning
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
# ensure a client is created and logged in
|
34
|
-
client
|
33
|
+
client # ensure a client is created and logged in
|
35
34
|
|
36
35
|
app = Application.find_or_create(bundle_id: bundle_id, name: app_name, mac: platform == :mac)
|
37
36
|
|
@@ -78,6 +77,7 @@ module MotionProvisioning
|
|
78
77
|
certificate_platform = platform == :mac ? :mac : :ios
|
79
78
|
certificate_sha1 = OpenSSL::Digest::SHA1.new(File.read(File.join(output_path, "#{certificate_platform}_distribution_certificate.cer")))
|
80
79
|
cert = client.distribution_certificates(mac: platform == :mac).detect do |c|
|
80
|
+
# Compare downloaded cert content against local cert content to make sure they match
|
81
81
|
OpenSSL::Digest::SHA1.new(c['certContent'].read) == certificate_sha1
|
82
82
|
end
|
83
83
|
|
@@ -5,7 +5,7 @@ module Spaceship
|
|
5
5
|
def teams
|
6
6
|
return @teams if @teams
|
7
7
|
req = request(:post, "https://developerservices2.apple.com/services/#{PROTOCOL_VERSION}/listTeams.action", nil, {
|
8
|
-
'X-Xcode-Version' => XCODE_VERSION # necessary in order to
|
8
|
+
'X-Xcode-Version' => XCODE_VERSION # necessary in order to list Xcode free team
|
9
9
|
})
|
10
10
|
@teams = parse_response(req, 'teams').sort_by do |team|
|
11
11
|
[
|
data/lib/motion-provisioning.rb
CHANGED
metadata
CHANGED
@@ -1,63 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motion-provisioning
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Villacampa
|
8
|
-
|
8
|
+
- Andrew Havens
|
9
|
+
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2021-08-27 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: highline
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.7.2
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 2.0.0
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 1.7.2
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 2.0.0
|
33
14
|
- !ruby/object:Gem::Dependency
|
34
15
|
name: fastlane
|
35
16
|
requirement: !ruby/object:Gem::Requirement
|
36
17
|
requirements:
|
37
18
|
- - "~>"
|
38
19
|
- !ruby/object:Gem::Version
|
39
|
-
version: 2.
|
20
|
+
version: '2.182'
|
40
21
|
type: :runtime
|
41
22
|
prerelease: false
|
42
23
|
version_requirements: !ruby/object:Gem::Requirement
|
43
24
|
requirements:
|
44
25
|
- - "~>"
|
45
26
|
- !ruby/object:Gem::Version
|
46
|
-
version: 2.
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: bundler
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - "~>"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '1.12'
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - "~>"
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '1.12'
|
27
|
+
version: '2.182'
|
61
28
|
- !ruby/object:Gem::Dependency
|
62
29
|
name: rake
|
63
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -106,14 +73,14 @@ dependencies:
|
|
106
73
|
requirements:
|
107
74
|
- - "~>"
|
108
75
|
- !ruby/object:Gem::Version
|
109
|
-
version: '
|
76
|
+
version: '3.7'
|
110
77
|
type: :development
|
111
78
|
prerelease: false
|
112
79
|
version_requirements: !ruby/object:Gem::Requirement
|
113
80
|
requirements:
|
114
81
|
- - "~>"
|
115
82
|
- !ruby/object:Gem::Version
|
116
|
-
version: '
|
83
|
+
version: '3.7'
|
117
84
|
- !ruby/object:Gem::Dependency
|
118
85
|
name: simplecov
|
119
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -132,13 +99,17 @@ description: A small library that manages certificates and profiles automaticall
|
|
132
99
|
from the command line, with minimal configuration.
|
133
100
|
email:
|
134
101
|
- m@markvillacampa.com
|
102
|
+
- email@andrewhavens.com
|
135
103
|
executables: []
|
136
104
|
extensions: []
|
137
105
|
extra_rdoc_files: []
|
138
106
|
files:
|
139
107
|
- LICENSE.txt
|
140
108
|
- README.md
|
109
|
+
- bin/console
|
141
110
|
- bin/export_private_key
|
111
|
+
- bin/setup
|
112
|
+
- export_private_key/export_private_key.c
|
142
113
|
- lib/motion-provisioning.rb
|
143
114
|
- lib/motion-provisioning/application.rb
|
144
115
|
- lib/motion-provisioning/certificate.rb
|
@@ -150,11 +121,11 @@ files:
|
|
150
121
|
- lib/motion-provisioning/tasks.rb
|
151
122
|
- lib/motion-provisioning/utils.rb
|
152
123
|
- lib/motion-provisioning/version.rb
|
153
|
-
homepage: https://github.com/
|
124
|
+
homepage: https://github.com/rubymotion-community/motion-provisioning
|
154
125
|
licenses:
|
155
126
|
- BSD
|
156
127
|
metadata: {}
|
157
|
-
post_install_message:
|
128
|
+
post_install_message:
|
158
129
|
rdoc_options: []
|
159
130
|
require_paths:
|
160
131
|
- lib
|
@@ -169,9 +140,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
169
140
|
- !ruby/object:Gem::Version
|
170
141
|
version: '0'
|
171
142
|
requirements: []
|
172
|
-
|
173
|
-
|
174
|
-
signing_key:
|
143
|
+
rubygems_version: 3.2.15
|
144
|
+
signing_key:
|
175
145
|
specification_version: 4
|
176
146
|
summary: Simplified provisioning for RubyMotion iOS, tvOS and macOS apps.
|
177
147
|
test_files: []
|