Class: Spaceship::Certificate

Inherits:
Base
  • Object
show all
Defined in:
lib/spaceship/certificate.rb

Overview

Represents a certificate from the Apple Developer Portal.

This can either be a code signing identity or a push profile

Defined Under Namespace

Classes: ApplePay, Development, DevelopmentPush, InHouse, Passbook, Production, ProductionPush, PushCertificate, VoipPush, WebsitePush

Constant Summary collapse

CERTIFICATE_TYPE_IDS =
{
  "5QPB9NHCEI" => Development,
  "R58UK2EWSO" => Production,
  "9RQEK7MSXA" => InHouse,
  "LA30L5BJEU" => Certificate,
  "BKLRAVXMGM" => DevelopmentPush,
  "3BQKVH9I2X" => ProductionPush,
  "Y3B2F3TYSI" => Passbook,
  "3T2ZP62QW8" => WebsitePush,
  "E5D663CMZW" => WebsitePush,
  "4APLUP237T" => ApplePay
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

attr_mapping, #client, #initialize, #inspect, method_missing, remap_keys!, set_client

Constructor Details

This class inherits a constructor from Spaceship::Base

Instance Attribute Details

#createdDate

Returns The date and time when the certificate was created.

Examples:

2015-04-01 21:24:00 UTC

Returns:

  • (Date)

    The date and time when the certificate was created



28
29
30
# File 'lib/spaceship/certificate.rb', line 28

def created
  @created
end

#expiresDate

Returns The date and time when the certificate will expire.

Examples:

2016-04-01 21:24:00 UTC

Returns:

  • (Date)

    The date and time when the certificate will expire



33
34
35
# File 'lib/spaceship/certificate.rb', line 33

def expires
  @expires
end

#idString

Returns The ID given from the developer portal. You’ll probably not need it.

Examples:

"P577TH3PAA"

Returns:

  • (String)

    The ID given from the developer portal. You’ll probably not need it.



11
12
13
# File 'lib/spaceship/certificate.rb', line 11

def id
  @id
end

#nameString

Returns The name of the certificate.

Examples:

Company

"SunApps GmbH"

Push Profile

"com.krausefx.app"

Returns:

  • (String)

    The name of the certificate



18
19
20
# File 'lib/spaceship/certificate.rb', line 18

def name
  @name
end

#owner_idString

Returns The ID of the owner, that can be used to fetch more information.

Examples:

"75B83SPLAA"

Returns:

  • (String)

    The ID of the owner, that can be used to fetch more information



56
57
58
# File 'lib/spaceship/certificate.rb', line 56

def owner_id
  @owner_id
end

#owner_nameString

Returns The name of the owner.

Examples:

Code Signing Identity (usually the company name)

"SunApps Gmbh"

Push Certificate (the name of your App ID)

"Awesome App"

Returns:

  • (String)

    The name of the owner



50
51
52
# File 'lib/spaceship/certificate.rb', line 50

def owner_name
  @owner_name
end

#owner_typeString

Returns The owner type that defines if it’s a push profile or a code signing identity.

Examples:

Code Signing Identity

"team"

Push Certificate

"bundle"

Returns:

  • (String)

    The owner type that defines if it’s a push profile or a code signing identity



42
43
44
# File 'lib/spaceship/certificate.rb', line 42

def owner_type
  @owner_type
end

#statusString

Returns Status of the certificate.

Examples:

"Issued"

Returns:

  • (String)

    Status of the certificate



23
24
25
# File 'lib/spaceship/certificate.rb', line 23

def status
  @status
end

#type_display_idString

Indicates the type of this certificate which is automatically used to determine the class of the certificate. Available values listed in CERTIFICATE_TYPE_IDS

Examples:

Production Certificate

"R58UK2EWSO"

Development Certificate

"5QPB9NHCEI"

Returns:

  • (String)

    The type of the certificate



66
67
68
# File 'lib/spaceship/certificate.rb', line 66

def type_display_id
  @type_display_id
end

Class Method Details

.allArray

Returns all certificates of this account. If this is called from a subclass of Certificate, this will only include certificates matching the current type.

Returns:

  • (Array)

    Returns all certificates of this account. If this is called from a subclass of Certificate, this will only include certificates matching the current type.



196
197
198
199
200
201
202
203
204
205
206
# File 'lib/spaceship/certificate.rb', line 196

def all
  if (self == Certificate) # are we the base-class?
    types = CERTIFICATE_TYPE_IDS.keys
  else
    types = [CERTIFICATE_TYPE_IDS.key(self)]
  end

  client.certificates(types).map do |cert|
    factory(cert)
  end
end

.create!(csr: nil, bundle_id: nil) ⇒ Device

Generate a new certificate based on a code certificate signing request

Examples:

# Create a new certificate signing request
csr, pkey = Spaceship::Certificate.create_certificate_signing_request

# Use the signing request to create a new distribution certificate
Spaceship::Certificate::Production.create!(csr: csr)

Parameters:

  • csr (OpenSSL::X509::Request) (defaults to: nil)

    (required): The certificate signing request to use. Get one using ‘create_certificate_signing_request`

  • bundle_id (String) (defaults to: nil)

    (optional): The app identifier this certificate is for. This value is only needed if you create a push profile. For normal code signing certificates, you must only pass a certificate signing request.

Returns:

  • (Device)

    : The newly created device



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/spaceship/certificate.rb', line 228

def create!(csr: nil, bundle_id: nil)
  type = CERTIFICATE_TYPE_IDS.key(self)

  # look up the app_id by the bundle_id
  if bundle_id
    app = Spaceship::App.find(bundle_id)
    raise "Could not find app with bundle id '#{bundle_id}'" unless app
    app_id = app.app_id
  end

  # ensure csr is a OpenSSL::X509::Request
  csr = OpenSSL::X509::Request.new(csr) if csr.is_a?(String)

  # if this succeeds, we need to save the .cer and the private key in keychain access or wherever they go in linux
  response = client.create_certificate!(type, csr.to_pem, app_id)
  # munge the response to make it work for the factory
  response['certificateTypeDisplayId'] = response['certificateType']['certificateTypeDisplayId']
  self.new(response)
end

.create_certificate_signing_requestObject

Create a new code signing request that can be used to generate a new certificate

Examples:

Create a new certificate signing request
csr, pkey = Spaceship.certificate.create_certificate_signing_request

# Use the signing request to create a new distribution certificate
Spaceship.certificate.production.create!(csr: csr)


142
143
144
145
146
147
148
149
150
151
152
# File 'lib/spaceship/certificate.rb', line 142

def create_certificate_signing_request
  key = OpenSSL::PKey::RSA.new 2048
  csr = OpenSSL::X509::Request.new
  csr.version = 0
  csr.subject = OpenSSL::X509::Name.new([
    ['CN', 'PEM', OpenSSL::ASN1::UTF8STRING]
  ])
  csr.public_key = key.public_key
  csr.sign(key, OpenSSL::Digest::SHA1.new)
  return [csr, key]
end

.factory(attrs) ⇒ Object

Create a new object based on a hash. This is used to create a new object based on the server response.



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/spaceship/certificate.rb', line 156

def factory(attrs)
  # Example:
  # => {"name"=>"iOS Distribution: SunApps GmbH",
  #  "certificateId"=>"XC5PH8DAAA",
  #  "serialNumber"=>"797E732CCE8B7AAA",
  #  "status"=>"Issued",
  #  "statusCode"=>0,
  #  "expirationDate"=>#<DateTime: 2015-11-25T22:45:50+00:00 ((2457352j,81950s,0n),+0s,2299161j)>,
  #  "certificatePlatform"=>"ios",
  #  "certificateType"=>
  #   {"certificateTypeDisplayId"=>"R58UK2EAAA",
  #    "name"=>"iOS Distribution",
  #    "platform"=>"ios",
  #    "permissionType"=>"distribution",
  #    "distributionType"=>"store",
  #    "distributionMethod"=>"app",
  #    "ownerType"=>"team",
  #    "daysOverlap"=>364,
  #    "maxActive"=>2}}

  if attrs['certificateType']
    # On some accounts this is nested, so we need to flatten it
    attrs.merge!(attrs['certificateType'])
    attrs.delete('certificateType')
  end

  # Parse the dates
  attrs['expirationDate'] = (Time.parse(attrs['expirationDate']) rescue attrs['expirationDate'])
  attrs['dateCreated'] = (Time.parse(attrs['dateCreated']) rescue attrs['dateCreated'])

  # Here we go
  klass = CERTIFICATE_TYPE_IDS[attrs['certificateTypeDisplayId']]
  klass ||= Certificate
  klass.client = @client
  klass.new(attrs)
end

.find(certificate_id) ⇒ Certificate

Returns Find a certificate based on the ID of the certificate.

Returns:

  • (Certificate)

    Find a certificate based on the ID of the certificate.



209
210
211
212
213
# File 'lib/spaceship/certificate.rb', line 209

def find(certificate_id)
  all.find do |c|
    c.id == certificate_id
  end
end

Instance Method Details

#downloadOpenSSL::X509::Certificate

Returns Downloads and parses the certificate.

Returns:

  • (OpenSSL::X509::Certificate)

    Downloads and parses the certificate



257
258
259
# File 'lib/spaceship/certificate.rb', line 257

def download
  OpenSSL::X509::Certificate.new(download_raw)
end

#download_rawString

Returns Download the raw data of the certificate without parsing.

Returns:

  • (String)

    Download the raw data of the certificate without parsing



252
253
254
# File 'lib/spaceship/certificate.rb', line 252

def download_raw
  client.download_certificate(id, type_display_id)
end

#is_push?Bool

Returns : Is this certificate a push profile for apps?.

Returns:

  • (Bool)

    : Is this certificate a push profile for apps?



267
268
269
# File 'lib/spaceship/certificate.rb', line 267

def is_push?
  self.kind_of?PushCertificate
end

#revoke!Object

Revoke the certificate. You shouldn’t use this method probably.



262
263
264
# File 'lib/spaceship/certificate.rb', line 262

def revoke!
  client.revoke_certificate!(id, type_display_id)
end