{"id":38764907,"url":"https://github.com/jacobsoderblom/fake-akv","last_synced_at":"2026-01-17T12:00:19.187Z","repository":{"id":323811178,"uuid":"1092789755","full_name":"JacobSoderblom/fake-akv","owner":"JacobSoderblom","description":null,"archived":false,"fork":false,"pushed_at":"2025-12-19T14:03:54.000Z","size":70,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-22T05:41:02.592Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","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/JacobSoderblom.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-11-09T10:16:30.000Z","updated_at":"2025-12-19T14:03:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/JacobSoderblom/fake-akv","commit_stats":null,"previous_names":["jacobsoderblom/fake-akv"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/JacobSoderblom/fake-akv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobSoderblom%2Ffake-akv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobSoderblom%2Ffake-akv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobSoderblom%2Ffake-akv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobSoderblom%2Ffake-akv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JacobSoderblom","download_url":"https://codeload.github.com/JacobSoderblom/fake-akv/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JacobSoderblom%2Ffake-akv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28508464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T11:50:55.898Z","status":"ssl_error","status_checked_at":"2026-01-17T11:50:55.569Z","response_time":85,"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-17T12:00:12.304Z","updated_at":"2026-01-17T12:00:19.106Z","avatar_url":"https://github.com/JacobSoderblom.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fake Azure Key Vault (Secrets)\n\nA lightweight, HTTPS-only mock of **Azure Key Vault – Secrets API**, designed for **local development**, **integration testing**, and **CI/CD pipelines**.  \nImplements secret versioning, soft delete, and standard API structure, compatible with official Azure SDKs for Python and .NET.\n\n---\n\n## Container Image\n\nPublished image:  \n\n```\nghcr.io/jacobsoderblom/fake-akv:latest\n```\n\n---\n\n## Quick Start (Local HTTPS)\n\nGenerate a self-signed certificate:\n\n```bash\nmkdir -p certs data\nopenssl req -x509 -newkey rsa:2048 -nodes   -keyout certs/dev.key -out certs/dev.crt -days 365   -subj \"/CN=localhost\"\n```\n\nRun:\n\n```bash\ndocker run --rm -p 8443:8443   -v \"$(pwd)/data:/data\"   -v \"$(pwd)/certs:/certs:ro\"  -e FAKE_AKV_REQUIRE_AUTH=true  -e FAKE_AKV_SSL_CERTFILE=/certs/dev.crt   -e FAKE_AKV_SSL_KEYFILE=/certs/dev.key   ghcr.io/\u003cyour-org\u003e/fake-akv:latest\n```\n\nService is available at:  \n`https://localhost:8443`\n\n---\n\n## Configuration\n\n| Environment Variable | Description | Default |\n|-----------------------|-------------|----------|\n| `FAKE_AKV_STORAGE` | Storage backend (`sqlite` or `memory`) | `sqlite` |\n| `FAKE_AKV_SQLITE_PATH` | Path to SQLite file | `/data/akv.sqlite` |\n| `FAKE_AKV_REQUIRE_AUTH` | Enforce bearer token auth challenge | `true` |\n| `FAKE_AKV_SSL_CERTFILE` | Path to TLS certificate (required) | — |\n| `FAKE_AKV_SSL_KEYFILE` | Path to TLS private key (required) | — |\n| `PORT` | HTTPS port | `8443` |\n\n---\n\n## Kubernetes Deployment\n\n**1. Create a TLS Secret**\n\n```bash\nkubectl create secret tls fake-akv-cert   --cert=certs/dev.crt   --key=certs/dev.key\n```\n\n**2. Create a PersistentVolumeClaim (optional)**\n\n```yaml\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: fake-akv-data\nspec:\n  accessModes: [\"ReadWriteOnce\"]\n  resources:\n    requests:\n      storage: 1Gi\n```\n\n**3. Deploy the service**\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: fake-akv\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: fake-akv\n  template:\n    metadata:\n      labels:\n        app: fake-akv\n    spec:\n      containers:\n        - name: fake-akv\n          image: ghcr.io/\u003cyour-org\u003e/fake-akv:latest\n          ports:\n            - containerPort: 8443\n          env:\n            - name: FAKE_AKV_REQUIRE_AUTH\n              value: true\n            - name: FAKE_AKV_SSL_CERTFILE\n              value: /certs/tls.crt\n            - name: FAKE_AKV_SSL_KEYFILE\n              value: /certs/tls.key\n            - name: FAKE_AKV_STORAGE\n              value: sqlite\n            - name: FAKE_AKV_SQLITE_PATH\n              value: /data/akv.sqlite\n          volumeMounts:\n            - name: certs\n              mountPath: /certs\n              readOnly: true\n            - name: data\n              mountPath: /data\n      volumes:\n        - name: certs\n          secret:\n            secretName: fake-akv-cert\n        - name: data\n          persistentVolumeClaim:\n            claimName: fake-akv-data\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: fake-akv\nspec:\n  ports:\n    - port: 8443\n      targetPort: 8443\n  selector:\n    app: fake-akv\n```\n\n**4. Access**\n\n- Inside cluster: `https://fake-akv:8443`\n- Outside: expose via `Ingress` or `kubectl port-forward`.\n\n---\n\n## Usage from Python\n\n```python\nfrom datetime import datetime, timedelta, timezone\nfrom azure.core.credentials import AccessToken\nfrom azure.core.pipeline.transport import RequestsTransport\nfrom azure.keyvault.secrets import SecretClient\n\nclass FakeCredential:\n    def get_token(self, *_, **__):\n        exp = int((datetime.now(timezone.utc) + timedelta(hours=1)).timestamp())\n        return AccessToken(\"fake-token\", exp)\n\nclient = SecretClient(\n    vault_url=\"https://localhost:8443\",\n    credential=FakeCredential(),\n    transport=RequestsTransport(connection_verify=False),\n    verify_challenge_resource=False,\n)\n\nclient.set_secret(\"demo-secret\", \"example\")\nprint(client.get_secret(\"demo-secret\").value)\n```\n\nNotes:\n\n- `connection_verify=False` skips TLS validation for self-signed certs.\n- `verify_challenge_resource=False` is required for non-`*.vault.azure.net` hosts.\n\n### Tag support\n\n- Set tags on create: `client.set_secret(\"demo\", \"value\", tags={\"env\": \"dev\"})`\n- Update tags/attributes without changing the value: `client.update_secret_properties(\"demo\", version, tags={\"env\": \"prod\"})`\n- List secrets filtered by tag via REST: `GET /secrets?tag-name=env\u0026tag-value=prod\u0026api-version=7.4`\n\n---\n\n## Usage from C #\n\n```csharp\nusing Azure;\nusing Azure.Core;\nusing Azure.Core.Pipeline;\nusing Azure.Security.KeyVault.Secrets;\nusing System;\nusing System.Net.Http;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nsealed class FakeCredential : TokenCredential\n{\n    public override AccessToken GetToken(TokenRequestContext ctx, CancellationToken _) =\u003e\n        new AccessToken(\"fake-token\", DateTimeOffset.UtcNow.AddHours(1));\n\n    public override ValueTask\u003cAccessToken\u003e GetTokenAsync(TokenRequestContext ctx, CancellationToken _) =\u003e\n        ValueTask.FromResult(GetToken(ctx, _));\n}\n\nvar handler = new HttpClientHandler\n{\n    ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator\n};\nvar transport = new HttpClientTransport(new HttpClient(handler));\n\nvar options = new SecretClientOptions\n{\n    Transport = transport,\n    DisableChallengeResourceVerification = true\n};\n\nvar client = new SecretClient(new Uri(\"https://localhost:8443\"), new FakeCredential(), options);\nclient.SetSecret(\"demo-secret\", \"example\");\nConsole.WriteLine(client.GetSecret(\"demo-secret\").Value.Value);\n```\n\n---\n\n## Notes\n\n- Intended for **development and testing only**.\n- Does not implement Azure RBAC, encryption at rest, or networking features.\n- For realistic integration, map a host like `myvault.vault.azure.net` to `127.0.0.1` and generate a certificate for that domain.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacobsoderblom%2Ffake-akv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjacobsoderblom%2Ffake-akv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacobsoderblom%2Ffake-akv/lists"}