From 5df81166edde5b70d7b651986899d60284543c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Simi=C4=87?= Date: Tue, 18 Aug 2020 20:02:16 +0200 Subject: [PATCH 1/4] Implement first GitLab proof logic I've just hacked up a simple solution for GitLab proof. It's using a project (repository) as a proof method since it's the easiest to do with api. It's a very hacky solution and it relies on GitLab being able to find the project using search. --- static/scripts.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/static/scripts.js b/static/scripts.js index 95f2a12..7281794 100644 --- a/static/scripts.js +++ b/static/scripts.js @@ -615,6 +615,37 @@ async function verifyProof(url, fingerprint) { return output; } } + // GitLab + if (/^https:\/\/gitlab.com/.test(url)) { + output.type = "gitlab"; + match = url.match(/https:\/\/gitlab.com\/(.*)\/(.*)/); + output.display = match[1]; + output.url = `https://gitlab.com/${match[1]}`; + output.proofUrlFetch = `https://gitlab.com/api/v4/projects?custom_attributes[search]=${match[1]}/${match[2]}&custom_attributes[search_namespaces]=true`; + try { + response = await fetch(output.proofUrlFetch, { + headers: { + Accept: 'application/json' + }, + credentials: 'omit' + }); + if (!response.ok) { + throw new Error('Response failed: ' + response.status); + } + json = await response.json(); + let project = json.find(proj => proj.web_url === url); + if (!project) { + throw new Error('No project at ' + url); + } + reVerify = new RegExp(`[Verifying my OpenPGP key: openpgp4fpr:${fingerprint}]`, 'i'); + if (reVerify.test(project.descroption)) { + output.isVerified = true; + } + } catch (e) { + } finally { + return output; + } + } // Lobsters if (/^https:\/\/lobste.rs/.test(url)) { output.type = "lobsters"; From be2cf693b1794cd59997bff34f6b97d50b907711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Simi=C4=87?= Date: Wed, 19 Aug 2020 20:05:41 +0200 Subject: [PATCH 2/4] Check for repo instead of domain When checking if url is GitLab proof, check if it points to a gitlab_proof repo instad of the gitlab.com domain. This way self hosted instances could be added. Also go back to searching for user first and then for the repo since repo search is unreliable. --- static/scripts.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/static/scripts.js b/static/scripts.js index 7281794..b344fca 100644 --- a/static/scripts.js +++ b/static/scripts.js @@ -616,24 +616,38 @@ async function verifyProof(url, fingerprint) { } } // GitLab - if (/^https:\/\/gitlab.com/.test(url)) { + if (/\/gitlab_proof$/.test(url)) { output.type = "gitlab"; - match = url.match(/https:\/\/gitlab.com\/(.*)\/(.*)/); - output.display = match[1]; - output.url = `https://gitlab.com/${match[1]}`; - output.proofUrlFetch = `https://gitlab.com/api/v4/projects?custom_attributes[search]=${match[1]}/${match[2]}&custom_attributes[search_namespaces]=true`; + match = url.match(/https:\/\/(.*)\/(.*)\/gitlab_proof/); + output.display = match[2]; + output.url = `https://${match[1]}/${match[2]}`; + output.proofUrlFetch = `https://gitlab.com/api/v4/users?username=${match[2]}`; + // output.proofUrlFetch = `https://gitlab.com/api/v4/projects?custom_attributes[search]=${match[2]}/gitlab_proof&custom_attributes[search_namespaces]=true`; try { - response = await fetch(output.proofUrlFetch, { + const opts = { headers: { Accept: 'application/json' }, credentials: 'omit' - }); + }; + // Get user + response = await fetch(output.proofUrlFetch, opts); if (!response.ok) { throw new Error('Response failed: ' + response.status); } json = await response.json(); - let project = json.find(proj => proj.web_url === url); + const user = json.find(user => user.username === match[2]); + if (!user) { + throw new Error('No user with username ' + match[2]); + } + // Get project + output.proofUrlFetch = `https://gitlab.com/api/v4/users/${user.id}/projects`; + response = await fetch(output.proofUrlFetch, opts); + if (!response.ok) { + throw new Error('Response failed: ' + response.status); + } + json = await response.json(); + const project = json.find(proj => proj.path === 'gitlab_proof'); if (!project) { throw new Error('No project at ' + url); } From 8d727607c091825fafdf20021c0c49f8f479bd4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Simi=C4=87?= Date: Wed, 19 Aug 2020 20:10:40 +0200 Subject: [PATCH 3/4] Use specified instance domain Use specified instance domain instead of gitlab.com. --- static/scripts.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/static/scripts.js b/static/scripts.js index b344fca..4f70231 100644 --- a/static/scripts.js +++ b/static/scripts.js @@ -621,8 +621,7 @@ async function verifyProof(url, fingerprint) { match = url.match(/https:\/\/(.*)\/(.*)\/gitlab_proof/); output.display = match[2]; output.url = `https://${match[1]}/${match[2]}`; - output.proofUrlFetch = `https://gitlab.com/api/v4/users?username=${match[2]}`; - // output.proofUrlFetch = `https://gitlab.com/api/v4/projects?custom_attributes[search]=${match[2]}/gitlab_proof&custom_attributes[search_namespaces]=true`; + output.proofUrlFetch = `https://${match[1]}/api/v4/users?username=${match[2]}`; try { const opts = { headers: { @@ -641,7 +640,7 @@ async function verifyProof(url, fingerprint) { throw new Error('No user with username ' + match[2]); } // Get project - output.proofUrlFetch = `https://gitlab.com/api/v4/users/${user.id}/projects`; + output.proofUrlFetch = `https://${match[1]}/api/v4/users/${user.id}/projects`; response = await fetch(output.proofUrlFetch, opts); if (!response.ok) { throw new Error('Response failed: ' + response.status); From 522abb809746e1ec380aaf279fa3f30d6ee54fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Simi=C4=87?= Date: Wed, 19 Aug 2020 20:23:37 +0200 Subject: [PATCH 4/4] Add guide --- guides/gitlab.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 guides/gitlab.md diff --git a/guides/gitlab.md b/guides/gitlab.md new file mode 100644 index 0000000..f849df9 --- /dev/null +++ b/guides/gitlab.md @@ -0,0 +1,45 @@ +# Adding a GitLab proof + +Let's add a decentralized GitLab proof to your OpenPGP keys. This will also work on self-hosted instances. + +[[toc]] + +## Post a GitLab proof message + +Log in to [gitlab.com](https://gitlab.com) or some other GitLab instance and click on **New project**. + +Set the project name to anything you want. + +Set the project slug to **gitlab_proof**. + +Set the project description to (make sure to replace FINGERPRINT): + +``` +[Verifying my OpenPGP key: openpgp4fpr:FINGERPRINT] +``` + +After creating the project, copy the link to the project. + +## Update the PGP key + +First, edit the key (make sure to replace FINGERPRINT): + +`gpg --edit-key FINGERPRINT` + +Add a new notation: + +`notation` + +Enter the notation (make sure to update with the link to the project copied above): + +`proof@metacode.biz=https://gitlab.example.com/USERNAME/gitlab_proof` + +Save the key: + +`save` + +Upload the key to WKD or use the following command to upload the key to [key.openpgp.org](https://keys.openpgp.org) (make sure to replace FINGERPRINT): + +`gpg --keyserver hkps://keys.openpgp.org --send-keys FINGERPRINT` + +And you're done! Reload your profile page, it should now show a verified GitLab account.