Skip to content

Commit

Permalink
Merge pull request #177 from OpenPathfinder/feat/adminRepoCreationOnly
Browse files Browse the repository at this point in the history
  • Loading branch information
UlisesGascon authored Jan 3, 2025
2 parents 42f2e7b + fb7996c commit 775d19e
Show file tree
Hide file tree
Showing 6 changed files with 387 additions and 2 deletions.
135 changes: 135 additions & 0 deletions __tests__/checks/adminRepoCreationOnly.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
const knexInit = require('knex')
const { getConfig } = require('../../src/config')
const adminRepoCreationOnly = require('../../src/checks/complianceChecks/adminRepoCreationOnly')
const {
resetDatabase, initializeStore
} = require('../../__utils__')
const { sampleGithubOrg } = require('../../__fixtures__')

const { dbSettings } = getConfig('test')

let knex
let project
let check

let addProject,
addGithubOrg,
getAllResults,
getAllTasks,
getAllAlerts,
addAlert,
addTask,
addResult,
getCheckByCodeName

beforeAll(async () => {
knex = knexInit(dbSettings);
({
addProject,
addGithubOrganization: addGithubOrg,
getAllResults,
getAllTasks,
getAllAlerts,
addAlert,
addTask,
addResult,
getCheckByCodeName
} = initializeStore(knex))
check = await getCheckByCodeName('adminRepoCreationOnly')
})

beforeEach(async () => {
await resetDatabase(knex)
project = await addProject({ name: sampleGithubOrg.login })
})

afterAll(async () => {
await knex.destroy()
})

describe('Integration: adminRepoCreationOnly', () => {
test('Should add results without alerts or tasks', async () => {
// Add a passed check scenario
await addGithubOrg({
login: sampleGithubOrg.login,
html_url: sampleGithubOrg.html_url,
project_id: project.id,
members_can_create_public_repositories: false
})
// Check that the database is empty
let results = await getAllResults()
expect(results.length).toBe(0)
let alerts = await getAllAlerts()
expect(alerts.length).toBe(0)
let tasks = await getAllTasks()
expect(tasks.length).toBe(0)
// Run the check
await expect(adminRepoCreationOnly(knex)).resolves.toBeUndefined()
// Check that the database has the expected results
results = await getAllResults()
expect(results.length).toBe(1)
expect(results[0].status).toBe('passed')
expect(results[0].compliance_check_id).toBe(check.id)
alerts = await getAllAlerts()
expect(alerts.length).toBe(0)
tasks = await getAllTasks()
expect(tasks.length).toBe(0)
})

test('Should delete (previous alerts and tasks) and add results', async () => {
// Prepare the Scenario
await addGithubOrg({
login: sampleGithubOrg.login,
html_url: sampleGithubOrg.html_url,
project_id: project.id,
members_can_create_public_repositories: false
})
await addAlert({ compliance_check_id: check.id, project_id: project.id, title: 'existing', description: 'existing', severity: 'critical' })
await addTask({ compliance_check_id: check.id, project_id: project.id, title: 'existing', description: 'existing', severity: 'critical' })
// Check that the database has the expected results
let results = await getAllResults()
expect(results.length).toBe(0)
let alerts = await getAllAlerts()
expect(alerts.length).toBe(1)
expect(alerts[0].compliance_check_id).toBe(check.id)
let tasks = await getAllTasks()
expect(tasks.length).toBe(1)
expect(tasks[0].compliance_check_id).toBe(check.id)
// Run the check
await adminRepoCreationOnly(knex)
// Check that the database has the expected results
results = await getAllResults()
expect(results.length).toBe(1)
expect(results[0].status).toBe('passed')
alerts = await getAllAlerts()
expect(alerts.length).toBe(0)
tasks = await getAllTasks()
expect(tasks.length).toBe(0)
})
test('Should add (alerts and tasks) and update results', async () => {
// Prepare the Scenario
await addGithubOrg({ login: sampleGithubOrg.login, html_url: sampleGithubOrg.html_url, project_id: project.id, members_can_create_public_repositories: true })
await addResult({ compliance_check_id: check.id, project_id: project.id, status: 'passed', rationale: 'failed previously', severity: 'critical' })
// Check that the database has the expected results
let results = await getAllResults()
expect(results.length).toBe(1)
expect(results[0].compliance_check_id).toBe(check.id)
let alerts = await getAllAlerts()
expect(alerts.length).toBe(0)
let tasks = await getAllTasks()
expect(tasks.length).toBe(0)
// Run the check
await adminRepoCreationOnly(knex)
// Check that the database has the expected results
results = await getAllResults()
expect(results.length).toBe(1)
expect(results[0].status).toBe('failed')
expect(results[0].rationale).not.toBe('failed previously')
alerts = await getAllAlerts()
expect(alerts.length).toBe(1)
expect(alerts[0].compliance_check_id).toBe(check.id)
tasks = await getAllTasks()
expect(tasks.length).toBe(1)
expect(tasks[0].compliance_check_id).toBe(check.id)
})
})
132 changes: 131 additions & 1 deletion __tests__/checks/validators.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { githubOrgMFA, softwareDesignTraining } = require('../../src/checks/validators')
const { githubOrgMFA, softwareDesignTraining, adminRepoCreationOnly } = require('../../src/checks/validators')
// @see: https://github.com/OpenPathfinder/visionBoard/issues/43
describe('githubOrgMFA', () => {
let organizations, check, projects
Expand Down Expand Up @@ -278,3 +278,133 @@ describe('softwareDesignTraining', () => {
})
})
})

