Skip to content

Commit

Permalink
Allow unattended execution (#62)
Browse files Browse the repository at this point in the history
* tested unattended version

* change user var

* run prettier:write
  • Loading branch information
jorsmatthys committed Apr 12, 2022
1 parent 9cfd8b2 commit 05be846
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 46 deletions.
64 changes: 57 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ There are two main actions this tool does:
Goes and collects repositories that will have Code Scanning(CodeQL)/Secret Scanning/Dependabot Alerts/Dependabot Security Updates enabled. There are three main ways these repositories are collected.

- Collect the repositories where the primary language matches a specific value. For example, if you provide JavaScript, all repositories will be collected where the primary language is, Javascript.
- Collect the repositories to which a user has administrative access, or a GitHub App has access.
- Collect the repositories to which a user (PAT) has administrative access, or a GitHub App has access.
- Manually create `repos.json`.

If you select option 1, the script will return all repositories in the language you specify (which you have access to). The repositories collected from this script are then stored within a `repos.json` file. If you specify option 2, the script will return all repositories you are an administrator over. The third option is to define the `repos.json` manually. We don't recommend this, but it's possible. If you want to go down this path, first run one of the above options for collecting repository information automatically, look at the structure, and build your fine of the laid out format.
Expand Down Expand Up @@ -49,11 +49,11 @@ If you pick Dependabot Security Updates:
- [Node v16](https://nodejs.org/en/download/) or higher installed.
- [Yarn](https://yarnpkg.com/)\*
- [TypeScript](https://www.typescriptlang.org/download)
- [Git](https://git-scm.com/downloads) installed on the user's machine running this tool.
- Someone who has at least admin access over the repositories they want to enable Code Scanning on. Or, access to GitHub App credentails which has access to the repositories you want to enable Code Scanning on
- [Git](https://git-scm.com/downloads) installed on the (user's) machine running this tool.
- A Personal Access Token (PAT) that has at least admin access over the repositories they want to enable Code Scanning on or GitHub App credentials which have access to the repositories you want to enable Code Scanning on.
- Some basic software development skills, e.g., can navigate their way around a terminal or command prompt.

* You can use `npm` but for the sake of this `README.md`; we are going to standardise the commands on yarn. These are easily replacable though with `npm` commands.
* You can use `npm` but for the sake of this `README.md`; we are going to standardise the commands on yarn. These are easily replaceable though with `npm` commands.

## Set up Instructions

Expand Down Expand Up @@ -175,17 +175,67 @@ There are some key considerations which you will need to put into place if you a
}
```

The reason you need this within your `.devcontainer/devcontainer.json` file is the `GITHUB_TOKEN` tied to the Codepsace will need to access other repositories within your organisation which this script may interact with. You will need to create a new Codespace **after** you have added the above and pushed it to your repository.
The reason you need this within your `.devcontainer/devcontainer.json` file is the `GITHUB_TOKEN` tied to the Codespace will need to access other repositories within your organisation which this script may interact with. You will need to create a new Codespace **after** you have added the above and pushed it to your repository.

You do not need to do the above if you are not running it from a Codespace.

## Running as a (scheduled) GitHub workflow

Since this tool uses a PAT or GitHub App Authentication wherever authentication is required, it can be run unattended. You can see in the example
below how you could run the tool in a scheduled GitHub workflow. Instead of using the `.env`
file you can configure all the variables from the `.env.sample` directly as environment variables. This will allow you to
(easily) make use of GitHub action secrets for the PAT or GitHub App credentials.

```yaml
on:
schedule:
- cron: "5 16 * * 1"

env:
APP_ID: ${{ secrets.GHAS_ENABLEMENT_APP_ID }}
APP_CLIENT_ID: ${{ secrets.GHAS_ENABLEMENT_APP_CLIENT_ID }}
APP_CLIENT_SECRET: ${{ secrets.GHAS_ENABLEMENT_APP_CLIENT_SECRET }}
APP_PRIVATE_KEY: ${{ secrets.GHAS_ENABLEMENT_APP_PRIVATE_KEY }}
ENABLE_ON: "codescanning,secretscanning,dependabot,dependabotupdates"
DEBUG: "ghas:*"
CREATE_ISSUE: "false"
GHES: "false"
# Organization specific variables
APP_INSTALLATION_ID: "12345678"
GITHUB_ORG: "my-target-org"

jobs:
enable-security-javascript:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
repository: NickLiffen/ghas-enablement
- name: Get dependencies and configure
run: |
yarn
git config --global user.name "ghas-enablement"
git config --global user.email "[email protected]"
- name: Enable security on organization (javascript)
run: |
npm run getRepos
npm run start
env:
LANGUAGE_TO_CHECK: "javascript"
```
You can duplicate the last step for the other languages commonly used within your enterprise/organisation.
If you didn't configure the tool as a GitHub App, you can remove all the `APP_*` and set `GITHUB_API_TOKEN` instead.
Above we rely on the sample codeql file for javascript included in this repository. Alternatively you could add this workflow to a repository
containing your customized codeql files and use those to overwrite the samples.

## Found an Issue?

Create an issue within the repository and make it to `@nickliffen`. Key things to mention within your issue:

- Windows or Mac
- Windows, Linux, Codespaces or Mac
- What version of NodeJS you are running.
- Print any logs that appear on the terminal or command prompt
- Add any logs that appeared when you ran into the issue.

## Want to Contribute?

Expand Down
3 changes: 2 additions & 1 deletion src/utils/clients/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { graphQLClient } from "./graphql";
import { restClient } from "./rest";
import { auth } from "./auth";

export { graphQLClient, restClient };
export { graphQLClient, restClient, auth };
1 change: 0 additions & 1 deletion src/utils/clients/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ let MyOctokit = Octokit.plugin(paginateRest, retry, throttling);
export const restClient = async (testPlugin?: any): Promise<unknown> => {
try {
const auth = (await generateAuth()) as string;

if (testPlugin) {
MyOctokit = Octokit.plugin(testPlugin, retry, throttling);
}
Expand Down
101 changes: 80 additions & 21 deletions src/utils/commands.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import { commands } from "../../types/common";

import {
destDir,
user,
winUser,
windestDir,
tempDIR,
baseURL,
} from "./globals";
import { destDir, user, windestDir, tempDIR } from "./globals";

export const codespacesCommands = (
owner: string,
repo: string,
branch: string,
fileName: string
fileName: string,
baseURL: string
): commands => {
const commands = [
{
Expand Down Expand Up @@ -85,7 +79,8 @@ export const macCommands = (
owner: string,
repo: string,
branch: string,
fileName: string
fileName: string,
baseURL: string
): commands => {
const commands = [
{
Expand Down Expand Up @@ -154,18 +149,19 @@ export const windowsCommands = (
owner: string,
repo: string,
branch: string,
fileName: string
fileName: string,
baseURL: string
): commands => {
const commands = [
{
command: "mkdir",
args: ["-p", `${tempDIR}`],
cwd: `/Users/${winUser}/${windestDir}`,
cwd: `/Users/${user}/${windestDir}`,
},
{
command: "git",
args: ["clone", `${baseURL}/${owner}/${repo}.git`],
cwd: `/Users/${winUser}/${windestDir}/${tempDIR}`,
cwd: `/Users/${user}/${windestDir}/${tempDIR}`,
},
{
command: "git",
Expand All @@ -175,45 +171,108 @@ export const windowsCommands = (
{
command: "mkdir",
args: ["-p", ".github/workflows"],
cwd: `/Users/${winUser}/${windestDir}/${tempDIR}/${repo}`,
cwd: `/Users/${user}/${windestDir}/${tempDIR}/${repo}`,
},
{
command: "cp",
args: [
`./bin/workflows/${fileName}`,
`c:\\Users\\${winUser}\\${windestDir}\\${tempDIR}/${repo}\\.github\\workflows\\`,
`c:\\Users\\${user}\\${windestDir}\\${tempDIR}/${repo}\\.github\\workflows\\`,
],
cwd: process.cwd(),
},
{
command: "rm",
args: ["-rf", '"./-p/"'],
cwd: `/Users/${winUser}/${windestDir}/${tempDIR}/${repo}`,
cwd: `/Users/${user}/${windestDir}/${tempDIR}/${repo}`,
},
{
command: "git",
args: ["add", `.github/workflows/${fileName}`],
cwd: `/Users/${winUser}/${windestDir}/${tempDIR}/${repo}`,
cwd: `/Users/${user}/${windestDir}/${tempDIR}/${repo}`,
},
{
command: "git",
args: ["commit", "-m", '"Commit CodeQL File"'],
cwd: `/Users/${winUser}/${windestDir}/${tempDIR}/${repo}`,
cwd: `/Users/${user}/${windestDir}/${tempDIR}/${repo}`,
},
{
command: "git",
args: ["push", "origin", `${branch}`],
cwd: `/Users/${winUser}/${windestDir}/${tempDIR}/${repo}`,
cwd: `/Users/${user}/${windestDir}/${tempDIR}/${repo}`,
},
{
command: "rm",
args: ["-rf", `"./${tempDIR}/"`],
cwd: `/Users/${winUser}/${windestDir}/`,
cwd: `/Users/${user}/${windestDir}/`,
},
{
command: "rm",
args: ["-rf", '"./-p/"'],
cwd: `/Users/${winUser}/${windestDir}`,
cwd: `/Users/${user}/${windestDir}`,
},
] as commands;
return commands;
};

export const wslLinuxCommands = (
owner: string,
repo: string,
branch: string,
fileName: string,
baseURL: string
): commands => {
const commands = [
{
command: "mkdir",
args: ["-p", `${tempDIR}`],
cwd: `/home/${user}`,
},
{
command: "git",
args: ["clone", `${baseURL}/${owner}/${repo}.git`],
cwd: `/home/${user}/${tempDIR}`,
},
{
command: "git",
args: ["checkout", "-b", `${branch}`],
cwd: `/home/${user}/${tempDIR}/${repo}`,
},
{
command: "mkdir",
args: ["-p", ".github/workflows"],
cwd: `/home/${user}/${tempDIR}/${repo}`,
},
{
command: "cp",
args: [
`./bin/workflows/${fileName}`,
`/home/${user}/${tempDIR}/${repo}/.github/workflows/`,
],
cwd: process.cwd(),
},
{
command: "mv",
args: [
`./.github/workflows/${fileName}`,
`./.github/workflows/codeql-analysis.yml`,
],
cwd: `/home/${user}/${tempDIR}/${repo}`,
},
{
command: "git",
args: ["add", ".github/workflows/codeql-analysis.yml"],
cwd: `/home/${user}/${tempDIR}/${repo}`,
},
{
command: "git",
args: ["commit", "-m", '"Commit CodeQL File"'],
cwd: `/home/${user}/${tempDIR}/${repo}`,
},
{
command: "git",
args: ["push", "--set-upstream", "origin", `${branch}`],
cwd: `/home/${user}/${tempDIR}/${repo}`,
},
] as commands;
return commands;
Expand Down
59 changes: 46 additions & 13 deletions src/utils/commitFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,28 @@ import delay from "delay";

import { existsSync } from "fs";

import os from "os";

import { inform, error } from "./globals";

import { macCommands, windowsCommands, codespacesCommands } from "./commands";
import {
inform,
error,
isWindows,
isLinux,
baseURL,
platform,
} from "./globals";

import {
macCommands,
windowsCommands,
codespacesCommands,
wslLinuxCommands,
} from "./commands";

import { execFile as ImportedExec } from "child_process";

import { response, commands } from "../../types/common";

const execFile = util.promisify(ImportedExec);

const platform = os.platform();

const isWindows = platform === "win32";
if (platform !== "win32" && platform !== "darwin" && platform !== "linux") {
error("You can only use either windows or mac machine!");
throw new Error(
Expand All @@ -30,12 +37,17 @@ if (platform !== "win32" && platform !== "darwin" && platform !== "linux") {
export const commitFileMac = async (
owner: string,
repo: string,
refs: string
refs: string,
authToken: string
): Promise<response> => {
let gitCommands: commands;
let index: number;
let isCodespace = false as boolean;

const authBaseURL = baseURL!.replace(
"https://",
`https://x-access-token:${authToken}@`
) as string;
const regExpExecArray = /[^/]*$/.exec(refs);
const branch = regExpExecArray ? regExpExecArray[0] : "";

Expand All @@ -53,12 +65,33 @@ export const commitFileMac = async (
: "codeql-analysis-standard.yml";

try {
/* Codespaces is also a linux environment, so this check has to happen first */
gitCommands =
isWindows === true
? (windowsCommands(owner, repo, branch, fileName) as commands)
: isWindows === false && isCodespace === false
? (macCommands(owner, repo, branch, fileName) as commands)
: (codespacesCommands(owner, repo, branch, fileName) as commands);
? (windowsCommands(
owner,
repo,
branch,
fileName,
authBaseURL
) as commands)
: isCodespace === true
? (codespacesCommands(
owner,
repo,
branch,
fileName,
authBaseURL
) as commands)
: isLinux === true
? (wslLinuxCommands(
owner,
repo,
branch,
fileName,
authBaseURL
) as commands)
: (macCommands(owner, repo, branch, fileName, authBaseURL) as commands);
inform(gitCommands);
} catch (err) {
error(err);
Expand Down
Loading

0 comments on commit 05be846

Please sign in to comment.