cert 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +156 -0
- data/bin/cert +55 -0
- data/lib/cert/cert_checker.rb +30 -0
- data/lib/cert/cert_runner.rb +7 -0
- data/lib/cert/dependency_checker.rb +18 -0
- data/lib/cert/developer_center.rb +174 -0
- data/lib/cert/keychain_importer.rb +10 -0
- data/lib/cert/signing_request.rb +33 -0
- data/lib/cert/version.rb +3 -0
- data/lib/cert.rb +21 -0
- metadata +169 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6144b46854a7c5b8125135062907eca353cef490
|
4
|
+
data.tar.gz: d107c1c5f6ad757c4b8cbf3340cdd306a34a6fe4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c084c2f0985bae99f5c43d79a3ac4388262351a13843f34472461658e884f92c401c36b25d5ee60670696cb594432a2bd7abcc28e459432cb3f8a9108ebde5c9
|
7
|
+
data.tar.gz: 7698d2b47357a8c504f2e10e579f92ad3ad532b258d805befc99a0efa82fb61655eedd275f6629d8e4eeed7db5c24715c8b7ced9d16b4ed100870dc5780d9db1
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Felix Krause
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
<h3 align="center">
|
2
|
+
<a href="https://github.com/KrauseFx/fastlane">
|
3
|
+
<img src="assets/fastlane.png" width="150" />
|
4
|
+
<br />
|
5
|
+
fastlane
|
6
|
+
</a>
|
7
|
+
</h3>
|
8
|
+
<p align="center">
|
9
|
+
<a href="https://github.com/KrauseFx/deliver">deliver</a> •
|
10
|
+
<a href="https://github.com/KrauseFx/snapshot">snapshot</a> •
|
11
|
+
<a href="https://github.com/KrauseFx/frameit">frameit</a> •
|
12
|
+
<a href="https://github.com/KrauseFx/pem">PEM</a> •
|
13
|
+
<a href="https://github.com/KrauseFx/sigh">sigh</a> •
|
14
|
+
<a href="https://github.com/KrauseFx/produce">produce</a> •
|
15
|
+
<b>cert</b>
|
16
|
+
</p>
|
17
|
+
-------
|
18
|
+
|
19
|
+
<p align="center">
|
20
|
+
<img src="assets/cert.png">
|
21
|
+
</p>
|
22
|
+
|
23
|
+
cert - Create new iOS signing certificates
|
24
|
+
============
|
25
|
+
|
26
|
+
[](https://twitter.com/KrauseFx)
|
27
|
+
[](https://github.com/KrauseFx/cert/blob/master/LICENSE)
|
28
|
+
[](http://rubygems.org/gems/cert)
|
29
|
+
|
30
|
+
###### Automatically create and maintain iOS code signing certificates.
|
31
|
+
|
32
|
+
##### This tool was sponsored by [AppInstitute](http://appinstitute.co.uk/).
|
33
|
+
|
34
|
+
Get in contact with the developer on Twitter: [@KrauseFx](https://twitter.com/KrauseFx)
|
35
|
+
|
36
|
+
-------
|
37
|
+
<p align="center">
|
38
|
+
<a href="#installation">Installation</a> •
|
39
|
+
<a href="#why">Why?</a> •
|
40
|
+
<a href="#usage">Usage</a> •
|
41
|
+
<a href="#how-does-it-work">How does it work?</a> •
|
42
|
+
<a href="#tips">Tips</a> •
|
43
|
+
<a href="#need-help">Need help?</a>
|
44
|
+
</p>
|
45
|
+
|
46
|
+
-------
|
47
|
+
|
48
|
+
<h5 align="center"><code>cert</code> is part of <a href="http://fastlane.tools">fastlane</a>: connect all deployment tools into one streamlined workflow.</h5>
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
# Installation
|
53
|
+
sudo gem install cert
|
54
|
+
|
55
|
+
Make sure, you have the latest version of the Xcode command line tools installed:
|
56
|
+
|
57
|
+
xcode-select --install
|
58
|
+
|
59
|
+
# Why?
|
60
|
+
|
61
|
+
Please check out [this guide](https://github.com/KrauseFx/cert/blob/master/ManualSteps.md) to get started with a signing certificate and a provisioning profile.
|
62
|
+
|
63
|
+
**After** checking out the [guide](https://github.com/KrauseFx/cert/blob/master/ManualSteps.md), take a look at this lovely gif:
|
64
|
+
|
65
|
+

|
66
|
+
|
67
|
+
In the gif I used `cert && sigh`, which will first create an iOS code signing certificate and then a provisioning profile for your app if `cert` succeeded.
|
68
|
+
|
69
|
+
# Usage
|
70
|
+
|
71
|
+
cert
|
72
|
+
|
73
|
+
This will check if any of the available signing certificates is installed.
|
74
|
+
|
75
|
+
Only if a new certificate needs to be created, `cert` will
|
76
|
+
|
77
|
+
- Create a new private key
|
78
|
+
- Create a new signing request
|
79
|
+
- Generate, downloads and installs the certificate
|
80
|
+
- Import all the generated files into your Keychain
|
81
|
+
|
82
|
+
|
83
|
+
```cert``` will never revoke your existing certificates. If you can't create any more certificates, `cert` will raise an exception, which means, you have to revoke one of the existing certificates to make room for a new one.
|
84
|
+
|
85
|
+
|
86
|
+
You can pass your Apple ID:
|
87
|
+
|
88
|
+
cert -u cert@krausefx.com
|
89
|
+
|
90
|
+
|
91
|
+
## Environment Variables
|
92
|
+
In case you prefer environment variables:
|
93
|
+
|
94
|
+
- ```CERT_USERNAME```
|
95
|
+
- ```CERT_TEAM_ID```
|
96
|
+
- ```CERT_KEYCHAIN_PATH``` The path to a specific Keychain if you don't want to use the default one
|
97
|
+
|
98
|
+
## Use with [`sigh`](https://github.com/KrauseFx/sigh)
|
99
|
+
|
100
|
+
`cert` is becomes really interesting when it's used in [`fastlane`](https://github.com/KrauseFx/fastlane) in combination with [`sigh`](https://github.com/KrauseFx/sigh).
|
101
|
+
|
102
|
+
Update your `Fastfile` to contain the following code:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
lane :beta do
|
106
|
+
cert
|
107
|
+
sigh :force
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
`:force` will make sure to re-generate the provisioning profile on each run.
|
112
|
+
This will result in `sigh` always using the correct signing certificate, which is installed on the local machine.
|
113
|
+
|
114
|
+
|
115
|
+
# How does it work?
|
116
|
+
|
117
|
+
- `cert` accesses the ```iOS Dev Center``` to create or download your certificate. See: [developer_center.rb](https://github.com/KrauseFx/cert/blob/master/lib/cert/developer_center.rb).
|
118
|
+
- The ```.certSigningRequest``` file will be generated in [signing_request.rb](https://github.com/KrauseFx/cert/blob/master/lib/cert/signing_request.rb)
|
119
|
+
|
120
|
+
|
121
|
+
## How is my password stored?
|
122
|
+
```cert``` uses the [password manager](https://github.com/KrauseFx/CredentialsManager) from `fastlane`. Take a look the [CredentialsManager README](https://github.com/KrauseFx/CredentialsManager) for more information.
|
123
|
+
|
124
|
+
# Tips
|
125
|
+
|
126
|
+
## [`fastlane`](http://fastlane.tools) Toolchain
|
127
|
+
|
128
|
+
- [`fastlane`](http://fastlane.tools): Connect all deployment tools into one streamlined workflow
|
129
|
+
- [`deliver`](https://github.com/KrauseFx/deliver): Upload screenshots, metadata and your app to the App Store using a single command
|
130
|
+
- [`snapshot`](https://github.com/KrauseFx/snapshot): Automate taking localized screenshots of your iOS app on every device
|
131
|
+
- [`frameit`](https://github.com/KrauseFx/frameit): Quickly put your screenshots into the right device frames
|
132
|
+
- [`PEM`](https://github.com/KrauseFx/pem): Automatically generate and renew your push notification profiles
|
133
|
+
- [`sigh`](https://github.com/KrauseFx/sigh): Because you would rather spend your time building stuff than fighting provisioning
|
134
|
+
- [`produce`](https://github.com/KrauseFx/produce): Create new iOS apps on iTunes Connect and Dev Portal using the command line
|
135
|
+
|
136
|
+
## Use the 'Provisioning Quicklook plugin'
|
137
|
+
Download and install the [Provisioning Plugin](https://github.com/chockenberry/Provisioning).
|
138
|
+
|
139
|
+

|
140
|
+
|
141
|
+
|
142
|
+
# Need help?
|
143
|
+
- If there is a technical problem with ```cert```, submit an issue.
|
144
|
+
- I'm available for contract work - drop me an email: cert@krausefx.com
|
145
|
+
|
146
|
+
# License
|
147
|
+
This project is licensed under the terms of the MIT license. See the LICENSE file.
|
148
|
+
|
149
|
+
# Contributing
|
150
|
+
|
151
|
+
1. Create an issue to discuss about your idea
|
152
|
+
2. Fork it (https://github.com/KrauseFx/cert/fork)
|
153
|
+
3. Create your feature branch (`git checkout -b my-new-feature`)
|
154
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
155
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
156
|
+
6. Create a new Pull Request
|
data/bin/cert
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
4
|
+
|
5
|
+
require 'cert'
|
6
|
+
require 'commander'
|
7
|
+
require 'credentials_manager/password_manager'
|
8
|
+
require 'credentials_manager/appfile_config'
|
9
|
+
|
10
|
+
HighLine.track_eof = false
|
11
|
+
|
12
|
+
class CertApplication
|
13
|
+
include Commander::Methods
|
14
|
+
|
15
|
+
def run
|
16
|
+
program :version, Cert::VERSION
|
17
|
+
program :description, 'CLI for \'cert\' - Create new iOS code signing certificates'
|
18
|
+
program :help, 'Author', 'Felix Krause <cert@krausefx.com>'
|
19
|
+
program :help, 'Website', 'http://fastlane.tools'
|
20
|
+
program :help, 'GitHub', 'https://github.com/krausefx/cert'
|
21
|
+
program :help_formatter, :compact
|
22
|
+
|
23
|
+
always_trace!
|
24
|
+
|
25
|
+
global_option '-u', '--username STRING', 'Your Apple ID username'
|
26
|
+
|
27
|
+
command :create do |c|
|
28
|
+
c.syntax = 'cert create'
|
29
|
+
c.description = 'Create new iOS code signing certificates'
|
30
|
+
|
31
|
+
c.action do |args, options|
|
32
|
+
username(options)
|
33
|
+
|
34
|
+
Cert::CertRunner.run
|
35
|
+
|
36
|
+
installed = Cert::CertChecker.is_installed?ENV["CER_FILE_PATH"]
|
37
|
+
raise "Could not find the newly generated certificate installed" unless installed
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def username(options)
|
42
|
+
user = options.username
|
43
|
+
user ||= ENV["CERT_USERNAME"]
|
44
|
+
user ||= CredentialsManager::AppfileConfig.try_fetch_value(:apple_id)
|
45
|
+
|
46
|
+
CredentialsManager::PasswordManager.shared_manager(user) if user
|
47
|
+
end
|
48
|
+
|
49
|
+
default_command :create
|
50
|
+
|
51
|
+
run!
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
CertApplication.new.run
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Cert
|
2
|
+
# This class checks if a specific certificate is installed on the current mac
|
3
|
+
class CertChecker
|
4
|
+
def self.is_installed?(path)
|
5
|
+
raise "Could not find file '#{path}'".red unless File.exists?(path)
|
6
|
+
|
7
|
+
ids = installed_identies
|
8
|
+
finger_print = sha1_fingerprint(path)
|
9
|
+
|
10
|
+
return ids.include?finger_print
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.installed_identies
|
14
|
+
available = `security find-identity -v -p codesigning`
|
15
|
+
ids = []
|
16
|
+
available.split("\n").each do |current|
|
17
|
+
(ids << current.match(/.*\) (.*) \".*/)[1]) rescue nil # the last line does not match
|
18
|
+
end
|
19
|
+
|
20
|
+
return ids
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.sha1_fingerprint(path)
|
24
|
+
result = `openssl x509 -in "#{path}" -inform der -noout -sha1 -fingerprint`
|
25
|
+
result = result.match(/SHA1 Fingerprint=(.*)/)[1]
|
26
|
+
result.gsub!(":", "")
|
27
|
+
return result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Cert
|
2
|
+
class DependencyChecker
|
3
|
+
def self.check_dependencies
|
4
|
+
self.check_xcode_select
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.check_xcode_select
|
8
|
+
unless `xcode-select -v`.include?"xcode-select version "
|
9
|
+
Helper.log.fatal '#############################################################'
|
10
|
+
Helper.log.fatal "# You have to install the Xcode commdand line tools to use cert"
|
11
|
+
Helper.log.fatal "# Install the latest version of Xcode from the AppStore"
|
12
|
+
Helper.log.fatal "# Run xcode-select --install to install the developer tools"
|
13
|
+
Helper.log.fatal '#############################################################'
|
14
|
+
raise "Run 'xcode-select --install' and start cert again"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'fastlane_core/developer_center/developer_center'
|
2
|
+
|
3
|
+
module FastlaneCore
|
4
|
+
class DeveloperCenter
|
5
|
+
CERTS_URL = "https://developer.apple.com/account/ios/certificate/certificateList.action"
|
6
|
+
CREATE_CERT_URL = "https://developer.apple.com/account/ios/certificate/certificateCreate.action"
|
7
|
+
|
8
|
+
# This will check if there is at least one of the certificates already installed on the local machine
|
9
|
+
# This will store the resulting file name in ENV 'CER_FILE_PATH' and the Cert ID in 'CER_CERTIFICATE_ID'
|
10
|
+
def run
|
11
|
+
file = find_existing_cert
|
12
|
+
if file
|
13
|
+
# We don't need to do anything :)
|
14
|
+
ENV["CER_FILE_PATH"] = file
|
15
|
+
else
|
16
|
+
create_certificate
|
17
|
+
end
|
18
|
+
rescue => ex
|
19
|
+
error_occured(ex)
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_existing_cert
|
23
|
+
visit "#{CERTS_URL}?type=distribution"
|
24
|
+
|
25
|
+
# Download all available certs to check if they are installed using the SHA1 hash
|
26
|
+
certs = code_signing_certificate
|
27
|
+
certs.each do |current|
|
28
|
+
display_id = current['certificateId']
|
29
|
+
type_id = current['certificateTypeDisplayId']
|
30
|
+
url = "/account/ios/certificate/certificateContentDownload.action?displayId=#{display_id}&type=#{type_id}"
|
31
|
+
|
32
|
+
output = File.join(TMP_FOLDER, "#{display_id}-#{type_id}.cer")
|
33
|
+
download_url(url, output)
|
34
|
+
if Cert::CertChecker.is_installed?output
|
35
|
+
# We'll use this one, since it's installed on the local machine
|
36
|
+
ENV["CER_CERTIFICATE_ID"] = display_id
|
37
|
+
Helper.log.info "Found the certificate #{display_id}-#{type_id} which is installed on the local machine. Using this one.".green
|
38
|
+
return output
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
Helper.log.info "Couldn't find an existing certificate... creating a new one"
|
43
|
+
return false
|
44
|
+
rescue => ex
|
45
|
+
error_occured(ex)
|
46
|
+
end
|
47
|
+
|
48
|
+
# This will actually create a new certificate
|
49
|
+
def create_certificate
|
50
|
+
visit CREATE_CERT_URL
|
51
|
+
wait_for_elements("form[name='certificateSave']")
|
52
|
+
|
53
|
+
Helper.log.info "Creating a new code signing certificate"
|
54
|
+
|
55
|
+
# select certificate type
|
56
|
+
app_store_toggle = first("input#type-iosNoOCSP")
|
57
|
+
if !!app_store_toggle['disabled']
|
58
|
+
# Limit of certificates already reached
|
59
|
+
raise "Could not create another certificate, reached the maximum number of available certificates.".red
|
60
|
+
end
|
61
|
+
|
62
|
+
app_store_toggle.click
|
63
|
+
|
64
|
+
click_next # submit the certificate type
|
65
|
+
sleep 2
|
66
|
+
click_next # information about how to upload the file (no action required on this step)
|
67
|
+
|
68
|
+
cert_signing_request = Cert::SigningRequest.get_path
|
69
|
+
Helper.log.info "Uploading the cert signing request '#{cert_signing_request}'"
|
70
|
+
|
71
|
+
|
72
|
+
wait_for_elements("input[name='upload']").first.set cert_signing_request # upload the cert signing request
|
73
|
+
sleep 1
|
74
|
+
click_next
|
75
|
+
|
76
|
+
sleep 3
|
77
|
+
|
78
|
+
while all(:css, '.loadingMessage').count > 0
|
79
|
+
Helper.log.debug "Waiting for iTC to generate the profile"
|
80
|
+
sleep 2
|
81
|
+
end
|
82
|
+
|
83
|
+
Helper.log.info "Downloading newly generated certificate"
|
84
|
+
sleep 2
|
85
|
+
|
86
|
+
# Now download the certificate
|
87
|
+
download_button = wait_for_elements(".button.small.blue").first
|
88
|
+
url = download_button['href']
|
89
|
+
|
90
|
+
path = File.join(TMP_FOLDER, "certificate.cer")
|
91
|
+
download_url(url, path)
|
92
|
+
|
93
|
+
certificate_id = url.match(/.*displayId=(.*)&type.*/)[1]
|
94
|
+
|
95
|
+
ENV["CER_FILE_PATH"] = path
|
96
|
+
ENV["CER_CERTIFICATE_ID"] = certificate_id
|
97
|
+
Helper.log.info "Successfully downloaded latest .cer file to '#{path}' (#{certificate_id})".green
|
98
|
+
|
99
|
+
Cert::KeychainImporter::import_file(path)
|
100
|
+
rescue => ex
|
101
|
+
error_occured(ex)
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
private
|
106
|
+
def download_url(url, output_path)
|
107
|
+
host = Capybara.current_session.current_host
|
108
|
+
url = [host, url].join('')
|
109
|
+
Helper.log.info "Downloading URL: '#{url}'"
|
110
|
+
|
111
|
+
cookieString = ""
|
112
|
+
page.driver.cookies.each do |key, cookie|
|
113
|
+
cookieString << "#{cookie.name}=#{cookie.value};" # append all known cookies
|
114
|
+
end
|
115
|
+
data = open(url, {'Cookie' => cookieString}).read
|
116
|
+
|
117
|
+
raise "Something went wrong when downloading the certificate" unless data
|
118
|
+
|
119
|
+
dataWritten = File.write(output_path, data)
|
120
|
+
|
121
|
+
if dataWritten == 0
|
122
|
+
raise "Can't write to #{output_path}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Returns a hash, that contains information about the iOS certificate
|
127
|
+
# @example
|
128
|
+
# {"certRequestId"=>"B23Q2P396B",
|
129
|
+
# "name"=>"SunApps GmbH",
|
130
|
+
# "statusString"=>"Issued",
|
131
|
+
# "expirationDate"=>"2015-11-25T22:45:50Z",
|
132
|
+
# "expirationDateString"=>"Nov 25, 2015",
|
133
|
+
# "ownerType"=>"team",
|
134
|
+
# "ownerName"=>"SunApps GmbH",
|
135
|
+
# "ownerId"=>"....",
|
136
|
+
# "canDownload"=>true,
|
137
|
+
# "canRevoke"=>true,
|
138
|
+
# "certificateId"=>"....",
|
139
|
+
# "certificateStatusCode"=>0,
|
140
|
+
# "certRequestStatusCode"=>4,
|
141
|
+
# "certificateTypeDisplayId"=>"...",
|
142
|
+
# "serialNum"=>"....",
|
143
|
+
# "typeString"=>"iOS Distribution"},
|
144
|
+
def code_signing_certificate
|
145
|
+
certs_url = "https://developer.apple.com/account/ios/certificate/certificateList.action?type=distribution"
|
146
|
+
visit certs_url
|
147
|
+
|
148
|
+
certificateDataURL = wait_for_variable('certificateDataURL')
|
149
|
+
certificateRequestTypes = wait_for_variable('certificateRequestTypes')
|
150
|
+
certificateStatuses = wait_for_variable('certificateStatuses')
|
151
|
+
|
152
|
+
url = [certificateDataURL, certificateRequestTypes, certificateStatuses].join('')
|
153
|
+
|
154
|
+
# https://developer.apple.com/services-account/.../account/ios/certificate/listCertRequests.action?content-type=application/x-www-form-urlencoded&accept=application/json&requestId=...&userLocale=en_US&teamId=...&types=...&status=4&certificateStatus=0&type=distribution
|
155
|
+
|
156
|
+
available = []
|
157
|
+
|
158
|
+
certs = post_ajax(url)['certRequests']
|
159
|
+
certs.each do |current_cert|
|
160
|
+
if current_cert['typeString'] == 'iOS Distribution'
|
161
|
+
# The other profiles are push profiles
|
162
|
+
# We only care about the distribution profile
|
163
|
+
available << current_cert # mostly we only care about the 'certificateId'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
return available
|
168
|
+
end
|
169
|
+
|
170
|
+
def click_next
|
171
|
+
wait_for_elements('.button.small.blue.right.submit').last.click
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Cert
|
2
|
+
class KeychainImporter
|
3
|
+
def self.import_file(path)
|
4
|
+
raise "Could not find file '#{path}'".red unless File.exists?(path)
|
5
|
+
keychain = ENV["CERT_KEYCHAIN_PATH"] || "#{Dir.home}/Library/Keychains/login.keychain"
|
6
|
+
|
7
|
+
puts `security import '#{path}' -k '#{keychain}'`
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Cert
|
2
|
+
class SigningRequest
|
3
|
+
def self.get_path
|
4
|
+
self.generate
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.generate
|
8
|
+
Helper.log.info "Creating a signing certificate for you.".green
|
9
|
+
key = OpenSSL::PKey::RSA.new 2048
|
10
|
+
|
11
|
+
# Generate CSR
|
12
|
+
csr = OpenSSL::X509::Request.new
|
13
|
+
csr.version = 0
|
14
|
+
csr.subject = OpenSSL::X509::Name.new([
|
15
|
+
['CN', "PEM", OpenSSL::ASN1::UTF8STRING]
|
16
|
+
])
|
17
|
+
csr.public_key = key.public_key
|
18
|
+
csr.sign key, OpenSSL::Digest::SHA1.new
|
19
|
+
|
20
|
+
path = File.join(TMP_FOLDER, 'CertCertificateSigningRequest.certSigningRequest')
|
21
|
+
private_key_path = File.join(TMP_FOLDER, 'private_key.p12')
|
22
|
+
File.write(path, csr.to_pem)
|
23
|
+
File.write(private_key_path, key)
|
24
|
+
|
25
|
+
# Import the private key into the Keychain
|
26
|
+
puts `chmod 600 '#{private_key_path}'` # otherwise we're not allowed to import the private key
|
27
|
+
KeychainImporter::import_file(private_key_path)
|
28
|
+
|
29
|
+
Helper.log.info "Successfully generated .certSigningRequest at path '#{path}'".green
|
30
|
+
return path
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/cert/version.rb
ADDED
data/lib/cert.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'cert/version'
|
2
|
+
require 'cert/dependency_checker'
|
3
|
+
require 'cert/developer_center'
|
4
|
+
require 'cert/cert_runner'
|
5
|
+
require 'cert/cert_checker'
|
6
|
+
require 'cert/signing_request'
|
7
|
+
require 'cert/keychain_importer'
|
8
|
+
|
9
|
+
require 'fastlane_core'
|
10
|
+
|
11
|
+
module Cert
|
12
|
+
TMP_FOLDER = "/tmp/cert/"
|
13
|
+
FileUtils.mkdir_p TMP_FOLDER
|
14
|
+
|
15
|
+
Helper = FastlaneCore::Helper # you gotta love Ruby: Helper.* should use the Helper class contained in FastlaneCore
|
16
|
+
|
17
|
+
ENV['FASTLANE_TEAM_ID'] ||= ENV["CERT_TEAM_ID"]
|
18
|
+
|
19
|
+
FastlaneCore::UpdateChecker.verify_latest_version('cert', Cert::VERSION)
|
20
|
+
DependencyChecker.check_dependencies
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cert
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Felix Krause
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fastlane_core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.1.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.1.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.8.7.4
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.8.7.4
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.19.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.19.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: codeclimate-test-reporter
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: Create new iOS code signing certificates
|
126
|
+
email:
|
127
|
+
- cert@krausefx.com
|
128
|
+
executables:
|
129
|
+
- cert
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- LICENSE
|
134
|
+
- README.md
|
135
|
+
- bin/cert
|
136
|
+
- lib/cert.rb
|
137
|
+
- lib/cert/cert_checker.rb
|
138
|
+
- lib/cert/cert_runner.rb
|
139
|
+
- lib/cert/dependency_checker.rb
|
140
|
+
- lib/cert/developer_center.rb
|
141
|
+
- lib/cert/keychain_importer.rb
|
142
|
+
- lib/cert/signing_request.rb
|
143
|
+
- lib/cert/version.rb
|
144
|
+
homepage: http://fastlane.tools
|
145
|
+
licenses:
|
146
|
+
- MIT
|
147
|
+
metadata: {}
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
require_paths:
|
151
|
+
- lib
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - '>='
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: 2.0.0
|
157
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - '>='
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
requirements: []
|
163
|
+
rubyforge_project:
|
164
|
+
rubygems_version: 2.2.2
|
165
|
+
signing_key:
|
166
|
+
specification_version: 4
|
167
|
+
summary: Create new iOS code signing certificates
|
168
|
+
test_files: []
|
169
|
+
has_rdoc:
|