Skip to content

Commit

Permalink
"Automatically enable for new repositories" when enabling on org level (
Browse files Browse the repository at this point in the history
#118)

* Bash script wrapper. Enable features on org level.

* Updated readme; limit 10 orgs in cli list

* fix Actions permissions endpoint

* Removed comments

* Info on .env file creation

* auto enable on new repos; remove build from tasks

* yarn lock update
  • Loading branch information
theztefan authored May 14, 2023
1 parent e8138bf commit 973d738
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 8 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,13 @@ Loops over the repositories found within the `repos.json` file and enables Code
10. **OPTIONAL**: If you are a GHES customer, then you will need to set the `GHES` env to `true` and then set `GHES_SERVER_BASE_URL` to the URL of your GHES instance. E.G `https://octodemo.com`.
11. If you are enabling Code Scanning (CodeQL), check the `codeql-analysis.yml` file. This is a sample file; please configure this file to suit your repositories needs.
11. **OPTIONAL**: If you are planning to enable features on an Organization level using the `yarn run enableOrg` then you additionally have the option `ENABLE_ON=...,automatic` to set also `Automatically enable for new repositories` for each product.
12. Run `yarn install` or `npm install`, which will install the necessary dependencies.
12. If you are enabling Code Scanning (CodeQL), check the `codeql-analysis.yml` file. This is a sample file; please configure this file to suit your repositories needs.
13. Run `yarn run build` or `npm run build`, which will create the JavaScript bundle from TypeScript.
13. Run `yarn install` or `npm install`, which will install the necessary dependencies.
14. Run `yarn run build` or `npm run build`, which will create the JavaScript bundle from TypeScript.
## How to use?
Expand Down
22 changes: 22 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
"lint:check": "npx eslint '**/*.{ts,json}'",
"lint:write": "npx eslint --fix '**/*.{ts,json}'",
"test": "npx jest --coverage --verbose",
"getRepos": "npm run build && node ./lib/getRepos.js",
"getOrgs": "npm run build && node ./lib/getOrgs.js",
"enableOrg": "npm run build && node ./lib/enableOrg.js",
"getRepos": "node ./lib/getRepos.js",
"getOrgs": "node ./lib/getOrgs.js",
"enableOrg": "node ./lib/enableOrg.js",
"start": "npm run build && node ./lib/enable.js"
},
"keywords": [
Expand Down Expand Up @@ -60,6 +60,7 @@
"debug": "^4.3.4",
"delay": "^5.0.0",
"dotenv": "^16.0.3",
"node": "^19.8.1",
"randomstring": "^1.2.3"
}
}
38 changes: 37 additions & 1 deletion src/enableOrg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { error, inform } from "./utils/globals";
import {
enableActionsOnAllOrgRepos,
enableSecurityProductOnAllOrgRepos,
enableAutomaticSecurityProductForNewRepos,
} from "./utils/enableProductOnOrg";
import { client as octokit } from "./utils/clients";

