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

test(policychecks): Implement IamPolicyChecks unit tests #5570

Merged
merged 3 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as fs from 'fs'
import * as path from 'path'
import { getLogger, Logger } from '../../../shared/logger'
import { localize } from '../../../shared/utilities/vsCodeUtils'
import { VueWebview } from '../../../webviews/main'
import { VueWebview, VueWebviewPanel } from '../../../webviews/main'
import { ExtContext } from '../../../shared/extensions'
import { telemetry } from '../../../shared/telemetry/telemetry'
import { AccessAnalyzer, SharedIniFileCredentials } from 'aws-sdk'
Expand All @@ -31,8 +31,8 @@ import { ExpiredTokenException } from '@aws-sdk/client-sso-oidc'

const defaultTerraformConfigPath = 'resources/policychecks-tf-default.yaml'
// Diagnostics for Custom checks are shared
const customPolicyCheckDiagnosticCollection = vscode.languages.createDiagnosticCollection('customPolicyCheck')
const validatePolicyDiagnosticCollection = vscode.languages.createDiagnosticCollection('validatePolicy')
export const customPolicyCheckDiagnosticCollection = vscode.languages.createDiagnosticCollection('customPolicyCheck')
export const validatePolicyDiagnosticCollection = vscode.languages.createDiagnosticCollection('validatePolicy')

export interface IamPolicyChecksInitialData {
checkNoNewAccessFilePath: string
Expand All @@ -56,7 +56,7 @@ export class IamPolicyChecksWebview extends VueWebview {
public static readonly sourcePath: string = 'src/awsService/accessanalyzer/vue/index.js'
public readonly id = 'iamPolicyChecks'
private static editedDocumentUri: vscode.Uri
private static editedDocumentFileName: string
public static editedDocumentFileName: string
private static editedDocument: string

public constructor(
Expand Down Expand Up @@ -715,9 +715,9 @@ export class IamPolicyChecksWebview extends VueWebview {
}

public pushCustomCheckDiagnostic(diagnostics: vscode.Diagnostic[], finding: any, isBlocking: boolean) {
const message = `${finding.findingType}: ${finding.message} - Resource name: ${finding.resourceName}, Policy name: ${finding.policyName}`
let message = `${finding.findingType}: ${finding.message} - Resource name: ${finding.resourceName}, Policy name: ${finding.policyName}`
if (message.includes('existingPolicyDocument')) {
message.replace('existingPolicyDocument', 'reference document')
message = message.replace('existingPolicyDocument', 'reference document')
kevluu-aws marked this conversation as resolved.
Show resolved Hide resolved
}
if (finding.details.reasons) {
finding.details.reasons.forEach((reason: any) => {
Expand All @@ -744,7 +744,7 @@ export class IamPolicyChecksWebview extends VueWebview {

const Panel = VueWebview.compilePanel(IamPolicyChecksWebview)

export async function renderIamPolicyChecks(context: ExtContext): Promise<void> {
export async function renderIamPolicyChecks(context: ExtContext): Promise<VueWebviewPanel | undefined> {
const logger: Logger = getLogger()
try {
const client = new AccessAnalyzer({ region: context.regionProvider.defaultRegionId })
Expand Down Expand Up @@ -795,13 +795,14 @@ export async function renderIamPolicyChecks(context: ExtContext): Promise<void>
viewColumn: vscode.ViewColumn.Beside,
title: localize('AWS.iamPolicyChecks.title', 'IAM Policy Checks'),
})
return wv
} catch (err) {
logger.error(err as Error)
}
}

// Helper function to get document contents from a path
async function _readCustomChecksFile(input: string): Promise<string> {
export async function _readCustomChecksFile(input: string): Promise<string> {
if (fs.existsSync(input)) {
return fs.readFileSync(input).toString()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please migrate the app code to use our fs.ts module, do not use nodefs directly

} else {
Expand All @@ -823,7 +824,7 @@ async function _readCustomChecksFile(input: string): Promise<string> {
}

//Check if Cfn and Tf tools are installed
function arePythonToolsInstalled(): boolean {
export function arePythonToolsInstalled(): boolean {
const logger: Logger = getLogger()
let cfnToolInstalled = true
let tfToolInstalled = true
Expand All @@ -846,12 +847,12 @@ function arePythonToolsInstalled(): boolean {
return cfnToolInstalled && tfToolInstalled
}

function isProcessNotFoundErr(errMsg: string) {
export function isProcessNotFoundErr(errMsg: string) {
return errMsg.includes('command not found') || errMsg.includes('ENOENT')
}

// Since TypeScript can only get the CLI tool's error output as a string, we have to parse and sanitize it ourselves
function parseCliErrorMessage(message: string, documentType: PolicyChecksDocumentType): string {
export function parseCliErrorMessage(message: string, documentType: PolicyChecksDocumentType): string {
const cfnMatch = message.match(/ERROR: .*/)
const botoMatch = message.match(/(?<=botocore\.exceptions\.).*/) // Boto errors have a special match
const terraformMatch = message.match(/AttributeError:.*/) // Terraform CLI responds with a different error schema... this catches invalid .json plans
Expand All @@ -876,7 +877,7 @@ function parseCliErrorMessage(message: string, documentType: PolicyChecksDocumen
return message
}

function getCheckNoNewAccessErrorMessage(finding: any) {
export function getCheckNoNewAccessErrorMessage(finding: any) {
if (finding.findingType === 'ERROR') {
if (
finding.message.includes(
Expand All @@ -888,7 +889,7 @@ function getCheckNoNewAccessErrorMessage(finding: any) {
}
}

function getResultCssColor(resultType: PolicyChecksResult): string {
export function getResultCssColor(resultType: PolicyChecksResult): string {
switch (resultType) {
case 'Success':
return 'var(--vscode-terminal-ansiGreen)'
Expand All @@ -899,17 +900,17 @@ function getResultCssColor(resultType: PolicyChecksResult): string {
}
}

function isCloudFormationTemplate(document: string): boolean {
export function isCloudFormationTemplate(document: string): boolean {
const cfnFileTypes = ['.yaml', '.yml', '.json']
return cfnFileTypes.some((t) => document.endsWith(t))
}

function isTerraformPlan(document: string) {
export function isTerraformPlan(document: string) {
const terraformPlanFileTypes = ['.json']
return terraformPlanFileTypes.some((t) => document.endsWith(t))
}

function isJsonPolicyLanguage(document: string) {
export function isJsonPolicyLanguage(document: string) {
const policyLanguageFileTypes = ['.json']
return policyLanguageFileTypes.some((t) => document.endsWith(t))
}
Expand Down
Loading
Loading