title: CloudSlash - Plugin gRPC Spec Reference description: Five methods. Every plugin implements exactly these five. The core scanning and lifecycle contract: Plugins that support active remediation implement this ad...
Plugin gRPC Spec¶
Five methods. Every plugin implements exactly these five.
Provider Service¶
provider.proto
The core scanning and lifecycle contract:
syntax = "proto3";
package cloudslash.provider.v1;
service Provider {
// Protocol negotiation: must be the first call
rpc Handshake(HandshakeRequest) returns (HandshakeResponse);
// Infrastructure discovery: streams resources into the Universal Graph
rpc Scan(ScanRequest) returns (stream ScanResponse);
// s.a.u quarantine enforcement
rpc ApplyQuarantine(QuarantineRequest) returns (QuarantineResponse);
// Safety check before remediation
rpc CheckReversibility(ReversibilityRequest) returns (ReversibilityProof);
}
Remediator Extension¶
Plugins that support active remediation implement this additional service:
service Remediator {
// Execute a remediation action on a cloud resource
rpc Remediate(RemediateRequest) returns (RemediateResponse);
}
Plugins that embed UnimplementedRemediatorServer degrade gracefully to scan-only mode.
Message Definitions¶
Handshake¶
message HandshakeRequest {
string daemon_version = 1;
}
message HandshakeResponse {
bool compatible = 1;
string plugin_version = 2;
string message = 3;
}
Scan¶
message ScanRequest {
map<string, string> config = 1; // region, project_id, subscription_id, etc.
}
message ScanResponse {
repeated Node nodes = 1;
repeated Edge edges = 2;
}
message Node {
string crn = 1; // CloudSlash Resource Name
bytes properties = 2; // JSON-encoded resource attributes
double cost = 3; // Monthly cost in USD
}
message Edge {
string source_crn = 1;
string target_crn = 2;
string relation = 3; // e.g. "ATTACHED_TO", "MEMBER_OF", "DEPENDS_ON"
}
Remediate¶
message RemediateRequest {
string crn = 1; // Target resource CRN
string action = 2; // "stop", "delete", "throttle", "pause", etc.
map<string, string> properties = 3; // Additional context (region, credentials)
bool dry_run = 4; // Validate without executing
}
message RemediateResponse {
bool success = 1;
string status = 2; // "stopped", "deleted", "throttled", etc.
string error = 3; // Empty on success
map<string, string> snapshot = 4; // Snapshot IDs for rollback
}
Quarantine¶
message QuarantineRequest {
string crn = 1;
string action = 2; // "ISOLATE", "DELETE", "STOP"
string reason = 3;
}
message QuarantineResponse {
bool success = 1;
string message = 2;
}
Reversibility¶
message ReversibilityRequest {
string crn = 1;
map<string, string> properties = 2;
}
message ReversibilityProof {
bool safe = 1;
string reason = 2; // e.g. "termination protection enabled"
}
CRN Format¶
| Segment | Description | Examples |
|---|---|---|
provider |
Cloud or system identifier | aws, gcp, azure, linode, hetzner, carbon |
region |
Geographic region or zone | us-east-1, us-central1-a, eu-central |
account |
Account/project/subscription ID | 123456789, my-gcp-project |
resource_type |
Type of resource | instance, volume, db, function |
resource_id |
Provider-specific identifier | i-0abc123, vol-456, my-db-1 |
Hashicorp go-plugin Integration¶
Every plugin binary must serve the gRPC server using go-plugin's Serve():
func main() {
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: shared.Handshake,
Plugins: map[string]plugin.Plugin{
"provider": &shared.ProviderPlugin{Impl: &MyProvider{}},
},
GRPCServer: plugin.DefaultGRPCServer,
})
}
The handshake config is defined in pkg/engine/plugin/shared/:
var Handshake = plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CLOUDSLASH_PLUGIN",
MagicCookieValue: "devi",
}
Official Plugin Capabilities¶
| Plugin | Scan | Remediate | CheckReversibility | PreflightCheck |
|---|---|---|---|---|
cloudslash-plugin-aws |
✅ EC2, EBS, RDS, EKS, Lambda, ElastiCache, NAT, DynamoDB, API GW, S3, SGs | ✅ EC2 stop/terminate, EBS delete, RDS stop/delete, Lambda throttle | ✅ Termination protection | ✅ STS GetCallerIdentity |
cloudslash-plugin-gcp |
✅ GCE, Disks, GKE, Cloud SQL, GCS, BigQuery, Cloud Run, Pub/Sub, Memorystore, Functions, Spanner, Dataproc | ✅ GCE stop/delete, Disk delete, Cloud SQL stop/delete | ✅ Deletion protection | : |
cloudslash-plugin-azure |
✅ VMs, Disks, Public IPs, SQL, AKS, Storage, App Service, Redis, Cosmos, LBs, Functions | ✅ VM deallocate/delete, Disk delete, SQL pause/delete | ✅ do-not-delete/production tags | : |
cloudslash-plugin-linode |
✅ Linodes, Volumes, NodeBalancers | ✅ Linode shutdown/delete, Volume detach/delete, NodeBalancer delete | ✅ Production tag | ✅ GetProfile |
Heuristic Plugin Service¶
Heuristic plugins extend waste detection. Two methods. No cloud credentials required: they operate entirely on the graph snapshot the engine sends them.
heuristic.proto
syntax = "proto3";
package cloudslash.heuristic.v1;
service HeuristicPlugin {
// Called once at startup to declare capability and data requirements.
rpc Metadata(MetadataRequest) returns (MetadataResponse);
// Bidirectional stream: engine sends NodeBatches, plugin emits HeuristicFindings.
rpc Analyze(stream NodeBatch) returns (stream HeuristicFinding);
}
message MetadataRequest {}
message MetadataResponse {
string name = 1;
string description = 2;
string version = 3;
repeated string resource_type_filter = 4; // empty = all types
repeated string required_properties = 5; // engine strips everything else
int32 preferred_batch_size = 6; // engine caps at global max
}
message GraphNode {
string crn = 1;
string resource_type = 2;
double cost_usd = 3;
map<string, string> properties = 4; // only declared keys
}
message NodeBatch {
repeated GraphNode nodes = 1;
bool is_last = 2;
}
message HeuristicFinding {
string crn = 1;
bool is_waste = 2;
int32 risk_score = 3; // 0–79; engine caps at 79
string reason = 4;
string suggested_action = 5;
double projected_savings_usd = 6;
map<string, string> annotations = 7;
}
Handshake Config¶
var HeuristicHandshake = plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CLOUDSLASH_HEURISTIC_PLUGIN",
MagicCookieValue: "devi-heuristic",
}
Serve Boilerplate¶
func main() {
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: shared.HeuristicHandshake,
Plugins: map[string]plugin.Plugin{
"heuristic": &shared.HeuristicGRPCPlugin{Impl: &MyHeuristic{}},
},
GRPCServer: plugin.DefaultGRPCServer,
})
}
Security Constraints¶
| Constraint | Detail |
|---|---|
| Binary signing | SHA-256 of the binary must match the adjacent .yaml manifest before subprocess launch |
| Property isolation | Engine strips all properties not in required_properties before streaming |
| CRN validation | Findings referencing CRNs not in the sent snapshot are discarded |
| Trust ceiling | risk_score > 79 is silently capped: community plugins cannot reach RISK or CRITICAL verdicts |