Skip to content

Commit

Permalink
Dev/js (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vigneshkna authored Sep 27, 2024
2 parents ddaf61e + cdf5de3 commit 59725f9
Show file tree
Hide file tree
Showing 24 changed files with 2,981 additions and 10 deletions.
File renamed without changes.
Empty file removed src/js/.gitkeep
Empty file.
45 changes: 45 additions & 0 deletions src/js/.releaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"branches": ["main"],
"tagFormat": "${version}",
"repositoryUrl": "https://github.com/Blackplums/how2validate",
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "conventionalcommits",
"releaseRules": [
{ "breaking": true, "release": "major" },
{ "revert": true, "release": "patch" },
{ "type": "build", "release": "patch" },
{ "type": "docs", "release": "patch" },
{ "type": "feat", "release": "minor" },
{ "type": "fix", "release": "patch" },
{ "type": "perf", "release": "patch" },
{ "type": "refactor", "release": "patch" },
{ "type": "chore", "release": "patch" }
]
}
],
[
"@semantic-release/release-notes-generator",
{
"preset": "conventionalcommits",
"presetConfig": {
"types": [
{ "type": "build", "section": "Build", "hidden": false },
{ "type": "chore", "section": "Chores", "hidden": false },
{ "type": "ci", "section": "CI/CD", "hidden": false },
{ "type": "docs", "section": "Docs", "hidden": false },
{ "type": "feat", "section": "Features", "hidden": false },
{ "type": "fix", "section": "Bug Fixes", "hidden": false },
{ "type": "perf", "section": "Performance", "hidden": false },
{ "type": "refactor", "section": "Refactor", "hidden": false },
{ "type": "style", "section": "Code Style", "hidden": false },
{ "type": "test", "section": "Tests", "hidden": false }
]
}
}
],
"@semantic-release/github"
]
}
21 changes: 21 additions & 0 deletions src/js/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 BlackPlum

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
14 changes: 14 additions & 0 deletions src/js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# How2Validate

How2Validate is a package designed to validate secrets and sensitive information across multiple platforms.

## Features

- Validate API keys, passwords, and other sensitive information.
- Cross-platform support (Windows, Linux, macOS).
- Easy integration with existing applications.

## Installation