describe('adminRepoCreationOnly', () => {
let organizations, check, projects
beforeEach(() => {
organizations = [
{
project_id: 1,
login: 'org1',
members_can_create_public_repositories: false
},
{
project_id: 1,
login: 'org2',
members_can_create_public_repositories: false
},
{
project_id: 2,
login: 'org3',
members_can_create_public_repositories: false
}
]

check = {
id: 1,
default_priority_group: 'P1',
details_url: 'https://example.com'
}

projects = [
{
id: 1
},
{
id: 2
}
]
})
it('Should generate a passed result if only admins can create public repos in all the organizations', () => {
const analysis = adminRepoCreationOnly({ organizations, check, projects })
expect(analysis).toEqual({
alerts: [],
results: [
{
project_id: 1,
compliance_check_id: 1,
severity: 'critical',
status: 'passed',
rationale: 'Only Admins can create public repositories in the organization(s)'
},
{
compliance_check_id: 1,
project_id: 2,
rationale: 'Only Admins can create public repositories in the organization(s)',
severity: 'critical',
status: 'passed'
}
],
tasks: []
})
})

it('should generate a failed result if some organizations have mixed permissions', () => {
organizations[0].members_can_create_public_repositories = true
// IMPORTANT: If one organization fails, the whole project fails no matter how other organizations are in the project
organizations[1].members_can_create_public_repositories = null

const analysis = adminRepoCreationOnly({ organizations, check, projects })
expect(analysis).toEqual({
alerts: [
{
project_id: 1,
compliance_check_id: 1,
severity: 'critical',
title: 'Not Only Admins can create public repositories in the following (org1) organization(s)',
description: 'Check the details on https://example.com'
}
],
results: [
{
project_id: 1,
compliance_check_id: 1,
severity: 'critical',
status: 'failed',
rationale: 'Not Only Admins can create public repositories in the following (org1) organization(s)'
},
{
project_id: 2,
compliance_check_id: 1,
severity: 'critical',
status: 'passed',
rationale: 'Only Admins can create public repositories in the organization(s)'
}
],
tasks: [
{
project_id: 1,
compliance_check_id: 1,
severity: 'critical',
title: 'Limit public repo creation to admins for the following (org1) organization(s)',
description: 'Check the details on https://example.com'
}
]
})
})

it('should generate an unknown result if some organizations have unknown permissions', () => {
organizations[1].members_can_create_public_repositories = null
const analysis = adminRepoCreationOnly({ organizations, check, projects })
expect(analysis).toEqual({
alerts: [],
results: [
{
project_id: 1,
compliance_check_id: 1,
severity: 'critical',
status: 'unknown',
rationale: 'It was not possible to confirm if only admins can create public repositories in the following (org2) organization(s)'
},
{
project_id: 2,
compliance_check_id: 1,
severity: 'critical',
status: 'passed',
rationale: 'Only Admins can create public repositories in the organization(s)'
}
],
tasks: []
})
})
})
31 changes: 31 additions & 0 deletions src/checks/complianceChecks/adminRepoCreationOnly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const validators = require('../validators')
const { initializeStore } = require('../../store')
const debug = require('debug')('checks:adminRepoCreationOnly')

