{"id":22379135,"url":"https://github.com/sky-uk/osprey","last_synced_at":"2025-04-08T03:16:59.172Z","repository":{"id":41867744,"uuid":"123275789","full_name":"sky-uk/osprey","owner":"sky-uk","description":"Kubernetes  OIDC CLI login","archived":false,"fork":false,"pushed_at":"2025-03-13T00:30:33.000Z","size":490,"stargazers_count":50,"open_issues_count":14,"forks_count":18,"subscribers_count":31,"default_branch":"master","last_synced_at":"2025-03-30T07:22:39.357Z","etag":null,"topics":["authentication","cli","dex","kubernetes","ldap","oidc"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sky-uk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","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}},"created_at":"2018-02-28T11:30:23.000Z","updated_at":"2025-02-24T14:52:21.000Z","dependencies_parsed_at":"2022-07-25T22:33:06.957Z","dependency_job_id":"5c7a093a-5749-42c0-8d5a-b95b4696802e","html_url":"https://github.com/sky-uk/osprey","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sky-uk%2Fosprey","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sky-uk%2Fosprey/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sky-uk%2Fosprey/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sky-uk%2Fosprey/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sky-uk","download_url":"https://codeload.github.com/sky-uk/osprey/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247767237,"owners_count":20992548,"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","cli","dex","kubernetes","ldap","oidc"],"created_at":"2024-12-04T23:09:05.204Z","updated_at":"2025-04-08T03:16:59.150Z","avatar_url":"https://github.com/sky-uk.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Osprey\n\nClient and service for providing OIDC access to Kubernetes clusters.\n\nThe client provides a `user login` command which will request a `username`\nand a `password` and forward them to the service. The service will forward\nthe credentials to an OpenId Connect Provider (OIDC) to authenticate the\nuser and will return a JWT token with the user details. The token along\nwith some additional cluster information will be used to generate the\n`kubectl` configuration to be used to access Kubernetes clusters.\n\n### Supported OIDC providers\n##### Dex\nThis implementation relies on one specific configuration detail of the OIDC\nprovider `SkipApprovalScreen : true` which eliminates the intermediate step\nrequiring a client to explicitly approve the requested grants before the\ntoken is provided. If the target provider does not support this feature,\nadditional work is required to handle that approval.\n\n##### Azure\nWhen Azure is configured as the OIDC provider, the `user login`\ncommand will generate a link to visit, which the user must open in a browser\nin order to authenticate. Upon a successful login, the browser will send a\nrequest to a local endpoint served by the osprey application. With the\ninformation contained in this request it is able to request a JWT token\non your behalf.\n\n## Quick links\n- [Installation](#installation)\n- [Client](#client)\n- [Server](#server)\n- [Examples](#examples)\n\n## Installation\n\nOsprey is currently supported on Linux, macOS and Windows. It can be\ninstalled as a standalone executable or run as a container (only\nLinux).\nThe Docker container is aimed to be used for the server side, while the\nbinaries' main use are the client commands.\n\n### Binaries\n\nThere is currently no binary install option for Osprey, due to the\nsunsetting of our old binary host.  You will need to build from source\nor install with Docker.\n\nFor example:\n```yaml\n$ go install github.com/sky-uk/osprey/v2@v2.8.1\n\n$ ~/go/bin/osprey --help\nUser authentication for Kubernetes clusters\n...\n```\n\n### Docker\n\nThe Docker image is based on [Alpine Linux](https://hub.docker.com/_/alpine).\nIt can be pulled from our [Docker Hub repository](https://hub.docker.com/r/skycirrus/osprey/)\n\nTo pull a specific version replace `\u003cversion\u003e` with the release version\n(e.g `v9.9.0`; mind the `v` prefix).\n\n```sh\n$ docker pull skycirrus/osprey:\u003cversion\u003e\n```\n\n# Client\n\nThe `osprey client` will request the user credentials and generate a\nkubeconfig file based on the contents of its [configuration](#client-configuration).\n\nTo get the version of the binary use the `--version` argument:\n```\n$ osprey --version\nosprey version 2.8.1 (2022-03-17T16:25:26Z))\n```\n\nYou can run Osprey client in Docker by bind-mounting your Osprey config and kubeconfig files:\n\n```\n$ docker run --rm \\\n    --network=host \\\n    --env HOME=/ \\\n    -v $HOME/.config/osprey/config:/.config/osprey/config:ro \\\n    -v $HOME/.kube/config:/.kube/config \\\n    skycirrus/osprey:v2.8.1 user login\n```\n\n## Client usage\n- [config](#config)\n- [groups](#groups)\n- [login](#login)\n- [logout](#logout)\n- [targets](#targets)\n- [user](#user)\n\nWith a [configuration](#client-configuration) file like:\n```yaml\nproviders:\n  osprey:\n    - targets:\n        local.cluster:\n          server: https://osprey.local.cluster\n        foo.cluster:\n          server: https://osprey.foo.cluster\n          alias: [foo]\n          groups: [foo, foobar]\n        bar.cluster:\n          server: https://osprey.bar.cluster\n          groups: [bar, foobar]\n```\n\nThe `groups` are labels that allow the targets to be organised into categories.\nThey can be used, for example, to split non-production and production clusters\ninto different groups, thus making the interaction explicit.\n\nMost of the client commands accept a `--group \u003cvalue\u003e` flag which indicate\nOsprey to execute the commands only against targets containing the specified\nvalue in their `groups` definition.\n\nA `default-group` may be defined at the top of the configuration which will\napply that group to any command if the `--group` flag is not used.\nWhen a default group exists *all targets should belong to at least one group*;\notherwise the configuration will become invalid and an error will be displayed\nwhen running any command.\n\nIf no group is provided, and no `default-group` is defined, the operations\nwill be performed against targets without group definitions.\n\n### Login\nRequests a Kubernetes access token for each of the configured targets\nand creates the kubeconfig's cluster, user and context elements for them.\n\n```\n$ osprey user login\nuser: someone\npassword: ***\nLogged in to local.cluster\n```\n* Note: When using a cloud identity provider, a link to the respective online\nlogin form will be shown in the terminal. The user must click on this link and\nfollow the login steps.\n\nIt will generate the kubeconfig file creating a `cluster` and `user` entry\nper osprey target and one context with the `target` name and as many extra\ncontexts as `aliases` have been specified.\n\nWhen specifying the `--group` flag, the operations will apply to the targets\nbelonging to the specified group. If targeting a group (provided or default)\nthe output will include the name of the group.\n```\n$ osprey user login --group foobar\nuser: someone\npassword: ***\n\nLogging in to group 'foobar'\n\nLogged in to foo.cluster | foo\nLogged in to bar.cluster\n```\n\nAt login, aliases are displayed after the pipes (i.e `| foo`)\n\n### User\nDisplays information about the currently logged-in user (it shows the details\neven if the token has already expired).\nIt contains the email of the logged-in user and the list of LDAP membership\ngroups the user is a part of. The latter come from the claims in the\nuser's token.\n\n```\n$ osprey user --group foobar\nfoo.cluster: someone@email.com [membership A, membership B]\nbar.cluster: someone@email.com [membership C]\n```\n\nIf no user is logged in, osprey displays `none` instead of the user details.\n\n### Logout\nRemoves the token for the currently logged-in user for every configured\ntarget.\n\n```\n$ osprey user logout --group foobar\nLogged out from foo.cluster\nLogged out from bar.cluster\n```\n\nIf no user is logged in the command is a no-op.\n\n### Config\nThis command is currently a no-op, used only to group the commands related\nto the osprey configuration.\n\n### Targets\nDisplays the list of defined targets within the client configuration.\nIt allows displaying the list of targets per group and to target a specific\ngroup via flags.\n\n```\n$ osprey config targets --by-groups\nConfigured targets:\n* \u003cungrouped\u003e\n    local.cluster\n  bar\n    bar.cluster\n  foo\n    foo.cluster | foo\n  foobar\n    bar.cluster\n    foo.cluster | foo\n```\n\nThis command will display targets that do not belong to any group, if there\nare any, under the special group `\u003cungrouped\u003e`.\n\nIf the configuration specifies a default group, it will be highlighted\nwith a `*` before its name, e.g. `* foobar`. If no default group is defined\nthe special `\u003cungrouped\u003e` grouping will be highlighted.\n\n#### Groups\nThe targets command flag `--list-groups` is useful to display only the\nlist of existing groups within the configuration, without any target\ninformation.\n```\n$ osprey config targets --list-groups\nConfigured groups:\n* \u003cungrouped\u003e\n  bar\n  foo\n  foobar\n```\n\n## Client configuration\nThe client installation script gets the configuration supported by the\ninstalled version.\n\nThe client uses a YAML configuration file. Its recommended location is:\n`$HOME/.osprey/config`. Its contents are as follows:\n### V2 Config\nThe structure of the osprey configuration supports multiple configuration for a provider type.\nThis structure will support scenarios where different azure providers can be configured for prod and non-prod targets.\n```yaml\napiVersion: v2\n\n# Optional path to the kubeconfig file to load/update when loging in.\n# Uses kubectl defaults if absent ($HOME/.kube/config).\n# kubeconfig: /home/jdoe/.kube/config\n\n# Optional group name to be the default for all commands that accept it.\n# When this value is defined, all targets must define at least one group.\n# default-group: my-group\n\n## Named map of supported providers (currently `osprey` and `azure`)\nproviders:\n  osprey:\n    - provider-name: (Optional)\n      # CA cert to use for HTTPS connections to Osprey.\n      # Uses system's CA certs if absent.\n      # certificate-authority: /tmp/osprey-238319279/cluster_ca.crt\n\n      # Alternatively, a Base64-encoded PEM format certificate.\n      # This will override certificate-authority if specified.\n      # certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk5vdCB2YWxpZAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==\n\n      # Named map of target Osprey servers to contact for access-tokens\n      targets:\n        # Target Osprey's environment name.\n        # Used for the name of the cluster, context, and users generated\n        foo.cluster:\n            # hostname:port of the target osprey server\n            server: https://osprey.foo.cluster\n\n            #  list of names to generate additional contexts against the target.\n            aliases: [foo.alias]\n\n            #  list of names that can be used to logically group different Osprey servers.\n            groups: [foo]\n\n            # CA cert to use for HTTPS connections to Osprey.\n            # Uses system's CA certs if absent.\n            # certificate-authority: /tmp/osprey-238319279/cluster_ca.crt\n\n            # Alternatively, a Base64-encoded PEM format certificate.\n            # This will override certificate-authority if specified.\n            # certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk5vdCB2YWxpZAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==\n  # Authenticating against Azure AD\n  azure:\n    - name: (Optional)\n      # These settings are required when authenticating against Azure\n      tenant-id: your-azure-tenant-id\n      server-application-id: azure-ad-server-application-id\n      client-id: azure-ad-client-id\n      client-secret: azure-ad-client-secret\n\n        # List of scopes to request as part of the request. This should be an Azure link to the API exposed on the server application\n      scopes:\n          - \"api://azure-tenant-id/Kubernetes.API.All\"\n\n        # This is required for the browser-based authentication flow. The port is configurable, but it must conform to\n        # the format: http://localhost:\u003cport\u003e/auth/callback\n      redirect-uri: http://localhost:65525/auth/callback\n      targets:\n          foo.cluster:\n              server: http://osprey.foo.cluster\n              # If \"use-gke-clientconfig\" is specified (default false) Osprey will fetch the API server URL and its\n              # CA cert from the GKE-specific ClientConfig resource in kube-public. This resource is created automatically\n              # by GKE when you enable to OIDC Identity Service. The \"api-server\" config element is also required.\n              # Usually \"api-server\" would be set to the public API server endpoint; the fetched API server URL will be\n              # the internal load balancer that proxies requests through the OIDC service.\n              # use-gke-clientconfig: true\n              #\n              # If \"skip-tls-verify\" is specified (default false) Osprey will skip TLS verification when attempting\n              # to make the connection to the specified server.  This can be used in conjunction with `server` or `api-server`.\n              # skip-tls-verify: true\n              #\n              # If api-server is specified (default \"\"), Osprey will fetch the CA cert from the API server itself.\n              # Overrides \"server\". A ConfigMap in kube-public called kube-root-ca.crt should be made accessible\n              # to the system:anonymous group. This ConfigMap is created automatically with the Kubernetes feature\n              # gate RootCAConfigMap which was alpha in Kubernetes v1.13 and became enabled by default in v1.20+\n              # api-server: http://apiserver.foo.cluster\n              aliases: [foo.alias]\n              groups: [foo]\n```\n\n### V1 Config (Deprecated)\nThis is the previously supported format.\nThe fields are the same but, the provider configuration is mapped to a provider type as opposed to being a list.\nThe config parsing will use this format unless specified to v2 on the apiVersion field in the config.\n```yaml\nproviders:\n    osprey:\n      targets:\n          local.cluster:\n              server: https://osprey.local.cluster\n          foo.cluster:\n              server: https://osprey.foo.cluster\n              alias: [foo]\n              groups: [foo, foobar]\n          bar.cluster:\n              server: https://osprey.bar.cluster\n              groups: [bar, foobar]\n\n  # Authenticating against Azure AD\n    azure:\n        tenant-id: your-tenant-id\n        server-application-id: api://SERVER-APPLICATION-ID   # Application ID of the \"Osprey - Kubernetes APIserver\"\n        client-id: azure-application-client-id               # Client ID for the \"Osprey - Client\" application\n        client-secret: azure-application-client-secret       # Client Secret for the \"Osprey - Client\" application\n        scopes:\n            # This must be in the format \"api://\" due to non-interactive logins appending this to the audience in the JWT.\n            - \"api://SERVER-APPLICATION-ID/Kubernetes.API.All\"\n        redirect-uri: http://localhost:65525/auth/callback   # Redirect URI configured for the \"Osprey - Client\" application\n        targets: ...\n```\n\nThe name of the configured targets will be used to name the managed clusters,\ncontexts, and user. They can be setup as desired. Use the `aliases` property\nof the targets to create alias contexts in the kubeconfig.\n\nThe previous configuration will result in the following `kubeconfig` file for the\nuser `jdoe`:\n\n```\n$ osprey user login --ospreyconfig /tmp/osprey-238319279/.osprey/config\n```\n\n```yaml\napiVersion: v1\nkind: Config\nclusters:\n- cluster:\n    certificate-authority-data: YUhSMGNITTZMeTloY0dselpYSjJaWEl1YzJGdVpHSnZlQzVqYjNOdGFXTXVjMnQ1\n    server: https://apiserver.foo.cluster\n  name: foo.cluster\ncontexts:\n- context:\n    cluster: foo.cluster\n    user: foo.cluster\n  name: foo.cluster\n- context:\n    cluster: foo.cluster\n    user: foo.cluster\n  name: foo.alias\ncurrent-context: \"\"\npreferences: {}\nusers:\n- name: foo.cluster\n  user:\n    auth-provider:\n      config:\n        client-id: oidc_client_id\n        client-secret: oidc_client_secret\n        id-token: jdoe_Token\n        idp-certificate-authority-data: aHR0cHM6Ly9kZXguc2FuZGJveC5jb3NtaWMuc2t5\n        idp-issuer-url: https://dex.foo.cluster\n      name: oidc\n```\n\nThe client will create/update one instance of `cluster`, `context`, and `user`\nin the `kubeconfig` file per `target` in the `ospreyconfig` file. We use\n`client-go`'s config api to manipulate the `kubeconfig`.\n\nIf previous contexts exist in the kubectl config file, they will get\nupdated/overridden when performing a login. It overrides values by `name`\n(e.g. `cluster.name`, `context.name`, `user.name`).\nIt is recommended that the first time using the Osprey for a specific cluster\nold values are removed, to keep the config clean.\n\nThe names of clusters, user and context will use the value defined in the\nOsprey config.\n\n# Server\n\nThe Osprey server can be started in two different ways:\n- `osprey serve cluster-info`\n- `osprey serve auth`\n\n### `osprey serve cluster-info`\nStarts an instance of the Osprey serve that will create a webserver that is capable of returning cluster information. In\nthis mode, authentication is disabled. This endpoint is used for service discovery for an osprey target.\n\nThis endpoint (`/cluster-info`) will return the API server URL and the CA for the API server.\n\nIn this mode, the required flags are:\n\n- `apiServerCA`, the path to the API server CA (defaults to `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`) which\nis the default location of the CA when running inside a Kubernetes cluster.\n- `apiServerURL`, the API server URL to return to the Osprey client\n\nNote that since v2.5.0 Osprey client can fetch the CA cert directly from the API server without needing a\ndeployment of Osprey server.\n\n### `osprey serve auth`\nStarts an instance of the osprey server that will listen for authentication\nrequests. The configuration is done through the commands flags. The Osprey service will receive the user's credentials\nand forward them to the OIDC provider (Dex) for authentication. On success it will return the token generated by the\nprovider along with additional information about the cluster so that the client can generate the kubectl config file.\n```\n$ osprey serve auth --help\n```\n\nWhen Osprey is being used for authentication, the following flags require to be\nthe same across the specified components:\n\n- `environment`, id of the cluster to be used as a client id\n  - Dex: registered client `id` (managed via the Dex api or `staticClients`)\n  - Kubernetes API server: `oidc-client-id` flag\n- `secret`, token to be shared between Dex and Osprey\n  - Dex: registered client `secret` (managed via the Dex api or `staticClients`)\n- `redirectURL`, Osprey's callback url\n  - Dex: registered client `redirectURIs` (managed via the Dex api or `staticClients`)\n- `issuerURL`, Dex's URL\n  - Dex: `issuer` value\n  - Kubernetes API server: `oidc-issuer-url` flag\n- `issuerCA`, Dex's CA certificate path\n  - Kubernetes API server: `oidc-ca-file` flag\n\nThe following diagram depicts the authentication flow from the moment the\nOsprey client requests a token.\n\n```\n                                       +------------------------+\n                                       |                        |\n                                       |      +----------------------------+\n                                       |      |                 |          |\n+------------------+                   |  +---v--------------+  |          |\n|                  | 1./access-token   |  |                  |  |          |\n|  Osprey Client   +----------------------\u003e   Osprey Server  +-----+       |\n|                  |                   |  |                  |  |  |       |\n+------------------+                   |  +--+--------+------+  |  |       |\n                                       |     |        |         |  |       |\n                                       |     |        |         |  |       |\n                                       |     | 2.     | 3.      |  |       |\n                                       |     |/auth   |/login   |  |6. code|exchange\n                                       |     |        |         |  |       |\n                                       |     |        |         |  |       |\n+------------------+                   |  +--v--------v------+  |  |       |\n|                  |                   |  |                  |  |  |       |\n|       LDAP       | 4. authenticate   |  |       Dex        \u003c-----+       |\n|                  \u003c----------------------+                  +-------------+\n+------------------+                   |  +------------------+  |  5. /callback\n                                       |                        |\n                                       |      Environment       |\n                                       +------------------------+\n```\n\nAfter the user enters their credentials through the `Osprey Client`:\n1. An HTTPS call is made to an `Osprey Server` per environment configured.\n2. Per environment:\n   1. The `Osprey Server` will make an authentication request to `Dex` which\n      will return an authentication url to use and a request ID.\n   2. The `Osprey Server` will post the user credentials using the auth request\n      details.\n   3. `Dex` will call `LDAP` to validate the user.\n   4. Upon a successful validation, `Dex` will redirect the request to the\n      `Osprey Server`'s callback url, with a generated code and the request ID.\n   5. The `Osprey Server` will exchange the code with `Dex` to get the final\n      token that is then returned to the client.\n   6. The `Osprey Client` updates the `kubeconfig` file with the updated token.\n\n### TLS\nBecause the Osprey client sends the users credentials to the server, the\ncommunication must always be done securely. The Osprey server has to run\nusing HTTPS, so a certificate and a key must be generated and provided at\nstartup.\nThe client must be configured with the CA used to sign the certificate in\norder to be able to communicate with the server.\n\nA script to generate a test self-signed certificate, key and CA can be found\nin the [examples](examples/local/generate-certs.sh)\n\n### Dex templates and static content\nBy default Dex searches for web resources in a `web` folder located in the\nsame directory where the server is started. This location can be overridden\nin Dex's configuration:\n\n```yaml\n...\nfrontend:\n  dir: /path/to/the/templates\n  theme: osprey\n...\n```\n\nDex also requires a `web/static` folder and a `web/themes/\u003ctheme\u003e` folder\nfor static content. Osprey does not require any of these, but the folders\nare required to be there, even if empty.\n\nBecause the authentication flow does not involve the user, the data exchanged\nbetween Dex and Osprey must be in `json` so the `html` templates need to be\ncustomized.\n\nA folder with the required configuration for Osprey can be taken from\n[out test setup](e2e/dextest/web). The only theme is `osprey` and it is\nempty. All the templates file are required to be present, but not all of\nthem are used in the authentication flow.\n\n### Identity Provider\nOsprey doesn't currently support Dex using multiple Identity Providers\nas the user would be required to select one of them (`login.html`) before\nproceeding to the authentication request.\n\nTherefore currently **only one** Identity Provider can be configured.\n\n### Token expiry and Refresh token\nDex allows for configuration of the token expiry, and it also provides\na refresh token, so that a client can request a new token without the need\nof user interaction.\n\nThe current usage of Osprey is such that it was decided to discard the\nrefresh token, to prevent a compromised token to be active for more than\na configured amount of time. If the need arises, this could be reintroduced\nand enabled/disabled by configuration.\n\n### API server\nThe Kubernetes API server needs to [enable the OIDC Authentication](https://kubernetes.io/docs/admin/authentication/#configuring-the-api-server)\nin order for the kubectl requests to be authenticated and then authorised.\n\nSome of those flags have been mentioned in the [configuration](#osprey-serve-auth).\n\n# Examples\n\n[Download and install](#binaries) the Osprey binaries so that the client\ncan be used for the examples.\n\n## Kubernetes\nA set of examples resources has been provided to create the required resources\nto deploy Dex and Osprey to a Kubernetes cluster.\nThe templates can be found in `examples/kubernetes`.\n\n1. Provide the required properties in `examples/kubernetes/kubernetes.properties`:\n   - `node`, the script uses a NodePort service, so in order to configure the\n     Osprey and Dex to talk to each other, a node IP from the target cluster\n     must be provided.\n     A list of IPs to chose from can be obtained via:\n     ```\n     kubectl --context \u003ccontext\u003e get nodes -o template --template='{{range.items}}{{range.status.addresses}}{{if eq .type \"InternalIP\"}} {{.address}}:{{end}}{{end}}{{end}}' | tr \":\" \"\\n\"\n     ```\n   - `context`, the script uses kubectl to apply the resources and for this it\n     needs a context to target.\n   - `ospreyNodePort`, `dexNodePort`, `dexTelemetryNodePort`, the ports\n     where Osprey and Dex (service and metrics) will be available across\n     the cluster. A default value is provided, but if the ports are already\n     in use, they must be changed.\n   - `ospreyImage`, if you want to try a different version for the server.\n\n2. Run the shell script to render the templates and to deploy the resources\n   to the specified cluster.\n   ```\n   examples/kubernetes/deploy-all.sh \u003c/full/path/to/runtime/dir\u003e\n   ```\n   To create an Osprey server that serves `/cluster-info` only, set `ospreyAuthenticationDisabled=true` in the properties\n   file.\n3. Use the Osprey client\n   ```\n   osprey --ospreyconfig \u003c/full/path/to/runtime/dir/\u003eosprey/ospreyconfig --help\n   ```\n\nMore properties are available to customize the resources at will.\n\n## Local docker containers\nAlthough the Osprey solution is intended to be run in a Kubernetes cluster,\nwith the OIDC Authentication enabled, it is possible to have a local instance\nof Osprey and Dex to try out and validate a specific configuration.\n\nA set of scripts have been provided to start an end to end run of a user\nlogging in, checking details and logging out.\n\nFrom the root of the project:\n```\n$ mkdir /tmp/osprey_local\n$ examples/local/end-to-end.sh /tmp/osprey_local\n```\nThe [end-to-end.sh](examples/local/end-to-end.sh) script will:\n1. Start a Dex server ([start-dex.sh](examples/local/start-dex.sh))\n2. Start an Osprey server ([start-osprey.sh](examples/local/start-osprey.sh))\n3. Execute the `osprey user login` command. It will request credentials,\n   use user/pass: `jane@foo.cluster`/`doe`, `john@foo.cluster`/`doe`\n4. Execute the `osprey user` command\n5. Execute the `osprey user logout` command\n6. Execute the `osprey user` command\n7. Shutdown Osprey and Dex\n\nYou can also start Dex and Osprey manually with the scripts and play with\nthe Osprey client yourself.\n\nThe scripts use templates for the [Dex configuration](examples/local/dex/config.template.yml)\nand the [Osprey client configuration](examples/local/osprey/ospreyconfig.template).\nThe scripts load a [properties file](examples/local/local.properties) to\nrender the templates.\n\n\n# Development\n\nFirst install the required dependencies:\n\n* `make setup` - installs required golang binaries\n* `slapd`, usually part of the `openldap` package - needed for end-to-end tests\n\nThen run the tests using make:\n\n```sh\n$ make\n```\n\n## Package structure\n\n* `/cmd` contains the cobra commands to start a server or a client.\n* `/client` contains code for the osprey cli client.\n* `/server` contains code for the osprey server.\n* `/common` contains code common to both client and server.\n* `/e2e` contains the end-to-end tests, and test utils for dependencies.\n* `/examples` contains scripts to start Dex and Osprey in a Kubernetes clusters\n  or locally.\n* `vendor` contains the dependencies of the project.\n\n## Server and client\n\nWe use [Cobra](https://github.com/spf13/cobra), to generate the client and server commands.\n\n### E2E tests\n\nThe e2e tests are executed against local Dex and LDAP servers.\n\nNote: The below docker image is only for linux/amd64. You might be able to get it working with other architectures, but it's not officially supported yet.\nThe e2e tests are executed against local Dex and LDAP servers. There is a Dockerfile located in the `e2e/` directory that will handle the dependencies for you. (This came around due to dependency issues with older versions of openldap in ubuntu).\n\nThe setup is as follows:\n\nOsprey Client (1) -\u003e (*) Osprey Server (1) -\u003e (1) Dex (*) -\u003e (1) LDAP\n\nEach pair of `osprey server`-`Dex` represents an environment (cluster) setup.\nOne `osprey client` contacts as many `osprey-servers` as configured in the\ntest setup.\nEach `osprey server` will talk to only one `Dex` instance located in the same\nenvironment.\nAll `Dex` instances from the different environments will talk to the single\n`LDAP` instance.\n\nFor cloud end-to-end tests, a mocked OIDC server is created and used to authenticate with.\n\n#### Running E2E tests locally\nThere's a docker file called `Dockerfile.localtest` which sets up the test environment similar to the one used by travis.\nTravis uses ubuntu 16.04 (xenial) as the default node to run build on unless changed with a `dist` directive.\nMore details available [here](https://docs.travis-ci.com/user/reference/linux/)\n\nTo run the test locally, run the following command\n\n1. Build the local image\n    `cd \u003cosprey root\u003e/e2e \u0026\u0026 docker build -f Dockerfile.localtest -t local-osprey-e2etest:1 .`\n2. Run the container with bash as the entry point\n    `docker run -it -v \u003cosprey root folder\u003e:/osprey local-osprey-e2etest:1`\n3. Inside the container run make test\n```\n   make build\n   make test\n```\n\n## HTTPS/ProtocolBuffers\n\nGiven that aws ELBs do not support HTTP/2 osprey needs to run over HTTP.\nWe still use ProtocolBuffers for the requests and responses between osprey\nand its client.\n\n*Any changes made to the proto files should be backwards compatible.* This guarantees older clients can continue\nto work against Osprey, and we don't need to worry about updates to older clients.\n\nTo update, update `common/pb/osprey.proto` then run protoc.\n\n```\n$ make proto\n```\n\nCheck in the `osprey.pb.go` file afterwards.\n\n## Azure Active Directory setup\n\nThe Azure AD Application setup requires two applications to be created. One for the Kubernetes API servers to use, and\none for the Osprey client to use. The Osprey client is then configured to request access on behalf of the Kubernetes\nOIDC provider.\n\n### Create Osprey Kubernetes Application\n1. Visit https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview and log in using your\n   organisations credentials.\n2. Select 'App Registrations' from the side-bar and click '+ New registration' on the top menu bar.\n3. Create an application with the following details:\n   - Name: \"Osprey - Kubernetes API Server\"\n   - Supported account types: \"Accounts in this organizational directory only\"\n4. Select 'API permissions' from the side-bar and click '+ Add a permission'\n   Add the following permissions:\n     - Microsoft Graph -\u003e Delegated permissions -\u003e Enable access to \"email\", \"openid\" and \"profile\"\n     - Click 'Add permissions' to save.\n5. Select 'Expose an API' from the side-bar and click '+ Add a scope'\n6. Create a scope with an appropriate/descriptive name. e.g. `Kubernetes.API.All`. The details in this form are what are\n   shown to users when they first authorize the application to log in on their behalf.\n7. Select 'Manifest' from the side-bar and find the field `groupMembershipClaims` in the JSON. Change this so that its\n   value is `\"groupMembershipClaims\": \"All\",` and not `\"groupMembershipClaims\": null,`\n8. The *server* client-id  is the Object ID of this application. This can be found in the Overview panel.\n\n### Create Osprey Client Application\n1. Visit https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview and log in using your\n   organisations credentials.\n2. Select 'App Registrations' from the side-bar and click '+ New registration' on the top menu bar.\n3. Create an application with the following details:\n   - Name: \"Osprey - Client\"\n   - Supported account types: \"Accounts in this organizational directory only\"\n   - RedirectURI:\n     - Type: Web\n       RedirectURI: This is a redirect URI that must be configured to match in both the Azure application config and the\n       Osprey config. It has to be in the `http://localhost:\u003cport\u003e/\u003cpath\u003e` format. This will be the port that Osprey\n       client opens up a webserver on, to listen to callbacks from the login page. We use `http://localhost:65525/auth/callback` in the\n       example configuration.\n4. Select 'API permissions' from the side-bar and click '+ Add a permission'\n   Add the following permissions:\n     - Microsoft Graph -\u003e Delegated permissions -\u003e Enable access to \"openid\"\n     - Click 'Add permissions' to save.\n5. Click '+ Add a permission' and select 'My APIs' from the top of the pop-out menu.\n     - Select the \"Osprey - Kubernetes API Server\"\n     - Click 'Add permissions' to save.\n6. Select 'Certificates \u0026 secrets' from the side-bar and click '+ New client secret'\n   - Choose an expiry for this secret. When a token expires, the osprey client config must be updated to include this as\n     the 'client-secret'. Copy this secret as soon as it is created, as it will be hidden when you leave the azure pane.\n7. The *osprey* client-id  is the Object ID of this application. This can be found in the Overview panel.\n\n\nThe client ID and secrets generated in this section are used to fill out the Osprey config file.\n```yaml\nproviders:\n  azure:\n    - tenant-id: your-tenant-id\n      server-application-id: api://SERVER-APPLICATION-ID   # Application ID of the \"Osprey - Kubernetes APIserver\"\n      client-id: azure-application-client-id               # Client ID for the \"Osprey - Client\" application\n      client-secret: azure-application-client-secret       # Client Secret for the \"Osprey - Client\" application\n      scopes:\n        # This must be in the format \"api://\" due to non-interactive logins appending this to the audience in the JWT.\n        - \"api://SERVER-APPLICATION-ID/Kubernetes.API.All\"\n      redirect-uri: http://localhost:65525/auth/callback   # Redirect URI configured for the \"Osprey - Client\" application\n```\n\nKubernetes API server flags:\n```yaml\n- --oidc-issuer-url=https://sts.windows.net/\u003ctenant-id\u003e/\n- --oidc-client-id=api://9bd903fd-f8df-4390-9a45-ab2fa28673b4\n- --oidc-username-claim=unique_name\n- --oidc-groups-claim=groups\n```\n\n## Dependency management\n\nDependencies are managed with [Go modules](https://github.com/golang/go/wiki/Modules).\nRun `go mod download` to download all dependencies.\n\nMake sure any Kubernetes dependencies are compatible with the `kubernetes-1.8.5`\n\n# Releasing\n\nTag the commit in `master` using an annotated tag and push it to release it.\nOnly maintainers can do this.\n\nOsprey gets released to:\n- [Docker-Hub](https://hub.docker.com/r/skycirrus/osprey/) as an alpine based docker image.\n\n# Code guidelines\n\n* Follow [Effective Go](https://go.dev/doc/effective_go).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsky-uk%2Fosprey","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsky-uk%2Fosprey","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsky-uk%2Fosprey/lists"}