```bash
npx jsr add @how2validate/how2validate
7 changes: 7 additions & 0 deletions src/js/config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[DEFAULT]
package_name = @how2validate/how2validate
version = 0.0.1

[SECRET]
secret_active = Active
secret_inactive = InActive
45 changes: 45 additions & 0 deletions src/js/how2validate/handler/validator_handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { validateSnykAuthKey } from "../validators/snyk/snyk_auth_key"; // Import the Snyk authentication key validator
import { validateSonarcloudToken } from "../validators/sonarcloud/sonarcloud_token"; // Import the Sonarcloud token validator
import { validateNpmAccessToken } from "../validators/npm/npm_access_token"; // Import the NPM access token validator

// Define a type for the validator function signature
type ValidatorFunction = (
service: string,
secret: string,
response: boolean,
report?: boolean
) => Promise<string>;

// Map of service names to their corresponding validator functions
const serviceHandlers: Record<string, ValidatorFunction> = {
snyk_auth_key: validateSnykAuthKey, // Snyk auth key validator
sonarcloud_token: validateSonarcloudToken, // Sonarcloud token validator
npm_access_token: validateNpmAccessToken, // NPM access token validator
// Add additional services and their validators here
};

/**
* Handle the validation of a service's secret.
* @param service - The name of the service to validate.
* @param secret - The secret (e.g., API key, token) to validate.
* @param response - A boolean indicating whether to include response data in the output.
* @param report - An optional parameter for additional reporting functionality.
* @returns A promise that resolves to a string message indicating the validation result.
*/
export async function validatorHandleService(
service: string,
secret: string,
response: boolean,
report?: boolean
): Promise<string> {
// Retrieve the handler function based on the provided service name
const handler = serviceHandlers[service];

if (handler) {
// If a handler exists, call it with the provided parameters
return handler(service, secret, response, report);
} else {
// Return an error message if no handler is found for the given service
return `Error: No handler for service '${service}'`;
}
}
130 changes: 130 additions & 0 deletions src/js/how2validate/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { Command } from "commander"; // Importing Commander for building CLI applications
import { setupLogging } from "./utility/log_utility"; // Importing the logging setup function
import {
getActiveSecretStatus,
getInactiveSecretStatus,
getPackageName,
getVersion,
} from "./utility/config_utility"; // Importing configuration utility functions
import {
formatServiceProviders,
formatServices,
getSecretProviders,
getSecretServices,
redactSecret,
updateTool,
validateChoice,
} from "./utility/tool_utility"; // Importing utility functions for secret validation
import { validatorHandleService } from "./handler/validator_handler"; // Importing the validation handler

// Call the logging setup function to configure logging
setupLogging();

const program = new Command(); // Create a new Commander program instance

// Configure the CLI program details
program
.name("How2Validate Tool") // Set the name of the CLI tool
.description("Validate various types of secrets for different services.") // Description of what the tool does
.version(
`How2Validate Tool version ${getVersion() as string}`,
"-v, --version",
"Expose the version"
); // Set the version and help flag

const providerChoices = getSecretProviders(); // Get supported secret providers
const serviceChoices = getSecretServices(); // Get supported secret services

// Define CLI options using Commander
program
.option(
"-provider <PROVIDER>",
`Secret provider to validate secrets\nSupported providers:\n${formatServiceProviders()}`,
(value) => validateChoice(value, providerChoices)
) // Option for provider
.option(
"-service <SERVICE>",
`Service / SecretType to validate secrets\nSupported services:\n${formatServices()}`,
(value) => validateChoice(value, serviceChoices)
) // Option for service
.option("-secret <SECRET>", "Pass the secret to be validated") // Option for secret
.option(
"-r, --response",
`Prints ${getActiveSecretStatus()} / ${getInactiveSecretStatus()} upon validating secrets`
) // Option for response
.option("-report", "Reports validated secrets over E-mail", false) // Option to report secrets via email
.option("--update", "Hack the tool to the latest version"); // Option to update the tool

// Function to validate the secret using the specified provider and service
export async function validate(
provider: string,
service: string,
secret: string,
response: boolean,
report: boolean
) {
console.info("Started validating secret...");
const result = await validatorHandleService(
service,
secret,
response,
report
); // Call the handler for validation
console.info(result);
}

// Main function to execute the CLI program logic
async function main() {
program.parse(process.argv); // Parse command-line arguments

// Convert options keys to lowercase for consistency
const options = Object.fromEntries(
Object.entries(program.opts()).map(([key, value]) => [
key.toLowerCase(),
value,
]) // Normalize option keys
);

// Check for the update option
if (options.update) {
try {
console.info("Initiating tool update...");
await updateTool(); // Call the update function
console.info("Tool updated successfully.");
return; // Exit after updating
} catch (error) {
console.error(`Error during tool update: ${error}`); // Log any errors
return;
}
}

// Validate required arguments
if (!options.provider || !options.service || !options.secret) {
console.error("Missing required arguments: -provider, -service, -secret");
console.error("Use '-h' or '--help' for tool usage information."); // Provide help info
return;
}

// Attempt to validate the secret
try {
console.info(
`Initiating validation for service: ${
options.service
} with secret: ${redactSecret(options.secret)}`
);
await validate(
options.provider,
options.service,
options.secret,
options.response,
options.report
); // Call validate function
console.info("Validation completed successfully.");
} catch (error) {
console.error(`An error occurred during validation: ${error}`); // Handle validation errors
console.log(`Error: ${error}`);
}
}

// Start the main function and handle any unexpected errors
main().catch((error) => console.error(`Unexpected error: ${error}`));
93 changes: 93 additions & 0 deletions src/js/how2validate/utility/config_utility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import * as path from "path";
import * as fs from "fs";

interface Config {
DEFAULT?: {
package_name?: string;
version?: string;
};
SECRET?: {
secret_active?: string;
secret_inactive?: string;
};
}

let config: Config | null = null;

export function initConfig() {
const configFilePath = path.resolve(__dirname, "..", "..", "config.ini");

try {
const configContent = fs.readFileSync(configFilePath, "utf-8");
config = parseConfigContent(configContent); // Use a custom parsing function
} catch (error) {
console.error(
`Error: The file '${configFilePath}' was not found or could not be read.`
);
}
}

function parseConfigContent(content: string): Config {
const lines = content.split("\n");
const result: Config = {};

let currentSection: keyof Config | null = null;

for (const line of lines) {
const trimmedLine = line.trim();
if (!trimmedLine || trimmedLine.startsWith(";")) continue; // Skip empty or comment lines

if (trimmedLine.startsWith("[") && trimmedLine.endsWith("]")) {
// New section
currentSection = trimmedLine.slice(1, -1) as keyof Config;
result[currentSection] = {}; // Initialize the section as an object
} else if (currentSection) {
const [key, value] = trimmedLine.split("=").map((part) => part.trim());

// Using type assertion to tell TypeScript that currentSection is valid
(result[currentSection] as Record<string, string | undefined>)[key] =
value;
}
}

return result;
}

// Function to get the package name from the DEFAULT section
export function getPackageName(): string | undefined {
if (config && config.DEFAULT) {
return config.DEFAULT.package_name as string;
} else {
throw new Error("Configuration not initialized. Call initConfig() first.");
}
}

// Function to get the active secret status from the SECRET section
export function getActiveSecretStatus(): string | undefined {
if (config && config.SECRET) {
return config.SECRET.secret_active as string;
} else {
throw new Error("Configuration not initialized. Call initConfig() first.");
}
}

// Function to get the inactive secret status from the SECRET section
export function getInactiveSecretStatus(): string | undefined {
if (config && config.SECRET) {
return config.SECRET.secret_inactive as string;
} else {
throw new Error("Configuration not initialized. Call initConfig() first.");
}
}

// Function to get the version from the DEFAULT section
export function getVersion(): string | undefined {
if (config && config.DEFAULT) {
return config.DEFAULT.version as string;
} else {
throw new Error("Configuration not initialized. Call initConfig() first.");
}
}

// Call initConfig when this file is imported or used
initConfig();
Loading

0 comments on commit 59725f9

Please sign in to comment.