module.exports = async (knex, { projects } = {}) => {
const {
getAllGithubOrganizationsByProjectsId, getCheckByCodeName,
getAllProjects, addAlert, addTask, upsertComplianceCheckResult,
deleteAlertsByComplianceCheckId, deleteTasksByComplianceCheckId
} = initializeStore(knex)
debug('Collecting relevant data...')
const check = await getCheckByCodeName('adminRepoCreationOnly')
if (!projects || (Array.isArray(projects) && projects.length === 0)) {
projects = await getAllProjects()
}
const organizations = await getAllGithubOrganizationsByProjectsId(projects.map(p => p.id))

debug('Extracting the validation results...')
const analysis = validators.adminRepoCreationOnly({ organizations, check, projects })

debug('Deleting previous alerts and tasks to avoid orphaned records...')
await deleteAlertsByComplianceCheckId(check.id)
await deleteTasksByComplianceCheckId(check.id)

debug('Upserting the new results...')
await Promise.all(analysis.results.map(result => upsertComplianceCheckResult(result)))

debug('Inserting the new Alerts and Tasks...')
await Promise.all(analysis.alerts.map(alert => addAlert(alert)))
await Promise.all(analysis.tasks.map(task => addTask(task)))
}
68 changes: 68 additions & 0 deletions src/checks/validators/adminRepoCreationOnly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const debug = require('debug')('checks:validator:adminRepoCreationOnly')
const { getSeverityFromPriorityGroup, groupArrayItemsByCriteria } = require('../../utils')

const groupByProject = groupArrayItemsByCriteria('project_id')

// @see: https://github.com/OpenPathfinder/visionBoard/issues/75
module.exports = ({ organizations = [], check, projects = [] }) => {
debug('Validating that only admins can create public repositories...')
debug('Grouping organizations by project...')
const organizationsGroupedByProject = groupByProject(organizations)

const alerts = []
const results = []
const tasks = []

debug('Processing organizations...')
organizationsGroupedByProject.forEach((projectOrgs) => {
debug(`Processing project (${projectOrgs[0].project_id})`)
const project = projects.find(p => p.id === projectOrgs[0].project_id)

const baseData = {
project_id: projectOrgs[0].project_id,
compliance_check_id: check.id,
severity: getSeverityFromPriorityGroup(check.default_priority_group)
}

const result = { ...baseData }
const task = { ...baseData }
const alert = { ...baseData }

const failedOrgs = projectOrgs.filter(org => org.members_can_create_public_repositories === true).map(org => org.login)
const unknownOrgs = projectOrgs.filter(org => org.members_can_create_public_repositories === null).map(org => org.login)

if (projectOrgs.every(org => org.members_can_create_public_repositories === false)) {
result.status = 'passed'
result.rationale = 'Only Admins can create public repositories in the organization(s)'
} else if (failedOrgs.length) {
result.status = 'failed'
result.rationale = `Not Only Admins can create public repositories in the following (${failedOrgs.join(',')}) organization(s)`
alert.title = `Not Only Admins can create public repositories in the following (${failedOrgs.join(',')}) organization(s)`
alert.description = `Check the details on ${check.details_url}`
task.title = `Limit public repo creation to admins for the following (${failedOrgs.join(',')}) organization(s)`
task.description = `Check the details on ${check.details_url}`
} else if (unknownOrgs.length) {
result.status = 'unknown'
result.rationale = `It was not possible to confirm if only admins can create public repositories in the following (${unknownOrgs.join(',')}) organization(s)`
}
// Include only the task if was populated
if (Object.keys(task).length > Object.keys(baseData).length) {
debug(`Adding task for project (${project.id})`)
tasks.push(task)
}
// Include only the alert if was populated
if (Object.keys(alert).length > Object.keys(baseData).length) {
debug(`Adding alert for project (${project.id})`)
alerts.push(alert)
}
// Always include the result
results.push(result)
debug(`Processed project (${project.id})`)
})

return {
alerts,
results,
tasks
}
}
4 changes: 3 additions & 1 deletion src/checks/validators/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const githubOrgMFA = require('./githubOrgMFA')
const softwareDesignTraining = require('./softwareDesignTraining')
const adminRepoCreationOnly = require('./adminRepoCreationOnly')

const validators = {
githubOrgMFA,
softwareDesignTraining
softwareDesignTraining,
adminRepoCreationOnly
}

module.exports = validators
Loading

0 comments on commit 775d19e

Please sign in to comment.