24 septembre 2025
Sharokey permet de créer des liens auto-destructeurs pour partager des identifiants de manière sécurisée directement depuis vos tickets Jira. Cette solution de partage temporaire sécurisé s'intègre parfaitement dans vos workflows existants.
// ==UserScript==
// @name Jira Sharokey Integration
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Intégration Sharokey pour partage sécurisé d'identifiants
// @author Sharokey
// @match https://*.atlassian.net/*
// @match https://*/jira/*
// @grant none
// @require https://cdn.jsdelivr.net/gh/Sharokey/sharokey-cdn@latest/sharokey.js
// ==/UserScript==
(function() {
'use strict';
// Configuration - Remplacez par votre token API Sharokey
const SHAROKEY_TOKEN = 'sk_live_VOTRE_TOKEN_API';
// Configuration Sharokey
if (typeof Sharokey !== 'undefined') {
Sharokey.config({token: SHAROKEY_TOKEN});
}
function getTicketInfo() {
const ticketKey = document.querySelector('[data-testid="issue.views.issue-base.foundation.breadcrumbs.current-issue.item"]')?.textContent?.trim()
|| document.querySelector('#key-val')?.textContent?.trim()
|| window.location.pathname.match(/([A-Z]+-\\\\d+)/)?.[1]
|| 'TICKET';
const ticketTitle = document.querySelector('[data-testid="issue.views.issue-base.foundation.summary.heading"]')?.textContent?.trim()
|| document.querySelector('#summary-val')?.textContent?.trim()
|| 'Demande support';
return { key: ticketKey, title: ticketTitle };
}
function showSecretForm() {
return new Promise((resolve, reject) => {
const modal = document.createElement('div');
modal.innerHTML = \`
<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:10000;display:flex;justify-content:center;align-items:center;font-family:Arial,sans-serif;">
<div style="background:white;padding:30px;border-radius:8px;max-width:500px;width:90%;">
<h2 style="margin-top:0;color:#0052CC;">Créer un accès sécurisé</h2>
<form id="secretForm">
<div style="margin-bottom:15px;">
<label style="display:block;margin-bottom:5px;font-weight:bold;">Contenu du secret :</label>
<textarea id="secretContent" required style="width:100%;height:150px;padding:8px;border:1px solid #ddd;border-radius:4px;resize:vertical;" placeholder="Entrez les identifiants, mots de passe ou informations à partager de manière sécurisée..."></textarea>
</div>
<div style="margin-bottom:20px;">
<label style="display:block;margin-bottom:5px;font-weight:bold;">Instructions (optionnel) :</label>
<input type="text" id="instructions" style="width:100%;padding:8px;border:1px solid #ddd;border-radius:4px;" placeholder="Instructions d'utilisation">
</div>
<div>
<button type="submit" style="background:#0052CC;color:white;border:none;padding:12px 20px;border-radius:4px;cursor:pointer;margin-right:10px;">Créer le secret</button>
<button type="button" id="cancelBtn" style="background:#666;color:white;border:none;padding:12px 20px;border-radius:4px;cursor:pointer;">Annuler</button>
</div>
</form>
</div>
</div>
\`;
document.body.appendChild(modal);
document.getElementById('secretContent').focus();
document.getElementById('secretForm').onsubmit = function(e) {
e.preventDefault();
const content = document.getElementById('secretContent').value.trim();
const instructions = document.getElementById('instructions').value.trim();
if (!content) {
alert('Le contenu du secret est obligatoire');
return;
}
document.body.removeChild(modal);
resolve({ content, instructions });
};
document.getElementById('cancelBtn').onclick = function() {
document.body.removeChild(modal);
reject(new Error('Annulé'));
};
});
}
async function createSecret(ticketInfo, secretData) {
let content = \`Ticket : \${ticketInfo.key}
Contexte : \${ticketInfo.title}
\${secretData.content}\`;
if (secretData.instructions) {
content += \`\\n\\nInstructions : \${secretData.instructions}\`;
}
const secret = await Sharokey.create(content, 24, 2, {
description: \`Accès temporaire - \${ticketInfo.key}\`
});
return secret;
}
function showResult(shareUrl, ticketKey) {
const modal = document.createElement('div');
modal.innerHTML = \`
<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:10000;display:flex;justify-content:center;align-items:center;font-family:Arial,sans-serif;">
<div style="background:white;padding:30px;border-radius:8px;max-width:500px;">
<h2 style="color:#0052CC;margin-top:0;">Secret créé avec succès</h2>
<p><strong>Ticket :</strong> \${ticketKey}</p>
<p><strong>Lien sécurisé :</strong></p>
<div style="background:#f4f5f7;padding:15px;border-radius:4px;word-break:break-all;font-family:monospace;border:1px solid #ddd;">\${shareUrl}</div>
<div style="margin-top:20px;">
<button id="copyBtn" style="background:#0052CC;color:white;border:none;padding:10px 20px;border-radius:4px;cursor:pointer;margin-right:10px;">Copier le lien</button>
<button id="closeBtn" style="background:#666;color:white;border:none;padding:10px 20px;border-radius:4px;cursor:pointer;">Fermer</button>
</div>
<p style="font-size:12px;color:#666;margin-top:15px;">
Le secret expire automatiquement<br>
Lien auto-destructible après consultation
</p>
</div>
</div>
\`;
document.body.appendChild(modal);
document.getElementById('copyBtn').onclick = function() {
navigator.clipboard.writeText(shareUrl).then(() => {
this.textContent = 'Copié !';
this.style.background = '#00C851';
setTimeout(() => {
this.textContent = 'Copier le lien';
this.style.background = '#0052CC';
}, 2000);
});
};
document.getElementById('closeBtn').onclick = function() {
document.body.removeChild(modal);
};
}
function createSharokeyButton() {
const ticketInfo = getTicketInfo();
if (!ticketInfo.key || ticketInfo.key === 'TICKET' || document.getElementById('sharokey-button')) {
return;
}
const targetElement = document.querySelector('[data-testid="issue.views.issue-base.foundation.summary.heading"]')
|| document.querySelector('#stalker')
|| document.querySelector('.aui-toolbar2-primary');
if (!targetElement) return;
const button = document.createElement('button');
button.id = 'sharokey-button';
button.innerHTML = '🔐 Créer un accès sécurisé';
button.style.cssText = \`
background:#0052CC;
color:white;
border:none;
padding:8px 16px;
border-radius:4px;
cursor:pointer;
font-size:14px;
margin-left:10px;
\`;
button.onclick = async function() {
if (SHAROKEY_TOKEN === 'sk_live_VOTRE_TOKEN_API') {
alert('Veuillez configurer votre token API Sharokey dans le script');
return;
}
const originalText = this.innerHTML;
this.innerHTML = 'Création...';
this.disabled = true;
try {
const secretData = await showSecretForm();
const result = await createSecret(getTicketInfo(), secretData);
showResult(result.share_url, getTicketInfo().key);
} catch (error) {
if (error.message !== 'Annulé') {
alert('Erreur : ' + error.message);
}
} finally {
this.innerHTML = originalText;
this.disabled = false;
}
};
targetElement.appendChild(button);
}
function init() {
setTimeout(createSharokeyButton, 2000);
setInterval(createSharokeyButton, 5000);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
sk_live_VOTRE_TOKEN_API
par votre token réelDans la fonction createSecret
, modifiez le paramètre hours
:
const secret = await Sharokey.create(content, 48, 1, { // Durée personnalisée
Modifiez les URLs dans l'en-tête du script pour correspondre à votre environnement :
// @match https://votre-jira.company.com/*
const secret = await Sharokey.create(content, expiration, consultations, {
description: `Accès temporaire - ${ticketInfo.key}`,
captcha: true, // Ajouter un CAPTCHA
otpEmail: "[email protected]" // Double authentification
});
Le script utilise plusieurs sélecteurs pour s'adapter aux différentes versions de Jira. Si nécessaire, ajustez les sélecteurs CSS dans la fonction getTicketInfo()
.
Cette intégration Sharokey-Jira démontre la facilité avec laquelle Sharokey peut s'intégrer dans n'importe quelle interface web existante. Le même principe peut être appliqué à ServiceNow, Zendesk, Salesforce, ou toute autre plateforme web que votre organisation utilise.
L'approche UserScript présentée ici illustre comment transformer rapidement n'importe quel workflow métier existant en ajoutant des capacités de partage sécurisé, sans modification de l'application principale.
Pour des besoins plus avancés, consultez la documentation API Sharokey qui propose des intégrations plus poussées via les SDKs Python, JavaScript et CLI.