-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
2,981 additions
and
10 deletions.
There are no files selected for viewing
File renamed without changes.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}'`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}`)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
Oops, something went wrong.