{"id":19925694,"url":"https://github.com/paloaltonetworks/a3s","last_synced_at":"2025-05-03T08:31:13.997Z","repository":{"id":41858540,"uuid":"418593758","full_name":"PaloAltoNetworks/a3s","owner":"PaloAltoNetworks","description":"Auth As A Service","archived":false,"fork":false,"pushed_at":"2025-05-02T21:25:57.000Z","size":4226,"stargazers_count":12,"open_issues_count":6,"forks_count":5,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-05-02T22:20:09.787Z","etag":null,"topics":["authentication","authorization","identity","normalization"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PaloAltoNetworks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-10-18T17:02:21.000Z","updated_at":"2025-05-02T21:14:12.000Z","dependencies_parsed_at":"2024-07-09T00:06:55.877Z","dependency_job_id":"bbad7322-869c-4349-b0e6-dfef92804d77","html_url":"https://github.com/PaloAltoNetworks/a3s","commit_stats":null,"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaloAltoNetworks%2Fa3s","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaloAltoNetworks%2Fa3s/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaloAltoNetworks%2Fa3s/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaloAltoNetworks%2Fa3s/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PaloAltoNetworks","download_url":"https://codeload.github.com/PaloAltoNetworks/a3s/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252162521,"owners_count":21704266,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["authentication","authorization","identity","normalization"],"created_at":"2024-11-12T22:23:46.870Z","updated_at":"2025-05-03T08:31:13.488Z","avatar_url":"https://github.com/PaloAltoNetworks.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A3S\n\n[![build](https://github.com/PaloAltoNetworks/a3s/actions/workflows/build-go.yaml/badge.svg)](https://github.com/PaloAltoNetworks/a3s/actions/workflows/build-go.yaml)\n[![grade](https://app.codacy.com/project/badge/Grade/ac9cca0885c34cdcae8116a4e34cc85c)](https://www.codacy.com/gh/PaloAltoNetworks/a3s/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=PaloAltoNetworks/a3s\u0026amp;utm_campaign=Badge_Grade)\n[![cov](https://app.codacy.com/project/badge/Coverage/ac9cca0885c34cdcae8116a4e34cc85c)](https://www.codacy.com/gh/PaloAltoNetworks/a3s/dashboard?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=PaloAltoNetworks/a3s\u0026utm_campaign=Badge_Coverage)\n\n\u003e NOTE: This is a work in progress.\n\nA3S (stands for Auth As A Service) is an authentication and ABAC authorization\nserver.\n\nIt allows to normalize various sources of authentication like OIDC,\nAWS/Azure/GCP tokens, LDAP and more into a generic identity token that contains\nidentity claims (rather than scopes). These claims can be used by some\nauthorization policies to give a particular subset of bearers various\npermissions.\n\nThese authorization policies match a set of bearers based on a logical claims\nexpression (like `group=red and color=blue or group=admin`) and they apply to a\nnamespace.\n\nA namespace is a node that is part of hierarchical tree that represents an\nabstract organizational unit. The root namespace is named `/`.\n\nBasically, an authorization policy allows a subset of bearers, defined by claims\nretrieved from an authentication source, to perform actions in a particular\nnamespace and all of its children.\n\nApps can receive a request alongside a delivered identity token then check with\nA3S if the current bearer is allowed to perform a particular action in a\nparticular namespace.\n\n![flowchart](docs/imgs/Diagram2.png)\n\n## Table of contents\n\n\u003c!-- vim-markdown-toc GFM --\u003e\n\n* [Quick start](#quick-start)\n* [Using the system](#using-the-system)\n  * [Install a3sctl](#install-a3sctl)\n  * [Obtain a root token](#obtain-a-root-token)\n  * [Test with the sample app](#test-with-the-sample-app)\n* [Obtaining identity tokens](#obtaining-identity-tokens)\n  * [Restrictions](#restrictions)\n  * [Cloaking](#cloaking)\n  * [Identity modifiers](#identity-modifiers)\n  * [Authentication sources](#authentication-sources)\n    * [MTLS](#mtls)\n      * [Create an MTLS source](#create-an-mtls-source)\n      * [Obtain a token from MTLS source](#obtain-a-token-from-mtls-source)\n    * [LDAP](#ldap)\n      * [Create an LDAP source](#create-an-ldap-source)\n      * [Obtain a token from LDAP source](#obtain-a-token-from-ldap-source)\n    * [HTTP](#http)\n      * [Create an HTTP source](#create-an-http-source)\n      * [Obtain a token from HTTP source](#obtain-a-token-from-http-source)\n    * [OIDC](#oidc)\n      * [Create an OIDC source](#create-an-oidc-source)\n      * [Obtain a token from OIDC source](#obtain-a-token-from-oidc-source)\n    * [A3S remote identity token](#a3s-remote-identity-token)\n      * [Create an A3S source](#create-an-a3s-source)\n      * [Obtain a token from A3S source](#obtain-a-token-from-a3s-source)\n    * [Amazon STS](#amazon-sts)\n    * [Google Cloud Platform token](#google-cloud-platform-token)\n    * [Azure token](#azure-token)\n    * [A3S local identity token](#a3s-local-identity-token)\n* [Writing authorizations](#writing-authorizations)\n  * [Subject](#subject)\n  * [Permissions](#permissions)\n  * [Target namespaces](#target-namespaces)\n  * [Examples](#examples)\n* [Check for permissions from your app](#check-for-permissions-from-your-app)\n* [Using a3sctl](#using-a3sctl)\n  * [Completion](#completion)\n    * [Bash](#bash)\n    * [Zsh](#zsh)\n    * [Fish](#fish)\n  * [Configuration file](#configuration-file)\n  * [Auto-authentication](#auto-authentication)\n* [Import](#import)\n  * [Simple import files with a3sctl](#simple-import-files-with-a3sctl)\n  * [Templating with a3sctl](#templating-with-a3sctl)\n* [Development environment](#development-environment)\n  * [Prerequesites](#prerequesites)\n  * [Initialize the environment](#initialize-the-environment)\n  * [Start everything](#start-everything)\n* [Support](#support)\n* [Contributing](#contributing)\n\n\u003c!-- vim-markdown-toc --\u003e\n\n## Quick start\n\nThe easiest way to get started is to use the `docker-compose.yaml` in the `dev`\nfolder.\n\nFirst, install the tools needed:\n\n    go install go.aporeto.io/tg@master\n    go install go.aporeto.io/elemental/cmd/elegen@master\n    go install go.aporeto.io/regolithe/cmd/rego@master\n    go install github.com/aporeto-inc/go-bindata/go-bindata@master\n\nThen generate the needed certificates:\n\n    dev/certs-init\n\nThis creates the certificates in `dev/.data/certificates` that the A3S container\nwill mount (the same certificates will be used by the dev environment, described\nlater).\n\nThen build the docker container:\n\n    make docker\n\nAnd finally start the docker-compose file:\n\n    cd ./dev\n    docker compose up\n\n## Using the system\n\nYou can start to interact with the system by using the raw API with curl or\nusing the provided cli named `a3sctl`. The later provide a streamlined interface\nthat makes it more pleasant to use than the raw API.\n\n### Install a3sctl\n\nTo install the cli, run:\n\n    make cli\n\nThis will install `a3sctl` into you`$GOBIN` folder. You should have this folder\nin your `$PATH` if you want to use the cli without needing to enter its full\npath.\n\n### Obtain a root token\n\nIn order to configure the system and create additional namespaces,\nauthorizations, etc., you need to obtain a root token to start interacting with\nthe server:\n\n    a3sctl auth mtls \\\n      --api https://127.0.0.1:44443 \\\n      --api-skip-verify \\\n      --cert dev/.data/certificates/user-cert.pem \\\n      --key dev/.data/certificates/user-key.pem \\\n      --source-name root\n\n\u003e NOTE: In production environment, never use --api-skip-verify. You should\n\u003e instead trust the CA used to issue A3S TLS certificate.\n\nThis will print a token that you can use for subsequent calls. You can set the\n`$A3SCTL_TOKEN` environment variable to use it automatically.\n\n\u003e NOTE: There are easier ways to deal with retrieving a token when using a3sctl\n\u003e as it will be explained later.\n\nIf you want to check the content of a token, you can use:\n\n    $ a3sctl auth check --token \u003ctoken\u003e\n    alg: ES256\n    kid: 1DAA6949AACB82DBEF1CFE7D93586DD0BF1F090A\n\n    {\n      \"exp\": 1636830341,\n      \"iat\": 1636743941,\n      \"identity\": [\n      \"@source:name=root\"\n      \"@source:namespace=/\",\n      \"@source:type=mtls\",\n      \"commonname=Jean-Michel\",\n      \"fingerprint=C8BB0E5FA7644DDC97FD54AEF09053E880EDA939\",\n      \"issuerchain=D98F838F491542CC238275763AA06B7DC949737D\",\n      \"serialnumber=219959457279438724775594138274989969558\",\n      ],\n      \"iss\": \"https://127.0.0.1\",\n      \"jti\": \"b2b441a0-5283-4586-baa7-4a45147aaf46\"\n    }\n\nYou can omit `--token` if you have set `$A3SCTL_TOKEN`. If you need to print the\nraw token, you can use the `--print` flag.\n\n### Test with the sample app\n\nThere is a very small python Flask server located in `/example/python/testapp`.\nIt comes with a script that creates a namespace, an MTLS source and two\nauthorizations that will be used to demo a basic use of A3S.\n\nYou can take a look at the [README](examples/python/testapp/README.md) in that\nfolder to get started.\n\n## Obtaining identity tokens\n\nThis section describes how to create the various sources of authentication, how\nto retrieve a token from them, apply restrictions or apply cloaking.\n\nAll the following examples will assume to work in the namespace `/tutorial`. To\ncreate it, you can run:\n\n    export A3SCTL_API=\"https://127.0.0.1:44443\"\n    export A3SCTL_API_SKIP_VERIFY=\"true\"\n    export A3SCTL_NAMESPACE=/tutorial\n\n    a3sctl api create namespace --with.name tutorial --namespace /\n\n\u003e NOTE: The env variable will tell a3sctl which namespace to target without\n\u003e having to pass the `--namespace` flag every time.\n\u003e\n\u003e NOTE: Some auth commands will require to pass the namespace of the auth\n\u003e source. You can either set `--source-namespace` or leave it empty to fallback\n\u003e on the value set by `--namespace`.\n\u003e\n\u003e NOTE: You can also get more info about a resource by using the `-h` flag.\n\u003e This will list all the possible properties the API supports.\n\n### Restrictions\n\nWhichever authentication source you are using, you can always ask for a\nrestricted token. A restricted token contains additional user requested\nrestrictions preventing actions that would normally be possible to do based on\nthe authorizations stored in the server, matching the bearer claims.\n\n* `--restrict-namespace`: a namespace restricted token will only be valid if\n    used on the restricted namespace or one of its children.\n* `--restrict-network`: a network restricted token can only be used if the\n    source network from which it is used is contained in one of the restricted\n    networks.\n* `--restrict-permissions`: limits what permissions the token will have. For\n    instance if your authorization set grants `dog:eat,sleep`, you may ask for a\n    token that will only work for `dog:eat`.\n\n### Cloaking\n\nIt is possible to limit the amount of identity claims that will be embedded into\nthe identity token by using the `--cloak` flag. This can be useful for privacy\nreasons. For instance, if a party requests you to have `color=blue` and this is\nthe only claim that matters, you can hide the rest of your claims by passing\n\n    --cloak color=blue\n\nCloaking uses prefix matching. So you can decide to only embed the color and\nsize claims (if you have multiple of them) by doing:\n\n    --cloak color= --cloak size=\n\n### Identity modifiers\n\nCertain authentication sources allow to set an additional identity modifier.\nThis is an URL to an HTTPS server running on your own premises, that will be be\ncalled by A3S when it is about to deliver a token from the source.\n\nOne reason one may want to do so is to enhance claims based on an external\nsystem. We can imagine an A3S server run by a health care provider, that may\ntrust a more global A3S instance. This instance could return a claim based the\nbearer's SSN and the health care provider may want to deliver a token that would\ncontain additional information, like a blood type for instance. The identity\nmodifier would then query an external database to match the blood type on record\nwith the bearer SSN.\n\nThe server will receive the claims that are about to be delivered, and will\nhave a chance to modify the list. The server must implement MTLS authentication\nand must accept the certificates set in the source modifier.\n\nThe server must return `200` if it did modify the claims or `204` if it did not.\nAny other code will be treated as an error.\n\nThe source modifier allows to set the HTTP method to use when calling the remote\nserver. If it is `POST`, `PUT` or `PATCH`, A3S will send the claims as a JSON\narray encoded in the body. For `GET`, the server will set the claims in the\nquery parameter `claim`.\n\nIn any case, the server will receive the following headers, describing the\nsource that was used to derive the identity claims:\n\n* `x-a3s-source-type`\n* `x-a3s-source-namespace`\n* `x-a3s-source-name`\n\nThe server must return the list of modified claims as a JSON-encoded array in\nthe body of the response.\n\nA server must not insert any identity claims starting with the symbol `@` or A3S\nwill refuse to deliver the token.\n\n\u003e NOTE: You can find a naive implementation of a claim modifier in\n\u003e `examples/python/claimmod`. You can take a look at the\n\u003e [README](examples/python/claimmod/README.md) in that folder.\n\n### Authentication sources\n\nWhile A3S allows to verify the identity of a token bearer, it does not provide\nany way to store information about the user. In order to derive identity\nclaims, A3S relies on third-party authentication sources, who hold the actual\ndata about a bearer.\n\n#### MTLS\n\nThe MTLS source uses mutual TLS to authenticate a client. The client must present\na client certificate (usage set to auth client) that is signed by the CA\nprovided in the designed MTLS auth source.\n\n\u003e NOTE: This authentication source supports identity modifiers.\n\n##### Create an MTLS source\n\nYou first need to have a CA that can issue certificates for your users. In this\nexample, we use `tg`, but you can use any PKI tool you like.\n\n    tg cert --name myca --is-ca\n    tg cert --name user1 \\\n      --signing-cert myca-cert.pem \\\n      --signing-cert-key myca-key.pem\n\n\u003e NOTE: tg can be installed by running `go install go.aporeto.io/tg@master`\n\u003e\n\u003e NOTE: Not protecting a private key with a passphrase is bad. Don't do this in\n\u003e production.\n\nThen we need to create the MTLS auth source:\n\n    a3sctl api create mtlssource \\\n      --with.name my-mtls-source \\\n      --with.ca \"$(cat myca-cert.pem)\"\n\n##### Obtain a token from MTLS source\n\nTo obtain a token from the newly created source:\n\n    a3sctl auth mtls \\\n      --source-name my-mtls-source \\\n      --source-namespace /tutorial \\\n      --cert user1-cert.pem \\\n      --key user1-key.pem\n\nIf the private key is encrypted, you need to set the flag `--pass \u003cpassphrase\u003e`.\n\n\u003e NOTE: You can set `-` for `--pass`. In that case, a3sctl will ask for user\n\u003e input from stdin.\n\n#### LDAP\n\nA3S supports using a remote LDAP as authentication source. The LDAP server must\nbe accessible from A3S. A3S will refuse to connect to an LDAP with no form of\nencryption (TLS or STARTTLS).\n\n\u003e NOTE: This authentication source supports identity modifiers.\n\n##### Create an LDAP source\n\nTo create an LDAP source, run:\n\n    a3sctl api create ldapsource \\\n      --with.name my-ldap-source \\\n      --with.address 127.0.0.1:389 \\\n      --with.certificate-authority \"$(cat ldap-ce-cert.pem)\" \\\n      --with.base-dn dc=universe,dc=io \\\n      --with.bind-dn cn=readonly,dc=universe,dc=io \\\n      --with.bind-password password\n\n* The `base-dn` is the DN to use to search for users.\n* Yhe `bind-dn` is the account A3S will use to connect to the ldap. It should be\n  a readonly account.\n* The `bind-password` is the password associated to the `bind-dn`.\n\nYou can also use `--certificate-auhority` to pass a custom CA if the\ncertificates used by the server are not trusted by the host running A3S.\n\nYou can decide to ignore certain attribute by using the flag `--ignore-keys`.\nThe opposite way is also posible by using `--include-keys` to only include the\ndesised attributes. If the same attribute is set in both flag, it will end up\nbeing ignored.\n\n##### Obtain a token from LDAP source\n\nTo obtain a token from the newly created source:\n\n    a3sctl auth ldap \\\n      --source-name my-ldap-source \\\n      --namespace /tutorial \\\n      --user bob \\\n      --pass s3cr3t\n\n\u003e NOTE: You can set `-` for `--user` and/or `--pass`. In that case, a3sctl will\n\u003e ask for user input from stdin.\n\n#### HTTP\n\nA3S supports using a remote HTTP server as authentication source. The HTTP\nserver must be accessible from A3S. A3S will refuse to connect if the server\ndoes not support MTLS. This can be used to link to your own internal account\nsystem.\n\nWhen an HTTP source is used, A3S will send a POST request to the corresponding\nserver containing a JSON-encoded map with the following items:\n\n* `username`: the user provided user name.\n* `password`: the user provided password.\n* `TOTP`: optional one-time password for 2FA.\n\nThe server must respond `200` with a body containing the claims to insert in the\ntoken as JSON-encoded array (for instance: `[\"username=bob\", \"bu=eng\"]`). Any\nother status code will be returned as an `401` error to the user.\n\n\u003e NOTE: This authentication source supports identity modifiers.\n\n##### Create an HTTP source\n\nTo create an HTTP source, run:\n\n    a3sctl api create httpsource \\\n      --with.name my-http-source \\\n      --with.url https://myserver.com/login \\\n      --with.certificate-authority \"$(cat ca-cert.pem)\" \\\n      --with.certificate \"$(cat client-cert.pem)\" \\\n      --with.key \"$(cat client-key.pem)\"\n\n##### Obtain a token from HTTP source\n\nTo obtain a token from the newly created source:\n\n    a3sctl auth http \\\n      --source-name my-http-source \\\n      --namespace /tutorial \\\n      --user bob \\\n      --pass s3cr3t \\\n      --totp 1234\n\n\u003e NOTE: You can set `-` for `--user` and/or `--pass`. In that case, a3sctl will\n\u003e ask for user input from stdin.\n\n#### OIDC\n\nA3S can retrieve an identity token from an existing OIDC provider in order to\ndeliver normalized identiy tokens.\n\n\u003e NOTE: This authentication source supports identity modifiers.\n\n##### Create an OIDC source\n\nConfiguring a valid OIDC provider is beyond the scope of this document. However,\nthey will all work the same and will provide you with a client ID, a client\nsecret and an endpoint.\n\nIt is however important to allow `http://localhost:65333` as a redirect URL from\nyour provider confguration if you plan to use a3sctl to authenticate.\n\nOnce the provider is configuired, create an OIDC source:\n\n    a3sctl api create oidcsource \\\n      --with.name my-oidc-source \\\n      --with.client-id \u003cclient id\u003e \\\n      --with.client-secret \u003cclient secret\u003e \\\n      --with.endpoint https://accounts.google.com \\\n      --with.scopes '[\"email\", \"given_name\"]'\n\nThe scopes indicate the OIDC provider which claims to return. They will vary\ndepending on your provider.\n\nYou can also use `--certificate-auhority` to pass a custom CA if the\ncertificates used by the OIDC providers are not trusted by the host running A3S.\n\n##### Obtain a token from OIDC source\n\nWhile all the other sources can be used easily with curl for instance, the OIDC\nsource needs to run an HTTP server and needs to perform a dance that is quite\npainful to do manually. a3sctl will do all of this transparently.\n\nTo obtain a token from the newly created source:\n\n    a3sctl auth oidc \\\n      --source-name my-oidc-source \\\n      --source-namespace /tutorial\n\nThis will print a URL to open in your browser to authenticate against the OIDC\nprovider. Once completed, the provider will reply and the token will be\ndisplayed.\n\n#### A3S remote identity token\n\nThis authentication source allows to issue a token from another one issued by\nanother A3S server. It allows to trust other A3S instances and issue local\ntokens from trusted ones, while potentially augmenting the identity claims.\n\n\u003e NOTE: This authentication source supports identity modifiers.\n\n##### Create an A3S source\n\nYou need to create an A3S source in order to validate the remote tokens. The\nsource requires to pass the raw address of the remote A3S server, as it will use\nthe well-known JWKS URL to retrieve the keys and verify the token signature.\n\nTo create an A3S source:\n\n    a3sctl api create a3ssource \\\n      --with.name my-remote-a3s-source \\\n      --with.issuer https://remote-a3s.com\n\nYou can also use `--certificate-auhority` to pass a custom CA if the\ncertificates used by the server are not trusted by the host running A3S.\n\nIf the issuer is not identical to the root URL of the remote A3S server, you can\nuse the `--with.endpoint` flag to pass the actual URL.\n\n##### Obtain a token from A3S source\n\nTo obtain a token from the newly created source:\n\n    a3sctl auth remote-a3s \\\n      --source-name my-remote-a3s-source \\\n      --source-namespace /tutorial \\\n      --input-token \u003ctoken\u003e\n\n#### Amazon STS\n\nThis authentication source does not need custom source creation as it uses AWS\nbroadly. How to retrieve a token from AWS is beyond the scope of this document.\nHowever, if you run a3sctl from an EC2 instance that has an IAM role assigned,\nit will retrieve one for you, if you don't pass any additional information.\n\nIf you are not running the command on AWS:\n\n    a3sctl auth aws \\\n      --access-key-id \u003ckid\u003e \\\n      --access-key-secret \u003csecret\u003e \\\n      --access-token \u003ctoken\u003e\n\nIf you are running it from an AWS EC2 instance, you just need to run:\n\n    a3sctl auth aws\n\n#### Google Cloud Platform token\n\nThis authentication source does not need custom source creation as it uses GCP\nbroadly. How to retrieve a token from GCP is beyond the scope of this document.\nHowever, if you run a3sctl from a GCP instance, it will retrieve one for you, if\nyou don't pass any additional information\n\nIf you are not running the command on GCP:\n\n    a3sctl auth gcp --access-token \u003ctoken\u003e\n\nIf you are running it from an GCP instance, you just need to run:\n\n    a3sctl auth gcp\n\n#### Azure token\n\nThis authentication source does not need custom source creation as it uses Azure\nbroadly. How to retrieve a token from Azure is beyond the scope of this\ndocument. However, if you run a3sctl from an Azure instance, it will retrieve\none for you, if you don't pass any additional information\n\nIf you are not running the command on Azure:\n\n    a3sctl auth azure --access-token \u003ctoken\u003e\n\nIf you are running it from an Azure instance, you just need to run:\n\n    a3sctl auth azure\n\n#### A3S local identity token\n\nYou can use an existing A3S identity token to ask for another one. Note that is\nnot a renew mechanism. The requested token cannot expire later than the original\none. The goal of this authentication source is to ask for a more restricted\nand/or cloaked version of the original.\n\nThis authentication source does not need custom source creation.\n\nTo get obtain a token:\n\n    a3sctl auth a3s --token \u003ctoken\u003e \\\n      --restrict-namespace /a/child/ns \\\n      --restrict-network 10.0.1.1/32 \\\n      --restrict-permissions \"dog:eat,sleep\"\n\n## Writing authorizations\n\nThe Authorizations allows to match a set of users (subjects) based on a claim\nexpression and assign them permissions. Authorizations work on a whitelist model.\nEverything that is not explicitely allowed is forbidden.\n\n### Subject\n\nA matching expression can be described as a basic boolean sequence like\n`(org=acme \u0026\u0026 group=finance) || group=admin`. They are represented by a\ntwo-dimensional array. As such, the expression above is written:\n\n    [\n      [ \"org=admin\", \"group=finance\" ],\n      [ \"group=admin\" ]\n    ]\n\nThe first dimension represents `or` clauses and the second represents `and`\nclauses.\n\nAs there are many sources of authorization and delivered claims can overlap,\npotentially given way broader permissions than expected, the identity token\nalways contains additional claims allowing to discriminate bearers based on the\nauthentication source they used.\n\n* `@source:type`: The type of source that was used to deliver the token.\n* `@source:namespace`: The namespace of the source that was used.\n* `@source:name`: The name of the source.\n\n\u003e NOTE: Claims starting with the symbol `@` are reserved. If an authentication\n\u003e source tries to insert such claims, all prefixing `@` will be removed.\n\nThis way, you can differentiate `name=bob` based on which Bob we are aiming. A\nsafe subject to use in that case:\n\n    [\n      [\"@source:type=ldap\", \"@source:namespace=/my/ns\", \"name=bob\"]\n    ]\n\nThe authorization will only match Bob who got a token from any LDAP\nauthentication source that has been declared in `/my/ns`. Another Bob from\nanother namespace or coming from an OIDC source will not match.\n\n### Permissions\n\nAuthorizations also contain a set of permissions that describes what the\nmatching bearers can do. They are generic (ie they don't make assumptions about\nthe underlying protocol you are using) and are represented by a string of the\nform:\n\n    \"resource:action1,...,actionN[:id2,...idN]\"\n\nFor instance, the following allows the bearer to walk and pet the dogs:\n\n    \"dogs:pet,walk\"\n\nThe following allows the bearer to GET /admin:\n\n    \"/admin:get\"\n\nThe following allows to GET and PUT authorizations with ID 1 or 2:\n\n    \"authorizations:get,put:1,2\"\n\nPermissions can use the `*` as resource or actions to match any. As such, the\nfollowing permission gives the bearer admin access:\n\n    \"*:*\"\n\nAn authorization contains an array of permissions, granting the bearer the union\nof them. If multiple authorizations match the bearer identity token, then the\nunion of all their permissions will be granted.\n\n### Target namespaces\n\nAn authorization lives in a nanmespace and can target the current namespace of\nsome of their children. Authorizations propagate down the namespace hierarchy\nstarting from where it applied. It can not affect parents or sibling namespaces.\n\n### Examples\n\nWe can create the authorization described above with the following command:\n\n    a3sctl api create authorization\n      --namespace /my/namespace \\\n      --with.name my-auth \\\n      --with.target-namespaces '[\"/my/namespace/app1\"]' \\\n      --with.subject '[\n        [\n          \"@source:type=oidc\",\n          \"@source:namespace=/my/namespace\",\n          \"org=admin\",\n          \"group=finance\",\n        ],\n        [\n          \"@source:type=mtls\",\n          \"@source:namespace=/my\",\n          \"@source:name=admins\",\n          \"group=admin\",\n        ]\n      ]' \\\n      --with.permissions '[\"dogs:pet,walk\"]'\n\n\u003e NOTE: If you omit `--target-namespace`, then the authorization applies to its\n\u003e own namespace and children.\n\n## Check for permissions from your app\n\nA3S provides an API to verify if a token bearer is allowed to performed some\nactions. The easiest way to implement this is to add an authentication\nmiddleware in whatever HTTP framework you are using to call A3S to verify a\ntoken and its permissions. This middleware can call the all-in-one check\nendpoint `/authz`. The following example uses curl, but you should use the HTTP\ncommunication layer currently used in your application.\n\n    curl -H \"Content-Type: application/json\" \\\n      -d '{\n        \"token\": \u003ctoken\u003e,\n        \"resource\": \"/dogs\"\n        \"action\": \"walk\",\n        \"namespace: /application/namespace\",\n        \"audience\": \"my-app\",\n      }' \\\n      https://127.0.0.1:44443/authz\n\nThis would return `204` if the bearer is allowed to walk the dogs in\n`/application/namespace`, or `403` if either the token is invalid or the bearer\nis not allowed to perform such action.\n\nThis method is the simplest but has a few drawbacks. For instance, you will\nmake A3S validate the token everytime, you need to make a call everytime, and\nyou need to transmit the bearer token at every call.\n\nA more optimized method will be described here soon, that allows to:\n\n* Validate token signature yourself locally\n* Retrieve the entire permissions set for a given token for caching\n* Validate the permissions locally\n* Be notified when cached permissions needs to be invalidated.\n\n\u003e NOTE: This method requires the third-party application to be able to connect\n\u003e to the push channel, and hence will require to be authenticated.\n\n## Using a3sctl\n\na3sctl is the command line that allows to use A3S APIs in a user-friendly manner.\nIt abstracts the ReST APIs and is self-documenting. You can always get additional\nhelp by passing the flags `--help` (or `-h`) in any command or subcommand.\n\n### Completion\n\na3sctl supports auto-completion:\n\n#### Bash\n\n    . \u003c(a3sctl completion bash)\n\n#### Zsh\n\n    compdef _a3sctl a3sctl\n    . \u003c(a3sctl completion zsh)\n\n#### Fish\n\n    . \u003c(a3sctl completion fish)\n\n### Configuration file\n\na3sctl can read the values of its flags from various places, in the following order:\n\n* A flag directly provided, or\n* Env variable (ie `$A3SCTL_SOURCE_NAME` for `--source-name`), or\n* The config file (default: `~/.config/a3sctl/default.yaml`)\n\nYou can choose the config file to use by setting the full path of the file\nusing the flag `--config` (or `$A3SCTL_CONFIG`).\n\nYou can also pass the name of the config, without its folder or its extension\nthrough the flag `--config-name` (or `$A3SCTL_CONFIG_NAME`). a3sctl will scan\nthe following folders, in the below order, to find a configuration file matching\nthe name:\n\n* `~/.config/a3sctl/`, or\n* `/usr/local/etc/a3sctl/`, or\n* `/etc/a3sctl/`\n\n### Auto-authentication\n\nIn addition to one-to-one mapping of a3sctl flags in the config file, you can\nalso add the key `autoauth` to automatically retrieve, cache, reuse and renew a\ntoken using a particular authentication source. This method works for MTLS and\nLDAP.\n\nFor instance, in `~/.config/a3sctl/default.yaml`:\n\n    api: https://127.0.0.1:44443\n    namespace: /\n\n    autoauth:\n        enable: mtls\n        ldap:\n            user: okenobi\n            pass: '-'\n            source:\n                name: root\n                namespace: /\n        mtls:\n            cert: /path/to/user-cert.pem\n            key: /path/to/user-key.pem\n            pass: '-'\n            source:\n                name: root\n                namespace: /\n\nYou can decide which source to use for auto-authentication by setting the\n`enable` key. Leave it empty to disable auto-authentication.\n\nThe token is cached in `$XDG_HOME_CACHE/a3sctl/token-\u003csrc\u003e-\u003capi-hash\u003e` and will\nautomatically renew if it's past its half-life.\n\n\u003e NOTE: Using `-` for secrets will automatically prompt the user for input during\n\u003e retrieval or renewal of the token.\n\n## Import\n\nA3S allows to manage the content of a namespace through declarative import. At\nits core, importing is done using the `/import` API.\n\nThe following resources can be imported:\n\n* All kind of sources (`oidcsources`, `mtlssources`, etc...)\n* `authorizations`\n\nAn import must provide a label in order to recognize all the resources imported.\nThis will help the system to realign any changes between the import declarartion\nand the current state of the system. You must ensure the provided label is\nunique to an import in a namespace, or you may face unintended side effects. The\nlabel will be stored into the `importLabel` property of the resources.\n\nImported resources use a hash (stored in `importHash`) to determine if the data\nprovided in the import request has changed or not. If the data is unmodified,\nthe import will leave the object in place. If it has been modified, the import\nsystem will delete, then recreate a new version of the object (that means its\n`ID` will change).\n\n### Simple import files with a3sctl\n\na3sctl provides an easy way to deal with import declarations stored in a YAML\nfile.\n\nFor instance:\n\n    label: my-import-label\n    Authorizations:\n      - name: authorization-a\n      subject:\n      - - \"@source:type=mtls\"\n        - \"@source:name=default\"\n        - \"@source:namespace=/ns\"\n        - \"commonname=john\"\n      permissions:\n      - /resource-a:GET\n      - name: top-secret-access\n      subject:\n      - - \"@source:type=mtls\"\n        - \"@source:name=default\"\n        - \"@source:namespace=/ns\"\n        - \"commonname=michael\"\n      permissions:\n      - /resource-b:GET\n      - /resource-c:GET\n\nThis file declares two `authorizations`, under the label `my-import-label`.\n\nTo import this file, run:\n\n    a3sctl import path/to/file.yaml\n\na3sctl also allows to point to a URL.\n\nFor instance:\n\n    apoctl import https://server.com/import.yaml\n\n### Templating with a3sctl\n\nImport files support [go templating](https://pkg.go.dev/text/template) with\n[sprig](https://masterminds.github.io/sprig/) functions, as well as `helm` style\nvalues management.\n\n\u003e NOTE: You can check the rendering of the template by passing `--render`\n\nFor instance, consider the following file:\n\n    label: my-templated-import:\n    MTLSSources:\n    - name: {{ .Values.name }}\n      description: {{ .Values.desc }}\n      CA: |-\n      {{ readFile \"path/to/ca.pem\" | indent 4 }}\n\nThis file can be imported using the following command:\n\n    a3sctl import mytemplate.gotmpl \\\n      --set name=hello \\\n      --set \"desc=the description\"\n\nThis will replace `{{ .Values.name }}` and `{{ .Values.desc }}` by `hello` and\n`the description` respectively. You can also notice the call to `readFile` that\nwill be replaced by the content of the file given as parameter.\n\nIn addition to the `.Values` dictionary, there are the following additional\nvalues that can be accessed:\n\n* `{{ .Common.API }}`: the value of the --api flag\n* `{{ .Common.Namespace }}`: The value of --namespace flag\n\nFinally, you can store the values in their own files, and use them to populate a\ntemplate. For instance:\n\n    name: hello world\n    description: the description\n\nYou can use the values in that file by doing:\n\n    a3sctl import mytemplate.gotmpl --values myvalues.yaml\n\n## Development environment\n\n### Prerequesites\n\nFirst, clone this repository and make sure you have the following installed:\n\n* go\n* mongodb\n* nats-server\n* tmux \u0026 tmuxinator\n\n### Initialize the environment\n\nIf this is the first time you start the environment, you need to initialize\nvarious things.\n\nFirst, initialize the needed certificates:\n\n    dev/certs-init\n\nThen initialize the database:\n\n    dev/mongo-init\n\nAll the development data stored stored in `dev/.data`. If you delete this\nfolder, you can reinitialize the environment.\n\nAll of A3S configuration is defined as env variables from `dev/env`\n\nFinally, you must initialize the root permissions. A3S makes no exceptions nor\nhas any hardcoded or weak credentials, so you must add an authentication source\nand an authorization.\n\nTo do so, run:\n\n    dev/a3s-run --init --init-root-ca dev/.data/certificates/ca-acme-cert.pem\n\n\u003e NOTE: Even if you are in the `dev` folder the root CA must be passed relative\n\u003e to the root of the repository.\n\n### Start everything\n\nOnce initialized, start the tmux session by running:\n\n    dev/env-run\n\nThis will launch a tmux session starting everything and giving you a working\nterminal. To exit:\n\n    env-kill\n\n## Support\n\nPlease read [SUPPORT.md](SUPPORT.md) for details on how to get support for this\nproject.\n\n## Contributing\n\nWe value your contributions! Please read [CONTRIBUTING.md](CONTRIBUTING.md)\nfor details on how to contribute and the process for submitting pull requests\nto us.\n\n\u003c!-- vim:ts=4:sw=2:sts=4:expandtab\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaloaltonetworks%2Fa3s","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaloaltonetworks%2Fa3s","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaloaltonetworks%2Fa3s/lists"}