@flamesshield/rules-engine
Version:
Independent rules engine for security analysis of Firebase
376 lines (299 loc) • 11.7 kB
Markdown
# @fireshield/rules-engine
An independent rules engine for security analysis of Firebase and cloud projects. This package provides a Firebase-agnostic rules execution engine that can analyze project configurations against security policies.
## Features
- **Firebase-Independent**: No Firebase dependencies, can be used with any project configuration data
- **Rules Engine**: Powered by json-rules-engine for flexible condition evaluation
- **SARIF Output**: Generate industry-standard SARIF reports for security findings
- **Extensible Scanners**: Plugin architecture for custom security scanners
- **TypeScript**: Full TypeScript support with comprehensive type definitions
## Installation
### From GitHub Packages
```bash
# Configure npm to use GitHub Packages for @fireshield scope
echo "@fireshield:registry=https://npm.pkg.github.com" >> ~/.npmrc
# Install the package
npm install @fireshield/rules-engine
```
### Alternative: Using .npmrc file
Create a `.npmrc` file in your project root:
```
@fireshield:registry=https://npm.pkg.github.com
```
Then install:
```bash
npm install @fireshield/rules-engine
```
### Authentication
For private packages, you'll need a GitHub Personal Access Token with `read:packages` permission:
```bash
echo "//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN" >> ~/.npmrc
```
## Basic Usage
```typescript
import {
executeRules,
createRuleExecutionContext,
generateSARIF
} from '@fireshield/rules-engine';
// Your project information
const projectInfo = {
project_id: 'my-project',
auth: { auth_enabled: false },
databases: [{ id: 'default', location: 'us-central1' }],
appcheck: {
app_check_enabled: true,
total_apps: 2,
total_services: 3,
enforced_services: 2
},
// ... other project data
};
// Your security rules
const rules = [
{
id: 'auth-not-enabled',
name: 'Authentication Not Enabled',
description: 'Checks if Firebase Authentication is enabled',
severity: 'high',
category: 'Authentication',
conditions: {
all: [{ fact: 'auth', path: 'auth_enabled', operator: 'equal', value: false }]
},
event: {
type: 'auth-not-enabled',
params: { message: 'Firebase Authentication is not enabled' }
}
}
];
// Execute rules - ProjectInformation is automatically enriched with computed properties
const context = createRuleExecutionContext(projectInfo, rules);
const results = await executeRules(context);
// Generate SARIF report
const analysisResult = {
scanId: 'scan-123',
project_id: 'my-project',
timestamp: new Date().toISOString(),
total_rules: rules.length,
triggered_rules: results.filter(r => r.triggered).length,
results: results
};
const sarifReport = generateSARIF(analysisResult);
```
## Core Types
### ProjectInformation
The core data structure containing Firebase project configuration. ProjectInformation is automatically enriched with computed properties during rule execution.
```typescript
interface ProjectInformation {
project_id: string;
databases: DatabaseInfo[];
functionsv1: FirebaseFunction[];
functionsv2: FirebaseFunction[];
storage_buckets: StorageBucket[];
auth: AuthSettings;
appcheck: AppCheckSettings;
function_secrets: SecretScanResult[];
}
// Enriched with computed properties during execution
interface EnrichedProjectInformation extends ProjectInformation {
computed: {
enforcement_ratio: number;
apps_without_attestation_providers: number;
security_score: number;
has_secrets: boolean;
multi_region_deployment: boolean;
};
}
```
### StaticRule
```typescript
interface StaticRule {
id: string;
name: string;
description: string;
severity?: 'low' | 'medium' | 'high' | 'critical';
category?: string;
conditions: Record<string, unknown>;
event: {
type: string;
params: {
message: string;
[key: string]: unknown;
};
};
}
```
### RuleResult
```typescript
interface RuleResult {
rule_id: string;
rule_name: string;
severity: string;
category: string;
message: string;
triggered: boolean;
facts_used: Record<string, unknown>;
event_params?: Record<string, unknown>;
}
```
## API Reference
### Core Functions
#### `executeRules(context: RuleExecutionContext): Promise<RuleResult[]>`
Executes security rules against project information.
#### `createRuleExecutionContext(projectInfo: ProjectInformation, rules: StaticRule[]): RuleExecutionContext`
Creates an execution context for rule evaluation.
#### `generateSARIF(analysisResult: AnalysisResult): any`
Generates SARIF (Static Analysis Results Interchange Format) output.
### Scanners
The package includes extensible scanners for different security aspects:
- **Secret Scanner**: Detects hardcoded secrets in function environment variables
- **Authentication Scanner**: Analyzes authentication configuration
- **Access Control Scanner**: Reviews database and storage permissions
- **Configuration Scanner**: Validates security settings
## Rule Examples
### Computed Properties
The rules engine automatically enriches ProjectInformation with computed properties that provide calculated values for complex security analysis:
```typescript
// Available computed properties:
{
computed: {
enforcement_ratio: number; // Ratio of enforced AppCheck services
apps_without_attestation_providers: number; // Count of apps missing attestation
security_score: number; // Overall security score (0-100)
has_secrets: boolean; // Whether functions contain secrets
multi_region_deployment: boolean; // Whether deployment spans multiple regions
}
}
```
### Rule Path Reference
| ProjectInformation Path | Description | Example Value |
| ---------------------------- | --------------------------------------- | ------------- |
| `auth.auth_enabled` | Whether authentication is enabled | `true` |
| `auth.email_enabled` | Whether email authentication is enabled | `true` |
| `auth.password_min_length` | Minimum password length | `8` |
| `appcheck.app_check_enabled` | Whether App Check is enabled | `true` |
| `appcheck.total_apps` | Total number of apps | `3` |
| `appcheck.total_services` | Total number of services | `5` |
| `appcheck.enforced_services` | Number of enforced services | `3` |
| `computed.enforcement_ratio` | Enforcement coverage ratio | `0.6` |
| `computed.has_secrets` | Whether secrets were detected | `false` |
## Rule Examples
### Authentication Rules
```typescript
{
id: 'weak-password-policy',
name: 'Weak Password Policy',
description: 'Checks for weak password policies',
severity: 'medium',
category: 'Authentication',
conditions: {
all: [
{ fact: 'auth', path: 'auth_enabled', operator: 'equal', value: true },
{ fact: 'auth', path: 'password_min_length', operator: 'lessThan', value: 8 }
]
},
event: {
type: 'weak-password-policy',
params: { message: 'Password policy is weak' }
}
}
```
### App Check Rules
```typescript
{
id: 'low-enforcement-coverage',
name: 'Low App Check Enforcement Coverage',
description: 'Less than 50% of services have App Check enforcement enabled',
severity: 'warning',
category: 'AppCheck',
conditions: {
all: [
{ fact: 'computed', path: 'enforcement_ratio', operator: 'lessThan', value: 0.5 }
]
},
event: {
type: 'low-enforcement-coverage',
params: { message: 'App Check enforcement coverage is too low' }
}
}
```
### Function Security Rules
```typescript
{
id: 'functions-have-secrets',
name: 'Functions Contain Secrets',
description: 'Detects hardcoded secrets in function environment variables',
severity: 'critical',
category: 'Secrets',
conditions: {
all: [{ fact: 'computed', path: 'has_secrets', operator: 'equal', value: true }]
},
event: {
type: 'functions-have-secrets',
params: { message: 'Functions contain hardcoded secrets' }
}
}
```
## Development Status
🚧 **This package is under active development as part of the Fireshield rules engine extraction.**
### Implementation Stages
- ✅ **Stage 1**: Package structure, types, and configuration
- ✅ **Stage 2**: Core logic extraction (fact-transformer migration to computed properties)
- ✅ **Stage 3**: Rules engine modernization and ProjectInformation integration
- ⏳ **Stage 4**: Scanner integration
- ⏳ **Stage 5**: Testing and validation
- ⏳ **Stage 6**: Documentation and examples
### Migration Notes
**Fact-Transformer Deprecation (June 2025)**
- ✅ Removed fact-transformer layer for simplified architecture
- ✅ Direct ProjectInformation usage with computed properties
- ✅ Enhanced type safety and performance
- ✅ All 26 rules migrated to new format
For legacy systems still using fact-transformer functions, please update to use `executeRules()` directly with ProjectInformation objects.
## Contributing
This package is part of the Fireshield project. Contributions are welcome!
## License
MIT License - see LICENSE file for details.
## Support
For issues and questions:
- GitHub Issues: [Fireshield Issues](https://github.com/fireshield/issues)
- Documentation: [Fireshield Docs](https://docs.fireshield.dev)
*Part of the Fireshield Security Platform*
## Publishing to GitHub Packages
To publish this package to a private GitHub npm repository, follow these steps:
### 1. Create a Personal Access Token (PAT)
- Go to your GitHub account settings.
- Navigate to "Developer settings" > "Personal access tokens" > "Tokens (classic)".
- Click "Generate new token" (or "Generate new token (classic)").
- Give your token a descriptive name (e.g., `npm-publish`).
- Select the scopes `read:packages` and `write:packages`.
- Click "Generate token" and copy the token. You will not be able to see it again.
### 2. Configure npm
Create or edit the `.npmrc` file in your user's home directory (e.g., `~/.npmrc` on Linux/macOS or `C:\Users\YOUR_USERNAME\.npmrc` on Windows). Add the following line, replacing `YOUR_PAT_HERE` with the PAT you just created:
```
//npm.pkg.github.com/:_authToken=YOUR_PAT_HERE
```
This tells npm to authenticate with your PAT when interacting with the GitHub Packages registry.
### 3. Update `package.json`
Ensure your `package.json` file includes the `repository` field and a `publishConfig` field pointing to the GitHub Packages registry. Replace `OWNER` and `REPO` with your GitHub username or organization name and the repository name.
```json
{
"name": "@OWNER/rules-engine", // It's good practice to scope your package name to your GitHub owner
// ... other package.json fields
"repository": {
"type": "git",
"url": "https://github.com/OWNER/REPO.git"
},
"publishConfig": {
"registry": "https://npm.pkg.github.com/"
}
// ...
}
```
**Note:** For this specific package, the name is `@fireshield/rules-engine`. If you are publishing to a personal fork or a different organization, you would change `fireshield` in the `name` property to your GitHub username or organization name (e.g., `@YOUR_USERNAME/rules-engine`).
### 4. Publish the Package
Once your PAT is configured and `package.json` is updated, you can publish the package using:
```bash
npm publish
```
This command will build your package (if a `prepublishOnly` script is defined) and upload it to the GitHub Packages registry associated with the repository specified in your `package.json`.