New to Claude Skills? Learn how to install them →

mukul975 on GitHub

Configuring AWS Verified Access for ZTNA

Free

Secure VPN-less access to AWS applications with Zero Trust.

Get this skill

Free · Opens the source repo

What Configuring AWS Verified Access for ZTNA does

Configuring AWS Verified Access for ZTNA is designed for organizations looking to implement a secure, VPN-less access model for their internal applications hosted on AWS. This skill facilitates the configuration of AWS Verified Access, which leverages Zero Trust principles to evaluate access requests based on user identity, device security posture, and granular access policies written in the Cedar policy language. By integrating with identity providers like AWS IAM Identity Center and Okta, as well as device management solutions such as CrowdStrike and Jamf, the skill ensures that only authorized users with compliant devices can access sensitive applications.

The skill is particularly useful when transitioning from traditional VPN access to a more secure ZTNA architecture. It provides detailed guidance on setting up Verified Access instances, groups, and endpoints across AWS accounts, making it easier to manage multi-account environments. The use of AWS Resource Access Manager (RAM) allows for efficient sharing of Verified Access groups, which is crucial for organizations with complex AWS setups.

Users will benefit from the comprehensive examples provided in the skill, including scripts for creating Verified Access instances, attaching trust providers, and defining access policies. This hands-on approach allows developers and security architects to implement best practices for security architecture and compliance requirements effectively. The skill is ideal for those involved in security assessments or looking to enhance their security posture through ZTNA.

Overall, this skill serves as a valuable resource for AWS users aiming to adopt a modern, secure access strategy that aligns with Zero Trust principles, ensuring that access to applications is tightly controlled and monitored.

When to use it

Use this skill when deploying or configuring AWS Verified Access for ZTNA capabilities in your environment or when establishing security controls aligned to compliance requirements.

When not to use it

This skill may not be suitable for environments that do not utilize AWS or those that require traditional VPN solutions without a Zero Trust framework.

What you can build with it

Transitioning from VPN to ZTNA

Use this skill to replace traditional VPN access with AWS Verified Access, ensuring secure access to internal applications.

Establishing Compliance Controls

Implement this skill to set up security controls that meet compliance requirements through detailed access policies.

Multi-Account AWS Management

Utilize this skill to configure Verified Access across multiple AWS accounts, streamlining access management.

How to install Configuring AWS Verified Access for ZTNA

View source

1. Install with the skills CLI

npx skills add mukul975/anthropic-cybersecurity-skills/configuring-aws-verified-access-for-ztna --agent claude-code

2. Or install it manually

Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.

Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs

Inside SKILL.md

Written by mukul975

Configuring AWS Verified Access for ZTNA

Overview

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.

When to Use

  • When deploying or configuring configuring aws verified access for ztna capabilities in your environment
  • When establishing security controls aligned to compliance requirements
  • When building or improving security architecture for this domain
  • When conducting security assessments that require this implementation

Prerequisites

  • AWS account with appropriate IAM permissions
  • Identity provider (AWS IAM Identity Center, Okta, or OIDC-compatible)
  • Device trust provider (CrowdStrike, Jamf, JumpCloud, or AWS Verified Access native)
  • Internal Application Load Balancer (ALB) or network interface endpoint
  • Understanding of Cedar policy language
  • VPC with application workloads to protect

Architecture

    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) |
  +--------------+

Core Components

Verified Access Instance

The regional entity that evaluates access requests against policies.

# 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}]'

Trust Providers

Identity Trust Provider (AWS IAM Identity Center)

# 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}]'

Identity Trust Provider (OIDC - Okta)

aws 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"

Device Trust Provider (CrowdStrike)

aws 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"

Attach Trust Providers to Instance

# 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

Verified Access Groups

# 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}]'

Verified Access Endpoints

# 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 Policy Language

Policy Basics

// 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"
};

Advanced Policy Examples

// 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"
};

Group-Level vs Endpoint-Level Policies

// 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")
};

Terraform Configuration

terraform {
  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
}

Multi-Account Deployment with AWS RAM

# 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
}

Monitoring and Logging

# 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

Security Best Practices

  1. Layer policies: Use group-level policies for broad controls and endpoint-level for app-specific restrictions
  2. Require device trust: Always include device posture checks in Cedar policies
  3. Enable access logging: Send to both CloudWatch and S3 for real-time monitoring and long-term retention
  4. Use RAM for multi-account: Share groups across OUs instead of duplicating configuration
  5. Rotate OIDC secrets: Automate client secret rotation via Secrets Manager
  6. Test policies in non-production: Validate Cedar policies before production deployment
  7. Set high device trust thresholds: Require overall score above 70 for production access
  8. Monitor for policy drift: Use AWS Config rules to detect unauthorized changes

References

Frequently asked questions about Configuring AWS Verified Access for ZTNA

Similar skills