Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Zapier security workflow to a GitHub App #2575

Open
trask opened this issue Feb 16, 2025 · 1 comment
Open

Move Zapier security workflow to a GitHub App #2575

trask opened this issue Feb 16, 2025 · 1 comment
Assignees
Labels
area/project-infra Non-GitHub project infra (DockerHub, etc.) area/security triage:deciding This issue needs more discussion or consideration.

Comments

@trask
Copy link
Member

trask commented Feb 16, 2025

This should be more secure, and also make it clearer to maintainers that it isn't @trask adding them as collaborators (since it's been using my PAT since #2420).

It took me a while to figure out the JWT signing in Zapier since only the standard node.js library is available, so adding the script here to at least dump it somewhere for tracking. Will discuss with Project Infra SIG where to store it long-term.

GitHub App JWT signing under Zapier library restrictions
const crypto = require('crypto');
const signatureFunction = crypto.createSign('RSA-SHA256');

function base64UrlEncoded(obj) {
    const base64 = Buffer.from(JSON.stringify(obj)).toString('base64');
	return base64ToBase64UrlEncoded(base64);
}

function base64ToBase64UrlEncoded(base64) {
    return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

const headerObj = {
    alg: 'RS256',
    typ: 'JWT',
};

const payloadObj = {
    iat: Math.round(Date.now() / 1000),
    exp: Math.round(Date.now() / 1000) + 120, // 2 minutes from now
    iss: inputData.clientId
};

const header = base64UrlEncoded(headerObj);
const payload = base64UrlEncoded(payloadObj);

signatureFunction.write(header + '.' + payload);
signatureFunction.end();

const signature = base64ToBase64UrlEncoded(signatureFunction.sign(inputData.privateKey, 'base64'));

const jwt = header + "." + payload + "." + signature

var response = await fetch('https://api.github.com/app/installations', {
    headers: {
        'Authorization': `Bearer ${jwt}`,
        'Accept': 'application/vnd.github+json'
    }
});

var body = await response.json();

response = await fetch(body[0].access_tokens_url, {
    method: 'POST',
    headers: {
        'Authorization': `Bearer ${jwt}`,
        'Accept': 'application/vnd.github+json'
    }
});

body = await response.json();

var token = body.token;

response = await fetch(inputData.repositoryTeamsUrl, {
    headers: {
        'Authorization': `Bearer ${token}`,
        'Accept': 'application/vnd.github+json'
    }
});

body = await response.json();

const maintainer_team_slugs = body.filter(team => team.permissions.maintain)
                                  .map(team => team.slug);

response = await fetch(inputData.repositoryAdvisoryUrl, {
    method: 'PATCH',
    headers: {
        'Authorization': `Bearer ${token}`,
        'Accept': 'application/vnd.github+json'
    },
    body: JSON.stringify({
        "collaborating_teams": maintainer_team_slugs
    })
})

body = await response.json();

return {
    status: response.status,
    body: body
}
@svrnm svrnm added area/project-infra Non-GitHub project infra (DockerHub, etc.) area/security labels Feb 17, 2025
@trask
Copy link
Member Author

trask commented Feb 18, 2025

Considering to create sig-project-infra repo

@trask trask self-assigned this Feb 18, 2025
@trask trask added the triage:deciding This issue needs more discussion or consideration. label Feb 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/project-infra Non-GitHub project infra (DockerHub, etc.) area/security triage:deciding This issue needs more discussion or consideration.
Projects
Development

No branches or pull requests

2 participants