@expo/cli 0.4.9 → 0.4.11

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.
package/build/bin/cli CHANGED
@@ -121,7 +121,7 @@ const args = (0, _arg).default({
121
121
  });
122
122
  if (args["--version"]) {
123
123
  // Version is added in the build script.
124
- console.log("0.4.9");
124
+ console.log("0.4.11");
125
125
  process.exit(0);
126
126
  }
127
127
  if (args["--non-interactive"]) {
@@ -248,7 +248,7 @@ commands[command]().then((exec)=>{
248
248
  logEventAsync("action", {
249
249
  action: `expo ${command}`,
250
250
  source: "expo/cli",
251
- source_version: "0.4.9"
251
+ source_version: "0.4.11"
252
252
  });
253
253
  });
254
254
 
@@ -130,7 +130,7 @@ async function createHostInfoAsync() {
130
130
  host: await _userSettings.default.getAnonymousIdentifierAsync(),
131
131
  server: "expo",
132
132
  // Defined in the build step
133
- serverVersion: "0.4.9",
133
+ serverVersion: "0.4.11",
134
134
  serverDriver: _manifestMiddleware.DEVELOPER_TOOL,
135
135
  serverOS: _os.default.platform(),
136
136
  serverOSVersion: _os.default.release()
@@ -94,7 +94,7 @@ async function logEventAsync(event, properties = {}) {
94
94
  }
95
95
  const { userId , deviceId } = identifyData;
96
96
  const commonEventProperties = {
97
- source_version: "0.4.9",
97
+ source_version: "0.4.11",
98
98
  source: "expo"
99
99
  };
100
100
  const identity = {
@@ -135,7 +135,7 @@ function getContext() {
135
135
  },
136
136
  app: {
137
137
  name: "expo",
138
- version: "0.4.9"
138
+ version: "0.4.11"
139
139
  },
140
140
  ci: ciInfo.isCI ? {
141
141
  name: ciInfo.name,
@@ -280,7 +280,7 @@ async function fetchAndCacheNewDevelopmentCodeSigningInfoAsync(easProjectId) {
280
280
  function signManifestString(stringifiedManifest, codeSigningInfo) {
281
281
  const privateKey = (0, _codeSigningCertificates).convertPrivateKeyPEMToPrivateKey(codeSigningInfo.privateKey);
282
282
  const certificate = (0, _codeSigningCertificates).convertCertificatePEMToCertificate(codeSigningInfo.certificateForPrivateKey);
283
- return (0, _codeSigningCertificates).signStringRSASHA256AndVerify(privateKey, certificate, stringifiedManifest);
283
+ return (0, _codeSigningCertificates).signBufferRSASHA256AndVerify(privateKey, certificate, Buffer.from(stringifiedManifest, "utf8"));
284
284
  }
285
285
 
286
286
  //# sourceMappingURL=codesigning.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/codesigning.ts"],"sourcesContent":["import {\n convertCertificatePEMToCertificate,\n convertKeyPairToPEM,\n convertCSRToCSRPEM,\n generateKeyPair,\n generateCSR,\n convertPrivateKeyPEMToPrivateKey,\n validateSelfSignedCertificate,\n signStringRSASHA256AndVerify,\n} from '@expo/code-signing-certificates';\nimport { ExpoConfig } from '@expo/config';\nimport { getExpoHomeDirectory } from '@expo/config/build/getUserState';\nimport JsonFile, { JSONObject } from '@expo/json-file';\nimport { promises as fs } from 'fs';\nimport { pki as PKI } from 'node-forge';\nimport path from 'path';\nimport { Dictionary, parseDictionary } from 'structured-headers';\n\nimport { getExpoGoIntermediateCertificateAsync } from '../api/getExpoGoIntermediateCertificate';\nimport { getProjectDevelopmentCertificateAsync } from '../api/getProjectDevelopmentCertificate';\nimport { APISettings } from '../api/settings';\nimport * as Log from '../log';\nimport { CommandError } from './errors';\n\nexport type CodeSigningInfo = {\n keyId: string;\n privateKey: string;\n certificateForPrivateKey: string;\n /**\n * Chain of certificates to serve in the manifest multipart body \"certificate_chain\" part.\n * The leaf certificate must be the 0th element of the array, followed by any intermediate certificates\n * necessary to evaluate the chain of trust ending in the implicitly trusted root certificate embedded in\n * the client.\n *\n * An empty array indicates that there is no need to serve the certificate chain in the multipart response.\n */\n certificateChainForResponse: string[];\n};\n\ntype StoredDevelopmentExpoRootCodeSigningInfo = {\n easProjectId: string | null;\n privateKey: string | null;\n certificateChain: string[] | null;\n};\nconst DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME = 'development-code-signing-settings.json';\n\nexport function getDevelopmentCodeSigningDirectory(): string {\n return path.join(getExpoHomeDirectory(), 'codesigning');\n}\n\nfunction getProjectDevelopmentCodeSigningInfoFile<T extends JSONObject>(defaults: T) {\n function getFile(easProjectId: string): JsonFile<T> {\n const filePath = path.join(\n getDevelopmentCodeSigningDirectory(),\n easProjectId,\n DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME\n );\n return new JsonFile<T>(filePath);\n }\n\n async function readAsync(easProjectId: string): Promise<T> {\n let projectSettings;\n try {\n projectSettings = await getFile(easProjectId).readAsync();\n } catch {\n projectSettings = await getFile(easProjectId).writeAsync(defaults, { ensureDir: true });\n }\n // Set defaults for any missing fields\n return { ...defaults, ...projectSettings };\n }\n\n async function setAsync(easProjectId: string, json: Partial<T>): Promise<T> {\n try {\n return await getFile(easProjectId).mergeAsync(json, {\n cantReadFileDefault: defaults,\n });\n } catch {\n return await getFile(easProjectId).writeAsync(\n {\n ...defaults,\n ...json,\n },\n { ensureDir: true }\n );\n }\n }\n\n return {\n getFile,\n readAsync,\n setAsync,\n };\n}\n\nexport const DevelopmentCodeSigningInfoFile =\n getProjectDevelopmentCodeSigningInfoFile<StoredDevelopmentExpoRootCodeSigningInfo>({\n easProjectId: null,\n privateKey: null,\n certificateChain: null,\n });\n\n/**\n * Get info necessary to generate a response `expo-signature` header given a project and incoming request `expo-expect-signature` header.\n * This only knows how to serve two code signing keyids:\n * - `expo-root` indicates that it should use a development certificate in the `expo-root` chain. See {@link getExpoRootDevelopmentCodeSigningInfoAsync}\n * - <developer's expo-updates keyid> indicates that it should sign with the configured certificate. See {@link getProjectCodeSigningCertificateAsync}\n */\nexport async function getCodeSigningInfoAsync(\n exp: ExpoConfig,\n expectSignatureHeader: string | null,\n privateKeyPath: string | undefined\n): Promise<CodeSigningInfo | null> {\n if (!expectSignatureHeader) {\n return null;\n }\n\n let parsedExpectSignature: Dictionary;\n try {\n parsedExpectSignature = parseDictionary(expectSignatureHeader);\n } catch {\n throw new CommandError('Invalid value for expo-expect-signature header');\n }\n\n const expectedKeyIdOuter = parsedExpectSignature.get('keyid');\n if (!expectedKeyIdOuter) {\n throw new CommandError('keyid not present in expo-expect-signature header');\n }\n\n const expectedKeyId = expectedKeyIdOuter[0];\n if (typeof expectedKeyId !== 'string') {\n throw new CommandError(\n `Invalid value for keyid in expo-expect-signature header: ${expectedKeyId}`\n );\n }\n\n let expectedAlg: string | null = null;\n const expectedAlgOuter = parsedExpectSignature.get('alg');\n if (expectedAlgOuter) {\n const expectedAlgTemp = expectedAlgOuter[0];\n if (typeof expectedAlgTemp !== 'string') {\n throw new CommandError('Invalid value for alg in expo-expect-signature header');\n }\n expectedAlg = expectedAlgTemp;\n }\n\n if (expectedKeyId === 'expo-root') {\n return await getExpoRootDevelopmentCodeSigningInfoAsync(exp);\n } else if (expectedKeyId === 'expo-go') {\n throw new CommandError(\n 'Invalid certificate requested: cannot sign with embedded keyid=expo-go key'\n );\n } else {\n return await getProjectCodeSigningCertificateAsync(\n exp,\n privateKeyPath,\n expectedKeyId,\n expectedAlg\n );\n }\n}\n\n/**\n * Get a development code signing certificate for the expo-root -> expo-go -> (development certificate) certificate chain.\n * This requires the user be logged in and online, otherwise try to use the cached development certificate.\n */\nasync function getExpoRootDevelopmentCodeSigningInfoAsync(\n exp: ExpoConfig\n): Promise<CodeSigningInfo | null> {\n const easProjectId = exp.extra?.eas?.projectId;\n // can't check for scope key validity since scope key is derived on the server from projectId and we may be offline.\n // we rely upon the client certificate check to validate the scope key\n if (!easProjectId) {\n Log.warn('No project ID specified in app.json, unable to sign manifest');\n return null;\n }\n\n const developmentCodeSigningInfoFromFile = await DevelopmentCodeSigningInfoFile.readAsync(\n easProjectId\n );\n const validatedCodeSigningInfo = validateStoredDevelopmentExpoRootCertificateCodeSigningInfo(\n developmentCodeSigningInfoFromFile,\n easProjectId\n );\n\n // 1. If online, ensure logged in, generate key pair and CSR, fetch and cache certificate chain for projectId\n // (overwriting existing dev cert in case projectId changed or it has expired)\n if (!APISettings.isOffline) {\n try {\n return await fetchAndCacheNewDevelopmentCodeSigningInfoAsync(easProjectId);\n } catch (e) {\n if (validatedCodeSigningInfo) {\n Log.warn(\n 'There was an error fetching the Expo development certificate, falling back to cached certificate'\n );\n return validatedCodeSigningInfo;\n } else {\n throw e;\n }\n }\n }\n\n // 2. check for cached cert/private key matching projectId and scopeKey of project, if found and valid return private key and cert chain including expo-go cert\n if (validatedCodeSigningInfo) {\n return validatedCodeSigningInfo;\n }\n\n // 3. if offline, return null\n Log.warn('Offline and no cached development certificate found, unable to sign manifest');\n return null;\n}\n\n/**\n * Get the certificate configured for expo-updates for this project.\n */\nasync function getProjectCodeSigningCertificateAsync(\n exp: ExpoConfig,\n privateKeyPath: string | undefined,\n expectedKeyId: string,\n expectedAlg: string | null\n): Promise<CodeSigningInfo | null> {\n const codeSigningCertificatePath = exp.updates?.codeSigningCertificate;\n if (!codeSigningCertificatePath) {\n return null;\n }\n\n if (!privateKeyPath) {\n throw new CommandError(\n 'Must specify --private-key-path argument to sign development manifest for requested code signing key'\n );\n }\n\n const codeSigningMetadata = exp.updates?.codeSigningMetadata;\n if (!codeSigningMetadata) {\n throw new CommandError(\n 'Must specify \"codeSigningMetadata\" under the \"updates\" field of your app config file to use EAS code signing'\n );\n }\n\n const { alg, keyid } = codeSigningMetadata;\n if (!alg || !keyid) {\n throw new CommandError(\n 'Must specify \"keyid\" and \"alg\" in the \"codeSigningMetadata\" field under the \"updates\" field of your app config file to use EAS code signing'\n );\n }\n\n if (expectedKeyId !== keyid) {\n throw new CommandError(`keyid mismatch: client=${expectedKeyId}, project=${keyid}`);\n }\n\n if (expectedAlg && expectedAlg !== alg) {\n throw new CommandError(`\"alg\" field mismatch (client=${expectedAlg}, project=${alg})`);\n }\n\n const { privateKeyPEM, certificatePEM } =\n await getProjectPrivateKeyAndCertificateFromFilePathsAsync({\n codeSigningCertificatePath,\n privateKeyPath,\n });\n\n return {\n keyId: keyid,\n privateKey: privateKeyPEM,\n certificateForPrivateKey: certificatePEM,\n certificateChainForResponse: [],\n };\n}\n\nasync function readFileWithErrorAsync(path: string, errorMessage: string): Promise<string> {\n try {\n return await fs.readFile(path, 'utf8');\n } catch {\n throw new CommandError(errorMessage);\n }\n}\n\nasync function getProjectPrivateKeyAndCertificateFromFilePathsAsync({\n codeSigningCertificatePath,\n privateKeyPath,\n}: {\n codeSigningCertificatePath: string;\n privateKeyPath: string;\n}): Promise<{ privateKeyPEM: string; certificatePEM: string }> {\n const [codeSigningCertificatePEM, privateKeyPEM] = await Promise.all([\n readFileWithErrorAsync(\n codeSigningCertificatePath,\n `Code signing certificate cannot be read from path: ${codeSigningCertificatePath}`\n ),\n readFileWithErrorAsync(\n privateKeyPath,\n `Code signing private key cannot be read from path: ${privateKeyPath}`\n ),\n ]);\n\n const privateKey = convertPrivateKeyPEMToPrivateKey(privateKeyPEM);\n const certificate = convertCertificatePEMToCertificate(codeSigningCertificatePEM);\n validateSelfSignedCertificate(certificate, {\n publicKey: certificate.publicKey as PKI.rsa.PublicKey,\n privateKey,\n });\n\n return { privateKeyPEM, certificatePEM: codeSigningCertificatePEM };\n}\n\n/**\n * Validate that the cached code signing info is still valid for the current project and\n * that it hasn't expired. If invalid, return null.\n */\nfunction validateStoredDevelopmentExpoRootCertificateCodeSigningInfo(\n codeSigningInfo: StoredDevelopmentExpoRootCodeSigningInfo,\n easProjectId: string\n): CodeSigningInfo | null {\n if (codeSigningInfo.easProjectId !== easProjectId) {\n return null;\n }\n\n const { privateKey: privateKeyPEM, certificateChain: certificatePEMs } = codeSigningInfo;\n if (!privateKeyPEM || !certificatePEMs) {\n return null;\n }\n\n const certificateChain = certificatePEMs.map((certificatePEM) =>\n convertCertificatePEMToCertificate(certificatePEM)\n );\n\n // TODO(wschurman): maybe move to @expo/code-signing-certificates\n const leafCertificate = certificateChain[0];\n const now = new Date();\n if (leafCertificate.validity.notBefore > now || leafCertificate.validity.notAfter < now) {\n return null;\n }\n\n // TODO(wschurman): maybe do more validation\n\n return {\n keyId: 'expo-go',\n certificateChainForResponse: certificatePEMs,\n certificateForPrivateKey: certificatePEMs[0],\n privateKey: privateKeyPEM,\n };\n}\n\nasync function fetchAndCacheNewDevelopmentCodeSigningInfoAsync(\n easProjectId: string\n): Promise<CodeSigningInfo> {\n const keyPair = generateKeyPair();\n const keyPairPEM = convertKeyPairToPEM(keyPair);\n const csr = generateCSR(keyPair, `Development Certificate for ${easProjectId}`);\n const csrPEM = convertCSRToCSRPEM(csr);\n const [developmentSigningCertificate, expoGoIntermediateCertificate] = await Promise.all([\n getProjectDevelopmentCertificateAsync(easProjectId, csrPEM),\n getExpoGoIntermediateCertificateAsync(easProjectId),\n ]);\n\n await DevelopmentCodeSigningInfoFile.setAsync(easProjectId, {\n easProjectId,\n privateKey: keyPairPEM.privateKeyPEM,\n certificateChain: [developmentSigningCertificate, expoGoIntermediateCertificate],\n });\n\n return {\n keyId: 'expo-go',\n certificateChainForResponse: [developmentSigningCertificate, expoGoIntermediateCertificate],\n certificateForPrivateKey: developmentSigningCertificate,\n privateKey: keyPairPEM.privateKeyPEM,\n };\n}\n/**\n * Generate the `expo-signature` header for a manifest and code signing info.\n */\nexport function signManifestString(\n stringifiedManifest: string,\n codeSigningInfo: CodeSigningInfo\n): string {\n const privateKey = convertPrivateKeyPEMToPrivateKey(codeSigningInfo.privateKey);\n const certificate = convertCertificatePEMToCertificate(codeSigningInfo.certificateForPrivateKey);\n return signStringRSASHA256AndVerify(privateKey, certificate, stringifiedManifest);\n}\n"],"names":["getDevelopmentCodeSigningDirectory","getCodeSigningInfoAsync","signManifestString","Log","DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME","path","join","getExpoHomeDirectory","getProjectDevelopmentCodeSigningInfoFile","defaults","getFile","easProjectId","filePath","JsonFile","readAsync","projectSettings","writeAsync","ensureDir","setAsync","json","mergeAsync","cantReadFileDefault","DevelopmentCodeSigningInfoFile","privateKey","certificateChain","exp","expectSignatureHeader","privateKeyPath","parsedExpectSignature","parseDictionary","CommandError","expectedKeyIdOuter","get","expectedKeyId","expectedAlg","expectedAlgOuter","expectedAlgTemp","getExpoRootDevelopmentCodeSigningInfoAsync","getProjectCodeSigningCertificateAsync","extra","eas","projectId","warn","developmentCodeSigningInfoFromFile","validatedCodeSigningInfo","validateStoredDevelopmentExpoRootCertificateCodeSigningInfo","APISettings","isOffline","fetchAndCacheNewDevelopmentCodeSigningInfoAsync","e","codeSigningCertificatePath","updates","codeSigningCertificate","codeSigningMetadata","alg","keyid","privateKeyPEM","certificatePEM","getProjectPrivateKeyAndCertificateFromFilePathsAsync","keyId","certificateForPrivateKey","certificateChainForResponse","readFileWithErrorAsync","errorMessage","fs","readFile","codeSigningCertificatePEM","Promise","all","convertPrivateKeyPEMToPrivateKey","certificate","convertCertificatePEMToCertificate","validateSelfSignedCertificate","publicKey","codeSigningInfo","certificatePEMs","map","leafCertificate","now","Date","validity","notBefore","notAfter","keyPair","generateKeyPair","keyPairPEM","convertKeyPairToPEM","csr","generateCSR","csrPEM","convertCSRToCSRPEM","developmentSigningCertificate","expoGoIntermediateCertificate","getProjectDevelopmentCertificateAsync","getExpoGoIntermediateCertificateAsync","stringifiedManifest","signStringRSASHA256AndVerify"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/utils/codesigning.ts"],"sourcesContent":["import {\n convertCertificatePEMToCertificate,\n convertKeyPairToPEM,\n convertCSRToCSRPEM,\n generateKeyPair,\n generateCSR,\n convertPrivateKeyPEMToPrivateKey,\n validateSelfSignedCertificate,\n signBufferRSASHA256AndVerify,\n} from '@expo/code-signing-certificates';\nimport { ExpoConfig } from '@expo/config';\nimport { getExpoHomeDirectory } from '@expo/config/build/getUserState';\nimport JsonFile, { JSONObject } from '@expo/json-file';\nimport { promises as fs } from 'fs';\nimport { pki as PKI } from 'node-forge';\nimport path from 'path';\nimport { Dictionary, parseDictionary } from 'structured-headers';\n\nimport { getExpoGoIntermediateCertificateAsync } from '../api/getExpoGoIntermediateCertificate';\nimport { getProjectDevelopmentCertificateAsync } from '../api/getProjectDevelopmentCertificate';\nimport { APISettings } from '../api/settings';\nimport * as Log from '../log';\nimport { CommandError } from './errors';\n\nexport type CodeSigningInfo = {\n keyId: string;\n privateKey: string;\n certificateForPrivateKey: string;\n /**\n * Chain of certificates to serve in the manifest multipart body \"certificate_chain\" part.\n * The leaf certificate must be the 0th element of the array, followed by any intermediate certificates\n * necessary to evaluate the chain of trust ending in the implicitly trusted root certificate embedded in\n * the client.\n *\n * An empty array indicates that there is no need to serve the certificate chain in the multipart response.\n */\n certificateChainForResponse: string[];\n};\n\ntype StoredDevelopmentExpoRootCodeSigningInfo = {\n easProjectId: string | null;\n privateKey: string | null;\n certificateChain: string[] | null;\n};\nconst DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME = 'development-code-signing-settings.json';\n\nexport function getDevelopmentCodeSigningDirectory(): string {\n return path.join(getExpoHomeDirectory(), 'codesigning');\n}\n\nfunction getProjectDevelopmentCodeSigningInfoFile<T extends JSONObject>(defaults: T) {\n function getFile(easProjectId: string): JsonFile<T> {\n const filePath = path.join(\n getDevelopmentCodeSigningDirectory(),\n easProjectId,\n DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME\n );\n return new JsonFile<T>(filePath);\n }\n\n async function readAsync(easProjectId: string): Promise<T> {\n let projectSettings;\n try {\n projectSettings = await getFile(easProjectId).readAsync();\n } catch {\n projectSettings = await getFile(easProjectId).writeAsync(defaults, { ensureDir: true });\n }\n // Set defaults for any missing fields\n return { ...defaults, ...projectSettings };\n }\n\n async function setAsync(easProjectId: string, json: Partial<T>): Promise<T> {\n try {\n return await getFile(easProjectId).mergeAsync(json, {\n cantReadFileDefault: defaults,\n });\n } catch {\n return await getFile(easProjectId).writeAsync(\n {\n ...defaults,\n ...json,\n },\n { ensureDir: true }\n );\n }\n }\n\n return {\n getFile,\n readAsync,\n setAsync,\n };\n}\n\nexport const DevelopmentCodeSigningInfoFile =\n getProjectDevelopmentCodeSigningInfoFile<StoredDevelopmentExpoRootCodeSigningInfo>({\n easProjectId: null,\n privateKey: null,\n certificateChain: null,\n });\n\n/**\n * Get info necessary to generate a response `expo-signature` header given a project and incoming request `expo-expect-signature` header.\n * This only knows how to serve two code signing keyids:\n * - `expo-root` indicates that it should use a development certificate in the `expo-root` chain. See {@link getExpoRootDevelopmentCodeSigningInfoAsync}\n * - <developer's expo-updates keyid> indicates that it should sign with the configured certificate. See {@link getProjectCodeSigningCertificateAsync}\n */\nexport async function getCodeSigningInfoAsync(\n exp: ExpoConfig,\n expectSignatureHeader: string | null,\n privateKeyPath: string | undefined\n): Promise<CodeSigningInfo | null> {\n if (!expectSignatureHeader) {\n return null;\n }\n\n let parsedExpectSignature: Dictionary;\n try {\n parsedExpectSignature = parseDictionary(expectSignatureHeader);\n } catch {\n throw new CommandError('Invalid value for expo-expect-signature header');\n }\n\n const expectedKeyIdOuter = parsedExpectSignature.get('keyid');\n if (!expectedKeyIdOuter) {\n throw new CommandError('keyid not present in expo-expect-signature header');\n }\n\n const expectedKeyId = expectedKeyIdOuter[0];\n if (typeof expectedKeyId !== 'string') {\n throw new CommandError(\n `Invalid value for keyid in expo-expect-signature header: ${expectedKeyId}`\n );\n }\n\n let expectedAlg: string | null = null;\n const expectedAlgOuter = parsedExpectSignature.get('alg');\n if (expectedAlgOuter) {\n const expectedAlgTemp = expectedAlgOuter[0];\n if (typeof expectedAlgTemp !== 'string') {\n throw new CommandError('Invalid value for alg in expo-expect-signature header');\n }\n expectedAlg = expectedAlgTemp;\n }\n\n if (expectedKeyId === 'expo-root') {\n return await getExpoRootDevelopmentCodeSigningInfoAsync(exp);\n } else if (expectedKeyId === 'expo-go') {\n throw new CommandError(\n 'Invalid certificate requested: cannot sign with embedded keyid=expo-go key'\n );\n } else {\n return await getProjectCodeSigningCertificateAsync(\n exp,\n privateKeyPath,\n expectedKeyId,\n expectedAlg\n );\n }\n}\n\n/**\n * Get a development code signing certificate for the expo-root -> expo-go -> (development certificate) certificate chain.\n * This requires the user be logged in and online, otherwise try to use the cached development certificate.\n */\nasync function getExpoRootDevelopmentCodeSigningInfoAsync(\n exp: ExpoConfig\n): Promise<CodeSigningInfo | null> {\n const easProjectId = exp.extra?.eas?.projectId;\n // can't check for scope key validity since scope key is derived on the server from projectId and we may be offline.\n // we rely upon the client certificate check to validate the scope key\n if (!easProjectId) {\n Log.warn('No project ID specified in app.json, unable to sign manifest');\n return null;\n }\n\n const developmentCodeSigningInfoFromFile = await DevelopmentCodeSigningInfoFile.readAsync(\n easProjectId\n );\n const validatedCodeSigningInfo = validateStoredDevelopmentExpoRootCertificateCodeSigningInfo(\n developmentCodeSigningInfoFromFile,\n easProjectId\n );\n\n // 1. If online, ensure logged in, generate key pair and CSR, fetch and cache certificate chain for projectId\n // (overwriting existing dev cert in case projectId changed or it has expired)\n if (!APISettings.isOffline) {\n try {\n return await fetchAndCacheNewDevelopmentCodeSigningInfoAsync(easProjectId);\n } catch (e) {\n if (validatedCodeSigningInfo) {\n Log.warn(\n 'There was an error fetching the Expo development certificate, falling back to cached certificate'\n );\n return validatedCodeSigningInfo;\n } else {\n throw e;\n }\n }\n }\n\n // 2. check for cached cert/private key matching projectId and scopeKey of project, if found and valid return private key and cert chain including expo-go cert\n if (validatedCodeSigningInfo) {\n return validatedCodeSigningInfo;\n }\n\n // 3. if offline, return null\n Log.warn('Offline and no cached development certificate found, unable to sign manifest');\n return null;\n}\n\n/**\n * Get the certificate configured for expo-updates for this project.\n */\nasync function getProjectCodeSigningCertificateAsync(\n exp: ExpoConfig,\n privateKeyPath: string | undefined,\n expectedKeyId: string,\n expectedAlg: string | null\n): Promise<CodeSigningInfo | null> {\n const codeSigningCertificatePath = exp.updates?.codeSigningCertificate;\n if (!codeSigningCertificatePath) {\n return null;\n }\n\n if (!privateKeyPath) {\n throw new CommandError(\n 'Must specify --private-key-path argument to sign development manifest for requested code signing key'\n );\n }\n\n const codeSigningMetadata = exp.updates?.codeSigningMetadata;\n if (!codeSigningMetadata) {\n throw new CommandError(\n 'Must specify \"codeSigningMetadata\" under the \"updates\" field of your app config file to use EAS code signing'\n );\n }\n\n const { alg, keyid } = codeSigningMetadata;\n if (!alg || !keyid) {\n throw new CommandError(\n 'Must specify \"keyid\" and \"alg\" in the \"codeSigningMetadata\" field under the \"updates\" field of your app config file to use EAS code signing'\n );\n }\n\n if (expectedKeyId !== keyid) {\n throw new CommandError(`keyid mismatch: client=${expectedKeyId}, project=${keyid}`);\n }\n\n if (expectedAlg && expectedAlg !== alg) {\n throw new CommandError(`\"alg\" field mismatch (client=${expectedAlg}, project=${alg})`);\n }\n\n const { privateKeyPEM, certificatePEM } =\n await getProjectPrivateKeyAndCertificateFromFilePathsAsync({\n codeSigningCertificatePath,\n privateKeyPath,\n });\n\n return {\n keyId: keyid,\n privateKey: privateKeyPEM,\n certificateForPrivateKey: certificatePEM,\n certificateChainForResponse: [],\n };\n}\n\nasync function readFileWithErrorAsync(path: string, errorMessage: string): Promise<string> {\n try {\n return await fs.readFile(path, 'utf8');\n } catch {\n throw new CommandError(errorMessage);\n }\n}\n\nasync function getProjectPrivateKeyAndCertificateFromFilePathsAsync({\n codeSigningCertificatePath,\n privateKeyPath,\n}: {\n codeSigningCertificatePath: string;\n privateKeyPath: string;\n}): Promise<{ privateKeyPEM: string; certificatePEM: string }> {\n const [codeSigningCertificatePEM, privateKeyPEM] = await Promise.all([\n readFileWithErrorAsync(\n codeSigningCertificatePath,\n `Code signing certificate cannot be read from path: ${codeSigningCertificatePath}`\n ),\n readFileWithErrorAsync(\n privateKeyPath,\n `Code signing private key cannot be read from path: ${privateKeyPath}`\n ),\n ]);\n\n const privateKey = convertPrivateKeyPEMToPrivateKey(privateKeyPEM);\n const certificate = convertCertificatePEMToCertificate(codeSigningCertificatePEM);\n validateSelfSignedCertificate(certificate, {\n publicKey: certificate.publicKey as PKI.rsa.PublicKey,\n privateKey,\n });\n\n return { privateKeyPEM, certificatePEM: codeSigningCertificatePEM };\n}\n\n/**\n * Validate that the cached code signing info is still valid for the current project and\n * that it hasn't expired. If invalid, return null.\n */\nfunction validateStoredDevelopmentExpoRootCertificateCodeSigningInfo(\n codeSigningInfo: StoredDevelopmentExpoRootCodeSigningInfo,\n easProjectId: string\n): CodeSigningInfo | null {\n if (codeSigningInfo.easProjectId !== easProjectId) {\n return null;\n }\n\n const { privateKey: privateKeyPEM, certificateChain: certificatePEMs } = codeSigningInfo;\n if (!privateKeyPEM || !certificatePEMs) {\n return null;\n }\n\n const certificateChain = certificatePEMs.map((certificatePEM) =>\n convertCertificatePEMToCertificate(certificatePEM)\n );\n\n // TODO(wschurman): maybe move to @expo/code-signing-certificates\n const leafCertificate = certificateChain[0];\n const now = new Date();\n if (leafCertificate.validity.notBefore > now || leafCertificate.validity.notAfter < now) {\n return null;\n }\n\n // TODO(wschurman): maybe do more validation\n\n return {\n keyId: 'expo-go',\n certificateChainForResponse: certificatePEMs,\n certificateForPrivateKey: certificatePEMs[0],\n privateKey: privateKeyPEM,\n };\n}\n\nasync function fetchAndCacheNewDevelopmentCodeSigningInfoAsync(\n easProjectId: string\n): Promise<CodeSigningInfo> {\n const keyPair = generateKeyPair();\n const keyPairPEM = convertKeyPairToPEM(keyPair);\n const csr = generateCSR(keyPair, `Development Certificate for ${easProjectId}`);\n const csrPEM = convertCSRToCSRPEM(csr);\n const [developmentSigningCertificate, expoGoIntermediateCertificate] = await Promise.all([\n getProjectDevelopmentCertificateAsync(easProjectId, csrPEM),\n getExpoGoIntermediateCertificateAsync(easProjectId),\n ]);\n\n await DevelopmentCodeSigningInfoFile.setAsync(easProjectId, {\n easProjectId,\n privateKey: keyPairPEM.privateKeyPEM,\n certificateChain: [developmentSigningCertificate, expoGoIntermediateCertificate],\n });\n\n return {\n keyId: 'expo-go',\n certificateChainForResponse: [developmentSigningCertificate, expoGoIntermediateCertificate],\n certificateForPrivateKey: developmentSigningCertificate,\n privateKey: keyPairPEM.privateKeyPEM,\n };\n}\n/**\n * Generate the `expo-signature` header for a manifest and code signing info.\n */\nexport function signManifestString(\n stringifiedManifest: string,\n codeSigningInfo: CodeSigningInfo\n): string {\n const privateKey = convertPrivateKeyPEMToPrivateKey(codeSigningInfo.privateKey);\n const certificate = convertCertificatePEMToCertificate(codeSigningInfo.certificateForPrivateKey);\n return signBufferRSASHA256AndVerify(\n privateKey,\n certificate,\n Buffer.from(stringifiedManifest, 'utf8')\n );\n}\n"],"names":["getDevelopmentCodeSigningDirectory","getCodeSigningInfoAsync","signManifestString","Log","DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME","path","join","getExpoHomeDirectory","getProjectDevelopmentCodeSigningInfoFile","defaults","getFile","easProjectId","filePath","JsonFile","readAsync","projectSettings","writeAsync","ensureDir","setAsync","json","mergeAsync","cantReadFileDefault","DevelopmentCodeSigningInfoFile","privateKey","certificateChain","exp","expectSignatureHeader","privateKeyPath","parsedExpectSignature","parseDictionary","CommandError","expectedKeyIdOuter","get","expectedKeyId","expectedAlg","expectedAlgOuter","expectedAlgTemp","getExpoRootDevelopmentCodeSigningInfoAsync","getProjectCodeSigningCertificateAsync","extra","eas","projectId","warn","developmentCodeSigningInfoFromFile","validatedCodeSigningInfo","validateStoredDevelopmentExpoRootCertificateCodeSigningInfo","APISettings","isOffline","fetchAndCacheNewDevelopmentCodeSigningInfoAsync","e","codeSigningCertificatePath","updates","codeSigningCertificate","codeSigningMetadata","alg","keyid","privateKeyPEM","certificatePEM","getProjectPrivateKeyAndCertificateFromFilePathsAsync","keyId","certificateForPrivateKey","certificateChainForResponse","readFileWithErrorAsync","errorMessage","fs","readFile","codeSigningCertificatePEM","Promise","all","convertPrivateKeyPEMToPrivateKey","certificate","convertCertificatePEMToCertificate","validateSelfSignedCertificate","publicKey","codeSigningInfo","certificatePEMs","map","leafCertificate","now","Date","validity","notBefore","notAfter","keyPair","generateKeyPair","keyPairPEM","convertKeyPairToPEM","csr","generateCSR","csrPEM","convertCSRToCSRPEM","developmentSigningCertificate","expoGoIntermediateCertificate","getProjectDevelopmentCertificateAsync","getExpoGoIntermediateCertificateAsync","stringifiedManifest","signBufferRSASHA256AndVerify","Buffer","from"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/cli",
3
- "version": "0.4.9",
3
+ "version": "0.4.11",
4
4
  "description": "The Expo CLI",
5
5
  "main": "build/bin/cli",
6
6
  "bin": {
@@ -37,10 +37,10 @@
37
37
  "homepage": "https://github.com/expo/expo/tree/main/packages/@expo/cli",
38
38
  "dependencies": {
39
39
  "@babel/runtime": "^7.14.0",
40
- "@expo/code-signing-certificates": "^0.0.2",
40
+ "@expo/code-signing-certificates": "0.0.5",
41
41
  "@expo/config": "~7.0.2",
42
42
  "@expo/config-plugins": "~5.0.3",
43
- "@expo/dev-server": "0.1.123",
43
+ "@expo/dev-server": "0.1.124",
44
44
  "@expo/devcert": "^1.0.0",
45
45
  "@expo/json-file": "^8.2.35",
46
46
  "@expo/metro-config": "~0.5.0",
@@ -138,5 +138,5 @@
138
138
  "structured-headers": "^0.4.1",
139
139
  "taskr": "1.1.0"
140
140
  },
141
- "gitHead": "1276d834868c23d843a1e0d47422bda556f2ac5a"
141
+ "gitHead": "8218adba4854b91617b20bb0980add4ffece6515"
142
142
  }