Expand All @@ -15,6 +16,14 @@ async function start() {
const org = process.env.GITHUB_ORG || "";
const client = await octokit(3);

// set a boolean flag 'automatic' if enable has the value 'automatic' and remove it from enable
let automatic = false;
const index = enable.indexOf("automatic");
if (index !== -1) {
enable.splice(index, 1);
automatic = true;
}

// mapping to map the input to the correct product name
const mapping: { [key: string]: string } = {
pushprotection: "secret_scanning_push_protection",
Expand All @@ -27,6 +36,21 @@ async function start() {
};
const parsedEnable = enable.map((product) => mapping[product]);

// mapping to input if automatic for new repos is set
let parsedAutomatic: string[] = [];
if (automatic) {
const mapping: { [key: string]: string } = {
dependabot_alerts: "secret_scanning_push_protection",
dependabot_security_updates:
"dependabot_security_updates_enabled_for_new_repositories",
advanced_security: "advanced_security_enabled_for_new_repositories",
secret_scanning: "secret_scanning_enabled_for_new_repositories",
secret_scanning_push_protection:
"secret_scanning_push_protection_enabled_for_new_repositories",
};
parsedAutomatic = parsedEnable.map((product) => mapping[product]);
}

if (org.trim() === "")
throw new Error(
"You must provide an ORG_NAME in the .env file to enable security products on"
Expand Down Expand Up @@ -56,14 +80,17 @@ async function start() {
}

if (
parsedEnable.includes("advanced_securtiy") ||
parsedEnable.includes("secret_scanning") ||
enable.includes("code_scanning_default_setup")
parsedEnable.includes("code_scanning_default_setup")
) {
await enableSecurityProductOnAllOrgRepos(
org,
"advanced_security",
client
);
// remove advanced_security from the list of products to enable
parsedEnable.splice(parsedEnable.indexOf("advanced_security"), 1);
}

for (const product of parsedEnable) {
Expand All @@ -73,6 +100,15 @@ async function start() {
await enableSecurityProductOnAllOrgRepos(org, product, client);
}
}

// if automatic is set, enable the automatic security features on new repos
if (automatic) {
await enableAutomaticSecurityProductForNewRepos(
org,
parsedAutomatic,
client
);
}
} catch (err) {
error(err);
return err;
Expand Down
34 changes: 34 additions & 0 deletions src/utils/enableProductOnOrg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
createActionsOrgResponse,
createSecurtyProductUpdatesParameters,
createSecurtyProductUpdatesResponse,
updateOrgParameters,
updateOrgResponse,
} from "./octokitTypes";
import { response } from "../../types/common";

Expand Down Expand Up @@ -83,3 +85,35 @@ export const enableGHASOnAllOrgRepos = async (
throw err;
}
};

export const enableAutomaticSecurityProductForNewRepos = async (
org: string,
automatic_security_product: string[],
octokit: Octokit
): Promise<response> => {
// Create an object with the feature names and values
const params = automatic_security_product.reduce((acc, curr) => {
acc[curr] = true;
return acc;
}, {} as { [key: string]: any });

// Add the org to the updateOrgParameters object
params.org = org;

try {
const { status } = (await octokit.request("PATCH /orgs/{org}", {
org: params.org,
...params,
} as updateOrgParameters)) as updateOrgResponse;

inform(
`Enabled automatic enablement of the selected products for new repositories ${org}. Status: ${status}`
);
return { status, message: "Enabled" } as response;
} catch (err) {
error(
`Problem enabling automatic enablement for new repos for selected se ${params.org}. The error was: ${err}`
);
throw err;
}
};
4 changes: 4 additions & 0 deletions src/utils/octokitTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ export type createActionsOrgParameters =
export type createActionsOrgResponse =
Endpoints["PUT /orgs/{org}/actions/permissions"]["response"];

export type updateOrgParameters = Endpoints["PATCH /orgs/{org}"]["parameters"];

export type updateOrgResponse = Endpoints["PATCH /orgs/{org}"]["response"];

export type putFileInPathParameters =
Endpoints["PUT /repos/{owner}/{repo}/contents/{path}"]["parameters"];
export type putFileInPathResponse =
Expand Down
25 changes: 24 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"


"@eslint/[email protected]":
version "8.39.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.39.0.tgz#58b536bcc843f4cd1e02a7e6171da5c040f4d44b"
Expand Down Expand Up @@ -764,6 +765,7 @@
"@octokit/types" "^9.0.0"
bottleneck "^2.15.3"


"@octokit/plugin-throttling@^5.1.1":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@octokit/plugin-throttling/-/plugin-throttling-5.1.1.tgz#7e7ff4646a8ad622d34d9e0c5be7a7e6ea35ba10"
Expand Down Expand Up @@ -806,7 +808,7 @@
integrity sha512-xySzJG4noWrIBFyMu4lg4tu9vAgNg9S0aoLRONhAEz6ueyi1evBzb40HitIosaYS4XOexphG305IVcLrIX/30g==
dependencies:
"@octokit/openapi-types" "^17.1.0"

"@sinclair/typebox@^0.25.16":
version "0.25.24"
resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz"
Expand Down Expand Up @@ -846,6 +848,7 @@
resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz"
integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==


"@tsconfig/node18@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tsconfig/node18/-/node18-2.0.0.tgz#58b52430d00913dc26c4459fbc7f05396e47886a"
Expand All @@ -854,6 +857,7 @@
"@types/aws-lambda@^8.10.114":
version "8.10.114"
resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.114.tgz#4048273ebcd517dd118ecaa34b1368d275b6c7ad"

integrity sha512-M8WpEGfC9iQ6V2Ccq6nGIXoQgeVc6z0Ngk8yCOL5V/TYIxshvb0MWQYLFFTZDesL0zmsoBc4OBjG9DB/4rei6w==

"@types/babel__core@^7.1.14":
Expand Down Expand Up @@ -1006,6 +1010,7 @@
dependencies:
"@types/yargs-parser" "*"


"@typescript-eslint/eslint-plugin@^5.59.2":
version "5.59.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz#684a2ce7182f3b4dac342eef7caa1c2bae476abd"
Expand All @@ -1022,6 +1027,7 @@
semver "^7.3.7"
tsutils "^3.21.0"


"@typescript-eslint/parser@^5.59.2":
version "5.59.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.2.tgz#c2c443247901d95865b9f77332d9eee7c55655e8"
Expand All @@ -1040,6 +1046,7 @@
"@typescript-eslint/types" "5.57.0"
"@typescript-eslint/visitor-keys" "5.57.0"


"@typescript-eslint/[email protected]":
version "5.59.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz#f699fe936ee4e2c996d14f0fdd3a7da5ba7b9a4c"
Expand Down Expand Up @@ -2690,6 +2697,12 @@ natural-compare@^1.4.0:
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==

node-bin-setup@^1.0.0:
version "1.1.3"
resolved "https://registry.npmjs.org/node-bin-setup/-/node-bin-setup-1.1.3.tgz"
integrity sha512-opgw9iSCAzT2+6wJOETCpeRYAQxSopqQ2z+N6BXwIMsQQ7Zj5M8MaafQY8JMlolRR6R1UXg2WmhKp0p9lSOivg==


node-fetch@^2.6.7:
version "2.6.9"
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz"
Expand All @@ -2707,6 +2720,14 @@ node-releases@^2.0.8:
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz"
integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==

node@^19.8.1:
version "19.8.1"
resolved "https://registry.npmjs.org/node/-/node-19.8.1.tgz"
integrity sha512-qAoX6xM9F/eEv4q4qgCXGSbXWruHVzVJX32XCZizSUNsg5ywYY7di9QMqSDFmPwvJrXjZuhNq2z80+lR9GumLg==
dependencies:
node-bin-setup "^1.0.0"


normalize-path@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
Expand Down Expand Up @@ -2859,6 +2880,7 @@ prettier@^2.8.8:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==


pretty-format@^29.0.0, pretty-format@^29.5.0:
version "29.5.0"
resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz"
Expand Down Expand Up @@ -3134,6 +3156,7 @@ tr46@~0.0.3:
resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==


ts-jest@^29.1.0:
version "29.1.0"
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.0.tgz#4a9db4104a49b76d2b368ea775b6c9535c603891"
Expand Down

0 comments on commit 973d738

Please sign in to comment.