@@ -22,12 +22,29 @@ limitations under the License.
2222const fs_1 = __importDefault ( require ( "fs" ) ) ;
2323const path_1 = __importDefault ( require ( "path" ) ) ;
2424const tuf_js_1 = require ( "tuf-js" ) ;
25+ const _1 = require ( "." ) ;
2526const target_1 = require ( "./target" ) ;
27+ const TUF_SEEDS_PATH = require . resolve ( '../seeds.json' ) ;
28+ const TARGETS_DIR_NAME = 'targets' ;
2629class TUFClient {
2730 constructor ( options ) {
28- initTufCache ( options ) ;
29- const remote = initRemoteConfig ( options ) ;
30- this . updater = initClient ( options . cachePath , remote , options ) ;
31+ const url = new URL ( options . mirrorURL ) ;
32+ const repoName = encodeURIComponent ( url . host + url . pathname . replace ( / \/ $ / , '' ) ) ;
33+ const cachePath = path_1 . default . join ( options . cachePath , repoName ) ;
34+ initTufCache ( cachePath ) ;
35+ seedCache ( {
36+ cachePath,
37+ mirrorURL : options . mirrorURL ,
38+ tufRootPath : options . rootPath ,
39+ forceInit : options . forceInit ,
40+ } ) ;
41+ this . updater = initClient ( {
42+ mirrorURL : options . mirrorURL ,
43+ cachePath,
44+ forceCache : options . forceCache ,
45+ retry : options . retry ,
46+ timeout : options . timeout ,
47+ } ) ;
3148 }
3249 async refresh ( ) {
3350 return this . updater . refresh ( ) ;
@@ -42,53 +59,55 @@ exports.TUFClient = TUFClient;
4259// created. If the targets directory does not exist, it will be created.
4360// If the root.json file does not exist, it will be copied from the
4461// rootPath argument.
45- function initTufCache ( { cachePath, rootPath : tufRootPath , force, } ) {
46- const targetsPath = path_1 . default . join ( cachePath , 'targets' ) ;
47- const cachedRootPath = path_1 . default . join ( cachePath , 'root.json' ) ;
62+ function initTufCache ( cachePath ) {
63+ const targetsPath = path_1 . default . join ( cachePath , TARGETS_DIR_NAME ) ;
4864 if ( ! fs_1 . default . existsSync ( cachePath ) ) {
4965 fs_1 . default . mkdirSync ( cachePath , { recursive : true } ) ;
5066 }
5167 if ( ! fs_1 . default . existsSync ( targetsPath ) ) {
5268 fs_1 . default . mkdirSync ( targetsPath ) ;
5369 }
54- // If the root.json file does not exist (or we're forcing re-initialization),
55- // copy it from the rootPath argument
56- if ( ! fs_1 . default . existsSync ( cachedRootPath ) || force ) {
57- fs_1 . default . copyFileSync ( tufRootPath , cachedRootPath ) ;
58- }
59- return cachePath ;
6070}
61- // Initializes the remote.json file, which contains the URL of the TUF
62- // repository. If the file does not exist, it will be created. If the file
63- // exists, it will be parsed and returned.
64- function initRemoteConfig ( { cachePath, mirrorURL, force, } ) {
65- let remoteConfig ;
66- const remoteConfigPath = path_1 . default . join ( cachePath , 'remote.json' ) ;
67- // If the remote config file exists, read it and parse it (skip if force is
68- // true)
69- if ( ! force && fs_1 . default . existsSync ( remoteConfigPath ) ) {
70- const data = fs_1 . default . readFileSync ( remoteConfigPath , 'utf-8' ) ;
71- remoteConfig = JSON . parse ( data ) ;
72- }
73- // If the remote config file does not exist (or we're forcing initialization),
74- // create it
75- if ( ! remoteConfig || force ) {
76- remoteConfig = { mirror : mirrorURL } ;
77- fs_1 . default . writeFileSync ( remoteConfigPath , JSON . stringify ( remoteConfig ) ) ;
71+ // Populates the TUF cache with the initial root.json file. If the root.json
72+ // file does not exist (or we're forcing re-initialization), copy it from either
73+ // the rootPath argument or from one of the repo seeds.
74+ function seedCache ( { cachePath, mirrorURL, tufRootPath, forceInit, } ) {
75+ const cachedRootPath = path_1 . default . join ( cachePath , 'root.json' ) ;
76+ // If the root.json file does not exist (or we're forcing re-initialization),
77+ // populate it either from the supplied rootPath or from one of the repo seeds.
78+ if ( ! fs_1 . default . existsSync ( cachedRootPath ) || forceInit ) {
79+ if ( tufRootPath ) {
80+ fs_1 . default . copyFileSync ( tufRootPath , cachedRootPath ) ;
81+ }
82+ else {
83+ // Load the embedded repo seeds
84+ const seeds = JSON . parse ( fs_1 . default . readFileSync ( TUF_SEEDS_PATH ) . toString ( 'utf-8' ) ) ;
85+ const repoSeed = seeds [ mirrorURL ] ;
86+ if ( ! repoSeed ) {
87+ throw new _1 . TUFError ( {
88+ code : 'TUF_INIT_CACHE_ERROR' ,
89+ message : `No root.json found for mirror: ${ mirrorURL } ` ,
90+ } ) ;
91+ }
92+ fs_1 . default . writeFileSync ( cachedRootPath , Buffer . from ( repoSeed [ 'root.json' ] , 'base64' ) ) ;
93+ // Copy any seed targets into the cache
94+ Object . entries ( repoSeed . targets ) . forEach ( ( [ targetName , target ] ) => {
95+ fs_1 . default . writeFileSync ( path_1 . default . join ( cachePath , TARGETS_DIR_NAME , targetName ) , Buffer . from ( target , 'base64' ) ) ;
96+ } ) ;
97+ }
7898 }
79- return remoteConfig ;
8099}
81- function initClient ( cachePath , remote , options ) {
82- const baseURL = remote . mirror ;
100+ function initClient ( options ) {
83101 const config = {
84102 fetchTimeout : options . timeout ,
85103 fetchRetry : options . retry ,
86104 } ;
87105 return new tuf_js_1 . Updater ( {
88- metadataBaseUrl : baseURL ,
89- targetBaseUrl : `${ baseURL } /targets` ,
90- metadataDir : cachePath ,
91- targetDir : path_1 . default . join ( cachePath , 'targets' ) ,
106+ metadataBaseUrl : options . mirrorURL ,
107+ targetBaseUrl : `${ options . mirrorURL } /targets` ,
108+ metadataDir : options . cachePath ,
109+ targetDir : path_1 . default . join ( options . cachePath , TARGETS_DIR_NAME ) ,
110+ forceCache : options . forceCache ,
92111 config,
93112 } ) ;
94113}
0 commit comments