xtra-cli 1.0.5 → 1.0.7
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/dist/bin/xtra.js +2 -2
- package/dist/commands/access.js +1 -1
- package/dist/commands/admin.js +3 -3
- package/dist/commands/audit.js +1 -1
- package/dist/commands/branch.js +1 -1
- package/dist/commands/checkout.js +1 -1
- package/dist/commands/ci.js +10 -10
- package/dist/commands/diff.js +6 -6
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/env.js +2 -2
- package/dist/commands/export.js +2 -2
- package/dist/commands/generate.js +3 -3
- package/dist/commands/history.js +3 -3
- package/dist/commands/import.js +1 -1
- package/dist/commands/init.js +4 -4
- package/dist/commands/integration.js +7 -7
- package/dist/commands/jit-run.js +3 -3
- package/dist/commands/local.js +5 -5
- package/dist/commands/login.js +6 -6
- package/dist/commands/login.test.js +4 -4
- package/dist/commands/logout.js +1 -1
- package/dist/commands/logs.js +3 -3
- package/dist/commands/project.js +1 -1
- package/dist/commands/rollback.js +1 -1
- package/dist/commands/rotate.js +2 -2
- package/dist/commands/run.js +5 -5
- package/dist/commands/secrets.js +5 -5
- package/dist/commands/service-account.js +7 -0
- package/dist/commands/simulate.js +3 -3
- package/dist/commands/status.js +2 -2
- package/dist/commands/template.js +4 -4
- package/dist/commands/ui.js +2 -2
- package/dist/commands/watch.js +8 -8
- package/dist/lib/api.js +1 -1
- package/dist/lib/api.test.js +1 -1
- package/dist/lib/audit.js +1 -1
- package/dist/lib/config.js +1 -1
- package/dist/lib/config.test.js +1 -1
- package/package.json +1 -1
package/dist/commands/env.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
2
|
-
Clone successful!`)),console.log(`Copied: ${g.summary.copied}`),console.log(`Updated: ${g.summary.updated} (overwrite: ${e.overwrite})`),console.log(`Skipped: ${g.summary.skipped}`))}catch(s){s.response&&s.response.data&&s.response.data.error?console.error(c.default.red("Error cloning environment:"),s.response.data.error):console.error(c.default.red("Error cloning environment:"),s
|
|
1
|
+
var A=Object.create;var d=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var L=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var _=(e,s)=>{for(var t in s)d(e,t,{get:s[t],enumerable:!0})},f=(e,s,t,n)=>{if(s&&typeof s=="object"||typeof s=="function")for(let o of R(s))!P.call(e,o)&&o!==t&&d(e,o,{get:()=>s[o],enumerable:!(n=U(s,o))||n.enumerable});return e};var a=(e,s,t)=>(t=e!=null?A(L(e)):{},f(s||!e||!e.__esModule?d(t,"default",{value:e,enumerable:!0}):t,e)),q=e=>f(d({},"__esModule",{value:!0}),e);var B={};_(B,{envCommand:()=>I});module.exports=q(B);var x=require("commander"),c=a(require("chalk"));var j=a(require("axios"));var v=a(require("conf")),l=a(require("fs")),h=a(require("path")),m="https://www.xtrasecurity.in/api",i=new v.default({projectName:"xtra-cli",defaults:{apiUrl:m}}),w=i.get("apiUrl");w&&!process.env.XTRA_API_URL&&w.includes("xtra-security.vercel.app")&&i.set("apiUrl",m);var u=()=>({...i.store,apiUrl:process.env.XTRA_API_URL||i.get("apiUrl")||m});var $=()=>i.get("token");var y=()=>{let e={};try{let s=h.default.join(process.cwd(),".xtrarc");l.default.existsSync(s)&&(e=JSON.parse(l.default.readFileSync(s,"utf-8")))}catch{}return{project:e.project||i.get("project")||"",env:e.env||i.get("env")||"development",branch:e.branch||i.get("branch")||"main"}};var S=a(require("fs")),b=a(require("path")),O=JSON.parse(S.readFileSync(b.join(__dirname,"../../package.json"),"utf-8")),r=()=>{let{apiUrl:e}=u(),s=$();return j.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":O.version,...s?{Authorization:`Bearer ${s}`}:{}}})},k={login:async(e,s,t)=>(await r().post("/auth/cli-login",{email:e,password:s,apiKey:t})).data,getSecrets:async(e,s,t="main")=>(await r().get(`/projects/${e}/envs/${s}/secrets?branch=${t}`)).data,getSecretVersions:async(e,s,t="main")=>(await r().get(`/projects/${e}/envs/${s}/secrets?includeVersions=true&branch=${t}`)).data,setSecrets:async(e,s,t,n,o="main")=>(await r().post(`/projects/${e}/envs/${s}/secrets`,{secrets:t,expectedVersions:n,branch:o})).data,getSecretDetails:async(e,s,t,n="main")=>(await r().get(`/projects/${e}/envs/${s}/secrets/${t}?branch=${n}`)).data,syncLogs:async e=>(await r().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,s,t,n,o,p)=>(await r().post(`/projects/${e}/envs/${s}/secrets/link`,{key:t,sourceProjectId:n,sourceEnv:o,sourceKey:p})).data,rotateSecret:async(e,s,t,n,o)=>(await r().post(`/projects/${e}/envs/${s}/secrets/${t}/rotate`,{strategy:n,parsedNewValue:o})).data,promoteSecret:async(e,s,t)=>(await r().post(`/projects/${e}/envs/${s}/secrets/${t}/promote`,{})).data,verifyAuditLogs:async()=>(await r().get("/audit/verify")).data,exportAuditLogs:async(e,s,t,n)=>{let o={format:e};return s&&(o.startDate=s),t&&(o.endDate=t),n&&(o.projectId=n),(await r().post("/audit/export",o,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,s,t,n)=>(await r().post("/access/request",{projectId:e,secretId:n,reason:s,duration:t})).data,approveAccess:async(e,s)=>(await r().post("/access/approve",{requestId:e,decision:s})).data,listAccessRequests:async e=>{let{workspace:s}=u(),t=s?`&workspaceId=${s}`:"";return(await r().get(`/access/list?mode=${e}${t}`)).data},getAccessRequestStatus:async e=>(await r().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=u(),s=e?`/project?workspaceId=${e}`:"/project";return(await r().get(s)).data},getBranches:async e=>(await r().get(`/branch?projectId=${e}`)).data,createBranch:async(e,s,t)=>(await r().post("/branch",{projectId:e,name:s,description:t})).data,deleteBranch:async e=>(await r().delete(`/branch/${e}`)).data,updateBranch:async(e,s)=>(await r().put("/branch",{id:e,...s})).data,getRoles:async()=>(await r().get("/admin/roles")).data,getUsers:async e=>{let s=e?`?teamId=${e}`:"";return(await r().get(`/admin/users${s}`)).data},setUserRole:async(e,s,t)=>(await r().put("/admin/users/role",{email:e,role:s,teamId:t})).data,getIntegrationStatus:async e=>(await r().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await r().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await r().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,s)=>{let t=new URLSearchParams(s).toString();return(await r().get(`/projects/${e}/kubernetes?${t}`)).data},getSecretHistory:async(e,s,t)=>(await r().get(`/projects/${e}/envs/${s}/secrets/${t}/history`)).data,rollbackSecret:async(e,s,t,n)=>(await r().post(`/projects/${e}/envs/${s}/secrets/${t}/history`,{version:n})).data,cloneEnvironment:async(e,s,t,n,o)=>(await r().post(`/projects/${e}/envs/clone`,{fromEnv:s,toEnv:t,overwrite:n,branch:o})).data,generateJitLink:async e=>(await r().post("/jit/generate",e)).data,claimJitLink:async e=>(await r().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await r().get(`/jit/${e}`)).data,getServiceAccounts:async e=>(await r().get(`/projects/${e}/service-accounts`)).data,createServiceAccount:async(e,s)=>(await r().post(`/projects/${e}/service-accounts`,s)).data,deleteServiceAccount:async(e,s)=>(await r().delete(`/projects/${e}/service-accounts/${s}`)).data,getServiceAccountKeys:async(e,s)=>(await r().get(`/projects/${e}/service-accounts/${s}/keys`)).data,createServiceAccountKey:async(e,s,t,n)=>(await r().post(`/projects/${e}/service-accounts/${s}/keys`,{label:t,expiresAt:n})).data,deleteServiceAccountKey:async(e,s,t)=>(await r().delete(`/projects/${e}/service-accounts/${s}/keys/${t}`)).data,post:async(e,s)=>(await r().post(e,s)).data};var C=a(require("inquirer")),I=new x.Command("env");I.command("clone").description("Clone secrets from one environment to another").requiredOption("--from <env>","Source environment (e.g. production)").requiredOption("--to <env>","Destination environment (e.g. staging)").option("-p, --project <id>","Project ID").option("-b, --branch <name>","Branch Name").option("--overwrite","Overwrite existing secrets",!1).action(async e=>{try{let s=e.project,t=e.branch||y().branch||"main";s||(s=y().project,s||(console.error(c.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1)));let n=e.from.toLowerCase(),o=e.to.toLowerCase();if(n===o&&(console.error(c.default.red("Source and destination must be different.")),process.exit(1)),console.log(c.default.blue(`Cloning secrets from ${n} to ${o} (branch: ${t})...`)),e.overwrite&&console.log(c.default.yellow("Warning: Existing secrets in destination will be overwritten!")),!(await C.default.prompt([{type:"confirm",name:"proceed",message:"Are you sure you want to proceed?",default:!1}])).proceed){console.log("Operation cancelled.");return}let g=await k.cloneEnvironment(s,n,o,e.overwrite,t);g.success&&(console.log(c.default.green(`
|
|
2
|
+
Clone successful!`)),console.log(`Copied: ${g.summary.copied}`),console.log(`Updated: ${g.summary.updated} (overwrite: ${e.overwrite})`),console.log(`Skipped: ${g.summary.skipped}`))}catch(s){s.response&&s.response.data&&s.response.data.error?console.error(c.default.red("Error cloning environment:"),s.response.data.error):console.error(c.default.red("Error cloning environment:"),s?.response?.data?.error||"Unknown error")}});0&&(module.exports={envCommand});
|
package/dist/commands/export.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var ot=Object.create;var h=Object.defineProperty;var
|
|
2
|
-
`);break;case"csv":let d=Object.entries(c).map(([
|
|
1
|
+
var ot=Object.create;var h=Object.defineProperty;var at=Object.getOwnPropertyDescriptor;var it=Object.getOwnPropertyNames;var ct=Object.getPrototypeOf,pt=Object.prototype.hasOwnProperty;var v=(t,e)=>()=>(t&&(e=t(t=0)),e);var L=(t,e)=>{for(var s in e)h(t,s,{get:e[s],enumerable:!0})},N=(t,e,s,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of it(e))!pt.call(t,n)&&n!==s&&h(t,n,{get:()=>e[n],enumerable:!(r=at(e,n))||r.enumerable});return t};var i=(t,e,s)=>(s=t!=null?ot(ct(t)):{},N(e||!t||!t.__esModule?h(s,"default",{value:t,enumerable:!0}):s,t)),P=t=>N(h({},"__esModule",{value:!0}),t);var T,A,_,I,g,B,f,D,C,w=v(()=>{T=i(require("conf")),A=i(require("fs")),_=i(require("path")),I="https://www.xtrasecurity.in/api",g=new T.default({projectName:"xtra-cli",defaults:{apiUrl:I}}),B=g.get("apiUrl");B&&!process.env.XTRA_API_URL&&B.includes("xtra-security.vercel.app")&&g.set("apiUrl",I);f=()=>({...g.store,apiUrl:process.env.XTRA_API_URL||g.get("apiUrl")||I}),D=()=>g.get("token"),C=()=>{let t={};try{let e=_.default.join(process.cwd(),".xtrarc");A.default.existsSync(e)&&(t=JSON.parse(A.default.readFileSync(e,"utf-8")))}catch{}return{project:t.project||g.get("project")||"",env:t.env||g.get("env")||"development",branch:t.branch||g.get("branch")||"main"}}});var J,F,q,gt,o,j,U=v(()=>{J=i(require("axios"));w();F=i(require("fs")),q=i(require("path")),gt=JSON.parse(F.readFileSync(q.join(__dirname,"../../package.json"),"utf-8")),o=()=>{let{apiUrl:t}=f(),e=D();return J.default.create({baseURL:t,headers:{"Content-Type":"application/json","X-CLI-Version":gt.version,...e?{Authorization:`Bearer ${e}`}:{}}})},j={login:async(t,e,s)=>(await o().post("/auth/cli-login",{email:t,password:e,apiKey:s})).data,getSecrets:async(t,e,s="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets?branch=${s}`)).data,getSecretVersions:async(t,e,s="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(t,e,s,r,n="main")=>(await o().post(`/projects/${t}/envs/${e}/secrets`,{secrets:s,expectedVersions:r,branch:n})).data,getSecretDetails:async(t,e,s,r="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets/${s}?branch=${r}`)).data,syncLogs:async t=>(await o().post("/audit/cli-logs",{logs:t})).data,linkSecret:async(t,e,s,r,n,a)=>(await o().post(`/projects/${t}/envs/${e}/secrets/link`,{key:s,sourceProjectId:r,sourceEnv:n,sourceKey:a})).data,rotateSecret:async(t,e,s,r,n)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/rotate`,{strategy:r,parsedNewValue:n})).data,promoteSecret:async(t,e,s)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await o().get("/audit/verify")).data,exportAuditLogs:async(t,e,s,r)=>{let n={format:t};return e&&(n.startDate=e),s&&(n.endDate=s),r&&(n.projectId=r),(await o().post("/audit/export",n,{responseType:t==="csv"?"text":"json"})).data},requestAccess:async(t,e,s,r)=>(await o().post("/access/request",{projectId:t,secretId:r,reason:e,duration:s})).data,approveAccess:async(t,e)=>(await o().post("/access/approve",{requestId:t,decision:e})).data,listAccessRequests:async t=>{let{workspace:e}=f(),s=e?`&workspaceId=${e}`:"";return(await o().get(`/access/list?mode=${t}${s}`)).data},getAccessRequestStatus:async t=>(await o().get(`/access/request?id=${t}`)).data,getProjects:async()=>{let{workspace:t}=f(),e=t?`/project?workspaceId=${t}`:"/project";return(await o().get(e)).data},getBranches:async t=>(await o().get(`/branch?projectId=${t}`)).data,createBranch:async(t,e,s)=>(await o().post("/branch",{projectId:t,name:e,description:s})).data,deleteBranch:async t=>(await o().delete(`/branch/${t}`)).data,updateBranch:async(t,e)=>(await o().put("/branch",{id:t,...e})).data,getRoles:async()=>(await o().get("/admin/roles")).data,getUsers:async t=>{let e=t?`?teamId=${t}`:"";return(await o().get(`/admin/users${e}`)).data},setUserRole:async(t,e,s)=>(await o().put("/admin/users/role",{email:t,role:e,teamId:s})).data,getIntegrationStatus:async t=>(await o().get(`/integrations/${t}`)).data,getIntegrationRepos:async t=>(await o().get(`/integrations/${t}/sync`)).data.repos,syncSecretsToGithub:async t=>(await o().post("/integrations/github/sync",t)).data,exportKubernetesSecret:async(t,e)=>{let s=new URLSearchParams(e).toString();return(await o().get(`/projects/${t}/kubernetes?${s}`)).data},getSecretHistory:async(t,e,s)=>(await o().get(`/projects/${t}/envs/${e}/secrets/${s}/history`)).data,rollbackSecret:async(t,e,s,r)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/history`,{version:r})).data,cloneEnvironment:async(t,e,s,r,n)=>(await o().post(`/projects/${t}/envs/clone`,{fromEnv:e,toEnv:s,overwrite:r,branch:n})).data,generateJitLink:async t=>(await o().post("/jit/generate",t)).data,claimJitLink:async t=>(await o().post("/jit/claim",{token:t})).data,getJitInfo:async t=>(await o().get(`/jit/${t}`)).data,getServiceAccounts:async t=>(await o().get(`/projects/${t}/service-accounts`)).data,createServiceAccount:async(t,e)=>(await o().post(`/projects/${t}/service-accounts`,e)).data,deleteServiceAccount:async(t,e)=>(await o().delete(`/projects/${t}/service-accounts/${e}`)).data,getServiceAccountKeys:async(t,e)=>(await o().get(`/projects/${t}/service-accounts/${e}/keys`)).data,createServiceAccountKey:async(t,e,s,r)=>(await o().post(`/projects/${t}/service-accounts/${e}/keys`,{label:s,expiresAt:r})).data,deleteServiceAccountKey:async(t,e,s)=>(await o().delete(`/projects/${t}/service-accounts/${e}/keys/${s}`)).data,post:async(t,e)=>(await o().post(t,e)).data}});function H(){let t=K.get("masterKey");t||(t=y.default.randomBytes(32).toString("hex"),K.set("masterKey",t));let e=(0,V.machineIdSync)();return y.default.createHash("sha256").update(t+e).digest()}var y,G,V,z,K,M,X,Q=v(()=>{y=i(require("crypto")),G=i(require("conf")),V=require("node-machine-id"),z="aes-256-gcm",K=new G.default({projectName:"xtra-cli-crypto"});M=t=>{let e=y.default.randomBytes(16),s=H(),r=y.default.createCipheriv(z,s,e),n=r.update(t,"utf8","hex");n+=r.final("hex");let a=r.getAuthTag();return{iv:e.toString("hex"),content:n,tag:a.toString("hex")}},X=t=>{let e=H(),s=Buffer.from(t.iv,"hex"),r=Buffer.from(t.tag,"hex"),n=y.default.createDecipheriv(z,e,s);n.setAuthTag(r);let a=n.update(t.content,"hex","utf8");return a+=n.final("utf8"),a}});var Z={};L(Z,{loadAuditLogs:()=>S,logAudit:()=>ut,saveAuditLogs:()=>x,syncAuditLogs:()=>ft});function dt(t){if(!t||typeof t!="object")return t;let e={...t},s=["password","token","secret","value","apiKey","secretValue"];for(let r of Object.keys(e))s.some(n=>r.toLowerCase().includes(n))&&(e[r]="[REDACTED]");return e}async function Y(t){try{if(!f().token)return!1;let s={action:t.action,entity:"cli-project",entityId:t.projectId||"global",details:dt(t.details),timestamp:t.timestamp,projectId:t.projectId};return await j.post("/audit/cli-logs",{logs:[s]}),!0}catch(e){return process.env.DEBUG&&console.error("Failed to send audit log to backend:",e),!1}}function ut(t,e,s,r){let n={id:(0,W.v4)(),timestamp:new Date().toISOString(),action:t,projectId:e,environment:s,details:r,synced:!1},a=S();a.push(n),x(a),Y(n).then($=>{if($){n.synced=!0;let u=S(),c=u.findIndex(p=>p.id===n.id);c!==-1&&(u[c].synced=!0,x(u))}}).catch(()=>{})}function S(){if(!l.default.existsSync(R))return[];try{let t=l.default.readFileSync(R,"utf-8"),e=JSON.parse(t),s=X(e);return JSON.parse(s)}catch{return[]}}function x(t){l.default.existsSync(O)||l.default.mkdirSync(O,{recursive:!0});let e=JSON.stringify(t),s=M(e);l.default.writeFileSync(R,JSON.stringify(s),"utf-8")}async function ft(){let t=S(),e=t.filter(r=>!r.synced);if(e.length===0)return 0;let s=0;for(let r of e)await Y(r)&&(r.synced=!0,s++);return s>0&&x(t),s}var l,E,W,O,R,tt=v(()=>{l=i(require("fs")),E=i(require("path")),W=require("uuid");Q();w();U();O=E.default.join(process.cwd(),".xtra"),R=E.default.join(O,"audit.enc")});var lt={};L(lt,{exportCommand:()=>yt});module.exports=P(lt);var et=require("commander");U();var m=i(require("chalk")),st=i(require("fs")),rt=i(require("path")),nt=require("csv-stringify/sync");w();var yt=new et.Command("export").description("Export secrets to a file (JSON, Dotenv, CSV)").option("-p, --project <projectId>","Project ID").option("-e, --env <environment>","Environment (development, staging, production)","development").option("-b, --branch <branchName>","Branch Name").option("-f, --format <format>","Output format (json, dotenv, csv)","json").option("-o, --output <file>","Output file path (default: stdout)").action(async t=>{let{project:e,env:s,branch:r,format:n,output:a}=t;e||(e=C().project),r||(r=C().branch||"main"),s={dev:"development",stg:"staging",prod:"production"}[s]||s,e||(console.error(m.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1));let u=require("ora")(`Fetching secrets for export (${s} @ ${r})...`).start();try{let c=await j.getSecrets(e,s,r);if(u.stop(),!c||Object.keys(c).length===0){console.warn(m.default.yellow("No secrets found to export."));return}let p="";switch(n.toLowerCase()){case"json":p=JSON.stringify(c,null,2);break;case"dotenv":p=Object.entries(c).map(([b,k])=>`${b}="${String(k).replace(/"/g,'\\"')}"`).join(`
|
|
2
|
+
`);break;case"csv":let d=Object.entries(c).map(([b,k])=>({key:b,value:k}));p=(0,nt.stringify)(d,{header:!0});break;default:console.error(m.default.red(`Error: Unsupported format '${n}'. Use json, dotenv, or csv.`)),process.exit(1)}if(a){let d=rt.default.resolve(process.cwd(),a);st.default.writeFileSync(d,p,"utf-8"),console.log(m.default.green(`\u2714 Secrets exported to ${d}`))}else console.log(p);try{let{logAudit:d}=(tt(),P(Z));d("SECRET_EXPORT",e,s,{format:n,destination:a||"stdout",branch:r})}catch{}}catch(c){u.fail("Export failed.");let p=c?.response?.data?.error||c?.response?.data?.error||"An unexpected error occurred";console.error(m.default.red(p)),process.exit(1)}});0&&(module.exports={exportCommand});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var pt=Object.create;var
|
|
2
|
-
`),added:r,updated:i}}var
|
|
3
|
-
`);break}A.default.writeFileSync(p,w,"utf-8");let{hash:at}=(Q(),U(Y)),{updateManifest:ct}=(st(),U(et));ct(e,s,d,at),u&&C?(h.succeed(m.default.green(`Updated ${g}`)),
|
|
1
|
+
var pt=Object.create;var x=Object.defineProperty;var gt=Object.getOwnPropertyDescriptor;var dt=Object.getOwnPropertyNames;var ut=Object.getPrototypeOf,ft=Object.prototype.hasOwnProperty;var B=(t,e)=>()=>(t&&(e=t(t=0)),e);var O=(t,e)=>{for(var s in e)x(t,s,{get:e[s],enumerable:!0})},F=(t,e,s,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of dt(e))!ft.call(t,r)&&r!==s&&x(t,r,{get:()=>e[r],enumerable:!(n=gt(e,r))||n.enumerable});return t};var c=(t,e,s)=>(s=t!=null?pt(ut(t)):{},F(e||!t||!t.__esModule?x(s,"default",{value:t,enumerable:!0}):s,t)),U=t=>F(x({},"__esModule",{value:!0}),t);var Y={};O(Y,{decrypt:()=>yt,encrypt:()=>mt,hash:()=>ht});function z(){let t=V.get("masterKey");t||(t=y.default.randomBytes(32).toString("hex"),V.set("masterKey",t));let e=(0,H.machineIdSync)();return y.default.createHash("sha256").update(t+e).digest()}var y,W,H,X,V,mt,yt,ht,Q=B(()=>{y=c(require("crypto")),W=c(require("conf")),H=require("node-machine-id"),X="aes-256-gcm",V=new W.default({projectName:"xtra-cli-crypto"});mt=t=>{let e=y.default.randomBytes(16),s=z(),n=y.default.createCipheriv(X,s,e),r=n.update(t,"utf8","hex");r+=n.final("hex");let i=n.getAuthTag();return{iv:e.toString("hex"),content:r,tag:i.toString("hex")}},yt=t=>{let e=z(),s=Buffer.from(t.iv,"hex"),n=Buffer.from(t.tag,"hex"),r=y.default.createDecipheriv(X,e,s);r.setAuthTag(n);let i=r.update(t.content,"hex","utf8");return i+=r.final("utf8"),i},ht=t=>y.default.createHash("sha256").update(t).digest("hex")});var et={};O(et,{MANIFEST_DIR:()=>k,MANIFEST_FILE:()=>I,loadManifest:()=>Z,saveManifest:()=>tt,updateManifest:()=>vt});function Z(){if(!v.default.existsSync(I))return null;try{let t=v.default.readFileSync(I,"utf-8");return JSON.parse(t)}catch{return null}}function tt(t){v.default.existsSync(k)||v.default.mkdirSync(k,{recursive:!0}),v.default.writeFileSync(I,JSON.stringify(t,null,2),"utf-8")}function vt(t,e,s,n){let r=Z()||{projectId:t,environment:e,lastSyncedAt:new Date().toISOString(),secrets:{}};r.projectId=t,r.environment=e,r.lastSyncedAt=new Date().toISOString(),Object.entries(s).forEach(([i,f])=>{let a=n(f);r.secrets[i]={hash:a,updatedAt:new Date().toISOString()}}),tt(r)}var v,L,k,I,st=B(()=>{v=c(require("fs")),L=c(require("path")),k=L.default.join(process.cwd(),".xtra"),I=L.default.join(k,"manifest.json")});var $t={};O($t,{generateCommand:()=>St});module.exports=U($t);var nt=require("commander");var q=c(require("axios"));var T=c(require("conf")),P=c(require("fs")),E=c(require("path")),M="https://www.xtrasecurity.in/api",l=new T.default({projectName:"xtra-cli",defaults:{apiUrl:M}}),_=l.get("apiUrl");_&&!process.env.XTRA_API_URL&&_.includes("xtra-security.vercel.app")&&l.set("apiUrl",M);var b=()=>({...l.store,apiUrl:process.env.XTRA_API_URL||l.get("apiUrl")||M});var D=()=>l.get("token");var N=()=>{let t={};try{let e=E.default.join(process.cwd(),".xtrarc");P.default.existsSync(e)&&(t=JSON.parse(P.default.readFileSync(e,"utf-8")))}catch{}return{project:t.project||l.get("project")||"",env:t.env||l.get("env")||"development",branch:t.branch||l.get("branch")||"main"}};var G=c(require("fs")),J=c(require("path")),lt=JSON.parse(G.readFileSync(J.join(__dirname,"../../package.json"),"utf-8")),o=()=>{let{apiUrl:t}=b(),e=D();return q.default.create({baseURL:t,headers:{"Content-Type":"application/json","X-CLI-Version":lt.version,...e?{Authorization:`Bearer ${e}`}:{}}})},K={login:async(t,e,s)=>(await o().post("/auth/cli-login",{email:t,password:e,apiKey:s})).data,getSecrets:async(t,e,s="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets?branch=${s}`)).data,getSecretVersions:async(t,e,s="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(t,e,s,n,r="main")=>(await o().post(`/projects/${t}/envs/${e}/secrets`,{secrets:s,expectedVersions:n,branch:r})).data,getSecretDetails:async(t,e,s,n="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets/${s}?branch=${n}`)).data,syncLogs:async t=>(await o().post("/audit/cli-logs",{logs:t})).data,linkSecret:async(t,e,s,n,r,i)=>(await o().post(`/projects/${t}/envs/${e}/secrets/link`,{key:s,sourceProjectId:n,sourceEnv:r,sourceKey:i})).data,rotateSecret:async(t,e,s,n,r)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/rotate`,{strategy:n,parsedNewValue:r})).data,promoteSecret:async(t,e,s)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await o().get("/audit/verify")).data,exportAuditLogs:async(t,e,s,n)=>{let r={format:t};return e&&(r.startDate=e),s&&(r.endDate=s),n&&(r.projectId=n),(await o().post("/audit/export",r,{responseType:t==="csv"?"text":"json"})).data},requestAccess:async(t,e,s,n)=>(await o().post("/access/request",{projectId:t,secretId:n,reason:e,duration:s})).data,approveAccess:async(t,e)=>(await o().post("/access/approve",{requestId:t,decision:e})).data,listAccessRequests:async t=>{let{workspace:e}=b(),s=e?`&workspaceId=${e}`:"";return(await o().get(`/access/list?mode=${t}${s}`)).data},getAccessRequestStatus:async t=>(await o().get(`/access/request?id=${t}`)).data,getProjects:async()=>{let{workspace:t}=b(),e=t?`/project?workspaceId=${t}`:"/project";return(await o().get(e)).data},getBranches:async t=>(await o().get(`/branch?projectId=${t}`)).data,createBranch:async(t,e,s)=>(await o().post("/branch",{projectId:t,name:e,description:s})).data,deleteBranch:async t=>(await o().delete(`/branch/${t}`)).data,updateBranch:async(t,e)=>(await o().put("/branch",{id:t,...e})).data,getRoles:async()=>(await o().get("/admin/roles")).data,getUsers:async t=>{let e=t?`?teamId=${t}`:"";return(await o().get(`/admin/users${e}`)).data},setUserRole:async(t,e,s)=>(await o().put("/admin/users/role",{email:t,role:e,teamId:s})).data,getIntegrationStatus:async t=>(await o().get(`/integrations/${t}`)).data,getIntegrationRepos:async t=>(await o().get(`/integrations/${t}/sync`)).data.repos,syncSecretsToGithub:async t=>(await o().post("/integrations/github/sync",t)).data,exportKubernetesSecret:async(t,e)=>{let s=new URLSearchParams(e).toString();return(await o().get(`/projects/${t}/kubernetes?${s}`)).data},getSecretHistory:async(t,e,s)=>(await o().get(`/projects/${t}/envs/${e}/secrets/${s}/history`)).data,rollbackSecret:async(t,e,s,n)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/history`,{version:n})).data,cloneEnvironment:async(t,e,s,n,r)=>(await o().post(`/projects/${t}/envs/clone`,{fromEnv:e,toEnv:s,overwrite:n,branch:r})).data,generateJitLink:async t=>(await o().post("/jit/generate",t)).data,claimJitLink:async t=>(await o().post("/jit/claim",{token:t})).data,getJitInfo:async t=>(await o().get(`/jit/${t}`)).data,getServiceAccounts:async t=>(await o().get(`/projects/${t}/service-accounts`)).data,createServiceAccount:async(t,e)=>(await o().post(`/projects/${t}/service-accounts`,e)).data,deleteServiceAccount:async(t,e)=>(await o().delete(`/projects/${t}/service-accounts/${e}`)).data,getServiceAccountKeys:async(t,e)=>(await o().get(`/projects/${t}/service-accounts/${e}/keys`)).data,createServiceAccountKey:async(t,e,s,n)=>(await o().post(`/projects/${t}/service-accounts/${e}/keys`,{label:s,expiresAt:n})).data,deleteServiceAccountKey:async(t,e,s)=>(await o().delete(`/projects/${t}/service-accounts/${e}/keys/${s}`)).data,post:async(t,e)=>(await o().post(t,e)).data};var m=c(require("chalk")),rt=c(require("ora")),A=c(require("fs")),ot=c(require("path")),it=c(require("yaml"));function wt(t){let e={},s=t.split(/\r?\n/);for(let n of s){let r=n.trim();if(!r||r.startsWith("#"))continue;let i=r.indexOf("=");if(i===-1)continue;let f=r.substring(0,i).trim(),a=r.substring(i+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),e[f]=a}return e}function jt(t,e){let s=t.split(/\r?\n/),n=new Set,r=[],i=[],f=s.map(a=>{let u=a.trim();if(!u||u.startsWith("#"))return a;let g=u.indexOf("=");if(g===-1)return a;let p=u.substring(0,g).trim();return n.add(p),p in e?(wt(a)[p]!==e[p]&&i.push(p),`${p}="${e[p]}"`):a});for(let[a,u]of Object.entries(e))n.has(a)||(f.push(`${a}="${u}"`),r.push(a));return{content:f.join(`
|
|
2
|
+
`),added:r,updated:i}}var St=new nt.Command("generate").description("Generate local configuration files from secrets").option("-p, --project <projectId>","Project ID").option("-e, --env <environment>","Environment (dev, stg, prod)","dev").option("-b, --branch <branchName>","Branch Name").option("-o, --output <path>","Output file path (forces complete overwrite)").option("-f, --format <format>","Output format (env, json, yaml)","env").option("--force","Skip confirmation prompts",!1).action(async t=>{let{project:e,env:s,branch:n,output:r,format:i,force:f}=t;e||(e=N().project),n||(n=N().branch||"main"),s={dev:"development",stg:"staging",prod:"production"}[s]||s,e||(console.error(m.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1));let u=!r&&i==="env",g=r;if(!g)switch(i){case"json":g="secrets.json";break;case"yaml":g="secrets.yaml";break;default:g=".env";break}let p=ot.default.resolve(process.cwd(),g),C=A.default.existsSync(p),h=(0,rt.default)(`Fetching secrets for ${s} (branch: ${n})...`).start();try{let d=await K.getSecrets(e,s,n);if(!d||Object.keys(d).length===0){h.warn(m.default.yellow("No secrets found. File not modified."));return}let w="",S=[],$=[];if(u&&C){h.text="Merging with existing .env file...";let R=A.default.readFileSync(p,"utf-8"),j=jt(R,d);if(w=j.content,S=j.added,$=j.updated,S.length===0&&$.length===0){h.succeed(m.default.green("No changes needed - .env is already up to date."));return}}else switch(i.toLowerCase()){case"json":w=JSON.stringify(d,null,2);break;case"yaml":w=it.default.stringify(d);break;default:w=Object.entries(d).map(([R,j])=>`${R}="${j}"`).join(`
|
|
3
|
+
`);break}A.default.writeFileSync(p,w,"utf-8");let{hash:at}=(Q(),U(Y)),{updateManifest:ct}=(st(),U(et));ct(e,s,d,at),u&&C?(h.succeed(m.default.green(`Updated ${g}`)),S.length>0&&console.log(m.default.cyan(` + Added: ${S.join(", ")}`)),$.length>0&&console.log(m.default.yellow(` ~ Updated: ${$.join(", ")}`))):h.succeed(`Generated ${g} (${Object.keys(d).length} secrets)`)}catch(d){h.fail("Failed to generate file."),console.error(m.default.red(d?.response?.data?.error||"An unexpected error occurred")),process.exit(1)}});0&&(module.exports={generateCommand});
|
package/dist/commands/history.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var C=Object.create;var g=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var P=Object.getPrototypeOf,L=Object.prototype.hasOwnProperty;var _=(e,t)=>{for(var s in t)g(e,s,{get:t[s],enumerable:!0})},$=(e,t,s,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of R(t))!L.call(e,o)&&o!==s&&g(e,o,{get:()=>t[o],enumerable:!(r=U(t,o))||r.enumerable});return e};var p=(e,t,s)=>(s=e!=null?C(P(e)):{},$(t||!e||!e.__esModule?g(s,"default",{value:e,enumerable:!0}):s,e)),D=e=>$(g({},"__esModule",{value:!0}),e);var B={};_(B,{historyCommand:()=>I,rollbackCommand:()=>A});module.exports=D(B);var f=require("commander"),a=p(require("chalk"));var k=p(require("axios"));var j=p(require("conf")),d=p(require("fs")),S=p(require("path")),u="https://www.xtrasecurity.in/api",i=new j.default({projectName:"xtra-cli",defaults:{apiUrl:u}}),v=i.get("apiUrl");v&&!process.env.XTRA_API_URL&&v.includes("xtra-security.vercel.app")&&i.set("apiUrl",u);var l=()=>({...i.store,apiUrl:process.env.XTRA_API_URL||i.get("apiUrl")||u});var h=()=>i.get("token");var y=()=>{let e={};try{let t=S.default.join(process.cwd(),".xtrarc");d.default.existsSync(t)&&(e=JSON.parse(d.default.readFileSync(t,"utf-8")))}catch{}return{project:e.project||i.get("project")||"",env:e.env||i.get("env")||"development",branch:e.branch||i.get("branch")||"main"}};var b=p(require("fs")),x=p(require("path")),V=JSON.parse(b.readFileSync(x.join(__dirname,"../../package.json"),"utf-8")),n=()=>{let{apiUrl:e}=l(),t=h();return k.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":V.version,...t?{Authorization:`Bearer ${t}`}:{}}})},m={login:async(e,t,s)=>(await n().post("/auth/cli-login",{email:e,password:t,apiKey:s})).data,getSecrets:async(e,t,s="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets?branch=${s}`)).data,getSecretVersions:async(e,t,s="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(e,t,s,r,o="main")=>(await n().post(`/projects/${e}/envs/${t}/secrets`,{secrets:s,expectedVersions:r,branch:o})).data,getSecretDetails:async(e,t,s,r="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets/${s}?branch=${r}`)).data,syncLogs:async e=>(await n().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,t,s,r,o,c)=>(await n().post(`/projects/${e}/envs/${t}/secrets/link`,{key:s,sourceProjectId:r,sourceEnv:o,sourceKey:c})).data,rotateSecret:async(e,t,s,r,o)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${s}/rotate`,{strategy:r,parsedNewValue:o})).data,promoteSecret:async(e,t,s)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await n().get("/audit/verify")).data,exportAuditLogs:async(e,t,s,r)=>{let o={format:e};return t&&(o.startDate=t),s&&(o.endDate=s),r&&(o.projectId=r),(await n().post("/audit/export",o,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,t,s,r)=>(await n().post("/access/request",{projectId:e,secretId:r,reason:t,duration:s})).data,approveAccess:async(e,t)=>(await n().post("/access/approve",{requestId:e,decision:t})).data,listAccessRequests:async e=>{let{workspace:t}=l(),s=t?`&workspaceId=${t}`:"";return(await n().get(`/access/list?mode=${e}${s}`)).data},getAccessRequestStatus:async e=>(await n().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=l(),t=e?`/project?workspaceId=${e}`:"/project";return(await n().get(t)).data},getBranches:async e=>(await n().get(`/branch?projectId=${e}`)).data,createBranch:async(e,t,s)=>(await n().post("/branch",{projectId:e,name:t,description:s})).data,deleteBranch:async e=>(await n().delete(`/branch/${e}`)).data,updateBranch:async(e,t)=>(await n().put("/branch",{id:e,...t})).data,getRoles:async()=>(await n().get("/admin/roles")).data,getUsers:async e=>{let t=e?`?teamId=${e}`:"";return(await n().get(`/admin/users${t}`)).data},setUserRole:async(e,t,s)=>(await n().put("/admin/users/role",{email:e,role:t,teamId:s})).data,getIntegrationStatus:async e=>(await n().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await n().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await n().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,t)=>{let s=new URLSearchParams(t).toString();return(await n().get(`/projects/${e}/kubernetes?${s}`)).data},getSecretHistory:async(e,t,s)=>(await n().get(`/projects/${e}/envs/${t}/secrets/${s}/history`)).data,rollbackSecret:async(e,t,s,r)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${s}/history`,{version:r})).data,cloneEnvironment:async(e,t,s,r,o)=>(await n().post(`/projects/${e}/envs/clone`,{fromEnv:t,toEnv:s,overwrite:r,branch:o})).data,generateJitLink:async e=>(await n().post("/jit/generate",e)).data,claimJitLink:async e=>(await n().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await n().get(`/jit/${e}`)).data,getServiceAccounts:async e=>(await n().get(`/projects/${e}/service-accounts`)).data,createServiceAccount:async(e,t)=>(await n().post(`/projects/${e}/service-accounts`,t)).data,deleteServiceAccount:async(e,t)=>(await n().delete(`/projects/${e}/service-accounts/${t}`)).data,getServiceAccountKeys:async(e,t)=>(await n().get(`/projects/${e}/service-accounts/${t}/keys`)).data,createServiceAccountKey:async(e,t,s,r)=>(await n().post(`/projects/${e}/service-accounts/${t}/keys`,{label:s,expiresAt:r})).data,deleteServiceAccountKey:async(e,t,s)=>(await n().delete(`/projects/${e}/service-accounts/${t}/keys/${s}`)).data,post:async(e,t)=>(await n().post(e,t)).data};var I=new f.Command("history");I.argument("<key>","Secret key").option("-p, --project <id>","Project ID").option("-e, --env <environment>","Environment","development").description("View version history of a secret").action(async(e,t)=>{try{let s=t.project;s||(s=y().project,s||(console.error(a.default.red("Error: Project ID not found. Use -p <id> or run 'xtra project set' first.")),process.exit(1)));let r=await m.getSecretHistory(s,t.env,e);console.log(a.default.bold(`
|
|
2
2
|
History for ${e} (${t.env})`)),console.log(a.default.gray(`Current Version: ${r.currentVersion}
|
|
3
|
-
`));let o=r.history||[];o.length===0?console.log("No history found."):o.forEach(
|
|
4
|
-
Successfully rolled back to v${t} (New current version: v${o.version})`)):console.log(a.default.red("Rollback failed."))}catch(r){console.error(a.default.red("Error rolling back:"),r
|
|
3
|
+
`));let o=r.history||[];o.length===0?console.log("No history found."):o.forEach(c=>{let w=new Date(c.updatedAt).toLocaleString();console.log(a.default.blue(`v${c.version}`)+` - ${w} by ${c.updatedBy}`),c.description&&console.log(a.default.gray(` ${c.description}`)),console.log("")})}catch(s){console.error(a.default.red("Error fetching history:"),s?.response?.data?.error||"Unknown error")}});var A=new f.Command("rollback");A.argument("<key>","Secret key").argument("<version>","Version to rollback to").option("-p, --project <id>","Project ID").option("-e, --env <environment>","Environment","development").description("Rollback a secret to a previous version").action(async(e,t,s)=>{try{let r=s.project;r||(r=y().project,r||(console.error(a.default.red("Error: Project ID not found. Use -p <id> or run 'xtra project set' first.")),process.exit(1))),console.log(a.default.yellow(`Rolling back ${e} to v${t}...`));let o=await m.rollbackSecret(r,s.env,e,t);o.success?console.log(a.default.green(`
|
|
4
|
+
Successfully rolled back to v${t} (New current version: v${o.version})`)):console.log(a.default.red("Rollback failed."))}catch(r){console.error(a.default.red("Error rolling back:"),r?.response?.data?.error||"Unknown error")}});0&&(module.exports={historyCommand,rollbackCommand});
|
package/dist/commands/import.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var gt=Object.create;var S=Object.defineProperty;var dt=Object.getOwnPropertyDescriptor;var ut=Object.getOwnPropertyNames;var ft=Object.getPrototypeOf,lt=Object.prototype.hasOwnProperty;var b=(t,e)=>()=>(t&&(e=t(t=0)),e);var D=(t,e)=>{for(var s in e)S(t,s,{get:e[s],enumerable:!0})},J=(t,e,s,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ut(e))!lt.call(t,n)&&n!==s&&S(t,n,{get:()=>e[n],enumerable:!(r=dt(e,n))||r.enumerable});return t};var a=(t,e,s)=>(s=t!=null?gt(ft(t)):{},J(e||!t||!t.__esModule?S(s,"default",{value:t,enumerable:!0}):s,t)),F=t=>J(S({},"__esModule",{value:!0}),t);var q,U,G,E,f,O,l,V,L,$=b(()=>{q=a(require("conf")),U=a(require("fs")),G=a(require("path")),E="https://www.xtrasecurity.in/api",f=new q.default({projectName:"xtra-cli",defaults:{apiUrl:E}}),O=f.get("apiUrl");O&&!process.env.XTRA_API_URL&&(O.includes("localhost")||O.includes("xtra-security.vercel.app"))&&f.set("apiUrl",E);l=()=>({...f.store,apiUrl:process.env.XTRA_API_URL||f.get("apiUrl")||E}),V=()=>f.get("token"),L=()=>{let t={};try{let e=G.default.join(process.cwd(),".xtrarc");U.default.existsSync(e)&&(t=JSON.parse(U.default.readFileSync(e,"utf-8")))}catch{}return{project:t.project||f.get("project")||"",env:t.env||f.get("env")||"development",branch:t.branch||f.get("branch")||"main"}}});var K,M,z,mt,o,k,P=b(()=>{K=a(require("axios"));$();M=a(require("fs")),z=a(require("path")),mt=JSON.parse(M.readFileSync(z.join(__dirname,"../../package.json"),"utf-8")),o=()=>{let{apiUrl:t}=l(),e=V();return K.default.create({baseURL:t,headers:{"Content-Type":"application/json","X-CLI-Version":mt.version,...e?{Authorization:`Bearer ${e}`}:{}}})},k={login:async(t,e,s)=>(await o().post("/auth/cli-login",{email:t,password:e,apiKey:s})).data,getSecrets:async(t,e,s="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets?branch=${s}`)).data,getSecretVersions:async(t,e,s="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(t,e,s,r,n="main")=>(await o().post(`/projects/${t}/envs/${e}/secrets`,{secrets:s,expectedVersions:r,branch:n})).data,getSecretDetails:async(t,e,s,r="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets/${s}?branch=${r}`)).data,syncLogs:async t=>(await o().post("/audit/cli-logs",{logs:t})).data,linkSecret:async(t,e,s,r,n,i)=>(await o().post(`/projects/${t}/envs/${e}/secrets/link`,{key:s,sourceProjectId:r,sourceEnv:n,sourceKey:i})).data,rotateSecret:async(t,e,s,r,n)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/rotate`,{strategy:r,parsedNewValue:n})).data,promoteSecret:async(t,e,s)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await o().get("/audit/verify")).data,exportAuditLogs:async(t,e,s,r)=>{let n={format:t};return e&&(n.startDate=e),s&&(n.endDate=s),r&&(n.projectId=r),(await o().post("/audit/export",n,{responseType:t==="csv"?"text":"json"})).data},requestAccess:async(t,e,s,r)=>(await o().post("/access/request",{projectId:t,secretId:r,reason:e,duration:s})).data,approveAccess:async(t,e)=>(await o().post("/access/approve",{requestId:t,decision:e})).data,listAccessRequests:async t=>{let{workspace:e}=l(),s=e?`&workspaceId=${e}`:"";return(await o().get(`/access/list?mode=${t}${s}`)).data},getAccessRequestStatus:async t=>(await o().get(`/access/request?id=${t}`)).data,getProjects:async()=>{let{workspace:t}=l(),e=t?`/project?workspaceId=${t}`:"/project";return(await o().get(e)).data},getBranches:async t=>(await o().get(`/branch?projectId=${t}`)).data,createBranch:async(t,e,s)=>(await o().post("/branch",{projectId:t,name:e,description:s})).data,deleteBranch:async t=>(await o().delete(`/branch/${t}`)).data,updateBranch:async(t,e)=>(await o().put("/branch",{id:t,...e})).data,getRoles:async()=>(await o().get("/admin/roles")).data,getUsers:async t=>{let e=t?`?teamId=${t}`:"";return(await o().get(`/admin/users${e}`)).data},setUserRole:async(t,e,s)=>(await o().put("/admin/users/role",{email:t,role:e,teamId:s})).data,getIntegrationStatus:async t=>(await o().get(`/integrations/${t}`)).data,getIntegrationRepos:async t=>(await o().get(`/integrations/${t}/sync`)).data.repos,syncSecretsToGithub:async t=>(await o().post("/integrations/github/sync",t)).data,exportKubernetesSecret:async(t,e)=>{let s=new URLSearchParams(e).toString();return(await o().get(`/projects/${t}/kubernetes?${s}`)).data},getSecretHistory:async(t,e,s)=>(await o().get(`/projects/${t}/envs/${e}/secrets/${s}/history`)).data,rollbackSecret:async(t,e,s,r)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/history`,{version:r})).data,cloneEnvironment:async(t,e,s,r,n)=>(await o().post(`/projects/${t}/envs/clone`,{fromEnv:e,toEnv:s,overwrite:r,branch:n})).data,generateJitLink:async t=>(await o().post("/jit/generate",t)).data,claimJitLink:async t=>(await o().post("/jit/claim",{token:t})).data,getJitInfo:async t=>(await o().get(`/jit/${t}`)).data,post:async(t,e)=>(await o().post(t,e)).data}});function W(){let t=H.get("masterKey");t||(t=m.default.randomBytes(32).toString("hex"),H.set("masterKey",t));let e=(0,Y.machineIdSync)();return m.default.createHash("sha256").update(t+e).digest()}var m,X,Y,Q,H,Z,tt,et=b(()=>{m=a(require("crypto")),X=a(require("conf")),Y=require("node-machine-id"),Q="aes-256-gcm",H=new X.default({projectName:"xtra-cli-crypto"});Z=t=>{let e=m.default.randomBytes(16),s=W(),r=m.default.createCipheriv(Q,s,e),n=r.update(t,"utf8","hex");n+=r.final("hex");let i=r.getAuthTag();return{iv:e.toString("hex"),content:n,tag:i.toString("hex")}},tt=t=>{let e=W(),s=Buffer.from(t.iv,"hex"),r=Buffer.from(t.tag,"hex"),n=m.default.createDecipheriv(Q,e,s);n.setAuthTag(r);let i=n.update(t.content,"hex","utf8");return i+=n.final("utf8"),i}});var nt={};D(nt,{loadAuditLogs:()=>I,logAudit:()=>ht,saveAuditLogs:()=>A,syncAuditLogs:()=>vt});function yt(t){if(!t||typeof t!="object")return t;let e={...t},s=["password","token","secret","value","apiKey","secretValue"];for(let r of Object.keys(e))s.some(n=>r.toLowerCase().includes(n))&&(e[r]="[REDACTED]");return e}async function rt(t){try{if(!l().token)return!1;let s={action:t.action,entity:"cli-project",entityId:t.projectId||"global",details:yt(t.details),timestamp:t.timestamp,projectId:t.projectId};return await k.post("/audit/cli-logs",{logs:[s]}),!0}catch(e){return process.env.DEBUG&&console.error("Failed to send audit log to backend:",e),!1}}function ht(t,e,s,r){let n={id:(0,st.v4)(),timestamp:new Date().toISOString(),action:t,projectId:e,environment:s,details:r,synced:!1},i=I();i.push(n),A(i),rt(n).then(h=>{if(h){n.synced=!0;let w=I(),d=w.findIndex(p=>p.id===n.id);d!==-1&&(w[d].synced=!0,A(w))}}).catch(()=>{})}function I(){if(!y.default.existsSync(B))return[];try{let t=y.default.readFileSync(B,"utf-8"),e=JSON.parse(t),s=tt(e);return JSON.parse(s)}catch{return[]}}function A(t){y.default.existsSync(N)||y.default.mkdirSync(N,{recursive:!0});let e=JSON.stringify(t),s=Z(e);y.default.writeFileSync(B,JSON.stringify(s),"utf-8")}async function vt(){let t=I(),e=t.filter(r=>!r.synced);if(e.length===0)return 0;let s=0;for(let r of e)await rt(r)&&(r.synced=!0,s++);return s>0&&A(t),s}var y,T,st,N,B,ot=b(()=>{y=a(require("fs")),T=a(require("path")),st=require("uuid");et();$();P();N=T.default.join(process.cwd(),".xtra"),B=T.default.join(N,"audit.enc")});var wt={};D(wt,{importCommand:()=>xt});module.exports=F(wt);var it=require("commander");P();var x=a(require("chalk")),_=a(require("fs")),C=a(require("path")),at=a(require("dotenv")),ct=require("csv-parse/sync");$();var xt=new it.Command("import").description("Import secrets from a file (JSON, Dotenv, CSV)").argument("<file>","Path to the file to import").option("-p, --project <projectId>","Project ID").option("-e, --env <environment>","Environment (development, staging, production)","development").option("-b, --branch <branchName>","Branch Name").option("-f, --format <format>","Input format (json, dotenv, csv). Auto-detected if omitted.").option("--prefix <prefix>","Add prefix to all imported keys").option("--overwrite","Overwrite existing secrets (default: merged, but API usually upserts)",!0).action(async(t,e)=>{let{project:s,env:r,branch:n,format:i,prefix:h}=e;s||(s=L().project),n||(n=L().branch||"main"),r={dev:"development",stg:"staging",prod:"production"}[r]||r,s||(console.error(x.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1));let d=C.default.resolve(process.cwd(),t);_.default.existsSync(d)||(console.error(x.default.red(`Error: File not found: ${d}`)),process.exit(1));let p=i;if(!p){let c=C.default.extname(d).toLowerCase();c===".json"?p="json":c===".env"?p="dotenv":c===".csv"?p="csv":(console.error(x.default.red("Error: Could not detect format. Please specify -f <format>")),process.exit(1))}let v=require("ora")(`Reading ${p} file...`).start(),R=_.default.readFileSync(d,"utf-8"),g={};try{switch(p.toLowerCase()){case"json":g=JSON.parse(R);break;case"dotenv":g=at.default.parse(R);break;case"csv":(0,ct.parse)(R,{columns:!0,skip_empty_lines:!0}).forEach(u=>{let j=u.key||u.Key||u.KEY,pt=u.value||u.Value||u.VALUE;j&&(g[j]=pt||"")});break;default:v.fail(`Unsupported format: ${p}`),process.exit(1)}if(Object.keys(g).length===0){v.fail("No valid secrets found in file.");return}if(h){let c={};Object.entries(g).forEach(([u,j])=>{c[`${h}${u}`]=j}),g=c}v.text=`Importing ${Object.keys(g).length} secrets to ${r} (branch: ${n})...`,await k.setSecrets(s,r,g,void 0,n),v.succeed(`Successfully imported ${Object.keys(g).length} secrets.`);try{let{logAudit:c}=(ot(),F(nt));c("SECRET_IMPORT",s,r,{file:C.default.basename(d),format:p,count:Object.keys(g).length,branch:n})}catch{}}catch(c){v.fail("Import failed."),console.error(x.default.red(c.message)),process.exit(1)}});0&&(module.exports={importCommand});
|
|
1
|
+
var ge=Object.create;var S=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var fe=Object.getPrototypeOf,le=Object.prototype.hasOwnProperty;var $=(e,t)=>()=>(e&&(t=e(e=0)),t);var _=(e,t)=>{for(var s in t)S(e,s,{get:t[s],enumerable:!0})},D=(e,t,s,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of ue(t))!le.call(e,n)&&n!==s&&S(e,n,{get:()=>t[n],enumerable:!(r=de(t,n))||r.enumerable});return e};var a=(e,t,s)=>(s=e!=null?ge(fe(e)):{},D(t||!e||!e.__esModule?S(s,"default",{value:e,enumerable:!0}):s,e)),J=e=>D(S({},"__esModule",{value:!0}),e);var K,O,V,U,f,F,l,q,E,b=$(()=>{K=a(require("conf")),O=a(require("fs")),V=a(require("path")),U="https://www.xtrasecurity.in/api",f=new K.default({projectName:"xtra-cli",defaults:{apiUrl:U}}),F=f.get("apiUrl");F&&!process.env.XTRA_API_URL&&F.includes("xtra-security.vercel.app")&&f.set("apiUrl",U);l=()=>({...f.store,apiUrl:process.env.XTRA_API_URL||f.get("apiUrl")||U}),q=()=>f.get("token"),E=()=>{let e={};try{let t=V.default.join(process.cwd(),".xtrarc");O.default.existsSync(t)&&(e=JSON.parse(O.default.readFileSync(t,"utf-8")))}catch{}return{project:e.project||f.get("project")||"",env:e.env||f.get("env")||"development",branch:e.branch||f.get("branch")||"main"}}});var G,M,z,me,o,k,L=$(()=>{G=a(require("axios"));b();M=a(require("fs")),z=a(require("path")),me=JSON.parse(M.readFileSync(z.join(__dirname,"../../package.json"),"utf-8")),o=()=>{let{apiUrl:e}=l(),t=q();return G.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":me.version,...t?{Authorization:`Bearer ${t}`}:{}}})},k={login:async(e,t,s)=>(await o().post("/auth/cli-login",{email:e,password:t,apiKey:s})).data,getSecrets:async(e,t,s="main")=>(await o().get(`/projects/${e}/envs/${t}/secrets?branch=${s}`)).data,getSecretVersions:async(e,t,s="main")=>(await o().get(`/projects/${e}/envs/${t}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(e,t,s,r,n="main")=>(await o().post(`/projects/${e}/envs/${t}/secrets`,{secrets:s,expectedVersions:r,branch:n})).data,getSecretDetails:async(e,t,s,r="main")=>(await o().get(`/projects/${e}/envs/${t}/secrets/${s}?branch=${r}`)).data,syncLogs:async e=>(await o().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,t,s,r,n,i)=>(await o().post(`/projects/${e}/envs/${t}/secrets/link`,{key:s,sourceProjectId:r,sourceEnv:n,sourceKey:i})).data,rotateSecret:async(e,t,s,r,n)=>(await o().post(`/projects/${e}/envs/${t}/secrets/${s}/rotate`,{strategy:r,parsedNewValue:n})).data,promoteSecret:async(e,t,s)=>(await o().post(`/projects/${e}/envs/${t}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await o().get("/audit/verify")).data,exportAuditLogs:async(e,t,s,r)=>{let n={format:e};return t&&(n.startDate=t),s&&(n.endDate=s),r&&(n.projectId=r),(await o().post("/audit/export",n,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,t,s,r)=>(await o().post("/access/request",{projectId:e,secretId:r,reason:t,duration:s})).data,approveAccess:async(e,t)=>(await o().post("/access/approve",{requestId:e,decision:t})).data,listAccessRequests:async e=>{let{workspace:t}=l(),s=t?`&workspaceId=${t}`:"";return(await o().get(`/access/list?mode=${e}${s}`)).data},getAccessRequestStatus:async e=>(await o().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=l(),t=e?`/project?workspaceId=${e}`:"/project";return(await o().get(t)).data},getBranches:async e=>(await o().get(`/branch?projectId=${e}`)).data,createBranch:async(e,t,s)=>(await o().post("/branch",{projectId:e,name:t,description:s})).data,deleteBranch:async e=>(await o().delete(`/branch/${e}`)).data,updateBranch:async(e,t)=>(await o().put("/branch",{id:e,...t})).data,getRoles:async()=>(await o().get("/admin/roles")).data,getUsers:async e=>{let t=e?`?teamId=${e}`:"";return(await o().get(`/admin/users${t}`)).data},setUserRole:async(e,t,s)=>(await o().put("/admin/users/role",{email:e,role:t,teamId:s})).data,getIntegrationStatus:async e=>(await o().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await o().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await o().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,t)=>{let s=new URLSearchParams(t).toString();return(await o().get(`/projects/${e}/kubernetes?${s}`)).data},getSecretHistory:async(e,t,s)=>(await o().get(`/projects/${e}/envs/${t}/secrets/${s}/history`)).data,rollbackSecret:async(e,t,s,r)=>(await o().post(`/projects/${e}/envs/${t}/secrets/${s}/history`,{version:r})).data,cloneEnvironment:async(e,t,s,r,n)=>(await o().post(`/projects/${e}/envs/clone`,{fromEnv:t,toEnv:s,overwrite:r,branch:n})).data,generateJitLink:async e=>(await o().post("/jit/generate",e)).data,claimJitLink:async e=>(await o().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await o().get(`/jit/${e}`)).data,getServiceAccounts:async e=>(await o().get(`/projects/${e}/service-accounts`)).data,createServiceAccount:async(e,t)=>(await o().post(`/projects/${e}/service-accounts`,t)).data,deleteServiceAccount:async(e,t)=>(await o().delete(`/projects/${e}/service-accounts/${t}`)).data,getServiceAccountKeys:async(e,t)=>(await o().get(`/projects/${e}/service-accounts/${t}/keys`)).data,createServiceAccountKey:async(e,t,s,r)=>(await o().post(`/projects/${e}/service-accounts/${t}/keys`,{label:s,expiresAt:r})).data,deleteServiceAccountKey:async(e,t,s)=>(await o().delete(`/projects/${e}/service-accounts/${t}/keys/${s}`)).data,post:async(e,t)=>(await o().post(e,t)).data}});function W(){let e=H.get("masterKey");e||(e=m.default.randomBytes(32).toString("hex"),H.set("masterKey",e));let t=(0,Y.machineIdSync)();return m.default.createHash("sha256").update(e+t).digest()}var m,X,Y,Q,H,Z,ee,te=$(()=>{m=a(require("crypto")),X=a(require("conf")),Y=require("node-machine-id"),Q="aes-256-gcm",H=new X.default({projectName:"xtra-cli-crypto"});Z=e=>{let t=m.default.randomBytes(16),s=W(),r=m.default.createCipheriv(Q,s,t),n=r.update(e,"utf8","hex");n+=r.final("hex");let i=r.getAuthTag();return{iv:t.toString("hex"),content:n,tag:i.toString("hex")}},ee=e=>{let t=W(),s=Buffer.from(e.iv,"hex"),r=Buffer.from(e.tag,"hex"),n=m.default.createDecipheriv(Q,t,s);n.setAuthTag(r);let i=n.update(e.content,"hex","utf8");return i+=n.final("utf8"),i}});var ne={};_(ne,{loadAuditLogs:()=>I,logAudit:()=>he,saveAuditLogs:()=>A,syncAuditLogs:()=>ve});function ye(e){if(!e||typeof e!="object")return e;let t={...e},s=["password","token","secret","value","apiKey","secretValue"];for(let r of Object.keys(t))s.some(n=>r.toLowerCase().includes(n))&&(t[r]="[REDACTED]");return t}async function re(e){try{if(!l().token)return!1;let s={action:e.action,entity:"cli-project",entityId:e.projectId||"global",details:ye(e.details),timestamp:e.timestamp,projectId:e.projectId};return await k.post("/audit/cli-logs",{logs:[s]}),!0}catch(t){return process.env.DEBUG&&console.error("Failed to send audit log to backend:",t),!1}}function he(e,t,s,r){let n={id:(0,se.v4)(),timestamp:new Date().toISOString(),action:e,projectId:t,environment:s,details:r,synced:!1},i=I();i.push(n),A(i),re(n).then(h=>{if(h){n.synced=!0;let j=I(),d=j.findIndex(p=>p.id===n.id);d!==-1&&(j[d].synced=!0,A(j))}}).catch(()=>{})}function I(){if(!y.default.existsSync(N))return[];try{let e=y.default.readFileSync(N,"utf-8"),t=JSON.parse(e),s=ee(t);return JSON.parse(s)}catch{return[]}}function A(e){y.default.existsSync(P)||y.default.mkdirSync(P,{recursive:!0});let t=JSON.stringify(e),s=Z(t);y.default.writeFileSync(N,JSON.stringify(s),"utf-8")}async function ve(){let e=I(),t=e.filter(r=>!r.synced);if(t.length===0)return 0;let s=0;for(let r of t)await re(r)&&(r.synced=!0,s++);return s>0&&A(e),s}var y,B,se,P,N,oe=$(()=>{y=a(require("fs")),B=a(require("path")),se=require("uuid");te();b();L();P=B.default.join(process.cwd(),".xtra"),N=B.default.join(P,"audit.enc")});var je={};_(je,{importCommand:()=>we});module.exports=J(je);var ie=require("commander");L();var w=a(require("chalk")),T=a(require("fs")),C=a(require("path")),ae=a(require("dotenv")),ce=require("csv-parse/sync");b();var we=new ie.Command("import").description("Import secrets from a file (JSON, Dotenv, CSV)").argument("<file>","Path to the file to import").option("-p, --project <projectId>","Project ID").option("-e, --env <environment>","Environment (development, staging, production)","development").option("-b, --branch <branchName>","Branch Name").option("-f, --format <format>","Input format (json, dotenv, csv). Auto-detected if omitted.").option("--prefix <prefix>","Add prefix to all imported keys").option("--overwrite","Overwrite existing secrets (default: merged, but API usually upserts)",!0).action(async(e,t)=>{let{project:s,env:r,branch:n,format:i,prefix:h}=t;s||(s=E().project),n||(n=E().branch||"main"),r={dev:"development",stg:"staging",prod:"production"}[r]||r,s||(console.error(w.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1));let d=C.default.resolve(process.cwd(),e);T.default.existsSync(d)||(console.error(w.default.red(`Error: File not found: ${d}`)),process.exit(1));let p=i;if(!p){let c=C.default.extname(d).toLowerCase();c===".json"?p="json":c===".env"?p="dotenv":c===".csv"?p="csv":(console.error(w.default.red("Error: Could not detect format. Please specify -f <format>")),process.exit(1))}let v=require("ora")(`Reading ${p} file...`).start(),R=T.default.readFileSync(d,"utf-8"),g={};try{switch(p.toLowerCase()){case"json":g=JSON.parse(R);break;case"dotenv":g=ae.default.parse(R);break;case"csv":(0,ce.parse)(R,{columns:!0,skip_empty_lines:!0}).forEach(u=>{let x=u.key||u.Key||u.KEY,pe=u.value||u.Value||u.VALUE;x&&(g[x]=pe||"")});break;default:v.fail(`Unsupported format: ${p}`),process.exit(1)}if(Object.keys(g).length===0){v.fail("No valid secrets found in file.");return}if(h){let c={};Object.entries(g).forEach(([u,x])=>{c[`${h}${u}`]=x}),g=c}v.text=`Importing ${Object.keys(g).length} secrets to ${r} (branch: ${n})...`,await k.setSecrets(s,r,g,void 0,n),v.succeed(`Successfully imported ${Object.keys(g).length} secrets.`);try{let{logAudit:c}=(oe(),J(ne));c("SECRET_IMPORT",s,r,{file:C.default.basename(d),format:p,count:Object.keys(g).length,branch:n})}catch{}}catch(c){v.fail("Import failed."),console.error(w.default.red(c?.response?.data?.error||"An unexpected error occurred")),process.exit(1)}});0&&(module.exports={importCommand});
|
package/dist/commands/init.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var
|
|
1
|
+
var lt=Object.create;var A=Object.defineProperty;var yt=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var ft=Object.getPrototypeOf,ht=Object.prototype.hasOwnProperty;var I=(t,e)=>()=>(t&&(e=t(t=0)),e);var C=(t,e)=>{for(var s in e)A(t,s,{get:e[s],enumerable:!0})},V=(t,e,s,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of mt(e))!ht.call(t,r)&&r!==s&&A(t,r,{get:()=>e[r],enumerable:!(n=yt(e,r))||n.enumerable});return t};var g=(t,e,s)=>(s=t!=null?lt(ft(t)):{},V(e||!t||!t.__esModule?A(s,"default",{value:t,enumerable:!0}):s,t)),wt=t=>V(A({},"__esModule",{value:!0}),t);var H={};C(H,{clearConfig:()=>jt,deleteConfig:()=>vt,getAuthToken:()=>T,getBreakGlassSession:()=>xt,getConfig:()=>h,getConfigValue:()=>O,getProjectConfig:()=>$t,getRcConfig:()=>bt,setBreakGlassSession:()=>St,setConfig:()=>x});var z,f,_,L,p,X,h,O,x,jt,vt,T,xt,St,$t,bt,S=I(()=>{z=g(require("conf")),f=g(require("fs")),_=g(require("path")),L="https://www.xtrasecurity.in/api",p=new z.default({projectName:"xtra-cli",defaults:{apiUrl:L}}),X=p.get("apiUrl");X&&!process.env.XTRA_API_URL&&X.includes("xtra-security.vercel.app")&&p.set("apiUrl",L);h=()=>({...p.store,apiUrl:process.env.XTRA_API_URL||p.get("apiUrl")||L}),O=t=>p.get(t),x=(t,e)=>{if(p.set(t,e),t==="token"&&process.platform!=="win32"&&f.default.existsSync(p.path))try{f.default.chmodSync(p.path,384)}catch{}},jt=()=>p.clear(),vt=t=>p.delete(t),T=()=>p.get("token"),xt=()=>p.get("breakGlassSessionId"),St=t=>{t?p.set("breakGlassSessionId",t):p.delete("breakGlassSessionId")},$t=async()=>{try{let t=_.default.join(process.cwd(),"xtra.json");if(f.default.existsSync(t)){let e=f.default.readFileSync(t,"utf-8");return JSON.parse(e)}return null}catch{return null}},bt=()=>{let t={};try{let e=_.default.join(process.cwd(),".xtrarc");f.default.existsSync(e)&&(t=JSON.parse(f.default.readFileSync(e,"utf-8")))}catch{}return{project:t.project||p.get("project")||"",env:t.env||p.get("env")||"development",branch:t.branch||p.get("branch")||"main"}}});var E={};C(E,{api:()=>N});var M,Y,Q,kt,o,N,P=I(()=>{M=g(require("axios"));S();Y=g(require("fs")),Q=g(require("path")),kt=JSON.parse(Y.readFileSync(Q.join(__dirname,"../../package.json"),"utf-8")),o=()=>{let{apiUrl:t}=h(),e=T();return M.default.create({baseURL:t,headers:{"Content-Type":"application/json","X-CLI-Version":kt.version,...e?{Authorization:`Bearer ${e}`}:{}}})},N={login:async(t,e,s)=>(await o().post("/auth/cli-login",{email:t,password:e,apiKey:s})).data,getSecrets:async(t,e,s="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets?branch=${s}`)).data,getSecretVersions:async(t,e,s="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(t,e,s,n,r="main")=>(await o().post(`/projects/${t}/envs/${e}/secrets`,{secrets:s,expectedVersions:n,branch:r})).data,getSecretDetails:async(t,e,s,n="main")=>(await o().get(`/projects/${t}/envs/${e}/secrets/${s}?branch=${n}`)).data,syncLogs:async t=>(await o().post("/audit/cli-logs",{logs:t})).data,linkSecret:async(t,e,s,n,r,a)=>(await o().post(`/projects/${t}/envs/${e}/secrets/link`,{key:s,sourceProjectId:n,sourceEnv:r,sourceKey:a})).data,rotateSecret:async(t,e,s,n,r)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/rotate`,{strategy:n,parsedNewValue:r})).data,promoteSecret:async(t,e,s)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await o().get("/audit/verify")).data,exportAuditLogs:async(t,e,s,n)=>{let r={format:t};return e&&(r.startDate=e),s&&(r.endDate=s),n&&(r.projectId=n),(await o().post("/audit/export",r,{responseType:t==="csv"?"text":"json"})).data},requestAccess:async(t,e,s,n)=>(await o().post("/access/request",{projectId:t,secretId:n,reason:e,duration:s})).data,approveAccess:async(t,e)=>(await o().post("/access/approve",{requestId:t,decision:e})).data,listAccessRequests:async t=>{let{workspace:e}=h(),s=e?`&workspaceId=${e}`:"";return(await o().get(`/access/list?mode=${t}${s}`)).data},getAccessRequestStatus:async t=>(await o().get(`/access/request?id=${t}`)).data,getProjects:async()=>{let{workspace:t}=h(),e=t?`/project?workspaceId=${t}`:"/project";return(await o().get(e)).data},getBranches:async t=>(await o().get(`/branch?projectId=${t}`)).data,createBranch:async(t,e,s)=>(await o().post("/branch",{projectId:t,name:e,description:s})).data,deleteBranch:async t=>(await o().delete(`/branch/${t}`)).data,updateBranch:async(t,e)=>(await o().put("/branch",{id:t,...e})).data,getRoles:async()=>(await o().get("/admin/roles")).data,getUsers:async t=>{let e=t?`?teamId=${t}`:"";return(await o().get(`/admin/users${e}`)).data},setUserRole:async(t,e,s)=>(await o().put("/admin/users/role",{email:t,role:e,teamId:s})).data,getIntegrationStatus:async t=>(await o().get(`/integrations/${t}`)).data,getIntegrationRepos:async t=>(await o().get(`/integrations/${t}/sync`)).data.repos,syncSecretsToGithub:async t=>(await o().post("/integrations/github/sync",t)).data,exportKubernetesSecret:async(t,e)=>{let s=new URLSearchParams(e).toString();return(await o().get(`/projects/${t}/kubernetes?${s}`)).data},getSecretHistory:async(t,e,s)=>(await o().get(`/projects/${t}/envs/${e}/secrets/${s}/history`)).data,rollbackSecret:async(t,e,s,n)=>(await o().post(`/projects/${t}/envs/${e}/secrets/${s}/history`,{version:n})).data,cloneEnvironment:async(t,e,s,n,r)=>(await o().post(`/projects/${t}/envs/clone`,{fromEnv:e,toEnv:s,overwrite:n,branch:r})).data,generateJitLink:async t=>(await o().post("/jit/generate",t)).data,claimJitLink:async t=>(await o().post("/jit/claim",{token:t})).data,getJitInfo:async t=>(await o().get(`/jit/${t}`)).data,getServiceAccounts:async t=>(await o().get(`/projects/${t}/service-accounts`)).data,createServiceAccount:async(t,e)=>(await o().post(`/projects/${t}/service-accounts`,e)).data,deleteServiceAccount:async(t,e)=>(await o().delete(`/projects/${t}/service-accounts/${e}`)).data,getServiceAccountKeys:async(t,e)=>(await o().get(`/projects/${t}/service-accounts/${e}/keys`)).data,createServiceAccountKey:async(t,e,s,n)=>(await o().post(`/projects/${t}/service-accounts/${e}/keys`,{label:s,expiresAt:n})).data,deleteServiceAccountKey:async(t,e,s)=>(await o().delete(`/projects/${t}/service-accounts/${e}/keys/${s}`)).data,post:async(t,e)=>(await o().post(t,e)).data}});function st(){let t=W.get("masterKey");t||(t=j.default.randomBytes(32).toString("hex"),W.set("masterKey",t));let e=(0,tt.machineIdSync)();return j.default.createHash("sha256").update(t+e).digest()}var j,Z,tt,et,W,nt,rt,ot=I(()=>{j=g(require("crypto")),Z=g(require("conf")),tt=require("node-machine-id"),et="aes-256-gcm",W=new Z.default({projectName:"xtra-cli-crypto"});nt=t=>{let e=j.default.randomBytes(16),s=st(),n=j.default.createCipheriv(et,s,e),r=n.update(t,"utf8","hex");r+=n.final("hex");let a=n.getAuthTag();return{iv:e.toString("hex"),content:r,tag:a.toString("hex")}},rt=t=>{let e=st(),s=Buffer.from(t.iv,"hex"),n=Buffer.from(t.tag,"hex"),r=j.default.createDecipheriv(et,e,s);r.setAuthTag(n);let a=r.update(t.content,"hex","utf8");return a+=r.final("utf8"),a}});var ct={};C(ct,{loadAuditLogs:()=>D,logAudit:()=>It,saveAuditLogs:()=>R,syncAuditLogs:()=>Ct});function At(t){if(!t||typeof t!="object")return t;let e={...t},s=["password","token","secret","value","apiKey","secretValue"];for(let n of Object.keys(e))s.some(r=>n.toLowerCase().includes(r))&&(e[n]="[REDACTED]");return e}async function it(t){try{if(!h().token)return!1;let s={action:t.action,entity:"cli-project",entityId:t.projectId||"global",details:At(t.details),timestamp:t.timestamp,projectId:t.projectId};return await N.post("/audit/cli-logs",{logs:[s]}),!0}catch(e){return process.env.DEBUG&&console.error("Failed to send audit log to backend:",e),!1}}function It(t,e,s,n){let r={id:(0,at.v4)(),timestamp:new Date().toISOString(),action:t,projectId:e,environment:s,details:n,synced:!1},a=D();a.push(r),R(a),it(r).then($=>{if($){r.synced=!0;let d=D(),b=d.findIndex(k=>k.id===r.id);b!==-1&&(d[b].synced=!0,R(d))}}).catch(()=>{})}function D(){if(!v.default.existsSync(J))return[];try{let t=v.default.readFileSync(J,"utf-8"),e=JSON.parse(t),s=rt(e);return JSON.parse(s)}catch{return[]}}function R(t){v.default.existsSync(F)||v.default.mkdirSync(F,{recursive:!0});let e=JSON.stringify(t),s=nt(e);v.default.writeFileSync(J,JSON.stringify(s),"utf-8")}async function Ct(){let t=D(),e=t.filter(n=>!n.synced);if(e.length===0)return 0;let s=0;for(let n of e)await it(n)&&(n.synced=!0,s++);return s>0&&R(t),s}var v,G,at,F,J,pt=I(()=>{v=g(require("fs")),G=g(require("path")),at=require("uuid");ot();S();P();F=G.default.join(process.cwd(),".xtra"),J=G.default.join(F,"audit.enc")});var Rt={};C(Rt,{initCommand:()=>Dt});module.exports=wt(Rt);var gt=require("commander"),c=g(require("chalk")),U=g(require("inquirer")),y=g(require("fs")),q=g(require("path"));S();var Pt=".xtrarc",Dt=new gt.Command("init").description("Bootstrap a new project \u2014 creates .xtrarc and recommended structure").option("--project <id>","Project ID (skip prompt)").option("--env <env>","Default environment","development").option("--branch <branch>","Default branch","main").option("-y, --yes","Accept all defaults without prompting",!1).action(async t=>{let e=process.cwd(),s=q.join(e,Pt);if(console.log(c.default.bold(`
|
|
2
2
|
\u{1F680} xtra init \u2014 setting up your project
|
|
3
|
-
`)),y.existsSync(
|
|
4
|
-
`));else{let i=k("Fetching your projects...").start();try{let{api:
|
|
3
|
+
`)),y.existsSync(s)){let{overwrite:d}=await U.default.prompt([{type:"confirm",name:"overwrite",message:c.default.yellow(".xtrarc already exists. Overwrite it?"),default:!1}]);if(!d){console.log(c.default.gray("Aborted."));return}}let{project:n,env:r,branch:a}=t;if(!t.yes){let{getAuthToken:d}=await Promise.resolve().then(()=>(S(),H)),b=d(),k=(await import("ora")).default,u=[];if(!b)console.log(c.default.yellow(" \u2139 Not logged in \u2014 project list unavailable. Run `xtra login` first.")),console.log(c.default.yellow(` You can still enter a Project ID manually below.
|
|
4
|
+
`));else{let i=k("Fetching your projects...").start();try{let{api:l}=await Promise.resolve().then(()=>(P(),E)),w=await l.getProjects();u=Array.isArray(w)?w:w.projects??[],u.length===0?i.warn(c.default.yellow("No projects found in your workspace. Create one at www.xtrasecurity.in first.")):i.succeed(`Found ${u.length} project${u.length>1?"s":""}`)}catch(l){let w=l?.response?.status===401?"session expired \u2014 run `xtra login` again":l?.response?.data?.error||l?.message||"network error";i.warn(c.default.yellow(`Could not fetch projects (${w}). Enter the Project ID manually.`))}}let dt=n||O("project")||"",{project:ut}=await U.default.prompt([{type:u.length>0?"list":"input",name:"project",message:u.length>0?"Select a project:":"Project ID:",choices:u.length>0?u.map(i=>({name:`${i.name} (${i.id})`,value:i.id})):void 0,default:dt,validate:i=>i.trim()?!0:"Project ID is required"}]);n=ut.trim();let m=[],K=k("Fetching branches...").start();try{let{api:i}=await Promise.resolve().then(()=>(P(),E));m=await i.getBranches(n),K.stop()}catch{K.warn(c.default.yellow("Could not fetch branches."))}let B=await U.default.prompt([{type:"list",name:"env",message:"Default environment:",choices:["development","staging","production"],default:r||"development"},{type:m.length>0?"list":"input",name:"branch",message:m.length>0?"Default branch:":"Default branch name:",choices:m.length>0?m.map(i=>({name:i.name,value:i.name})):void 0,default:a||(m.length>0?m[0].name:"main")},{type:"confirm",name:"addGitignore",message:"Add .xtrarc to .gitignore? (recommended)",default:!0}]);if(r=B.env,a=B.branch,B.addGitignore){let i=q.join(e,".gitignore"),l="";try{l=y.readFileSync(i,"utf8")}catch{}l.includes(".xtrarc")||(y.appendFileSync(i,`
|
|
5
5
|
# XtraSecurity config
|
|
6
6
|
.xtrarc
|
|
7
|
-
`),console.log(c.default.gray(" \u2714 Added .xtrarc to .gitignore")))}}
|
|
7
|
+
`),console.log(c.default.gray(" \u2714 Added .xtrarc to .gitignore")))}}n||(console.error(c.default.red("Error: Project ID is required.")),process.exit(1));let $={project:n,env:r,branch:a,apiUrl:process.env.XTRA_API_URL||"https://www.xtrasecurity.in/api",createdAt:new Date().toISOString()};y.writeFileSync(s,JSON.stringify($,null,2),"utf8"),x("project",n),x("env",r),x("branch",a),console.log(c.default.gray(` Branch : ${c.default.white(a)}`)),console.log();try{let{logAudit:d}=await Promise.resolve().then(()=>(pt(),ct));d("PROJECT_INIT",n,r,{branch:a,rcPath:s})}catch{}console.log(c.default.bold(" Next steps:")),console.log(c.default.gray(" xtra login # authenticate")),console.log(c.default.gray(" xtra secrets list # view secrets")),console.log(c.default.gray(" xtra run node app.js # inject and run")),console.log(c.default.gray(" xtra doctor # verify everything works")),console.log()});0&&(module.exports={initCommand});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
var E=Object.create;var d=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var
|
|
1
|
+
var E=Object.create;var d=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var K=Object.getPrototypeOf,L=Object.prototype.hasOwnProperty;var _=(e,t)=>{for(var r in t)d(e,r,{get:t[r],enumerable:!0})},j=(e,t,r,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of q(t))!L.call(e,o)&&o!==r&&d(e,o,{get:()=>t[o],enumerable:!(s=G(t,o))||s.enumerable});return e};var i=(e,t,r)=>(r=e!=null?E(K(e)):{},j(t||!e||!e.__esModule?d(r,"default",{value:e,enumerable:!0}):r,e)),D=e=>j(d({},"__esModule",{value:!0}),e);var T={};_(T,{integrationCommand:()=>R,kubernetesCommand:()=>h});module.exports=D(T);var $=require("commander"),a=i(require("chalk"));var I=i(require("axios"));var S=i(require("conf")),w=i(require("fs")),k=i(require("path")),v="https://www.xtrasecurity.in/api",p=new S.default({projectName:"xtra-cli",defaults:{apiUrl:v}}),b=p.get("apiUrl");b&&!process.env.XTRA_API_URL&&b.includes("xtra-security.vercel.app")&&p.set("apiUrl",v);var m=()=>({...p.store,apiUrl:process.env.XTRA_API_URL||p.get("apiUrl")||v});var x=()=>p.get("token");var y=()=>{let e={};try{let t=k.default.join(process.cwd(),".xtrarc");w.default.existsSync(t)&&(e=JSON.parse(w.default.readFileSync(t,"utf-8")))}catch{}return{project:e.project||p.get("project")||"",env:e.env||p.get("env")||"development",branch:e.branch||p.get("branch")||"main"}};var A=i(require("fs")),U=i(require("path")),N=JSON.parse(A.readFileSync(U.join(__dirname,"../../package.json"),"utf-8")),n=()=>{let{apiUrl:e}=m(),t=x();return I.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":N.version,...t?{Authorization:`Bearer ${t}`}:{}}})},u={login:async(e,t,r)=>(await n().post("/auth/cli-login",{email:e,password:t,apiKey:r})).data,getSecrets:async(e,t,r="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets?branch=${r}`)).data,getSecretVersions:async(e,t,r="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets?includeVersions=true&branch=${r}`)).data,setSecrets:async(e,t,r,s,o="main")=>(await n().post(`/projects/${e}/envs/${t}/secrets`,{secrets:r,expectedVersions:s,branch:o})).data,getSecretDetails:async(e,t,r,s="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets/${r}?branch=${s}`)).data,syncLogs:async e=>(await n().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,t,r,s,o,c)=>(await n().post(`/projects/${e}/envs/${t}/secrets/link`,{key:r,sourceProjectId:s,sourceEnv:o,sourceKey:c})).data,rotateSecret:async(e,t,r,s,o)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${r}/rotate`,{strategy:s,parsedNewValue:o})).data,promoteSecret:async(e,t,r)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${r}/promote`,{})).data,verifyAuditLogs:async()=>(await n().get("/audit/verify")).data,exportAuditLogs:async(e,t,r,s)=>{let o={format:e};return t&&(o.startDate=t),r&&(o.endDate=r),s&&(o.projectId=s),(await n().post("/audit/export",o,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,t,r,s)=>(await n().post("/access/request",{projectId:e,secretId:s,reason:t,duration:r})).data,approveAccess:async(e,t)=>(await n().post("/access/approve",{requestId:e,decision:t})).data,listAccessRequests:async e=>{let{workspace:t}=m(),r=t?`&workspaceId=${t}`:"";return(await n().get(`/access/list?mode=${e}${r}`)).data},getAccessRequestStatus:async e=>(await n().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=m(),t=e?`/project?workspaceId=${e}`:"/project";return(await n().get(t)).data},getBranches:async e=>(await n().get(`/branch?projectId=${e}`)).data,createBranch:async(e,t,r)=>(await n().post("/branch",{projectId:e,name:t,description:r})).data,deleteBranch:async e=>(await n().delete(`/branch/${e}`)).data,updateBranch:async(e,t)=>(await n().put("/branch",{id:e,...t})).data,getRoles:async()=>(await n().get("/admin/roles")).data,getUsers:async e=>{let t=e?`?teamId=${e}`:"";return(await n().get(`/admin/users${t}`)).data},setUserRole:async(e,t,r)=>(await n().put("/admin/users/role",{email:e,role:t,teamId:r})).data,getIntegrationStatus:async e=>(await n().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await n().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await n().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,t)=>{let r=new URLSearchParams(t).toString();return(await n().get(`/projects/${e}/kubernetes?${r}`)).data},getSecretHistory:async(e,t,r)=>(await n().get(`/projects/${e}/envs/${t}/secrets/${r}/history`)).data,rollbackSecret:async(e,t,r,s)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${r}/history`,{version:s})).data,cloneEnvironment:async(e,t,r,s,o)=>(await n().post(`/projects/${e}/envs/clone`,{fromEnv:t,toEnv:r,overwrite:s,branch:o})).data,generateJitLink:async e=>(await n().post("/jit/generate",e)).data,claimJitLink:async e=>(await n().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await n().get(`/jit/${e}`)).data,getServiceAccounts:async e=>(await n().get(`/projects/${e}/service-accounts`)).data,createServiceAccount:async(e,t)=>(await n().post(`/projects/${e}/service-accounts`,t)).data,deleteServiceAccount:async(e,t)=>(await n().delete(`/projects/${e}/service-accounts/${t}`)).data,getServiceAccountKeys:async(e,t)=>(await n().get(`/projects/${e}/service-accounts/${t}/keys`)).data,createServiceAccountKey:async(e,t,r,s)=>(await n().post(`/projects/${e}/service-accounts/${t}/keys`,{label:r,expiresAt:s})).data,deleteServiceAccountKey:async(e,t,r)=>(await n().delete(`/projects/${e}/service-accounts/${t}/keys/${r}`)).data,post:async(e,t)=>(await n().post(e,t)).data};var C=i(require("inquirer")),P=i(require("fs")),R=new $.Command("integration");R.command("sync").description("Sync secrets to external integrations (GitHub)").option("-p, --project <id>","Project ID (defaults to current directory config)").option("-e, --env <environment>","Environment (development, staging, production)","development").option("--github","Sync to GitHub").option("--repo <owner/repo>","GitHub repository (e.g., owner/repo)").option("--prefix <prefix>","Prefix for secret keys").action(async e=>{try{let t=e.project;t||(t=y().project,t||(console.error(a.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1)));let r=await u.getIntegrationStatus("github");r.connected||(console.log(a.default.yellow(`
|
|
2
2
|
GitHub not connected. Please connect via the web dashboard first.`)),console.log(a.default.blue(`Visit: https://www.xtrasecurity.in/integrations
|
|
3
3
|
`)),process.exit(1)),console.log(a.default.green(`
|
|
4
|
-
Connected as: ${r.username}`));let s=e.repo;if(s){let[
|
|
5
|
-
Syncing secrets from ${e.env} to GitHub repo: ${s.owner}/${s.name}...`));let
|
|
6
|
-
Successfully synced ${
|
|
7
|
-
Error syncing secrets:`),t
|
|
4
|
+
Connected as: ${r.username}`));let s=e.repo;if(s){let[c,l]=s.split("/");(!c||!l)&&(console.error(a.default.red("Error: Invalid repository format. Use owner/repo")),process.exit(1)),s={owner:c,name:l}}else{console.log("Fetching repositories...");let c=await u.getIntegrationRepos("github"),l=await C.default.prompt([{type:"list",name:"repo",message:"Select a repository to sync to:",choices:c.map(g=>({name:`${g.fullName} ${g.private?"(\u{1F512})":""}`,value:g.id.toString(),short:g.fullName}))}]),f=c.find(g=>g.id.toString()===l.repo);f&&(s={owner:f.owner,name:f.name})}console.log(a.default.blue(`
|
|
5
|
+
Syncing secrets from ${e.env} to GitHub repo: ${s.owner}/${s.name}...`));let o=await u.syncSecretsToGithub({projectId:t,environment:e.env,repoOwner:s.owner,repoName:s.name,secretPrefix:e.prefix});console.log(a.default.green(`
|
|
6
|
+
Successfully synced ${o.summary.synced} secrets!`)),o.summary.failed>0&&console.log(a.default.red(`${o.summary.failed} secrets failed to sync.`)),o.results.forEach(c=>{c.success?console.log(a.default.green(`\u2713 ${c.key}`)):console.log(a.default.red(`\u2717 ${c.key}: ${c.error}`))})}catch(t){console.error(a.default.red(`
|
|
7
|
+
Error syncing secrets:`),t?.response?.data?.error||"Unknown error"),process.exit(1)}});var h=new $.Command("kubernetes");h.command("export").description("Export secrets as Kubernetes manifest").option("-p, --project <id>","Project ID").option("-e, --env <environment>","Environment","development").option("-n, --namespace <namespace>","Kubernetes namespace","default").option("-o, --output <file>","Output file path").option("--name <name>","Secret resource name").action(async e=>{try{let t=e.project;t||(t=y().project,t||(console.error(a.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1))),console.log(a.default.blue(`Generating Kubernetes manifest for ${e.env}...`));let r=await u.exportKubernetesSecret(t,{environment:e.env,namespace:e.namespace,name:e.name});e.output?(P.default.writeFileSync(e.output,r),console.log(a.default.green(`
|
|
8
8
|
Manifest saved to ${e.output}`))):console.log(`
|
|
9
9
|
`+r)}catch(t){console.error(a.default.red(`
|
|
10
|
-
Error generating manifest:`),t
|
|
11
|
-
Error:`),t
|
|
10
|
+
Error generating manifest:`),t?.response?.data?.error||"Unknown error"),process.exit(1)}});h.command("apply").description("Apply secrets directly to Kubernetes cluster (requires kubectl)").option("-p, --project <id>","Project ID").option("-e, --env <environment>","Environment","development").option("-n, --namespace <namespace>","Kubernetes namespace","default").action(async e=>{try{let{execSync:t}=require("child_process");try{t("kubectl version --client",{stdio:"ignore"})}catch{console.error(a.default.red("Error: kubectl not found or not configured.")),process.exit(1)}let r=e.project;r||(r=y().project,r||(console.error(a.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1))),console.log(a.default.blue(`Fetching secrets for ${e.env}...`));let s=await u.exportKubernetesSecret(r,{environment:e.env,namespace:e.namespace});console.log(a.default.blue("Applying to Kubernetes..."));try{let o=require("child_process").spawn("kubectl",["apply","-f","-"]);o.stdin.write(s),o.stdin.end(),o.stdout.on("data",c=>{console.log(c.toString())}),o.stderr.on("data",c=>{console.error(a.default.yellow(c.toString()))})}catch(o){console.error(a.default.red("Failed to apply manifest:"),o?.response?.data?.error||"An unexpected error occurred")}}catch(t){console.error(a.default.red(`
|
|
11
|
+
Error:`),t?.response?.data?.error||"Unknown error"),process.exit(1)}});0&&(module.exports={integrationCommand,kubernetesCommand});
|
package/dist/commands/jit-run.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var _=Object.create;var f=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var G=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty;var D=(e,s)=>{for(var t in s)f(e,t,{get:s[t],enumerable:!0})},
|
|
1
|
+
var _=Object.create;var f=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var G=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty;var D=(e,s)=>{for(var t in s)f(e,t,{get:s[t],enumerable:!0})},k=(e,s,t,n)=>{if(s&&typeof s=="object"||typeof s=="function")for(let o of B(s))!N.call(e,o)&&o!==t&&f(e,o,{get:()=>s[o],enumerable:!(n=O(s,o))||n.enumerable});return e};var c=(e,s,t)=>(t=e!=null?_(G(e)):{},k(s||!e||!e.__esModule?f(t,"default",{value:e,enumerable:!0}):t,e)),E=e=>k(f({},"__esModule",{value:!0}),e);var K={};D(K,{jitRunCommand:()=>F});module.exports=E(K);var U=require("commander");var C=c(require("axios"));var x=c(require("conf")),v=c(require("fs")),I=c(require("path")),h="https://www.xtrasecurity.in/api",i=new x.default({projectName:"xtra-cli",defaults:{apiUrl:h}}),S=i.get("apiUrl");S&&!process.env.XTRA_API_URL&&S.includes("xtra-security.vercel.app")&&i.set("apiUrl",h);var w=()=>({...i.store,apiUrl:process.env.XTRA_API_URL||i.get("apiUrl")||h});var b=()=>i.get("token");var A=()=>{let e={};try{let s=I.default.join(process.cwd(),".xtrarc");v.default.existsSync(s)&&(e=JSON.parse(v.default.readFileSync(s,"utf-8")))}catch{}return{project:e.project||i.get("project")||"",env:e.env||i.get("env")||"development",branch:e.branch||i.get("branch")||"main"}};var R=c(require("fs")),T=c(require("path")),V=JSON.parse(R.readFileSync(T.join(__dirname,"../../package.json"),"utf-8")),r=()=>{let{apiUrl:e}=w(),s=b();return C.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":V.version,...s?{Authorization:`Bearer ${s}`}:{}}})},$={login:async(e,s,t)=>(await r().post("/auth/cli-login",{email:e,password:s,apiKey:t})).data,getSecrets:async(e,s,t="main")=>(await r().get(`/projects/${e}/envs/${s}/secrets?branch=${t}`)).data,getSecretVersions:async(e,s,t="main")=>(await r().get(`/projects/${e}/envs/${s}/secrets?includeVersions=true&branch=${t}`)).data,setSecrets:async(e,s,t,n,o="main")=>(await r().post(`/projects/${e}/envs/${s}/secrets`,{secrets:t,expectedVersions:n,branch:o})).data,getSecretDetails:async(e,s,t,n="main")=>(await r().get(`/projects/${e}/envs/${s}/secrets/${t}?branch=${n}`)).data,syncLogs:async e=>(await r().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,s,t,n,o,p)=>(await r().post(`/projects/${e}/envs/${s}/secrets/link`,{key:t,sourceProjectId:n,sourceEnv:o,sourceKey:p})).data,rotateSecret:async(e,s,t,n,o)=>(await r().post(`/projects/${e}/envs/${s}/secrets/${t}/rotate`,{strategy:n,parsedNewValue:o})).data,promoteSecret:async(e,s,t)=>(await r().post(`/projects/${e}/envs/${s}/secrets/${t}/promote`,{})).data,verifyAuditLogs:async()=>(await r().get("/audit/verify")).data,exportAuditLogs:async(e,s,t,n)=>{let o={format:e};return s&&(o.startDate=s),t&&(o.endDate=t),n&&(o.projectId=n),(await r().post("/audit/export",o,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,s,t,n)=>(await r().post("/access/request",{projectId:e,secretId:n,reason:s,duration:t})).data,approveAccess:async(e,s)=>(await r().post("/access/approve",{requestId:e,decision:s})).data,listAccessRequests:async e=>{let{workspace:s}=w(),t=s?`&workspaceId=${s}`:"";return(await r().get(`/access/list?mode=${e}${t}`)).data},getAccessRequestStatus:async e=>(await r().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=w(),s=e?`/project?workspaceId=${e}`:"/project";return(await r().get(s)).data},getBranches:async e=>(await r().get(`/branch?projectId=${e}`)).data,createBranch:async(e,s,t)=>(await r().post("/branch",{projectId:e,name:s,description:t})).data,deleteBranch:async e=>(await r().delete(`/branch/${e}`)).data,updateBranch:async(e,s)=>(await r().put("/branch",{id:e,...s})).data,getRoles:async()=>(await r().get("/admin/roles")).data,getUsers:async e=>{let s=e?`?teamId=${e}`:"";return(await r().get(`/admin/users${s}`)).data},setUserRole:async(e,s,t)=>(await r().put("/admin/users/role",{email:e,role:s,teamId:t})).data,getIntegrationStatus:async e=>(await r().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await r().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await r().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,s)=>{let t=new URLSearchParams(s).toString();return(await r().get(`/projects/${e}/kubernetes?${t}`)).data},getSecretHistory:async(e,s,t)=>(await r().get(`/projects/${e}/envs/${s}/secrets/${t}/history`)).data,rollbackSecret:async(e,s,t,n)=>(await r().post(`/projects/${e}/envs/${s}/secrets/${t}/history`,{version:n})).data,cloneEnvironment:async(e,s,t,n,o)=>(await r().post(`/projects/${e}/envs/clone`,{fromEnv:s,toEnv:t,overwrite:n,branch:o})).data,generateJitLink:async e=>(await r().post("/jit/generate",e)).data,claimJitLink:async e=>(await r().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await r().get(`/jit/${e}`)).data,getServiceAccounts:async e=>(await r().get(`/projects/${e}/service-accounts`)).data,createServiceAccount:async(e,s)=>(await r().post(`/projects/${e}/service-accounts`,s)).data,deleteServiceAccount:async(e,s)=>(await r().delete(`/projects/${e}/service-accounts/${s}`)).data,getServiceAccountKeys:async(e,s)=>(await r().get(`/projects/${e}/service-accounts/${s}/keys`)).data,createServiceAccountKey:async(e,s,t,n)=>(await r().post(`/projects/${e}/service-accounts/${s}/keys`,{label:t,expiresAt:n})).data,deleteServiceAccountKey:async(e,s,t)=>(await r().delete(`/projects/${e}/service-accounts/${s}/keys/${t}`)).data,post:async(e,s)=>(await r().post(e,s)).data};var J=require("child_process"),a=c(require("chalk")),q=c(require("ora"));var F=new U.Command("jit-run").description("Claim a JIT link and run a command once approved").requiredOption("-t, --token <token>","JIT Access Token").option("-e, --env <environment>","Environment (development, staging, production)","development").argument("<command>","Command to run").argument("[args...]","Command arguments").action(async(e,s,t)=>{let{token:n,env:o}=t,p=A(),g=(0,q.default)("Claiming JIT link...").start();try{let d=await $.claimJitLink(n),j=d.requestId;g.text=`Access request submitted (ID: ${j}). Waiting for admin approval...`;let u=d.status||"pending",l="";for(;u==="pending";){await new Promise(P=>setTimeout(P,5e3));let y=await $.getAccessRequestStatus(j);u=y.status,l=y.projectId,u==="rejected"&&(g.fail(a.default.red("Access request rejected by admin.")),process.exit(1)),(u==="revoked"||u==="expired")&&(g.fail(a.default.red(`Access request ${u}.`)),process.exit(1))}g.succeed(a.default.green("Access approved! Fetching secrets...")),l||(l=p.project),l||(g.fail("Error: Could not determine project ID for JIT session."),process.exit(1));let m=await $.getSecrets(l,o);!m||Object.keys(m).length===0?console.warn(a.default.yellow(`
|
|
2
2
|
Warning: No secrets returned. Ensure JIT link allowed specific secrets.`)):console.log(a.default.cyan(`
|
|
3
3
|
\u221A Loaded ${Object.keys(m).length} JIT-authorized secrets.`));let L={...process.env,...m};console.log(a.default.gray(`> ${e} ${s.join(" ")}`)),(0,J.spawn)(e,s,{env:L,stdio:"inherit",shell:process.platform==="win32"}).on("exit",y=>{process.exit(y??0)})}catch(d){g.fail("JIT Run failed."),d.response?console.error(a.default.red(`
|
|
4
|
-
Error: ${d.response.data.error||d
|
|
5
|
-
Error: ${d
|
|
4
|
+
Error: ${d.response.data.error||d?.response?.data?.error||"An unexpected error occurred"}`)):console.error(a.default.red(`
|
|
5
|
+
Error: ${d?.response?.data?.error||"An unexpected error occurred"}`)),process.exit(1)}});0&&(module.exports={jitRunCommand});
|
package/dist/commands/local.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var G=Object.create;var
|
|
1
|
+
var G=Object.create;var f=Object.defineProperty;var J=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var X=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty;var K=(e,t)=>{for(var s in t)f(e,s,{get:t[s],enumerable:!0})},A=(e,t,s,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of V(t))!H.call(e,o)&&o!==s&&f(e,o,{get:()=>t[o],enumerable:!(r=J(t,o))||r.enumerable});return e};var i=(e,t,s)=>(s=e!=null?G(X(e)):{},A(t||!e||!e.__esModule?f(s,"default",{value:e,enumerable:!0}):s,e)),z=e=>A(f({},"__esModule",{value:!0}),e);var W={};K(W,{localCommand:()=>y});module.exports=z(W);var E=require("commander");var U=i(require("axios"));var L=i(require("conf")),u=i(require("fs")),P=i(require("path")),$="https://www.xtrasecurity.in/api",c=new L.default({projectName:"xtra-cli",defaults:{apiUrl:$}}),I=c.get("apiUrl");I&&!process.env.XTRA_API_URL&&I.includes("xtra-security.vercel.app")&&c.set("apiUrl",$);var m=()=>({...c.store,apiUrl:process.env.XTRA_API_URL||c.get("apiUrl")||$}),j=e=>c.get(e),S=(e,t)=>{if(c.set(e,t),e==="token"&&process.platform!=="win32"&&u.default.existsSync(c.path))try{u.default.chmodSync(c.path,384)}catch{}};var R=()=>c.get("token");var O=()=>{let e={};try{let t=P.default.join(process.cwd(),".xtrarc");u.default.existsSync(t)&&(e=JSON.parse(u.default.readFileSync(t,"utf-8")))}catch{}return{project:e.project||c.get("project")||"",env:e.env||c.get("env")||"development",branch:e.branch||c.get("branch")||"main"}};var T=i(require("fs")),_=i(require("path")),Y=JSON.parse(T.readFileSync(_.join(__dirname,"../../package.json"),"utf-8")),n=()=>{let{apiUrl:e}=m(),t=R();return U.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":Y.version,...t?{Authorization:`Bearer ${t}`}:{}}})},D={login:async(e,t,s)=>(await n().post("/auth/cli-login",{email:e,password:t,apiKey:s})).data,getSecrets:async(e,t,s="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets?branch=${s}`)).data,getSecretVersions:async(e,t,s="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(e,t,s,r,o="main")=>(await n().post(`/projects/${e}/envs/${t}/secrets`,{secrets:s,expectedVersions:r,branch:o})).data,getSecretDetails:async(e,t,s,r="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets/${s}?branch=${r}`)).data,syncLogs:async e=>(await n().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,t,s,r,o,p)=>(await n().post(`/projects/${e}/envs/${t}/secrets/link`,{key:s,sourceProjectId:r,sourceEnv:o,sourceKey:p})).data,rotateSecret:async(e,t,s,r,o)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${s}/rotate`,{strategy:r,parsedNewValue:o})).data,promoteSecret:async(e,t,s)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await n().get("/audit/verify")).data,exportAuditLogs:async(e,t,s,r)=>{let o={format:e};return t&&(o.startDate=t),s&&(o.endDate=s),r&&(o.projectId=r),(await n().post("/audit/export",o,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,t,s,r)=>(await n().post("/access/request",{projectId:e,secretId:r,reason:t,duration:s})).data,approveAccess:async(e,t)=>(await n().post("/access/approve",{requestId:e,decision:t})).data,listAccessRequests:async e=>{let{workspace:t}=m(),s=t?`&workspaceId=${t}`:"";return(await n().get(`/access/list?mode=${e}${s}`)).data},getAccessRequestStatus:async e=>(await n().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=m(),t=e?`/project?workspaceId=${e}`:"/project";return(await n().get(t)).data},getBranches:async e=>(await n().get(`/branch?projectId=${e}`)).data,createBranch:async(e,t,s)=>(await n().post("/branch",{projectId:e,name:t,description:s})).data,deleteBranch:async e=>(await n().delete(`/branch/${e}`)).data,updateBranch:async(e,t)=>(await n().put("/branch",{id:e,...t})).data,getRoles:async()=>(await n().get("/admin/roles")).data,getUsers:async e=>{let t=e?`?teamId=${e}`:"";return(await n().get(`/admin/users${t}`)).data},setUserRole:async(e,t,s)=>(await n().put("/admin/users/role",{email:e,role:t,teamId:s})).data,getIntegrationStatus:async e=>(await n().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await n().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await n().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,t)=>{let s=new URLSearchParams(t).toString();return(await n().get(`/projects/${e}/kubernetes?${s}`)).data},getSecretHistory:async(e,t,s)=>(await n().get(`/projects/${e}/envs/${t}/secrets/${s}/history`)).data,rollbackSecret:async(e,t,s,r)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${s}/history`,{version:r})).data,cloneEnvironment:async(e,t,s,r,o)=>(await n().post(`/projects/${e}/envs/clone`,{fromEnv:t,toEnv:s,overwrite:r,branch:o})).data,generateJitLink:async e=>(await n().post("/jit/generate",e)).data,claimJitLink:async e=>(await n().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await n().get(`/jit/${e}`)).data,getServiceAccounts:async e=>(await n().get(`/projects/${e}/service-accounts`)).data,createServiceAccount:async(e,t)=>(await n().post(`/projects/${e}/service-accounts`,t)).data,deleteServiceAccount:async(e,t)=>(await n().delete(`/projects/${e}/service-accounts/${t}`)).data,getServiceAccountKeys:async(e,t)=>(await n().get(`/projects/${e}/service-accounts/${t}/keys`)).data,createServiceAccountKey:async(e,t,s,r)=>(await n().post(`/projects/${e}/service-accounts/${t}/keys`,{label:s,expiresAt:r})).data,deleteServiceAccountKey:async(e,t,s)=>(await n().delete(`/projects/${e}/service-accounts/${t}/keys/${s}`)).data,post:async(e,t)=>(await n().post(e,t)).data};var a=i(require("chalk")),N=i(require("ora")),g=i(require("fs")),d=i(require("path")),M=i(require("readline")),x=".env.local";function Q(){return j("localMode")===!0||process.env.XTRA_LOCAL_MODE==="true"}var y=new E.Command("local").description("Toggle cloud/local mode for offline development").addHelpText("after",`
|
|
2
2
|
In local mode, 'xtra run' reads secrets from .env.local instead of the cloud API.
|
|
3
3
|
This allows fully offline development without any API calls.
|
|
4
4
|
|
|
@@ -8,9 +8,9 @@ Examples:
|
|
|
8
8
|
$ xtra local off # Disable \xE2\u20AC\u201D back to cloud mode
|
|
9
9
|
$ xtra local sync # Pull cloud secrets \xE2\u2020\u2019 .env.local
|
|
10
10
|
$ xtra local sync -p proj -e production # Pull production to .env.local
|
|
11
|
-
`);
|
|
11
|
+
`);y.command("status").description("Show current cloud/local mode").action(()=>{let e=Q(),t=d.join(process.cwd(),x),s=g.existsSync(t);console.log(a.default.bold(`
|
|
12
12
|
Mode Status:
|
|
13
|
-
`)),console.log(` Mode : ${e?a.default.yellow("\u{1F50C} LOCAL (offline)"):a.default.green("\u2601 CLOUD")}`),console.log(` .env.local : ${s?a.default.green("Found"):a.default.gray("Not found")}`),console.log(` Config flag : ${a.default.gray(j("localMode")?"true":"false")}`),console.log(` Env var : ${a.default.gray(process.env.XTRA_LOCAL_MODE||"(not set)")}`),console.log(),e?(console.log(a.default.gray(" Run 'xtra local off' to switch back to cloud mode.")),s||console.log(a.default.yellow(" \u26A0 No .env.local file found. Run 'xtra local sync' to pull secrets."))):console.log(a.default.gray(" Run 'xtra local on' to switch to offline mode.")),console.log()});
|
|
13
|
+
`)),console.log(` Mode : ${e?a.default.yellow("\u{1F50C} LOCAL (offline)"):a.default.green("\u2601 CLOUD")}`),console.log(` .env.local : ${s?a.default.green("Found"):a.default.gray("Not found")}`),console.log(` Config flag : ${a.default.gray(j("localMode")?"true":"false")}`),console.log(` Env var : ${a.default.gray(process.env.XTRA_LOCAL_MODE||"(not set)")}`),console.log(),e?(console.log(a.default.gray(" Run 'xtra local off' to switch back to cloud mode.")),s||console.log(a.default.yellow(" \u26A0 No .env.local file found. Run 'xtra local sync' to pull secrets."))):console.log(a.default.gray(" Run 'xtra local on' to switch to offline mode.")),console.log()});y.command("on").description("Enable local mode \xE2\u20AC\u201D secrets read from .env.local").action(()=>{S("localMode",!0),console.log(a.default.yellow("\u{1F50C} Local mode ENABLED.")),console.log(a.default.gray(" 'xtra run' will now read from .env.local instead of the cloud."));let e=d.join(process.cwd(),x);g.existsSync(e)||console.log(a.default.yellow(" \u26A0 No .env.local file found. Run 'xtra local sync' to populate it."))});y.command("off").description("Disable local mode \xE2\u20AC\u201D secrets fetched from cloud again").action(()=>{S("localMode",!1),console.log(a.default.green("\xE2\u02DC\x81 Cloud mode ENABLED.")),console.log(a.default.gray(" 'xtra run' will now fetch secrets from XtraSecurity Cloud."))});y.command("sync").description("Pull cloud secrets to .env.local for offline use").option("-p, --project <id>","Project ID").option("-e, --env <environment>","Environment","development").option("-b, --branch <branch>","Branch","main").option("-o, --output <file>","Output file",x).option("--overwrite","Overwrite existing file without prompt",!1).action(async e=>{let{project:t,env:s,branch:r,output:o,overwrite:p}=e;s={dev:"development",stg:"staging",prod:"production"}[s]||s,t||(t=O().project),t||(console.error(a.default.red("Error: Project ID required. Use -p <id>.")),process.exit(1));let B=d.resolve(process.cwd(),o);if(s==="production"&&!p){console.log(a.default.red(`\u26A0 You are syncing PRODUCTION secrets to ${o}.`));let l=M.createInterface({input:process.stdin,output:process.stdout});if(!await new Promise(h=>{l.question(a.default.yellow("Type 'yes' to confirm: "),v=>{l.close(),h(v.trim().toLowerCase()==="yes")})})){console.log(a.default.gray("Sync cancelled."));return}}let b=(0,N.default)(`Fetching ${s} secrets from cloud...`).start();try{let l=await D.getSecrets(t,s,r);b.stop();let w=Object.keys(l).length;if(w===0){console.log(a.default.yellow("No secrets found."));return}let h=[`# xtra local sync \xE2\u20AC\u201D ${s}/${r}`,`# Generated: ${new Date().toISOString()}`,"# DO NOT COMMIT THIS FILE","",...Object.entries(l).map(([C,q])=>`${C}=${q}`)];g.writeFileSync(B,h.join(`
|
|
14
14
|
`)+`
|
|
15
|
-
`,"utf8"),console.log(a.default.green(`\u2705 Synced ${w} secrets to ${
|
|
16
|
-
\u26A0 Remember to add '${
|
|
15
|
+
`,"utf8"),console.log(a.default.green(`\u2705 Synced ${w} secrets to ${o}`)),console.log(a.default.gray(" Run 'xtra local on' to switch to local mode."));let v=d.join(process.cwd(),".gitignore"),k="";try{k=g.readFileSync(v,"utf8")}catch{}k.includes(o)||console.log(a.default.yellow(`
|
|
16
|
+
\u26A0 Remember to add '${o}' to your .gitignore!`))}catch(l){b.fail("Sync failed."),console.error(a.default.red(l?.response?.data?.error||l?.response?.data?.error||"An unexpected error occurred")),process.exit(1)}});0&&(module.exports={localCommand});
|