eas-cli
Version:
EAS command line tool
116 lines (115 loc) • 5.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateProvisioningProfileAsync = void 0;
const tslib_1 = require("tslib");
const assert_1 = tslib_1.__importDefault(require("assert"));
const crypto_1 = tslib_1.__importDefault(require("crypto"));
const minimatch_1 = tslib_1.__importDefault(require("minimatch"));
const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
const generated_1 = require("../../../graphql/generated");
const log_1 = tslib_1.__importDefault(require("../../../log"));
const target_1 = require("../../../project/ios/target");
const provisioningProfile_1 = require("../appstore/provisioningProfile");
const p12Certificate_1 = require("../utils/p12Certificate");
const provisioningProfile_2 = require("../utils/provisioningProfile");
async function validateProvisioningProfileAsync(ctx, target, app, buildCredentials) {
if (!buildCredentials?.distributionCertificate || !buildCredentials.provisioningProfile) {
return false;
}
const resultWithoutApple = validateProvisioningProfileWithoutApple(app, buildCredentials);
if (!resultWithoutApple) {
return false;
}
if (!ctx.appStore.authCtx) {
log_1.default.warn("Skipping Provisioning Profile validation on Apple Servers because we aren't authenticated.");
return true;
}
return await validateProvisioningProfileWithAppleAsync(ctx, target, app, buildCredentials);
}
exports.validateProvisioningProfileAsync = validateProvisioningProfileAsync;
function validateProvisioningProfileWithoutApple(app, { provisioningProfile, distributionCertificate }) {
try {
const profilePlist = (0, provisioningProfile_2.parse)((0, nullthrows_1.default)(provisioningProfile?.provisioningProfile));
let distCertFingerprint;
try {
distCertFingerprint = (0, p12Certificate_1.getP12CertFingerprint)((0, nullthrows_1.default)(distributionCertificate?.certificateP12), (0, nullthrows_1.default)(distributionCertificate?.certificatePassword));
}
catch (e) {
log_1.default.warn(`Failed to calculate fingerprint for Distribution Certificate: ${e.toString()}`);
return false;
}
const devCertStatus = validateDeveloperCertificate(profilePlist, distCertFingerprint);
if (!devCertStatus) {
return false;
}
const bundleIdentifierStatus = validateBundleIdentifier(profilePlist, app.bundleIdentifier);
if (!bundleIdentifierStatus) {
return false;
}
const isExpired = new Date(profilePlist['ExpirationDate']) <= new Date();
if (isExpired) {
log_1.default.warn('Provisioning Profile has expired.');
return false;
}
}
catch {
log_1.default.warn('Provisioning Profile is malformed.');
return false;
}
return true;
}
async function validateProvisioningProfileWithAppleAsync(ctx, target, app, buildCredentials) {
(0, assert_1.default)(buildCredentials.provisioningProfile, 'Provisioning Profile must be defined');
const { developerPortalIdentifier, provisioningProfile } = buildCredentials.provisioningProfile;
const applePlatform = (0, target_1.getApplePlatformFromTarget)(target);
const profilesFromApple = await ctx.appStore.listProvisioningProfilesAsync(app.bundleIdentifier, applePlatform, buildCredentials.iosDistributionType === generated_1.IosDistributionType.AdHoc
? provisioningProfile_1.ProfileClass.Adhoc
: provisioningProfile_1.ProfileClass.General);
const configuredProfileFromApple = profilesFromApple.find(appleProfile => developerPortalIdentifier
? appleProfile.provisioningProfileId === developerPortalIdentifier
: appleProfile.provisioningProfile === provisioningProfile);
if (!configuredProfileFromApple) {
log_1.default.warn(`Provisioning profile (id: ${developerPortalIdentifier}) does not exist in Apple Developer Portal`);
return false;
}
if (configuredProfileFromApple.status !== 'ACTIVE') {
log_1.default.warn(`Provisioning profile (id: ${developerPortalIdentifier}) is no longer valid`);
return false;
}
return true;
}
function validateDeveloperCertificate(plistData, distCertFingerprint) {
const devCertBase64 = plistData?.DeveloperCertificates?.[0];
if (!devCertBase64) {
log_1.default.warn('Missing certificate fingerprint in provisioning profile.');
return false;
}
const devCertBuffer = Buffer.from(devCertBase64, 'base64');
const devCertFingerprint = crypto_1.default
.createHash('sha1')
.update(devCertBuffer)
.digest('hex')
.toUpperCase();
if (devCertFingerprint !== distCertFingerprint) {
log_1.default.warn('Provisioning profile is not associated with uploaded Distribution Certificate.');
return false;
}
return true;
}
function validateBundleIdentifier(plistData, expectedBundleIdentifier) {
const actualApplicationIdentifier = plistData.Entitlements?.['application-identifier'];
if (!actualApplicationIdentifier) {
log_1.default.warn('Missing application-identifier in provisioning profile entitlements');
return false;
}
const actualBundleIdentifier = /\.(.+)/.exec(actualApplicationIdentifier)?.[1];
if (!actualBundleIdentifier) {
log_1.default.warn('Malformed application-identifier field in provisioning profile');
return false;
}
if (!(0, minimatch_1.default)(expectedBundleIdentifier, actualBundleIdentifier)) {
log_1.default.warn(`Wrong bundleIdentifier found in provisioning profile; expected: ${expectedBundleIdentifier}, found (in provisioning profile): ${actualBundleIdentifier}`);
return false;
}
return true;
}