During my recent audit of a Tier-4 data center in Bengaluru, I identified a recurring failure in traditional SSH management: the inability to enforce contextual, time-bound, and geo-specific access controls at scale. While public-key authentication is the standard, it lacks the granularity required to satisfy the 2022 CERT-In Cyber Security Directions or the data protection mandates of the DPDP Act 2023. We observed that even with hardened SSH configurations, lateral movement remained a significant risk. Many organizations are now moving toward a shared SSH key alternative to eliminate the risks associated with static credentials and lack of visibility.
Introduction to Policy as Code (PaC) and OPA
Policy as Code (PaC) is the transition from manual, document-based security checks to automated, version-controlled scripts. In my experience, manual security reviews are the primary bottleneck in CI/CD pipelines. By treating policy as code, we integrate security into the development lifecycle, ensuring that every infrastructure change is validated against a set of predefined rules before deployment.
What is Policy as Code OPA?
Open Policy Agent (OPA) is an open-source, general-purpose policy engine that decouples policy decision-making from policy enforcement. When an entity (a user or a service) requests access to a resource, the enforcement point (like an SSH daemon or a Kubernetes API server) sends a JSON query to OPA. OPA evaluates this query against its policies and data, then returns a decision.
The evolution of authorization in cloud-native environments
We have moved past simple Role-Based Access Control (RBAC). In modern distributed systems, authorization must consider environment variables: Is the request coming from an approved Indian IP range? Is it within business hours (IST)? Is the requester’s MFA token still valid? OPA allows us to ingest these external data points to make "context-aware" decisions that static IAM roles cannot handle, aligning with modern SSH security best practices.
Key benefits of using Open Policy Agent for governance
- Unified Framework: Use the same policy language (Rego) for SSH, Kubernetes, Terraform, and Envoy.
- Auditability: Policies are stored in Git, providing a clear audit trail of who changed which rule and when.
- Reduced Latency: OPA is designed to run as a sidecar, making decisions locally in microseconds.
- Compliance: Automates compliance with Indian regulations like the DPDP Act by ensuring only authorized personnel access PII-sensitive servers.
The Foundation: Policy as Code OPA Rego
Rego is the core of OPA. It is a declarative query language, which means I describe what I want the policy to achieve, rather than how to execute the logic. This is a significant shift for engineers used to imperative languages like Python or Bash.
Understanding Rego: The declarative query language
In Rego, you define rules that are either true or false. We found that the most effective way to learn Rego is to think of it as a series of assertions. If all assertions in a rule are true, the rule itself is true. If any assertion fails, the rule is undefined or false.
How to write your first policy with Rego
We developed the following policy to secure SSH access for an Indian MSP. It restricts access based on user groups, IP ranges, and specific time windows to mitigate the risk of unauthorized access during off-hours.
package ssh.authz
default allow = false
Policy: Allow access only if user is in 'sysadmin' group and connecting from internal subnet
allow { input.user == data.users[i].name data.users[i].group == "sysadmin" net.cidr_contains("10.0.0.0/8", input.source_ip) not is_weekend }
is_weekend { day := time.weekday(time.now_ns()) day == "Saturday" }
is_weekend { day := time.weekday(time.now_ns()) day == "Sunday" }
Decoupling policy logic from application code
By using the logic above, the SSH server doesn't need to know the definition of "weekend" or the list of "sysadmins." It simply sends the metadata to OPA. I have seen this significantly simplify codebase maintenance, as security teams can update the is_weekend rule without touching the SSH configuration or restarting services.
OPA vs. Competitors: Sentinel and Kyverno
Choosing the right engine depends on your stack. While OPA is the industry standard for general-purpose policy, other tools have niche advantages.
Policy as code opa vs sentinel: Comparing OPA with HashiCorp’s engine
Sentinel is HashiCorp’s proprietary policy-as-code framework. It is deeply integrated into Terraform Enterprise and Vault. However, it is not open-source. In our testing, OPA’s community support and its ability to run anywhere—from a Linux binary to a WASM module—make it more versatile for multi-cloud strategies. If you are not strictly tied to the HashiCorp ecosystem, OPA is usually the better investment.
Policy as code opa vs kyverno: Kubernetes-native vs. general-purpose policy engines
Kyverno is built specifically for Kubernetes. It uses YAML, which is familiar to K8s administrators. While Kyverno is excellent for managing Kubernetes resources, it cannot be used to secure an SSH daemon or a custom Java application. OPA, being general-purpose, allows us to maintain a single source of truth for policies across the entire stack, not just the container orchestrator.
When to choose OPA over alternative frameworks
I recommend OPA when your infrastructure includes a mix of legacy VMs, cloud-native containers, and serverless functions. If you need to enforce geofencing for SSH access on a fleet of EC2 instances while simultaneously managing ingress rules in Kubernetes, OPA is the only tool that covers both use cases with a unified language.
Integrating OPA into the DevOps Pipeline
Security must be proactive. We use OPA to catch misconfigurations in the CI/CD pipeline before they reach production. This "shift-left" approach reduces the cost of remediation significantly.
Terraform policy as code opa: Securing Infrastructure as Code (IaC)
We use OPA to inspect Terraform plans. For instance, we can block the creation of any Security Group that allows SSH (Port 22) from 0.0.0.0/0. This is critical for Indian firms to remain compliant with CERT-In mandates regarding the hardening of internet-facing assets.
Policy as code opa conftest: Validating configuration files in CI/CD
Conftest is a utility that helps you write tests against structured configuration data. I use it to validate Kubernetes manifests, Dockerfiles, and even SSH config files.
Example: Running conftest against a deployment manifest
conftest test deployment.yaml --policy policy/
Preventing misconfigurations before deployment
By integrating OPA into Jenkins or GitHub Actions, we can fail builds that violate security policies. For example, if a developer attempts to deploy a container running as root, OPA identifies the violation in the input.json representation of the manifest and blocks the merge request.
Advanced Policy Management with OPAL
One limitation of OPA is that it is functionally stateless. It makes decisions based on the data it has at that moment. In dynamic environments, where user permissions change in real-time, we need a way to keep OPA synced.
Introduction to OPAL policy as code (Open Policy Administration Layer)
OPAL acts as the administration layer for OPA. It monitors your data sources (like a Postgres DB, Git repo, or an AWS Cognito pool) and pushes updates to OPA agents in real-time. This is essential for implementing "Instant Revocation" of SSH access.
Keeping OPA in sync with real-time data changes
If a sysadmin in your Delhi office resigns, their access must be revoked immediately across all 500+ servers. Implementing secure SSH access for teams ensures that when a user is removed from the directory, their active sessions and access rights are terminated immediately as OPAL pushes a new data snapshot to all OPA sidecars.
Architecting a scalable policy distribution system
We recommend a Hub-and-Spoke model. A central OPAL server tracks the state, while OPAL clients run alongside OPA instances on every node. This ensures that even if the central server is unreachable, the local OPA instance can still make decisions based on the last known good state.
Best Practices for Implementing Policy as Code OPA
Implementation is only half the battle. Maintaining Rego policies requires the same rigor as maintaining production code.
Testing and debugging Rego policies
Never deploy a policy without tests. OPA provides a built-in testing framework. I always include a _test.rego file for every policy.
Run the test suite
opa test . -v
Performance optimization for high-scale environments
Rego can be slow if you use too many nested loops or large data sets. I've found that using partial evaluation and indexing can drastically improve performance. For SSH authz, OPA should respond in under 5ms to avoid noticeable lag during login.
Future trends in the Policy as Code ecosystem
We are seeing a move toward "Intent-based Security." Instead of writing specific rules for every service, we define high-level intents (e.g., "No unencrypted traffic in the Mumbai region") and OPA translates these into specific enforcement actions across the stack.
Practical Implementation: Hardening SSH Access
To implement this, I start by running OPA in server mode. This allows me to query it via a REST API from a PAM (Pluggable Authentication Module) or a wrapper script around the SSH shell.
Start OPA server with debug logging
opa run --server --log-level debug --addr :8181
I then perform a baseline audit of the target server to identify vulnerabilities like the 'regreSSHion' (CVE-2024-6387) or the 'Terrapin Attack' (CVE-2023-48795) as documented by NIST NVD.
Audit the target SSH server
ssh-audit --level hard 192.168.1.100
Once the baseline is established, I test the OPA policy by simulating an SSH login attempt. The following curl command mimics the data an SSH enforcement point would send to OPA, following security guidelines from OpenSSH Security.
Simulate an authorization request
curl -s -X POST http://localhost:8181/v1/data/ssh/authz/allow \ -d '{"input": {"user": "admin", "source_ip": "10.0.5.20", "method": "publickey"}}'
If OPA returns {"result": true}, the user is granted access. If the source IP was changed to a public IP, OPA would immediately return false, blocking the connection even if the SSH key was valid. This layer of defense-in-depth is what separates a standard setup from a hardened, compliant infrastructure.
Next Command: Evaluating Local Policies
To verify your Rego logic locally against a JSON input file, use the eval command. This is the fastest way to debug complex rules before pushing them to the OPA server.
opa eval -i input.json -d policy.rego "data.ssh.authz.allow" --format pretty
