Skip to content

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

crn:devi:<provider>:<region>:<account>:<resource_type>:<resource_id>
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