{"id":36712702,"url":"https://github.com/hops-ops/aws-irsa","last_synced_at":"2026-02-27T23:42:56.064Z","repository":{"id":324763214,"uuid":"1075739959","full_name":"hops-ops/aws-irsa","owner":"hops-ops","description":"Crossplane XRD and Configuration to configure AWS IRSA resources","archived":false,"fork":false,"pushed_at":"2026-02-09T13:13:50.000Z","size":99,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-09T18:21:59.782Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"KCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hops-ops.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-13T23:36:04.000Z","updated_at":"2026-02-09T13:09:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hops-ops/aws-irsa","commit_stats":null,"previous_names":["hops-ops/configuration-aws-irsa","hops-ops/aws-irsa"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/hops-ops/aws-irsa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-irsa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-irsa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-irsa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-irsa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hops-ops","download_url":"https://codeload.github.com/hops-ops/aws-irsa/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hops-ops%2Faws-irsa/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29634836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T18:02:07.722Z","status":"ssl_error","status_checked_at":"2026-02-19T18:01:46.144Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-12T11:50:26.383Z","updated_at":"2026-02-19T22:09:55.226Z","avatar_url":"https://github.com/hops-ops.png","language":"KCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# aws-irsa\n\nProvisions IAM Roles for Service Accounts (IRSA) so Kubernetes workloads can assume AWS roles without static credentials.\n\n## Why IRSA?\n\n**Without IRSA:**\n- Static AWS credentials stored in Kubernetes Secrets\n- Credentials shared across pods, hard to audit\n- Manual rotation of access keys\n- Overly broad permissions to avoid complexity\n- Security risk if credentials leak\n\n**With IRSA:**\n- No static credentials - pods assume IAM roles via OIDC\n- Fine-grained, per-service-account permissions\n- Automatic credential rotation by AWS\n- Full CloudTrail audit trail\n- Follows AWS security best practices\n\n## The Journey\n\n### Stage 1: Getting Started (Single Service)\n\nMinimal configuration for a single service needing AWS access.\n\n**Why start here?**\n- Establishes secure credential-free pattern from day one\n- No migration pain when you scale\n- Each service gets exactly the permissions it needs\n\n```yaml\napiVersion: aws.hops.ops.com.ai/v1alpha1\nkind: IRSA\nmetadata:\n  name: my-app\n  namespace: production\nspec:\n  clusterName: my-cluster\n  accountId: \"123456789012\"\n  oidc: oidc.eks.us-east-1.amazonaws.com/id/EXAMPLE123\n  policy:\n    document: |\n      {\n        \"Version\": \"2012-10-17\",\n        \"Statement\": [\n          {\n            \"Effect\": \"Allow\",\n            \"Action\": [\"s3:GetObject\", \"s3:PutObject\"],\n            \"Resource\": [\"arn:aws:s3:::my-bucket/*\"]\n          }\n        ]\n      }\n  serviceAccount:\n    namespace: production\n    name: my-app\n```\n\n### Stage 2: Growing (Multiple Services)\n\nAdd naming conventions and permissions boundaries as your team grows.\n\n**Why expand?**\n- Consistent naming across services\n- Permissions boundaries prevent privilege escalation\n- Custom labels for cost allocation and ownership tracking\n\n```yaml\napiVersion: aws.hops.ops.com.ai/v1alpha1\nkind: IRSA\nmetadata:\n  name: loki\n  namespace: logging\nspec:\n  clusterName: prod-cluster\n  providerConfigRef:\n    name: shared-aws\n  accountId: \"123456789012\"\n  oidc: oidc.eks.us-west-2.amazonaws.com/id/CLUSTER123\n  permissionsBoundary: \"arn:aws:iam::123456789012:policy/eks-boundary\"\n  role:\n    namePrefix: irsa-\n  policy:\n    namePrefix: irsa-\n    document: |\n      {\n        \"Version\": \"2012-10-17\",\n        \"Statement\": [\n          {\n            \"Effect\": \"Allow\",\n            \"Action\": [\"s3:*\"],\n            \"Resource\": [\n              \"arn:aws:s3:::loki-chunks\",\n              \"arn:aws:s3:::loki-chunks/*\"\n            ]\n          }\n        ]\n      }\n  labels:\n    team: platform\n    service: logging\n  tags:\n    team: platform\n    cost-center: infrastructure\n  serviceAccount:\n    namespace: logging\n    name: loki\n```\n\n### Stage 3: Enterprise Scale\n\nStandardized patterns across multiple clusters and accounts.\n\n**Why this matters at scale?**\n- Exact name control for cross-account role assumptions\n- Consistent tagging for compliance and cost allocation\n- Integration with organizational governance policies\n\n```yaml\napiVersion: aws.hops.ops.com.ai/v1alpha1\nkind: IRSA\nmetadata:\n  name: cross-account-reader\n  namespace: data-platform\nspec:\n  clusterName: analytics-cluster\n  providerConfigRef:\n    name: data-account-aws\n  accountId: \"987654321098\"\n  oidc: oidc.eks.us-east-1.amazonaws.com/id/ANALYTICS\n  permissionsBoundary: \"arn:aws:iam::987654321098:policy/strict-boundary\"\n  role:\n    nameOverride: \"analytics-cross-account-reader\"\n  policy:\n    nameOverride: \"analytics-cross-account-policy\"\n    document: |\n      {\n        \"Version\": \"2012-10-17\",\n        \"Statement\": [\n          {\n            \"Effect\": \"Allow\",\n            \"Action\": [\"sts:AssumeRole\"],\n            \"Resource\": [\"arn:aws:iam::123456789012:role/data-reader\"]\n          }\n        ]\n      }\n  labels:\n    compliance: pci-dss\n    data-classification: confidential\n  tags:\n    compliance: pci-dss\n    environment: production\n  serviceAccount:\n    namespace: data-platform\n    name: data-reader\n```\n\n### Stage 4: Import Existing\n\nBring existing IAM roles under Crossplane management without recreation.\n\n**Why import?**\n- Preserve existing role ARNs referenced by other systems\n- Gradual adoption path\n- No disruption to running workloads\n\n```yaml\napiVersion: aws.hops.ops.com.ai/v1alpha1\nkind: IRSA\nmetadata:\n  name: legacy-service\n  namespace: production\nspec:\n  # Use orphan policy to manage without deletion rights\n  managementPolicies: [\"Create\", \"Observe\", \"Update\", \"LateInitialize\"]\n  clusterName: my-cluster\n  accountId: \"123456789012\"\n  oidc: oidc.eks.us-east-1.amazonaws.com/id/CLUSTER\n  role:\n    externalName: existing-irsa-role\n  policy:\n    externalName: existing-irsa-policy\n    document: |\n      {\n        \"Version\": \"2012-10-17\",\n        \"Statement\": [...]\n      }\n  serviceAccount:\n    namespace: production\n    name: legacy-app\n```\n\n## Using IRSA\n\nReference the role ARN in your pod's service account annotation:\n\n```yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: my-app\n  namespace: production\n  annotations:\n    # Get this from IRSA status\n    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-cluster-my-app\n```\n\nOr query the status programmatically:\n\n```bash\nkubectl get irsa my-app -n production -o jsonpath='{.status.role.arn}'\n```\n\n## Status\n\nThe IRSA resource exposes typed status fields from the created AWS resources:\n\n| Field | Description |\n|-------|-------------|\n| `ready` | Whether all composed resources are ready |\n| `role.arn` | ARN of the IAM role - use for ServiceAccount annotations |\n| `role.name` | Name of the IAM role in AWS |\n| `policy.arn` | ARN of the IAM policy |\n| `policy.name` | Name of the IAM policy in AWS |\n| `attachment.id` | ID of the role-policy attachment in AWS |\n\nExample:\n```yaml\nstatus:\n  ready: true\n  role:\n    arn: \"arn:aws:iam::123456789012:role/cluster-x-loki\"\n    name: \"cluster-x-loki\"\n  policy:\n    arn: \"arn:aws:iam::123456789012:policy/cluster-x-loki\"\n    name: \"cluster-x-loki\"\n  attachment:\n    id: \"cluster-x-loki-20240115123456789\"\n```\n\n## Composed Resources\n\nThis XRD creates:\n\n- **IAM Role** - With web identity trust policy for the OIDC provider\n- **IAM Policy** - Contains the permissions you define\n- **RolePolicyAttachment** - Links the policy to the role\n- **Usage** (2x) - Deletion protection for Role and Policy\n\n## Development\n\n```bash\nmake render          # Render all examples\nmake validate        # Validate all examples against schemas\nmake test            # Run unit tests\nmake e2e             # Run E2E tests (requires AWS credentials)\nmake publish tag=v1  # Build and push package\n```\n\n## License\n\nApache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhops-ops%2Faws-irsa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhops-ops%2Faws-irsa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhops-ops%2Faws-irsa/lists"}