Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Configure AWS Verified Access to provide VPN-less zero trust network access to internal applications using identity and device posture verification with Cedar policy language.
.claude/skills/configuring-aws-verified-access-for-ztna/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-22 | ✗→✓ | ▲ Improved | — | — |
| case-19 | ✗→✓ | ▲ Improved | — | — |
| case-10 | ✗→✓ | ▲ Improved | — | — |
AWS Verified Access is a Zero Trust Network Access (ZTNA) service that provides secure, VPN-less access to corporate applications hosted in AWS. It evaluates each access request in real-time against granular conditional access policies written in the Cedar policy language, ensuring access is granted per-application only when specific security requirements such as user identity and device security posture are met and maintained. Verified Access integrates with AWS IAM Identity Center, third-party identity providers (Okta, CrowdStrike, JumpCloud, Jamf), and device management solutions. For multi-account deployments, AWS Resource Access Manager (RAM) enables sharing Verified Access groups across organizational units.
End User (Browser)
|
| HTTPS
v
+------+--------+
| Verified |
| Access |
| Endpoint |
| (Public DNS) |
+------+--------+
|
+------+--------+
| Verified | <-- Cedar Access Policies
| Access | <-- Identity Provider Signals
| Instance | <-- Device Trust Signals
| (Policy |
| Evaluation) |
+------+--------+
|
+------+--------+
| Verified |
| Access Group |
| (App Group) |
+------+--------+
|
+------+--------+
| Internal ALB |
| or ENI Target |
+------+--------+
|
+------+--------+
| Application |
| (Private VPC) |
+--------------+The regional entity that evaluates access requests against policies.
bash# Create Verified Access Instance via AWS CLI aws ec2 create-verified-access-instance \ --description "Production Zero Trust Instance" \ --tag-specifications 'ResourceType=verified-access-instance,Tags=[{Key=Environment,Value=production}]'
bash# Create identity trust provider aws ec2 create-verified-access-trust-provider \ --trust-provider-type user \ --user-trust-provider-type iam-identity-center \ --policy-reference-name "idc" \ --description "IAM Identity Center trust provider" \ --tag-specifications 'ResourceType=verified-access-trust-provider,Tags=[{Key=Type,Value=identity}]'
bashaws ec2 create-verified-access-trust-provider \ --trust-provider-type user \ --user-trust-provider-type oidc \ --oidc-options '{ "Issuer": "https://company.okta.com/oauth2/default", "AuthorizationEndpoint": "https://company.okta.com/oauth2/default/v1/authorize", "TokenEndpoint": "https://company.okta.com/oauth2/default/v1/token", "UserInfoEndpoint": "https://company.okta.com/oauth2/default/v1/userinfo", "ClientId": "0oa1234567890", "ClientSecret": "client-secret-here", "Scope": "openid profile groups" }' \ --policy-reference-name "okta" \ --description "Okta OIDC trust provider"
bashaws ec2 create-verified-access-trust-provider \ --trust-provider-type device \ --device-trust-provider-type crowdstrike \ --device-options '{ "TenantId": "crowdstrike-tenant-id", "PublicSigningKeyUrl": "https://api.crowdstrike.com/zero-trust/v2/certificates" }' \ --policy-reference-name "crowdstrike" \ --description "CrowdStrike device trust provider"
bash# Attach identity provider aws ec2 attach-verified-access-trust-provider \ --verified-access-instance-id vai-0123456789abcdef \ --verified-access-trust-provider-id vatp-0123456789abcdef # Attach device provider aws ec2 attach-verified-access-trust-provider \ --verified-access-instance-id vai-0123456789abcdef \ --verified-access-trust-provider-id vatp-device123456
bash# Create a group for web applications aws ec2 create-verified-access-group \ --verified-access-instance-id vai-0123456789abcdef \ --description "Production Web Applications" \ --policy-document 'permit(principal, action, resource) when { context.okta.groups.contains("production-access") && context.crowdstrike.assessment.overall > 50 };' \ --tag-specifications 'ResourceType=verified-access-group,Tags=[{Key=Tier,Value=web}]'
bash# Create endpoint for ALB-backed application aws ec2 create-verified-access-endpoint \ --verified-access-group-id vag-0123456789abcdef \ --endpoint-type load-balancer \ --attachment-type vpc \ --domain-certificate-arn arn:aws:acm:us-east-1:123456789012:certificate/xxxx \ --application-domain app.internal.company.com \ --endpoint-domain-prefix myapp \ --load-balancer-options '{ "LoadBalancerArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/internal-alb/xxxx", "Port": 443, "Protocol": "https", "SubnetIds": ["subnet-abc123", "subnet-def456"] }' \ --security-group-ids sg-0123456789abcdef \ --description "Internal HR Application"
cedar// Allow access for users in the engineering group with compliant devices permit(principal, action, resource) when { context.okta.groups.contains("engineering") && context.crowdstrike.assessment.overall > 70 && context.crowdstrike.assessment.sensor_config.status == "active" }; // Deny access from unmanaged devices forbid(principal, action, resource) when { !context.crowdstrike.assessment.sensor_config.status == "active" };
cedar// Time-based access - only during business hours (UTC) permit(principal, action, resource) when { context.okta.groups.contains("contractors") && context.http_request.http_method == "GET" && context.crowdstrike.assessment.overall > 80 }; // Restrict admin access to specific user group with high device trust permit(principal, action, resource) when { context.idc.groups.contains("admins") && context.crowdstrike.assessment.overall > 90 && context.crowdstrike.assessment.os_version.startswith("Windows 11") || context.crowdstrike.assessment.os_version.startswith("macOS 14") }; // Allow read-only access for lower trust levels permit(principal, action, resource) when { context.okta.groups.contains("read-only") && context.crowdstrike.assessment.overall > 30 && context.http_request.http_method == "GET" };
cedar// Group-level policy (applies to all endpoints in the group) // Set on the Verified Access Group permit(principal, action, resource) when { context.okta.groups.contains("employees") && context.crowdstrike.assessment.overall > 50 }; // Endpoint-level policy (additional restrictions for specific app) // Set on the Verified Access Endpoint permit(principal, action, resource) when { context.okta.groups.contains("hr-team") && context.okta.email.endsWith("@company.com") };
hclterraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } # Verified Access Instance resource "aws_verifiedaccess_instance" "main" { description = "Production Zero Trust Access" tags = { Environment = "production" } } # Identity Trust Provider (OIDC) resource "aws_verifiedaccess_trust_provider" "okta" { policy_reference_name = "okta" trust_provider_type = "user" user_trust_provider_type = "oidc" description = "Okta identity provider" oidc_options { authorization_endpoint = "https://company.okta.com/oauth2/default/v1/authorize" client_id = var.okta_client_id client_secret = var.okta_client_secret issuer = "https://company.okta.com/oauth2/default" scope = "openid profile groups" token_endpoint = "https://company.okta.com/oauth2/default/v1/token" user_info_endpoint = "https://company.okta.com/oauth2/default/v1/userinfo" } } # Device Trust Provider (CrowdStrike) resource "aws_verifiedaccess_trust_provider" "crowdstrike" { policy_reference_name = "crowdstrike" trust_provider_type = "device" device_trust_provider_type = "crowdstrike" description = "CrowdStrike device trust" device_options { tenant_id = var.crowdstrike_tenant_id } } # Attach providers to instance resource "aws_verifiedaccess_instance_trust_provider_attachment" "okta" { verifiedaccess_instance_id = aws_verifiedaccess_instance.main.id verifiedaccess_trust_provider_id = aws_verifiedaccess_trust_provider.okta.id } resource "aws_verifiedaccess_instance_trust_provider_attachment" "crowdstrike" { verifiedaccess_instance_id = aws_verifiedaccess_instance.main.id verifiedaccess_trust_provider_id = aws_verifiedaccess_trust_provider.crowdstrike.id } # Verified Access Group resource "aws_verifiedaccess_group" "web_apps" { verifiedaccess_instance_id = aws_verifiedaccess_instance.main.id description = "Production Web Applications" policy_document = <<-CEDAR permit(principal, action, resource) when { context.okta.groups.contains("production-access") && context.crowdstrike.assessment.overall > 50 }; CEDAR tags = { Tier = "web" } } # Verified Access Endpoint resource "aws_verifiedaccess_endpoint" "internal_app" { verified_access_group_id = aws_verifiedaccess_group.web_apps.id endpoint_type = "load-balancer" attachment_type = "vpc" domain_certificate_arn = aws_acm_certificate.app.arn application_domain = "app.internal.company.com" endpoint_domain_prefix = "myapp" description = "Internal Application" load_balancer_options { load_balancer_arn = aws_lb.internal.arn port = 443 protocol = "https" subnet_ids = var.private_subnet_ids } security_group_ids = [aws_security_group.verified_access.id] policy_document = <<-CEDAR permit(principal, action, resource) when { context.okta.groups.contains("app-users") }; CEDAR } # Logging configuration resource "aws_verifiedaccess_instance_logging_configuration" "main" { verifiedaccess_instance_id = aws_verifiedaccess_instance.main.id access_logs { cloudwatch_logs { enabled = true log_group = aws_cloudwatch_log_group.verified_access.name } s3 { enabled = true bucket_name = aws_s3_bucket.access_logs.id prefix = "verified-access/" } } } resource "aws_cloudwatch_log_group" "verified_access" { name = "/aws/verified-access/production" retention_in_days = 90 }
hcl# Share Verified Access Group across accounts via RAM resource "aws_ram_resource_share" "verified_access" { name = "verified-access-share" allow_external_principals = false } resource "aws_ram_resource_association" "group_share" { resource_arn = aws_verifiedaccess_group.web_apps.verified_access_group_arn resource_share_arn = aws_ram_resource_share.verified_access.arn } resource "aws_ram_principal_association" "workload_ou" { principal = "arn:aws:organizations::123456789012:ou/o-xxxx/ou-xxxx-xxxxxxxx" resource_share_arn = aws_ram_resource_share.verified_access.arn }
bash# Query access logs in CloudWatch aws logs filter-log-events \ --log-group-name /aws/verified-access/production \ --filter-pattern '{ $.status_code = "403" }' \ --start-time $(date -d '1 hour ago' +%s000) # CloudWatch alarm for access denials aws cloudwatch put-metric-alarm \ --alarm-name "VerifiedAccess-HighDenialRate" \ --metric-name "AccessDenied" \ --namespace "AWS/VerifiedAccess" \ --statistic Sum \ --period 300 \ --threshold 100 \ --comparison-operator GreaterThanThreshold \ --evaluation-periods 2 \ --alarm-actions arn:aws:sns:us-east-1:123456789012:security-alerts
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +36 percentage points is the difference between those two pass rates over the 22 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.