Skip to content
This repository has been archived by the owner on Jun 27, 2024. It is now read-only.

Commit

Permalink
feat: Haraka relay tests, reusable workflow fix (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
lholota committed Aug 16, 2023
1 parent fd07692 commit bbf25cc
Show file tree
Hide file tree
Showing 17 changed files with 175 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
- name: Run tests
working-directory: e2e
run: |
# yarn test:${{ inputs.client }}:${{ inputs.environment }}
yarn test:${{ inputs.client }}:${{ inputs.environment }}
echo "exitcode=$?"
env:
WEBDRIVER_HOST: host.docker.internal
Expand Down
2 changes: 1 addition & 1 deletion environments/local.lab.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
DNS1=10.1.8.128
DNS2=10.1.8.129
DNS2=10.1.8.129
2 changes: 1 addition & 1 deletion environments/local.prod.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
DNS1=10.1.2.128
DNS2=10.1.2.129
DNS2=10.1.2.129
10 changes: 8 additions & 2 deletions environments/secrets.lab.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ admin_user_totp_secret: ENC[AES256_GCM,data:RYs4wfs9J6Woc7FNnlO98Q==,iv:6hNiQEp/
nonadmin_user_email: ENC[AES256_GCM,data:936vJ4eDLxFH/KF5/AchAe34andA4aZN1au50hLJ/e+tbVh5dkY1uL75,iv:jYpCZ4UH4UsOfeGzECnOrpiW8lDM7E8RKP8nAZhynQk=,tag:EWUKg3SHBfFYzoGWJzlMzQ==,type:str]
nonadmin_user_password: ENC[AES256_GCM,data:5v9I0TjRmeB335uOudmn31me0z9e8ekp9y6P0kUduB4UIf0LnyP6HJNabE+1Qm+FG00VHxHiuypAiZwedqh9,iv:h3KdwogTXwVz/51Kvz649tJpE6pWLpBBKFFA0SH4PbI=,tag:P4cbLmjbSAy2XMNC4pUsxg==,type:str]
nonadmin_user_totp_secret: ENC[AES256_GCM,data:HC9qMizk0zO4hdTQCUuXZA==,iv:bFlDRAJS9jx6znPajcxFnfRHsl9p+IUoDRxFePCmfSk=,tag:I6YU4e3MzOB1d61/U1FeXA==,type:str]
smtp_relay_host: ENC[AES256_GCM,data:4K5HxQrnWRHenA==,iv:ZOiJuTPA4RLIeIRdvSp53R53apvUZwrEGB/k8/4dXYY=,tag:dvCH05c10mT1/Xx2rLfKQQ==,type:str]
smtp_relay_servername: ENC[AES256_GCM,data:G1j/MY9VstlrzZm/oEoGgWUb29wcjg==,iv:ChYh0xEbIJz3Ph3ynjvSE7FqXjjrJOKlKEgja8+RxUs=,tag:mPtTorZRiwJuPZNXq0JxTg==,type:str]
smtp_relay_username: ENC[AES256_GCM,data:U1Lt,iv:CxxGRI6gvghpSv9RwvjTXsm+76ePMMdCvcORex0cDCQ=,tag:FvWDwmm0j/juum9B4MDQFw==,type:str]
smtp_relay_password: ENC[AES256_GCM,data:C2hNgECf+DlAGF3RmF7FHqeg3l0=,iv:X2xGjQ+G/Y/Brwj6nZBZg0NbBAM1gDzeEePTc9/uXfQ=,tag:35xEfngNMExm0Qn0E/0qWg==,type:str]
smtp_relay_sender: ENC[AES256_GCM,data:OzeYoX08FwmELYuRoELct8g=,iv:Jo9Oq0QqvEEMJkOWB0xFSlY01sS+UVPslCZtk6Bp3m4=,tag:ND5gTv+oZ2oZ63g0ebCw6Q==,type:str]
smtp_relay_recipient: ENC[AES256_GCM,data:SKfBSaKsffNCDFtt0DHafVQ=,iv:bc4IUIr9t0xPU8kZkcrWdzYfk+2zVEMPXoSTpBD5XbY=,tag:D5Vhfl21r8ItOw8Z2jVdzA==,type:str]
sops:
kms: []
gcp_kms: []
Expand All @@ -19,8 +25,8 @@ sops:
WlFYaW9naGM5RURrblp6dXZ3NUtscTgKjSZPu9KB7hK1sO5kq4CbyA1kh9P51FRQ
Hoqk2ZelOzAn/oTNI6hfUQ5hp8n9OAr19kXet4DOXej1LLF2Pb5qpA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2023-04-25T08:59:02Z"
mac: ENC[AES256_GCM,data:ERD9A4AMv3RrVLTTWc7kwbQgeYbyu4waP0bMhsVB9mpERJz+81GU9nrbV52O0d45cdWSTv+rrY+hJYeWRTZRBHiJReo2fEE8EHyxEAOkET5/8wg1Wh+LiTfNNWLRQKIDpPzuPRbbQ/cYZVGMM4uNBIN8D/YKxKdlBGnBguRPYTk=,iv:aX9YOkzkePmBJDWjtX+KeQp5gxdWxyfZ1RYW0v+co74=,tag:ABYyixukDe6f81URxS4f4g==,type:str]
lastmodified: "2023-08-15T09:59:52Z"
mac: ENC[AES256_GCM,data:/0IVFspXl3I5XMymew0pKqjFTK7N7IUgfCwZgJJEh40veX6Cs0bBpTB39TVGKdPMSCw3aieKtufM7fPTDeWsHue13sTiuEAJbATUi0GlT39Iz5kJfKUkw0SJCOW9r5BqE9eZk3fGkDW3oqgzsoFbknTBoispgn0Ta5R6W35ZCNo=,iv:74v34Oip/+4yQQj9y6E0ohUJsSFujSlHmpBDntoc3/g=,tag:PeZ0e+i4gK0jbUsAc/ThQg==,type:str]
pgp:
- created_at: "2023-05-22T15:44:10Z"
enc: "-----BEGIN PGP MESSAGE-----\r\n\r\nhQIMA7Pg+ndCcR5CARAAjCHbw0aHusUPjQeR3d7sWTY9cVV3krshzHUeMtbPtkLQ\r\nb/2rEM37/kXF2iB64sa0xVukWOglfPa4+irrEYwv6eqJ2avrhOvWYZq3c/9N9sUP\r\nNoYYWr5jkF9hxLiqjjdAs1bNQY4vMbWnt3v7UWw+kYoEa/RJBsS0UtvOcZZQor1L\r\nGT7gqyD/Izt7ta2WGuWsUqiTadnNLBCDU6P/KcCJpUUKnyoYyq0UcyZm5IspUbFG\r\nxCc3trt62mvydypWJICWPFsEpfM0bg01DKpz4qHjiGNurHKaYw9Ct9aO+bQW7akD\r\n5lGrPeZm06NTOxbtlp10Znch30EUBBojKp/KABtj9jI+uj26Czdmb9H7N9FfapMy\r\nk3ghAYwHgQCYWg6/dRAxHCa0OkMOjsl9y4dUhG0nnKOVIyX8VRXiaVDAtExcvmDx\r\nNl3kAq6C5PXD3ZI2chuDdEvqkShPJuY8hGPrL5oENIOWCBZjc6mAUFnh9Oo9Lx1K\r\ntpn3uzx7m1ctAIQ8Z6P4EV/hs9YnWvRBKJelHnFU/Nvb44bzql+BQMn+kyiwvYND\r\nBWo8jWvpQz0AVVLacM0sCLQrgVUAogP2fXNjT2gU7o3ApYE7+8LRIvsIEUPR6El8\r\nxzOK7fd6szwI0jb7xrUEZZJiXurvPGfnUTYRSmmLewtKGCq0tdJP9lUsYsdtWe3S\r\nXgGJ8V+cJA6fznNTtVPTILEgxoP9MJRsbtJz/GJnVLCKl+2ZzFLcaBazPkjjsqbW\r\navcg39zbA0EImVH1GX1ehMj9ArviUPQIO3TREUSXqvEGglHpngF9ZUHlwIUEip0=\r\n=W3XR\r\n-----END PGP MESSAGE-----\r\n"
Expand Down
10 changes: 8 additions & 2 deletions environments/secrets.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ admin_user_totp_secret: ENC[AES256_GCM,data:KUA9MRIHJh7DGDcUnWst7g==,iv:EIX0JD/7
nonadmin_user_email: ENC[AES256_GCM,data:CuO0R0QIiBSrQk50QMQdSEwAQgvFUSemhbx+mEbo7s+PQsIyWpWf,iv:RBwaGgWUApORtNM0aiKeJLYv2Af42VGVN+9WGfQjLVo=,tag:Id6jX0XVoUgLgOaoHnblfQ==,type:str]
nonadmin_user_password: ENC[AES256_GCM,data:RLJMR99N6x3GzRhODhpvo2KQgkO44fBpqO/qc40ZbiaIiWasQ//BQE+6bVMpoe0FoDI=,iv:6eVA/uZ6lduSNcIRMoqcyAQGDzKcavSwxDHuKRLDO9U=,tag:gUnTDAHFpK/Ro60I7X+/LA==,type:str]
nonadmin_user_totp_secret: ENC[AES256_GCM,data:YUQ39S4VG65PdNAiLFKqiQ==,iv:Hpnbhwd6GVzLj3Pzd/wC/dYPL0xsaOeysEKzCnFxhH0=,tag:5ByyFMsEMydwJksluroX+w==,type:str]
smtp_relay_host: ENC[AES256_GCM,data:G+0RfS0sV909kw==,iv:w+Uml/zgZcwrJILgJQSJSIPG3/jHLTPWNbHHvasRE8E=,tag:jrQucPUtIVJaxK/2Pe/sBQ==,type:str]
smtp_relay_servername: ENC[AES256_GCM,data:YL/N7nwQb2dY1nojinltLLpd,iv:0xTv+70OCzU7YzIn+ZucliKqo4DR343R1HyoWNL/ZlE=,tag:WbWXJkPxVFnTKe3b/oQC4w==,type:str]
smtp_relay_username: ENC[AES256_GCM,data:R2r4,iv:jKhS9MZuUO+VbzbOE0tp3qTaQf5kPiSXxUbB6fr7SqU=,tag:/1BtdD/bQiX9t3CpyXUzbQ==,type:str]
smtp_relay_password: ENC[AES256_GCM,data:2eViWnQg2EurGFYklEpJZQZZ3u0=,iv:55UoizyY8XrhwmX21//nwO1P7eTmOSRJywZvQetonk8=,tag:ESsW7j9819VZZLeJrG3wRw==,type:str]
smtp_relay_sender: ENC[AES256_GCM,data:dVV3vJrxCPInq8QBDe+2wtQ=,iv:7iRCL4Oc2yhFs8wfkFeI2p7AWwzAm1OpWc6zdYOiO8I=,tag:2wVMn5xcUnixEp/l5K37BQ==,type:str]
smtp_relay_recipient: ENC[AES256_GCM,data:BV4M2vNuaolyQNiwGKmg4PY=,iv:+5VTH3LDRomFuDPlY3V/iuiYBNUEKuXbA4Kgcb2tvFk=,tag:4Oyo1hPmhaRlJwCBxHG6Qg==,type:str]
sops:
kms: []
gcp_kms: []
Expand All @@ -19,8 +25,8 @@ sops:
YWkvd0FBK0pNMi9GNmdJbXlYT2IzaTQKNsbrKyhgigstwQ+KmnyAV0WZWti6h08J
nEBh6LSBWnXANr8vwKv9URTh7Sf40m9pyrfBT38SVk0KMgMwItDeaQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2023-06-06T22:07:20Z"
mac: ENC[AES256_GCM,data:5Xt8F3v4JUZvEy4gVDaj2Y6kn4oNPAdmrjKeC5iXBoJus/YGj2h526KteBCqLlAlRqcyIffEzRuaBjb8I0MH18exOL38QwXQ7mR0DAfdzPQ0FOz7uX3ouCuuTAaBbH3I/cY4RpIIs2nVArTfV3/ZdimATITxC1BRn0zcu7itBFs=,iv:TPSrrwTttVIJRKMTFUGlOk4NV4b2ErOflfaCxjv1iuM=,tag:Nrvsj8SPaY1e/KmMOG3ciA==,type:str]
lastmodified: "2023-08-15T10:00:10Z"
mac: ENC[AES256_GCM,data:/EICcI7DYWvUuRdOy4FeAU6qSfVkMnlfh4de4nPeOxAC7HiN1KRZ9vmc61RV3yXV9ye8sWWxLUElybCCwLjylgoZMMwooSle88zJYo9j9SP8rxaOBxvWD1a9gCca8hiLAD90WNlC6PvbRyIYFpIjsFwGouM+w85o8YG8Sw6wXJI=,iv:faB2E4g3zxk6NenSqjXEn9Qf/PYCgEY3K6T0YH1G210=,tag:8m5mM7t8nFYRfoXOCao8cg==,type:str]
pgp:
- created_at: "2023-06-06T22:06:37Z"
enc: "-----BEGIN PGP MESSAGE-----\r\n\r\nhQIMA7Pg+ndCcR5CAQ//cdCjtQMCmtmLZTCKt26NMpe37d7xbuCEUVyTQ3MWM8ov\r\n99LBw9qb7JcI03Tz8Tc44jSIciFnhXdWa2c2XZGovMva0D9D0f0DvioL+uRqFDVO\r\nZjLzInCkJM0WGYJW/ae8SPNcy/8FN8yIOzlPxtl9t8oNhLIg28R9zZPvYgVmsoOh\r\nh38P+32lsaDc44LEN8dTEigRcSvqgntLyrnWkTJZby86SD0ijQgWvLJCbLKmta0B\r\noBDR2ZOffyAVPANAHOAGOY2V/4O3O3v6wli8suWrIPTY35JZ6Lk+TxRkub4T4lGg\r\nFAihOUtJ1XF6k7d5Qo0QR1aSKHPfW8/+oxnD0TwjcY7I0V6BnVcB9jI/2PbvrNJj\r\nc2E6qaObJrRy2YHojhxwHNl64XLbMv/3JtkCldeVANwLr+NF2bGa73neSVsGCkfQ\r\nF+cC6gH5JXikWRU+Yf3vmkfF99Q4oleceeAGTNGdKopknHf0wLUrZLb7sm3p8mqm\r\n/ZbgG0BbOn7J4GBXxuQpcgUPekiOi1AUBSUuYD6xqbaVgOLYKKlUGWo+UWD7IdIp\r\nu2XU56CYzPgKX7/HcgvpmAorU3xtdRLEQTmsrOQNpiADtgJukJPwZBmGxt8z94vE\r\ndM1j6mj4tOopZt2TGWl6WuSJUnZngPgqzEIEN3rSyHsPjKsvGu4+SOvzlYaMTk3S\r\nXgHJygIiNSTHrHPdIUQbYlbLXRbS71ZzGfUgmjVm6izsI2KqbA7KfniOJtjAPgNK\r\n9UIz9uOvKsuGTH83ARe0Z5USzWYPmJP8IwodBEsowHRpI/pfbIMJ1tcrGJws9ZM=\r\n=V1Ee\r\n-----END PGP MESSAGE-----\r\n"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const isPomeriumPermissionRejectedPage = require("./isPomeriumPermissionRejectedPage")
const isCloudflarePermissionRejectedPage = require("./isCloudflarePermissionRejectedPage")

const assertion = function () {
if (this.__nightwatchInstance.settings.globals.isRemote) {
isCloudflarePermissionRejectedPage.reusable(this)
} else {
isPomeriumPermissionRejectedPage.reusable(this)
}
}

module.exports = {
assertion
}
39 changes: 39 additions & 0 deletions nightwatch/assertions/isPomeriumPermissionRejectedPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const reusable = function (context) {
context.formatMessage = () => {
const message = `Checking if the page ${this.negate ? 'doesn\'t indicate' : 'indicates'} Pomerium permission rejected`;

return {
message,
args: []
}
};

context.expected = () => {
return "403 Forbidden"
}

context.value = function (result) {
return result.value;
};

context.failure = function (result) {
return !result;
};

context.evaluate = function (value) {
return value && value.startsWith(this.expected())
};

context.command = async function (callback) {
this.api.getText("div[role=alert]", callback)
};
};

const assertion = function () {
reusable(this)
};

module.exports = {
reusable,
assertion
}
20 changes: 13 additions & 7 deletions nightwatch/commands/signIn.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ module.exports = {
.waitForElementVisible("css selector", "input[type=password].form-control") // Checking the e-mail may take a few seconds
.setValue("input[type=password].form-control", password)
.click("input[value='Sign in']")

.element("css selector", "input[type=button][value=No]", result => {
if(result.status != -1) {
// Sign in succeeded and AAD showed the "Stay signed in?" screen
browser.click("input[type=button][value=No]")
}
})
// Wait for the Sign in button to disappear
.waitForElementNotPresent("input[value='Sign in']", 2000)
// Check whether the "Stay signed in?" page was shown
.isPresent({
suppressNotFoundErrors: true,
selector: "input[type=button][value=No]",
timeout: 1000
},
result => {
if (result.status > -1) {
this.click("input[type=button][value=No]")
}
})
}
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"devDependencies": {
"env-cmd": "^10.1.0",
"nightwatch": "^3.1.2",
"sops-wrapper": "^1.0.0"
"sops-wrapper": "^1.0.0",
"nodemailer": "^6.9.4"
}
}
23 changes: 23 additions & 0 deletions tests/argocd-local.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
describe('Argo CD when accessed locally should', () => {
this.tags = [ "localonly" ]

afterEach((browser) => {
browser.end()
})

it('Load main screen after signing in as admin', (browser) => {
browser
.subdomain('argocd')
.click('a > button') // Redirects to AAD
.signInAsAdmin()
.assert.textContains("div.sidebar__logo", "Argo CD")
});

it('Not allow non-admins to use the app', (browser) => {
browser
.subdomain('argocd')
.click('a > button') // Redirects to AAD
.signInAsNonAdmin()
.assert.isAadPermissionRejectedPage()
});
});
24 changes: 0 additions & 24 deletions tests/argocd.js → tests/argocd-remote.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,3 @@
describe('Argo CD when accessed locally should', () => {
this.tags = [ "localonly" ]

afterEach((browser) => {
browser.end()
})

it('Load main screen after signing in as admin', (browser) => {
browser
.subdomain('argocd')
.click('a > button') // Redirects to AAD
.signInAsAdmin()
.assert.textContains("div.sidebar__logo", "Argo CD")
});

it('Not allow non-admins to use the app', (browser) => {
browser
.subdomain('argocd')
.click('a > button') // Redirects to AAD
.signInAsNonAdmin()
.assert.isAadPermissionRejectedPage()
});
});

describe('Argo CD when accessed remotely should', () => {
this.tags = [ "remoteonly" ]

Expand Down
32 changes: 32 additions & 0 deletions tests/haraka-relay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const nodemailer = require("nodemailer");

describe('Mailrelay when accessed locally should', async () => {
this.tags = ["localonly"]

// Note: these tests are not running inside of selenium but directly in the runner
// which is why the tests bypass dns resolution (the runner does not use Homecentr's custom DNS)

it('Send e-mail', async (browser) => {
const transport = nodemailer.createTransport({
host: browser.globals.smtp_relay_host,
port: 25,
auth: {
user: browser.globals.smtp_relay_username,
pass: browser.globals.smtp_relay_password
},
tls: {
// Server has only domain in certificate and we are using a direct ip to skip dns resolution
servername: browser.globals.smtp_relay_servername
}
});

const receipt = await transport.sendMail({
from: browser.globals.smtp_relay_sender,
to: browser.globals.smtp_relay_recipient,
subject: "E2E test ✔",
text: "Hello, world!"
});

expect(receipt.accepted.length).to.be.equal(1)
});
});
2 changes: 1 addition & 1 deletion tests/k8s-dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ describe('Kubernetes dashboard should', () => {
browser
.subdomain('k8s')
.signInAsNonAdmin()
.assert.isPermissionRejectedPage()
.assert.isCloudflareOrPomeriumPermissionRejectedPage()
});
});
27 changes: 3 additions & 24 deletions tests/proxmox-ve.js → tests/proxmox-ve-local.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ describe('Proxmox VE when accessed locally should', () => {
browser
.subdomain('pve')
.setValue('#pveloginrealm-inputEl', 'Azure Active Directory')
.waitForElementVisible("a#button-1070")
.click('a#button-1070') // Redirects to AAD
.signInAsAdmin()
.assert.textContains("#versioninfo-innerCt", "Virtual Environment")
Expand All @@ -18,32 +19,10 @@ describe('Proxmox VE when accessed locally should', () => {
browser
.subdomain('pve')
.setValue('#pveloginrealm-inputEl', 'Azure Active Directory')
.waitForElementVisible("a#button-1070")
.click('a#button-1070') // Redirects to AAD
.signInAsNonAdmin()
.pause(6000)
.assert.isAadPermissionRejectedPage()
});
});

describe('Proxmox VE when accessed remotely should', () => {
this.tags = [ "remoteonly" ]

afterEach((browser) => {
browser.end()
})

it('Load main screen after signing in as admin', (browser) => {
browser
.subdomain('pve')
.signInAsAdmin() // Sign into Cloudflare Access
.setValue('#pveloginrealm-inputEl', 'Azure Active Directory')
.click('a#button-1070') // Redirects to AAD
.assert.textContains("#versioninfo-innerCt", "Virtual Environment")
});

it('Not allow non-admins to use the app', (browser) => {
browser
.subdomain('pve')
.signInAsNonAdmin() // Sign into Cloudflare Access
.assert.isCloudflarePermissionRejectedPage()
});
});
24 changes: 24 additions & 0 deletions tests/proxmox-ve-remote.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
describe('Proxmox VE when accessed remotely should', () => {
this.tags = [ "remoteonly" ]

afterEach((browser) => {
browser.end()
})

it('Load main screen after signing in as admin', (browser) => {
browser
.subdomain('pve')
.signInAsAdmin() // Sign into Cloudflare Access
.setValue('#pveloginrealm-inputEl', 'Azure Active Directory')
.waitForElementVisible("a#button-1070")
.click('a#button-1070') // Redirects to AAD
.assert.textContains("#versioninfo-innerCt", "Virtual Environment")
});

it('Not allow non-admins to use the app', (browser) => {
browser
.subdomain('pve')
.signInAsNonAdmin() // Sign into Cloudflare Access
.assert.isCloudflarePermissionRejectedPage()
});
});
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1318,6 +1318,11 @@ node-gyp-build@^4.2.2:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055"
integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==

nodemailer@^6.9.4:
version "6.9.4"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.4.tgz#93bd4a60eb0be6fa088a0483340551ebabfd2abf"
integrity sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==

normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
Expand Down

0 comments on commit bbf25cc

Please sign in to comment.