Skip to content

Commit

Permalink
Fix repository secrets (#873)
Browse files Browse the repository at this point in the history
* Fix repository secrets

* Add ENCRYPTION_KEY

* Fix for NOTIFICATION_TRANSPORT & SMTP_SECURE

* Make SMTP_SECURE a choices question

* add repository secrets to existing variables, print out unknown variables that exist in Github but are not known by the script

---------

Co-authored-by: Riku Rouvila <[email protected]>
  • Loading branch information
euanmillar and rikukissa authored Jan 26, 2024
1 parent cbc90a2 commit 342a74a
Show file tree
Hide file tree
Showing 4 changed files with 952 additions and 507 deletions.
187 changes: 154 additions & 33 deletions infrastructure/ci/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,76 @@ export async function getRepositoryId(
return response.data.id
}

export async function createSecret(
async function getRepositoryPublicKey(
octokit: Octokit,
owner: string,
repo: string
): Promise<any> {
const res = await octokit.request(
'GET /repos/{owner}/{repo}/actions/secrets/public-key',
{
owner: owner,
repo: repo
}
)

return res.data
}

async function getPublicKey(
octokit: Octokit,
environment: string,
ORGANISATION: string,
REPOSITORY_NAME: string
): Promise<any> {
const repositoryId = await getRepositoryId(
octokit,
ORGANISATION,
REPOSITORY_NAME
)

await octokit.request(
`PUT /repos/${ORGANISATION}/${REPOSITORY_NAME}/environments/${environment}`,
{
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
}
)

const res = await octokit.request(
`GET /repositories/${repositoryId}/environments/${environment}/secrets/public-key`,
{
owner: ORGANISATION,
repo: REPOSITORY_NAME,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
}
)

return res.data
}

export async function createEnvironmentSecret(
octokit: Octokit,
repositoryId: number,
environment: string,
key: string,
keyId: string,
name: string,
secret: string
secret: string,
organisationName: string,
repositoryName: string
): Promise<void> {
//Check if libsodium is ready and then proceed.
await sodium.ready

const { key, key_id } = await getPublicKey(
octokit,
environment,
organisationName,
repositoryName
)

// Convert Secret & Base64 key to Uint8Array.
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL)
const binsec = sodium.from_string(secret)
Expand All @@ -87,52 +145,89 @@ export async function createSecret(
environment_name: environment,
secret_name: name,
encrypted_value: encryptedValue,
key_id: keyId,
key_id,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
}
)
}

export async function getPublicKey(
export async function createRepositorySecret(
octokit: Octokit,
environment: string,
ORGANISATION: string,
REPOSITORY_NAME: string
): Promise<any> {
const repositoryId = await getRepositoryId(
repositoryId: number,
name: string,
secret: string,
organisationName: string,
repositoryName: string
): Promise<void> {
//Check if libsodium is ready and then proceed.
await sodium.ready
const { key, key_id } = await getRepositoryPublicKey(
octokit,
ORGANISATION,
REPOSITORY_NAME
organisationName,
repositoryName
)

// Convert Secret & Base64 key to Uint8Array.
const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL)
const binsec = sodium.from_string(secret)

//Encrypt the secret using LibSodium
const encBytes = sodium.crypto_box_seal(binsec, binkey)

// Convert encrypted Uint8Array to Base64
const encryptedValue = sodium.to_base64(
encBytes,
sodium.base64_variants.ORIGINAL
)

await octokit.request(
`PUT /repos/${ORGANISATION}/${REPOSITORY_NAME}/environments/${environment}`,
`PUT /repositories/${repositoryId}/actions/secrets/${name}`,
{
encrypted_value: encryptedValue,
key_id,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
}
)
}

const res = await octokit.request(
`GET /repositories/${repositoryId}/environments/${environment}/secrets/public-key`,
{
owner: ORGANISATION,
repo: REPOSITORY_NAME,
headers: {
'X-GitHub-Api-Version': '2022-11-28'
export async function createEnvironment(
octokit: Octokit,
environment: string,
ORGANISATION: string,
REPOSITORY_NAME: string
): Promise<boolean> {
try {
await octokit.request(
`PUT /repos/${ORGANISATION}/${REPOSITORY_NAME}/environments/${environment}`,
{
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
}
}
)
)
return true
} catch (err) {
throw new Error('Cannot create environment')
}
}

return res.data
export type Secret = {
type: 'SECRET'
name: string
scope: 'ENVIRONMENT' | 'REPOSITORY'
}
export type Variable = {
type: 'VARIABLE'
name: string
value: string
scope: 'ENVIRONMENT' | 'REPOSITORY'
}
export type Secret = { type: 'SECRET'; name: string }
export type Variable = { type: 'VARIABLE'; name: string; value: string }

export async function listRepoSecrets(
export async function listEnvironmentSecrets(
octokit: Octokit,
owner: string,
repositoryId: number,
Expand All @@ -146,10 +241,33 @@ export async function listRepoSecrets(
environment_name: environmentName
}
)
return response.data.secrets.map((secret) => ({ ...secret, type: 'SECRET' }))
return response.data.secrets.map((secret) => ({
...secret,
type: 'SECRET',
scope: 'ENVIRONMENT'
}))
}

export async function listRepoVariables(
export async function listRepositorySecrets(
octokit: Octokit,
owner: string,
repositoryName: string
): Promise<Secret[]> {
const response = await octokit.request(
'GET /repos/{owner}/{repo}/actions/secrets',
{
owner: owner,
repo: repositoryName
}
)
return response.data.secrets.map((secret) => ({
...secret,
type: 'SECRET',
scope: 'REPOSITORY'
}))
}

export async function listEnvironmentVariables(
octokit: Octokit,
repositoryId: number,
environmentName: string
Expand All @@ -166,8 +284,11 @@ export async function listRepoVariables(
}
)

return response.data.variables.map((variable) => ({
...variable,
type: 'VARIABLE'
}))
return response.data.variables
.map((variable) => ({
...variable,
type: 'VARIABLE' as const,
scope: 'ENVIRONMENT' as const
}))
.filter((variable) => variable.name !== 'ACTIONS_RUNNER_DEBUG')
}
Loading

0 comments on commit 342a74a

Please sign in to comment.