Merge branch 'main' into impersonation-proxy

This commit is contained in:
Ryan Richard 2021-02-25 14:50:40 -08:00
commit f8111db5ff
61 changed files with 1157 additions and 547 deletions

View File

@ -8,7 +8,7 @@ Please see the [Code of Conduct](./CODE_OF_CONDUCT.md).
## Project Scope
Learn about the [scope](https://pinniped.dev/docs/scope/) of the project.
See [SCOPE.md](./SCOPE.md) for some guidelines about what we consider in and out of scope for Pinniped.
## Community Meetings

View File

@ -10,7 +10,7 @@ install procedure across all types and origins of Kubernetes clusters,
declarative configuration via Kubernetes APIs, enterprise-grade integrations
with IDPs, and distribution-specific integration strategies.
### Example Use Cases
### Example use cases
* Your team uses a large enterprise IDP, and has many clusters that they
manage. Pinniped provides:
@ -39,17 +39,15 @@ The Pinniped Concierge can be configured to hook into the Pinniped Supervisor's
federated credentials, or it can authenticate users directly via external IDP
credentials.
To learn more, see [architecture](https://pinniped.dev/docs/architecture/).
To learn more, see [architecture](https://pinniped.dev/docs/background/architecture/).
<img src="site/content/docs/img/pinniped_architecture_concierge_supervisor.svg" alt="Pinniped Architecture Sketch"/>
## Trying Pinniped
## Getting started with Pinniped
Care to kick the tires? It's easy to [install and try Pinniped](https://pinniped.dev/docs/demo/).
## Community Meetings
## Community meetings
Pinniped is better because of our contributors and maintainers. It is because of you that we can bring great software to the community. Please join us during our online community meetings, occuring every first and third Thursday of the month at 9AM PT / 12PM PT. Use [this Zoom Link](https://vmware.zoom.us/j/93798188973?pwd=T3pIMWxReEQvcWljNm1admRoZTFSZz09) to attend and add any agenda items you wish to discuss to [the notes document](https://hackmd.io/rd_kVJhjQfOvfAWzK8A3tQ?view). Join our [Google Group](https://groups.google.com/u/1/g/project-pinniped) to receive invites to this meeting.
Pinniped is better because of our contributors and maintainers. It is because of you that we can bring great software to the community. Please join us during our online community meetings, occurring every first and third Thursday of the month at 9 AM PT / 12 PM PT. Use [this Zoom Link](https://vmware.zoom.us/j/93798188973?pwd=T3pIMWxReEQvcWljNm1admRoZTFSZz09) to attend and add any agenda items you wish to discuss to [the notes document](https://hackmd.io/rd_kVJhjQfOvfAWzK8A3tQ?view). Join our [Google Group](https://groups.google.com/u/1/g/project-pinniped) to receive invites to this meeting.
If the meeting day falls on a US holiday, please consider that occurrence of the meeting to be canceled.
@ -61,7 +59,7 @@ Got a question, comment, or idea? Please don't hesitate to reach out via the Git
Contributions are welcome. Before contributing, please see the [contributing guide](CONTRIBUTING.md).
## Reporting Security Vulnerabilities
## Reporting security vulnerabilities
Please follow the procedure described in [SECURITY.md](SECURITY.md).

32
SCOPE.md Normal file
View File

@ -0,0 +1,32 @@
# Project Scope
The Pinniped project is guided by the following principles.
- Pinniped lets you plug any external identity providers into Kubernetes.
These integrations follow enterprise-grade security principles.
- Pinniped is easy to install and use on any Kubernetes cluster via distribution-specific integration mechanisms.
- Pinniped uses a declarative configuration via Kubernetes APIs.
- Pinniped provides optimal user experience when authenticating to many clusters at one time.
- Pinniped provides enterprise-grade security posture via secure defaults and revocable or very short-lived credentials.
- Where possible, Pinniped will contribute ideas and code to upstream Kubernetes.
When contributing to Pinniped, please consider whether your contribution follows
these guiding principles.
## Out Of Scope
The following items are out of scope for the Pinniped project.
- Authorization.
- Standalone identity provider for general use.
- Machine-to-machine (service) identity.
- Running outside of Kubernetes.
## Roadmap
See our [open milestones][milestones] and the [`priority/backlog` label][backlog] for an idea about what's next on our roadmap.
For more details on proposing features and bugs, check out our [contributing](./CONTRIBUTING.md) doc.
[milestones]: https://github.com/vmware-tanzu/pinniped/milestones
[backlog]: https://github.com/vmware-tanzu/pinniped/labels/priority%2Fbacklog

View File

@ -1,39 +1,3 @@
# Deploying
# Pinniped Concierge Deployment
## Connecting Pinniped to an Identity Provider
If you would like to try Pinniped, but you don't have a compatible identity provider,
you can use Pinniped's test identity provider.
See [deploy/local-user-authenticator/README.md](../../deploy/local-user-authenticator/README.md)
for details.
## Installing the Latest Version with Default Options
```bash
kubectl apply -f https://get.pinniped.dev/latest/install-pinniped-concierge.yaml
```
## Installing a Specific Version with Default Options
Choose your preferred [release](https://github.com/vmware-tanzu/pinniped/releases) version number
and use it to replace the version number in the URL below.
```bash
# Replace v0.4.1 with your preferred version in the URL below
kubectl apply -f https://get.pinniped.dev/v0.4.1/install-pinniped-concierge.yaml
```
## Installing with Custom Options
Creating your own deployment YAML file requires `ytt` from [Carvel](https://carvel.dev/) to template the YAML files
in the `deploy/concierge` directory.
Either [install `ytt`](https://get-ytt.io/) or use the [container image from Dockerhub](https://hub.docker.com/r/k14s/image/tags).
1. `git clone` this repo and `git checkout` the release version tag of the release that you would like to deploy.
1. The configuration options are in [deploy/concierge/values.yml](values.yaml).
Fill in the values in that file, or override those values using additional `ytt` command-line options in
the command below. Use the release version tag as the `image_tag` value.
2. In a terminal, cd to this `deploy/concierge` directory
3. To generate the final YAML files, run `ytt --file .`
4. Deploy the generated YAML using your preferred deployment tool, such as `kubectl` or [`kapp`](https://get-kapp.io/).
For example: `ytt --file . | kapp deploy --yes --app pinniped --diff-changes --file -`
See [the how-to guide for details](https://pinniped.dev/docs/howto/install-concierge/).

View File

@ -1,184 +1,3 @@
# Deploying the Pinniped Supervisor
# Pinniped Supervisor Deployment
## What is the Pinniped Supervisor?
The Pinniped Supervisor app is a component of the Pinniped OIDC and Cluster Federation solutions.
It can be deployed when those features are needed.
## Installing the Latest Version with Default Options
```bash
kubectl apply -f https://get.pinniped.dev/latest/install-pinniped-supervisor.yaml
```
## Installing a Specific Version with Default Options
Choose your preferred [release](https://github.com/vmware-tanzu/pinniped/releases) version number
and use it to replace the version number in the URL below.
```bash
# Replace v0.4.1 with your preferred version in the URL below
kubectl apply -f https://get.pinniped.dev/v0.4.1/install-pinniped-supervisor.yaml
```
## Installing with Custom Options
Creating your own deployment YAML file requires `ytt` from [Carvel](https://carvel.dev/) to template the YAML files
in the `deploy/supervisor` directory.
Either [install `ytt`](https://get-ytt.io/) or use the [container image from Dockerhub](https://hub.docker.com/r/k14s/image/tags).
1. `git clone` this repo and `git checkout` the release version tag of the release that you would like to deploy.
1. The configuration options are in [deploy/supervisor/values.yml](values.yaml).
Fill in the values in that file, or override those values using additional `ytt` command-line options in
the command below. Use the release version tag as the `image_tag` value.
2. In a terminal, cd to this `deploy/supervisor` directory
3. To generate the final YAML files, run `ytt --file .`
4. Deploy the generated YAML using your preferred deployment tool, such as `kubectl` or [`kapp`](https://get-kapp.io/).
For example: `ytt --file . | kapp deploy --yes --app pinniped-supervisor --diff-changes --file -`
## Configuring After Installing
### Exposing the Supervisor App as a Service
The Supervisor app's endpoints should be exposed as HTTPS endpoints with proper TLS certificates signed by a
Certificate Authority which will be trusted by your user's web browsers. Because there are
many ways to expose TLS services from a Kubernetes cluster, the Supervisor app leaves this up to the user.
The most common ways are:
1. Define an [`Ingress` resource](https://kubernetes.io/docs/concepts/services-networking/ingress/) with TLS certificates.
In this case, the ingress will terminate TLS. Typically, the ingress will then talk plain HTTP to its backend,
which would be a NodePort or LoadBalancer Service in front of the HTTP port 8080 of the Supervisor pods.
The required configuration of the Ingress is specific to your cluster's Ingress Controller, so please refer to the
documentation from your Kubernetes provider. If you are using a cluster from a cloud provider, then you'll probably
want to start with that provider's documentation. For example, if your cluster is a Google GKE cluster, refer to
the [GKE documentation for Ingress](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress).
Otherwise, the Kubernetes documentation provides a list of popular
[Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/), including
[Contour](https://projectcontour.io/) and many others.
1. Or, define a [TCP LoadBalancer Service](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer)
which is a layer 4 load balancer and does not terminate TLS. In this case, the Supervisor app will need to be
configured with TLS certificates and will terminate the TLS connection itself (see the section about FederationDomain
below). The LoadBalancer Service should be configured to use the HTTPS port 443 of the Supervisor pods as its `targetPort`.
*Warning:* Do not expose the Supervisor's port 8080 to the public. It would not be secure for the OIDC protocol
to use HTTP, because the user's secret OIDC tokens would be transmitted across the network without encryption.
1. Or, expose the Supervisor app using a Kubernetes service mesh technology, e.g. [Istio](https://istio.io/).
Please see the documentation for your service mesh. Generally, the setup would be similar to the description
above for defining an ingress, expect the service mesh would probably provide both the ingress with TLS termination
and the service.
For either of the first two options mentioned above, if you installed using `ytt` then you can use
the related `service_*` options from [deploy/supervisor/values.yml](values.yaml) to create a Service.
If you installed using `install-supervisor.yaml` then you can create
the Service separately after installing the Supervisor app. There is no `Ingress` included in the `ytt` templates,
so if you choose to use an Ingress then you'll need to create that separately after installing the Supervisor app.
#### Example: Using a LoadBalancer Service
This is an example of creating a LoadBalancer Service to expose port 8443 of the Supervisor app outside the cluster.
```yaml
apiVersion: v1
kind: Service
metadata:
name: pinniped-supervisor-loadbalancer
# Assuming that this is the namespace where the supervisor was installed. This is the default in install-supervisor.yaml.
namespace: pinniped-supervisor
spec:
type: LoadBalancer
selector:
# Assuming that this is how the supervisor pods are labeled. This is the default in install-supervisor.yaml.
app: pinniped-supervisor
ports:
- protocol: TCP
port: 443
targetPort: 8443
```
#### Example: Using a NodePort Service
A NodePort Service exposes the app as a port on the nodes of the cluster.
This is convenient for use with kind clusters, because kind can
[expose node ports as localhost ports on the host machine](https://kind.sigs.k8s.io/docs/user/configuration/#extra-port-mappings)
without requiring an Ingress, although
[kind also supports several Ingress Controllers](https://kind.sigs.k8s.io/docs/user/ingress).
A NodePort Service could also be used behind an Ingress which is terminating TLS.
For example:
```yaml
apiVersion: v1
kind: Service
metadata:
name: pinniped-supervisor-nodeport
# Assuming that this is the namespace where the supervisor was installed. This is the default in install-supervisor.yaml.
namespace: pinniped-supervisor
spec:
type: NodePort
selector:
# Assuming that this is how the supervisor pods are labeled. This is the default in install-supervisor.yaml.
app: pinniped-supervisor
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 31234 # This is the port that you would forward to the kind host. Or omit this key for a random port.
```
### Configuring the Supervisor to Act as an OIDC Provider
The Supervisor can be configured as an OIDC provider by creating `FederationDomain` resources
in the same namespace where the Supervisor app was installed. For example:
```yaml
apiVersion: config.supervisor.pinniped.dev/v1alpha1
kind: FederationDomain
metadata:
name: my-provider
# Assuming that this is the namespace where the supervisor was installed. This is the default in install-supervisor.yaml.
namespace: pinniped-supervisor
spec:
# The hostname would typically match the DNS name of the public ingress or load balancer for the cluster.
# Any path can be specified, which allows a single hostname to have multiple different issuers. The path is optional.
issuer: https://my-issuer.example.com/any/path
# Optionally configure the name of a Secret in the same namespace, of type `kubernetes.io/tls`,
# which contains the TLS serving certificate for the HTTPS endpoints served by this OIDC Provider.
tls:
secretName: my-tls-cert-secret
```
#### Configuring TLS for the Supervisor OIDC Endpoints
If you have terminated TLS outside the app, for example using an Ingress with TLS certificates, then you do not need to
configure TLS certificates on the FederationDomain.
If you are using a LoadBalancer Service to expose the Supervisor app outside your cluster, then you will
also need to configure the Supervisor app to terminate TLS. There are two places to configure TLS certificates:
1. Each `FederationDomain` can be configured with TLS certificates, using the `spec.tls.secretName` field.
1. The default TLS certificate for all OIDC providers can be configured by creating a Secret called
`pinniped-supervisor-default-tls-certificate` in the same namespace in which the Supervisor was installed.
The default TLS certificate will be used for all OIDC providers which did not declare a `spec.tls.secretName`.
Also, the `spec.tls.secretName` will be ignored for incoming requests to the OIDC endpoints
that use an IP address as the host, so those requests will always present the default TLS certificates
to the client. When the request includes the hostname, and that hostname matches the hostname of an `Issuer`,
then the TLS certificate defined by the `spec.tls.secretName` will be used. If that issuer did not
define `spec.tls.secretName` then the default TLS certificate will be used. If neither exists,
then the client will get a TLS error because the server will not present any TLS certificate.
It is recommended that you have a DNS entry for your load balancer or Ingress, and that you configure the
OIDC provider's `Issuer` using that DNS hostname, and that the TLS certificate for that provider also
covers that same hostname.
You can create the certificate Secrets however you like, for example you could use [cert-manager](https://cert-manager.io/)
or `kubectl create secret tls`.
Keep in mind that your users will load some of these endpoints in their web browsers, so the TLS certificates
should be signed by a Certificate Authority that will be trusted by their browsers.
See [the how-to guide for details](https://pinniped.dev/docs/howto/install-supervisor/).

11
go.mod
View File

@ -7,8 +7,8 @@ require (
github.com/MakeNowJust/heredoc/v2 v2.0.1
github.com/coreos/go-oidc/v3 v3.0.0
github.com/davecgh/go-spew v1.1.1
github.com/go-logr/logr v0.3.0
github.com/go-logr/stdr v0.2.0
github.com/go-logr/logr v0.4.0
github.com/go-logr/stdr v0.4.0
github.com/go-openapi/spec v0.19.9
github.com/gofrs/flock v0.8.0
github.com/golang/mock v1.4.4
@ -24,16 +24,15 @@ require (
github.com/pkg/errors v0.9.1
github.com/sclevine/agouti v3.0.0+incompatible
github.com/sclevine/spec v1.4.0
github.com/spf13/cobra v1.1.1
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.6.1
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/square/go-jose.v2 v2.5.1
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
k8s.io/api v0.20.4
k8s.io/apimachinery v0.20.4
@ -41,7 +40,7 @@ require (
k8s.io/client-go v0.20.4
k8s.io/component-base v0.20.4
k8s.io/gengo v0.0.0-20201113003025-83324d819ded
k8s.io/klog/v2 v2.4.0
k8s.io/klog/v2 v2.5.0
k8s.io/kube-aggregator v0.20.4
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd
k8s.io/utils v0.0.0-20201110183641-67b214c5f920

17
go.sum
View File

@ -209,10 +209,10 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs=
github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/stdr v0.2.0 h1:EuTFw3BCZ6H/+1VNFlOLVK/sPKwmGMLx8/FTOFWuXpU=
github.com/go-logr/stdr v0.2.0/go.mod h1:NO1vneyJDqKVgJYnxhwXWWmQPOvNM391IG3H8ql3jiA=
github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/stdr v0.4.0 h1:ijk9G/xzDRZdMU1QRhLYdHuWvNZWqte+NZMOGsiKWbc=
github.com/go-logr/stdr v0.4.0/go.mod h1:NO1vneyJDqKVgJYnxhwXWWmQPOvNM391IG3H8ql3jiA=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
@ -961,8 +961,9 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
@ -987,8 +988,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.1.1/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
@ -1515,8 +1517,9 @@ k8s.io/gengo v0.0.0-20201113003025-83324d819ded h1:JApXBKYyB7l9xx+DK7/+mFjC7A9Bt
k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.5.0 h1:8mOnjf1RmUPW6KRqQCfYSZq/K20Unmp3IhuZUhxl8KI=
k8s.io/klog/v2 v2.5.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/kube-aggregator v0.20.4 h1:j/SUwPy1eO+ud3XOUGmH18gISPyerqhXOoNRZDbv3fs=
k8s.io/kube-aggregator v0.20.4/go.mod h1:0ixQ9De7KXyHteXizS6nVtrnKqGa4kiuxl9rEBsNccw=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c=

View File

@ -152,7 +152,7 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="secret \"test-client-secret\" not found" "reason"="SecretNotFound" "status"="False" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="discovered issuer configuration" "reason"="Success" "status"="True" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="secret \"test-client-secret\" not found" "name"="test-name" "namespace"="test-namespace" "reason"="SecretNotFound" "type"="ClientCredentialsValid"`,
`upstream-observer "msg"="found failing condition" "error"="OIDCIdentityProvider has a failing condition" "message"="secret \"test-client-secret\" not found" "name"="test-name" "namespace"="test-namespace" "reason"="SecretNotFound" "type"="ClientCredentialsValid"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
@ -198,7 +198,7 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="referenced Secret \"test-client-secret\" has wrong type \"some-other-type\" (should be \"secrets.pinniped.dev/oidc-client\")" "reason"="SecretWrongType" "status"="False" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="discovered issuer configuration" "reason"="Success" "status"="True" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="referenced Secret \"test-client-secret\" has wrong type \"some-other-type\" (should be \"secrets.pinniped.dev/oidc-client\")" "name"="test-name" "namespace"="test-namespace" "reason"="SecretWrongType" "type"="ClientCredentialsValid"`,
`upstream-observer "msg"="found failing condition" "error"="OIDCIdentityProvider has a failing condition" "message"="referenced Secret \"test-client-secret\" has wrong type \"some-other-type\" (should be \"secrets.pinniped.dev/oidc-client\")" "name"="test-name" "namespace"="test-namespace" "reason"="SecretWrongType" "type"="ClientCredentialsValid"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
@ -243,7 +243,7 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="referenced Secret \"test-client-secret\" is missing required keys [\"clientID\" \"clientSecret\"]" "reason"="SecretMissingKeys" "status"="False" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="discovered issuer configuration" "reason"="Success" "status"="True" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="referenced Secret \"test-client-secret\" is missing required keys [\"clientID\" \"clientSecret\"]" "name"="test-name" "namespace"="test-namespace" "reason"="SecretMissingKeys" "type"="ClientCredentialsValid"`,
`upstream-observer "msg"="found failing condition" "error"="OIDCIdentityProvider has a failing condition" "message"="referenced Secret \"test-client-secret\" is missing required keys [\"clientID\" \"clientSecret\"]" "name"="test-name" "namespace"="test-namespace" "reason"="SecretMissingKeys" "type"="ClientCredentialsValid"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
@ -291,7 +291,7 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="spec.certificateAuthorityData is invalid: illegal base64 data at input byte 7" "reason"="InvalidTLSConfig" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="spec.certificateAuthorityData is invalid: illegal base64 data at input byte 7" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidTLSConfig" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "msg"="found failing condition" "error"="OIDCIdentityProvider has a failing condition" "message"="spec.certificateAuthorityData is invalid: illegal base64 data at input byte 7" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidTLSConfig" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
@ -339,7 +339,7 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="spec.certificateAuthorityData is invalid: no certificates found" "reason"="InvalidTLSConfig" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="spec.certificateAuthorityData is invalid: no certificates found" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidTLSConfig" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "msg"="found failing condition" "error"="OIDCIdentityProvider has a failing condition" "message"="spec.certificateAuthorityData is invalid: no certificates found" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidTLSConfig" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
@ -384,7 +384,7 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="failed to perform OIDC discovery against \"invalid-url\"" "reason"="Unreachable" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="failed to perform OIDC discovery against \"invalid-url\"" "name"="test-name" "namespace"="test-namespace" "reason"="Unreachable" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "msg"="found failing condition" "error"="OIDCIdentityProvider has a failing condition" "message"="failed to perform OIDC discovery against \"invalid-url\"" "name"="test-name" "namespace"="test-namespace" "reason"="Unreachable" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
@ -430,7 +430,7 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="failed to parse authorization endpoint URL: parse \"%\": invalid URL escape \"%\"" "reason"="InvalidResponse" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="failed to parse authorization endpoint URL: parse \"%\": invalid URL escape \"%\"" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidResponse" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "msg"="found failing condition" "error"="OIDCIdentityProvider has a failing condition" "message"="failed to parse authorization endpoint URL: parse \"%\": invalid URL escape \"%\"" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidResponse" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
@ -476,7 +476,7 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="authorization endpoint URL scheme must be \"https\", not \"http\"" "reason"="InvalidResponse" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="authorization endpoint URL scheme must be \"https\", not \"http\"" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidResponse" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "msg"="found failing condition" "error"="OIDCIdentityProvider has a failing condition" "message"="authorization endpoint URL scheme must be \"https\", not \"http\"" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidResponse" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{

View File

@ -22,17 +22,13 @@ markup:
noClasses: false
style: monokailight
tabWidth: 4
menu:
docs:
- name: Overview
url: /docs/
weight: 100
- name: Install
url: /docs/install/
weight: 110
- name: Architecture
url: /docs/architecture/
- name: Demo
url: /docs/demo/
- name: Scope
url: /docs/scope/
related:
includeNewer: true
indices:
- name: tags
weight: 50
- name: date
weight: 50
threshold: 0
toLower: true

View File

@ -16,8 +16,8 @@ layout: section
<a href="{{< param "github_url" >}}"><img src="/img/github-image.svg" /></a>
</div>
<div class="content">
<h3><a href="{{< param "github_url" >}}">Check out Github</a></h3>
<p>Head over to our git repo and check out the discussions and issues sections.</p>
<h3><a href="{{< param "github_url" >}}">Check out GitHub</a></h3>
<p>Head over to our GitHub repo and check out the <a href="https://github.com/vmware-tanzu/pinniped/discussions">discussions</a> and <a href="https://github.com/vmware-tanzu/pinniped/issues">issues</a>.</p>
</div>
</div>
<div class="col">
@ -35,7 +35,7 @@ layout: section
</div>
<div class="content">
<h3><a href="{{< param "community_url" >}}">Community Meetings</a></h3>
<p>Pinniped Community Meetings are held every 1st and 3rd Thursday of the month at 9AM PT / 12PM ET</p>
<p>Pinniped Community Meetings are held every first and third Thursday of the month at 9 AM PT / 12 PM ET</p>
<p>Join our <a href="https://groups.google.com/u/1/g/project-pinniped">Google Group</a> to receive invites to the meeting</p>
<p>Watch previous community meetings on our <a href="https://www.youtube.com/playlist?list=PL7bmigfV0EqQ8qYn8ornuJnuGvCt0belt">YouTube playlist</a></p>
</div>

View File

@ -1,61 +1,31 @@
---
title: "Pinniped Documentation"
cascade:
layout: docs
menu:
docs:
name: Overview
weight: 1
---
![Pinniped Logo](/docs/img/pinniped_logo.svg)
# Getting started with Pinniped
## Overview
Pinniped is an authentication service for Kubernetes clusters.
As a Kubernetes cluster administrator or user, you can learn how Pinniped works, see how to use it on your clusters, and dive into internals of Pinniped's APIs and architecture.
Pinniped provides identity services to Kubernetes.
Have a question, comment, or idea? Please reach out via [GitHub Discussions](https://github.com/vmware-tanzu/pinniped/discussions) or [join the Pinniped community meetings]({{< ref "/community" >}}).
Pinniped allows cluster administrators to easily plug in external identity
providers (IDPs) into Kubernetes clusters. This is achieved via a uniform
install procedure across all types and origins of Kubernetes clusters,
declarative configuration via Kubernetes APIs, enterprise-grade integrations
with IDPs, and distribution-specific integration strategies.
## Tutorials
### Example Use Cases
{{< docsmenu "tutorials" >}}
* Your team uses a large enterprise IDP, and has many clusters that they
manage. Pinniped provides:
* Seamless and robust integration with the IDP
* Easy installation across clusters of any type and origin
* A simplified login flow across all clusters
* Your team shares a single cluster. Pinniped provides:
* Simple configuration to integrate an IDP
* Individual, revocable identities
## How-to guides
### Architecture
{{< docsmenu "howtos" >}}
Pinniped offers credential exchange to enable a user to exchange an external IDP
credential for a short-lived, cluster-specific credential. Pinniped supports various
IDP types and implements different integration strategies for various Kubernetes
distributions to make authentication possible.
## Reference
To learn more, see [docs/architecture](/docs/architecture).
{{< docsmenu "reference" >}}
<img src="docs/img/pinniped_architecture_concierge_supervisor.svg" alt="Pinniped Architecture Sketch" width="300px"/>
## Background
## Trying Pinniped
Care to kick the tires? It's easy to [install and try Pinniped](/docs/demo).
## Discussion
Got a question, comment, or idea? Please don't hesitate to reach out via the GitHub [Discussions](https://github.com/vmware-tanzu/pinniped/discussions) tab at the top of this page.
## Contributions
Contributions are welcome. Before contributing, please see the [contributing guide](https://github.com/vmware-tanzu/pinniped/blob/main/CONTRIBUTING.md).
## Reporting Security Vulnerabilities
Please follow the procedure described in [SECURITY.md](https://github.com/vmware-tanzu/pinniped/blob/main/SECURITY.md).
## License
Pinniped is open source and licensed under Apache License Version 2.0. See [LICENSE](https://github.com/vmware-tanzu/pinniped/blob/main/LICENSE).
Copyright 2020 the Pinniped contributors. All Rights Reserved.
{{< docsmenu "background" >}}

View File

@ -0,0 +1,13 @@
---
cascade:
layout: docs
menu:
docs:
name: Background
identifier: background
weight: 110
---
# Pinniped background
{{< docsmenu "background" >}}

View File

@ -1,16 +1,20 @@
---
title: "Pinniped Architecture"
title: Architecture
description: Dive into the overall design and implementation details of Pinniped.
cascade:
layout: docs
menu:
docs:
name: Architecture
weight: 100
parent: background
---
# Architecture
The principal purpose of Pinniped is to allow users to access Kubernetes
clusters. Pinniped hopes to enable this access across a wide range of Kubernetes
environments with zero configuration.
Pinniped is composed of two parts.
1. The Pinniped Supervisor is an OIDC server which allows users to authenticate
with an external identity provider (IDP), and then issues its own federation ID tokens
to be passed on to clusters based on the user information from the IDP.
@ -24,14 +28,6 @@ understood by the host Kubernetes cluster.
Pinniped supports various authenticator types and OIDC identity providers and implements different integration strategies
for various Kubernetes distributions to make authentication possible.
## Supported Kubernetes Cluster Types
Pinniped supports the following types of Kubernetes clusters:
- Clusters where the Kube Controller Manager pod is accessible from Pinniped's pods.
Support for other types of Kubernetes distributions is coming soon.
## External Identity Provider Integrations
The Pinniped Supervisor will federate identity from one or more IDPs.

View File

@ -1,9 +0,0 @@
---
title: "Pinniped Demo"
cascade:
layout: docs
---
# Trying Pinniped
1. [Concierge with webhook demo](/docs/concierge-only-demo)
1. [Concierge with Supervisor and JWT authenticator demo](/docs/concierge-and-supervisor-demo)

View File

@ -0,0 +1,14 @@
---
title: Pinniped How-To Guides
cascade:
layout: docs
menu:
docs:
name: How-to Guides
identifier: howtos
weight: 50
---
These how-to guides show you how to install and configure the Pinniped command-line tool, Concierge, and Supervisor:
{{< docsmenu "howtos" >}}

View File

@ -0,0 +1,142 @@
---
title: Configure the Pinniped Concierge to validate JWT tokens
description: Set up JSON Web Token (JWT) based token authentication on an individual Kubernetes cluster.
cascade:
layout: docs
menu:
docs:
name: Configure Concierge JWT Authentication
weight: 25
parent: howtos
---
The Concierge can validate [JSON Web Tokens (JWTs)](https://tools.ietf.org/html/rfc7519), which are commonly issued by [OpenID Connect (OIDC)](https://openid.net/connect/) identity providers.
This guide shows you how to use this capability _without_ the Pinniped Supervisor.
This is most useful if you have only a single cluster and want to authenticate to it via an existing OIDC provider.
If you have multiple clusters, you may want to [install]({{< ref "install-supervisor" >}}) and [configure]({{< ref "configure-supervisor" >}}) the Pinniped Supervisor.
## Prerequisites
Before starting, you should have the [command-line tool installed]({{< ref "install-cli" >}}) locally and [Concierge running in your cluster]({{< ref "install-concierge" >}}).
You should also have some existing OIDC issuer configuration:
- An OIDC provider that supports [discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) and the `email` scope.
- A public client with callback URI `http://127.0.0.1:12345/callback` and `email` scope.
## Create a JWTAuthenticator
Create a JWTAuthenticator describing how to validate tokens from your OIDC issuer:
```yaml
apiVersion: authentication.concierge.pinniped.dev/v1alpha1
kind: JWTAuthenticator
metadata:
name: my-jwt-authenticator
spec:
issuer: https://my-issuer.example.com/any/path
audience: my-client-id
claims:
username: email
```
If you've saved this into a file `my-jwt-authenticator.yaml`, then install it into your cluster using:
```sh
kubectl apply -f my-jwt-authenticator.yaml
```
## Generate a kubeconfig file
Generate a kubeconfig file to target the JWTAuthenticator:
```sh
pinniped get kubeconfig \
--oidc-client-id my-client-id \
--oidc-scopes openid,email \
--oidc-listen-port 12345 \
> my-cluster.yaml
```
This creates a kubeconfig YAML file `my-cluster.yaml` that targets your JWTAuthenticator using `pinniped login oidc` as an [ExecCredential plugin](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins).
It should look something like below:
```yaml
apiVersion: v1
kind: Config
current-context: pinniped
clusters:
- cluster:
certificate-authority-data: LS0tLS[...]
server: https://my-kubernetes-api-endpoint.example.com:59986
name: pinniped
contexts:
- context:
cluster: pinniped
user: pinniped
name: pinniped
users:
- name: pinniped
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: /usr/local/bin/pinniped
args:
- login
- oidc
- --enable-concierge
- --concierge-api-group-suffix=pinniped.dev
- --concierge-authenticator-name=my-jwt-authenticator
- --concierge-authenticator-type=jwt
- --concierge-endpoint=https://my-kubernetes-api-endpoint.example.com:59986
- --concierge-ca-bundle-data=LS0tLS[...]
- --issuer=https://my-oidc-issuer.example.com/any/path
- --client-id=my-client-id
- --scopes=offline_access,openid,email
- --listen-port=12345
- --request-audience=my-client-id
```
## Use the kubeconfig file
Use the kubeconfig with `kubectl` to access your cluster:
```sh
kubectl --kubeconfig my-cluster.yaml get namespaces
```
You should see:
- The `pinniped login oidc` command is executed automatically by `kubectl`.
- Pinniped opens your browser window and directs you to login with your identity provider.
- After you've logged in, you see a page telling you `you have been logged in and may now close this tab`.
- In your shell, you see your clusters namespaces.
If instead you get an access denied error, you may need to create a ClusterRoleBinding for the `email` of your OIDC account, for example:
```sh
kubectl create clusterrolebinding my-user-admin \
--clusterrole admin \
--user my-username@example.com
```
## Other notes
- Pinniped kubeconfig files do not contain secrets and are safe to share between users.
- Temporary OIDC session credentials such as ID, access, and refresh tokens are stored in:
- `~/.config/pinniped/sessions.yaml` (macOS/Linux)
- `%USERPROFILE%/.config/pinniped/sessions.yaml` (Windows).
- If your OIDC provider supports [wildcard port number matching](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-16#section-2.1) for localhost URIs, you can omit the `--oidc-listen-port` flag to use a randomly chosen ephemeral TCP port.
- The Pinniped command-line tool can only act as a public client with no client secret.
If your provider only supports non-public clients, consider using the Pinniped Supervisor.
- In general, it is not safe to use the same OIDC client across multiple clusters.
If you need to access multiple clusters, please [install the Pinniped Supervisor]({{< ref "install-supervisor" >}}).

View File

@ -0,0 +1,116 @@
---
title: Configure the Pinniped Concierge to validate webhook tokens
description: Set up webhook-based token authentication on an individual Kubernetes cluster.
cascade:
layout: docs
menu:
docs:
name: Configure Concierge Webhook Authentication
weight: 26
parent: howtos
---
The Concierge can validate arbitrary tokens via an external webhook endpoint using the [same validation process as Kubernetes itself](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication).
## Prerequisites
Before starting, you should have the [command-line tool installed]({{< ref "install-cli" >}}) locally and [Concierge running in your cluster]({{< ref "install-concierge" >}}).
You should also have a custom TokenReview webhook endpoint:
- Your webhook endpoint must handle the `authentication.k8s.io/v1` [TokenReview API](https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-review-v1/#TokenReview).
- Your webhook must be accessible from the Concierge pod over HTTPS.
## Create a WebhookAuthenticator
Create a WebhookAuthenticator describing how to validate tokens using your webhook:
```yaml
apiVersion: authentication.concierge.pinniped.dev/v1alpha1
kind: WebhookAuthenticator
metadata:
name: my-webhook-authenticator
spec:
# HTTPS endpoint to be called as a webhook
endpoint: https://my-webhook.example.com/any/path
tls:
# base64-encoded PEM CA bundle (optional)
certificateAuthorityData: "LS0tLS1CRUdJTi[...]"
```
If you've saved this into a file `my-webhook-authenticator.yaml`, then install it into your cluster using:
```sh
kubectl apply -f my-webhook-authenticator.yaml
```
## Generate a kubeconfig file
Generate a kubeconfig file to target the WebhookAuthenticator:
```sh
pinniped get kubeconfig \
--static-token-env MY_CLUSTER_ACCESS_TOKEN \
> my-cluster.yaml
```
This creates a kubeconfig YAML file `my-cluster.yaml` that targets your WebhookAuthenticator using `pinniped login static` as an [ExecCredential plugin](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins).
It should look something like below:
```yaml
apiVersion: v1
kind: Config
current-context: pinniped
clusters:
- cluster:
certificate-authority-data: LS0tLS[...]
server: https://my-kubernetes-api-endpoint.example.com:59986
name: pinniped
contexts:
- context:
cluster: pinniped
user: pinniped
name: pinniped
users:
- name: pinniped
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: /usr/local/bin/pinniped
args:
- login
- oidc
- login
- static
- --enable-concierge
- --concierge-api-group-suffix=pinniped.dev
- --concierge-authenticator-name=my-webhook-authenticator
- --concierge-authenticator-type=webhook
- --concierge-endpoint=https://127.0.0.1:59986
- --concierge-ca-bundle-data=LS0tLS[...]
- --token-env=MY_CLUSTER_ACCESS_TOKEN
```
## Use the kubeconfig file
Set the `$MY_CLUSTER_ACCESS_TOKEN` environment variable and use the kubeconfig with `kubectl` to access your cluster:
```sh
MY_CLUSTER_ACCESS_TOKEN=secret-token kubectl --kubeconfig my-cluster.yaml get namespaces
```
You should see:
- The `pinniped login static` command is silently executed automatically by `kubectl`.
- The command-line tool sends your token to the Concierge which validates it by making a request to your webhook endpoint.
- In your shell, you see your clusters namespaces.
If instead you get an access denied error, you may need to create a ClusterRoleBinding for the username/groups returned by your webhook, for example:
```sh
kubectl create clusterrolebinding my-user-admin --clusterrole admin --user my-username
```

View File

@ -0,0 +1,161 @@
---
title: Configure the Pinniped Supervisor as an OIDC issuer
description: Set up the Pinniped Supervisor to provide seamless login flows across multiple clusters.
cascade:
layout: docs
menu:
docs:
name: Configure Supervisor
weight: 35
parent: howtos
---
The Supervisor is an [OpenID Connect (OIDC)](https://openid.net/connect/) issuer that supports connecting a single "upstream" OIDC identity provider to many "downstream" cluster clients.
This guide show you how to use this capability to issue [JSON Web Tokens (JWTs)](https://tools.ietf.org/html/rfc7519) that can be validated by the [Pinniped Concierge]({{< ref "configure-concierge-jwt" >}}).
Before starting, you should have the [command-line tool installed]({{< ref "install-cli" >}}) locally and the Concierge [installed]({{< ref "install-concierge" >}}) in your cluster.
## Expose the Supervisor app as a service
The Supervisor app's endpoints should be exposed as HTTPS endpoints with proper TLS certificates signed by a certificate authority (CA) which is trusted by your user's web browsers.
Because there are many ways to expose TLS services from a Kubernetes cluster, the Supervisor app leaves this up to the user.
The most common ways are:
1. Define an [`Ingress` resource](https://kubernetes.io/docs/concepts/services-networking/ingress/) with TLS certificates.
In this case, the ingress terminates TLS. Typically, the ingress then talks plain HTTP to its backend,
which would be a NodePort or LoadBalancer Service in front of the HTTP port 8080 of the Supervisor pods.
The required configuration of the Ingress is specific to your cluster's Ingress Controller, so please refer to the
documentation from your Kubernetes provider. If you are using a cluster from a cloud provider, then you'll probably
want to start with that provider's documentation. For example, if your cluster is a Google GKE cluster, refer to
the [GKE documentation for Ingress](https://cloud.google.com/kubernetes-engine/docs/concepts/ingress).
Otherwise, the Kubernetes documentation provides a list of popular
[Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/), including
[Contour](https://projectcontour.io/) and many others.
1. Or, define a [TCP LoadBalancer Service](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer)
which is a layer 4 load balancer and does not terminate TLS. In this case, the Supervisor app needs to be
configured with TLS certificates and terminates the TLS connection itself (see the section about FederationDomain
below). The LoadBalancer Service should be configured to use the HTTPS port 443 of the Supervisor pods as its `targetPort`.
*Warning:* do not expose the Supervisor's port 8080 to the public. It would not be secure for the OIDC protocol
to use HTTP, because the user's secret OIDC tokens would be transmitted across the network without encryption.
1. Or, expose the Supervisor app using a Kubernetes service mesh technology, for example [Istio](https://istio.io/).
Please see the documentation for your service mesh. Generally, the setup would be similar to the previous description
for defining an ingress, except the service mesh would probably provide both the ingress with TLS termination
and the service.
For either of the first two options, if you installed using `ytt` then you can use
the related `service_*` options from [deploy/supervisor/values.yml](values.yaml) to create a Service.
If you installed using `install-supervisor.yaml` then you can create
the Service separately after installing the Supervisor app. There is no `Ingress` included in the `ytt` templates,
so if you choose to use an Ingress then you'll need to create that separately after installing the Supervisor app.
#### Example: Using a LoadBalancer Service
This is an example of creating a LoadBalancer Service to expose port 8443 of the Supervisor app outside the cluster.
```yaml
apiVersion: v1
kind: Service
metadata:
name: pinniped-supervisor-loadbalancer
# Assuming that this is the namespace where the supervisor was installed. This is the default in install-supervisor.yaml.
namespace: pinniped-supervisor
spec:
type: LoadBalancer
selector:
# Assuming that this is how the supervisor pods are labeled. This is the default in install-supervisor.yaml.
app: pinniped-supervisor
ports:
- protocol: TCP
port: 443
targetPort: 8443
```
#### Example: Using a NodePort Service
A NodePort Service exposes the app as a port on the nodes of the cluster.
This is convenient for use with kind clusters, because kind can
[expose node ports as localhost ports on the host machine](https://kind.sigs.k8s.io/docs/user/configuration/#extra-port-mappings)
without requiring an Ingress, although
[kind also supports several Ingress Controllers](https://kind.sigs.k8s.io/docs/user/ingress).
A NodePort Service could also be used behind an Ingress which is terminating TLS.
For example:
```yaml
apiVersion: v1
kind: Service
metadata:
name: pinniped-supervisor-nodeport
# Assuming that this is the namespace where the supervisor was installed. This is the default in install-supervisor.yaml.
namespace: pinniped-supervisor
spec:
type: NodePort
selector:
# Assuming that this is how the supervisor pods are labeled. This is the default in install-supervisor.yaml.
app: pinniped-supervisor
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 31234 # This is the port that you would forward to the kind host. Or omit this key for a random port.
```
### Configuring the Supervisor to act as an OIDC provider
The Supervisor can be configured as an OIDC provider by creating `FederationDomain` resources
in the same namespace where the Supervisor app was installed. For example:
```yaml
apiVersion: config.supervisor.pinniped.dev/v1alpha1
kind: FederationDomain
metadata:
name: my-provider
# Assuming that this is the namespace where the supervisor was installed. This is the default in install-supervisor.yaml.
namespace: pinniped-supervisor
spec:
# The hostname would typically match the DNS name of the public ingress or load balancer for the cluster.
# Any path can be specified, which allows a single hostname to have multiple different issuers. The path is optional.
issuer: https://my-issuer.example.com/any/path
# Optionally configure the name of a Secret in the same namespace, of type `kubernetes.io/tls`,
# which contains the TLS serving certificate for the HTTPS endpoints served by this OIDC Provider.
tls:
secretName: my-tls-cert-secret
```
#### Configuring TLS for the Supervisor OIDC endpoints
If you have terminated TLS outside the app, for example using an Ingress with TLS certificates, then you do not need to
configure TLS certificates on the FederationDomain.
If you are using a LoadBalancer Service to expose the Supervisor app outside your cluster, then you
also need to configure the Supervisor app to terminate TLS. There are two places to configure TLS certificates:
1. Each `FederationDomain` can be configured with TLS certificates, using the `spec.tls.secretName` field.
1. The default TLS certificate for all OIDC providers can be configured by creating a Secret called
`pinniped-supervisor-default-tls-certificate` in the same namespace in which the Supervisor was installed.
The default TLS certificate are used for all OIDC providers which did not declare a `spec.tls.secretName`.
Also, the `spec.tls.secretName` is ignored for incoming requests to the OIDC endpoints
that use an IP address as the host, so those requests always present the default TLS certificates
to the client. When the request includes the hostname, and that hostname matches the hostname of an `Issuer`,
then the TLS certificate defined by the `spec.tls.secretName` is used. If that issuer did not
define `spec.tls.secretName` then the default TLS certificate is used. If neither exists,
then the client gets a TLS error because the server does not present any TLS certificate.
It is recommended that you have a DNS entry for your load balancer or Ingress, and that you configure the
OIDC provider's `Issuer` using that DNS hostname, and that the TLS certificate for that provider also
covers that same hostname.
You can create the certificate Secrets however you like, for example you could use [cert-manager](https://cert-manager.io/)
or `kubectl create secret tls`.
Keep in mind that your users must load some of these endpoints in their web browsers, so the TLS certificates
should be signed by a certificate authority that is trusted by their browsers.

View File

@ -0,0 +1,55 @@
---
title: Install the Pinniped command-line tool
description: Download and set up the `pinniped` command-line tool on macOS, Linux, or Windows clients.
cascade:
layout: docs
menu:
docs:
name: Install CLI
weight: 10
parent: howtos
---
The `pinniped` command-line tool is used to generate Pinniped-compatible kubeconfig files, and is also an important part of the Pinniped-based login flow.
It must be installed by administrators setting up a Pinniped cluster as well as by users accessing a Pinniped-enabled cluster.
## Install using Homebrew on macOS or Linux
Use [Homebrew](https://brew.sh/) to install from the Pinniped [tap](https://github.com/vmware-tanzu/homebrew-pinniped):
- `brew install vmware-tanzu/pinniped/pinniped-cli`
## Download binaries
Find the appropriate binary for your platform from the [latest release](https://github.com/vmware-tanzu/pinniped/releases/latest):
{{< buttonlink href="https://get.pinniped.dev/latest/pinniped-cli-darwin-amd64" >}}Download for macOS/amd64{{< buttonicon "download.png" >}}{{< /buttonlink >}}
{{< buttonlink href="https://get.pinniped.dev/latest/pinniped-cli-linux-amd64" >}}Download for Linux/amd64{{< buttonicon "download.png" >}}{{< /buttonlink >}}
{{< buttonlink href="https://get.pinniped.dev/latest/pinniped-cli-windows-amd64.exe" >}}Download for Windows/amd64{{< buttonicon "download.png" >}}{{< /buttonlink >}}
You should put the command-line tool somewhere on your `$PATH`, such as `/usr/local/bin` on macOS/Linux.
You'll also need to mark the file as executable.
To find specific versions or view all available platforms and architectures, visit the [releases page](https://github.com/vmware-tanzu/pinniped/releases/).
### Gatekeeper
If you are using macOS, you may get an error dialog when you first run `pinniped` that says `“pinniped” cannot be opened because the developer cannotbe verified`.
Cancel this dialog, open System Preferences, click Security & Privacy, and click the Allow Anyway button next to the Pinniped message.
Run the command again and another dialog appears saying `macOS cannot verify the developer of “pinniped”. Are you sure you want to open it?`.
Click Open to allow the command to proceed.
## Install a specific version via script
For example, to install v0.4.1 on Linux/amd64:
```sh
curl -Lso pinniped https://get.pinniped.dev/v0.4.1/pinniped-cli-linux-amd64 \
&& chmod +x pinniped \
&& sudo mv pinniped /usr/local/bin/pinniped
```
*Next, [install the Concierge]({{< ref "install-concierge.md" >}})!*

View File

@ -0,0 +1,60 @@
---
title: Install the Pinniped Concierge
description: Install the Pinniped Concierge service in a Kubernetes cluster.
cascade:
layout: docs
menu:
docs:
name: Install Concierge
weight: 20
parent: howtos
---
This guide shows you how to install the Pinniped Concierge.
You should have a [supported Kubernetes cluster]({{< ref "../reference/supported-clusters" >}}).
## With default options
1. Install the latest version of the Concierge into the `pinniped-concierge` namespace with default options:
- `kubectl apply -f https://get.pinniped.dev/latest/install-pinniped-concierge.yaml`
## With specific version and default options
1. Choose your preferred [release](https://github.com/vmware-tanzu/pinniped/releases) version number and use it to replace the version number in the URL below.
1. Install the Concierge into the `pinniped-concierge` namespace with default options:
- `kubectl apply -f https://get.pinniped.dev/v0.4.1/install-pinniped-concierge.yaml`
*Replace v0.4.1 with your preferred version number.*
## With custom options
Pinniped uses [ytt](https://carvel.dev/ytt/) from [Carvel](https://carvel.dev/) as a templating system.
1. Install the `ytt` command-line tool using the instructions from the [Carvel documentation](https://carvel.dev/#whole-suite).
1. Clone the Pinniped GitHub repository and visit the `deploy/concierge` directory:
- `git clone git@github.com:vmware-tanzu/pinniped.git`
- `cd pinniped/deploy/concierge`
1. Customize configuration parameters:
- Edit `values.yaml` with your custom values.
- See the [default values](http://github.com/vmware-tanzu/pinniped/tree/main/deploy/concierge/values.yaml) for documentation about individual configuration parameters.
1. Render templated YAML manifests:
- `ytt --file .`
1. Deploy the templated YAML manifests:
- *If you're using `kubectl`:*
`ytt --file . | kubectl apply -f -`
- *If you're using [`kapp` from Carvel](https://carvel.dev/kapp/):*
`ytt --file . | kapp deploy --yes --app pinniped-concierge --diff-changes --file -`
*Next, configure the Concierge for [JWT]({{< ref "configure-concierge-jwt.md" >}}) or [webhook]({{< ref "configure-concierge-webhook.md" >}}) authentication.*

View File

@ -0,0 +1,59 @@
---
title: Install the Pinniped Supervisor
description: Install the Pinniped Supervisor service in a Kubernetes cluster.
cascade:
layout: docs
menu:
docs:
name: Install Supervisor
weight: 30
parent: howtos
---
This guide shows you how to install the Pinniped Supervisor, which allows seamless login across one or many Kubernetes clusters.
You should have a supported Kubernetes cluster with working HTTPS ingress capabilities.
<!-- TODO: link to support matrix -->
## With default options
1. Install the latest version of the Supervisor into the `pinniped-supervisor` namespace with default options:
- `kubectl apply -f https://get.pinniped.dev/latest/install-pinniped-supervisor.yaml`
## With specific version and default options
1. Choose your preferred [release](https://github.com/vmware-tanzu/pinniped/releases) version number and use it to replace the version number in the URL below.
1. Install the Supervisor into the `pinniped-supervisor` namespace with default options:
- `kubectl apply -f https://get.pinniped.dev/v0.4.1/install-pinniped-supervisor.yaml`
*Replace v0.4.1 with your preferred version number.*
## With custom options
Pinniped uses [ytt](https://carvel.dev/ytt/) from [Carvel](https://carvel.dev/) as a templating system.
1. Install the `ytt` command-line tool using the instructions from the [Carvel documentation](https://carvel.dev/#whole-suite).
1. Clone the Pinniped GitHub repository and visit the `deploy/supervisor` directory:
- `git clone git@github.com:vmware-tanzu/pinniped.git`
- `cd pinniped/deploy/supervisor`
1. Customize configuration parameters:
- Edit `values.yaml` with your custom values.
- See the [default values](http://github.com/vmware-tanzu/pinniped/tree/main/deploy/supervisor/values.yaml) for documentation about individual configuration parameters.
1. Render templated YAML manifests:
- `ytt --file .`
1. Deploy the templated YAML manifests:
- *If you're using `kubectl`:*
`ytt --file . | kubectl apply -f -`
- *If you're using [`kapp` from Carvel](https://carvel.dev/kapp/):*
`ytt --file . | kapp deploy --yes --app pinniped-supervisor --diff-changes --file -`

View File

@ -1,21 +0,0 @@
---
title: "Installing Pinniped"
cascade:
layout: docs
---
# Installing Pinniped
## Install the CLI
- Find the appropriate binary for your platform from the [latest release](https://github.com/vmware-tanzu/pinniped/releases/latest).
- Use Homebrew on macOS: `brew install vmware-tanzu/pinniped/pinniped-cli`.
## Install the Concierge
- See the [concierge deployment guide](https://github.com/vmware-tanzu/pinniped/tree/main/deploy/concierge).
## Install the Supervisor
- See the [supervisor deployment guide](https://github.com/vmware-tanzu/pinniped/tree/main/deploy/supervisor).

View File

@ -0,0 +1,13 @@
---
cascade:
layout: docs
menu:
docs:
name: Reference
identifier: reference
weight: 100
---
# Pinniped reference
{{< docsmenu "reference" >}}

View File

@ -0,0 +1,12 @@
---
title: API Types
description: Reference for the `*.pinniped.dev` Kubernetes API groups.
cascade:
layout: docs
menu:
docs:
name: API Types
weight: 35
parent: reference
---
Full API reference documentation for the Pinniped Kubernetes API is available [on GitHub](https://github.com/vmware-tanzu/pinniped/blob/main/generated/1.20/README.adoc).

View File

@ -0,0 +1,84 @@
---
title: Command-Line Options Reference
description: Reference for the `pinniped` command-line tool
cascade:
layout: docs
menu:
docs:
name: Command-Line Options
weight: 30
parent: reference
---
## `pinniped version`
Print the version of this Pinniped CLI.
```sh
pinniped version [flags]
```
- `-h`, `--help`:
help for kubeconfig
## `pinniped get kubeconfig`
Generate a Pinniped-based kubeconfig for a cluster.
```sh
pinniped get kubeconfig [flags]
```
- `-h`, `--help`:
help for kubeconfig
- `--concierge-api-group-suffix string`:
Concierge API group suffix (default "pinniped.dev")
- `--concierge-authenticator-name string`:
Concierge authenticator name (default: autodiscover)
- `--concierge-authenticator-type string`:
Concierge authenticator type (e.g., 'webhook', 'jwt') (default: autodiscover)
- `--kubeconfig string`:
Path to kubeconfig file
- `--kubeconfig-context string`:
Kubeconfig context name (default: current active context)
- `--no-concierge`:
Generate a configuration which does not use the concierge, but sends the credential to the cluster directly
- `--oidc-ca-bundle strings`:
Path to TLS certificate authority bundle (PEM format, optional, can be repeated)
- `--oidc-client-id string`:
OpenID Connect client ID (default: autodiscover) (default "pinniped-cli")
- `--oidc-issuer string`:
OpenID Connect issuer URL (default: autodiscover)
- `--oidc-listen-port uint16`:
TCP port for localhost listener (authorization code flow only)
- `--oidc-request-audience string`:
Request a token with an alternate audience using RFC8693 token exchange
- `--oidc-scopes strings`:
OpenID Connect scopes to request during login (default [offline_access,openid,pinniped:request-audience])
- `--oidc-session-cache string`:
Path to OpenID Connect session cache file
- `--oidc-skip-browser`:
During OpenID Connect login, skip opening the browser (just print the URL)
- `--static-token string`:
Instead of doing an OIDC-based login, specify a static token
- `--static-token-env string`:
Instead of doing an OIDC-based login, read a static token from the environment

View File

@ -0,0 +1,29 @@
---
title: Supported cluster types
description: See the supported cluster types for the Pinniped Concierge.
cascade:
layout: docs
menu:
docs:
name: Supported Cluster Types
weight: 10
parent: reference
---
| **Cluster Type** | **Concierge Works?** |
|-|-|
| [VMware Tanzu Kubernetes Grid (TKG) clusters](https://tanzu.vmware.com/kubernetes-grid) | Yes |
| [Kind clusters](https://kind.sigs.k8s.io/) | Yes |
| [Kubeadm-based clusters](https://kubernetes.io/docs/reference/setup-tools/kubeadm/) | Yes |
| [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/) | No |
| [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) | No |
| [Azure Kubernetes Service (AKS)](https://azure.microsoft.com/en-us/overview/kubernetes-on-azure) | No |
## Background
The Pinniped Concierge currently supports clusters where a custom pod can be executed on the same node running `kube-controller-manager`.
This type of cluster is typically called "self-hosted" because the cluster's control plane is running on nodes that are part of the cluster itself.
In practice, this means that many Kubernetes distributions are supported, but not most managed Kubernetes services
Support for more cluster types, including managed Kubernetes environments, is planned.

View File

@ -1,39 +0,0 @@
---
title: "Pinniped Scope"
cascade:
layout: docs
---
# Project Scope
The Pinniped project is guided by the following principles.
* Pinniped lets you plug any external identity providers into
Kubernetes. These integrations follow enterprise-grade security principles.
* Pinniped is easy to install and use on any Kubernetes cluster via
distribution-specific integration mechanisms.
* Pinniped uses a declarative configuration via Kubernetes APIs.
* Pinniped provides optimal user experience when authenticating to many
clusters at one time.
* Pinniped provides enterprise-grade security posture via secure defaults and
revocable or very short-lived credentials.
* Where possible, Pinniped will contribute ideas and code to upstream
Kubernetes.
When contributing to Pinniped, please consider whether your contribution follows
these guiding principles.
## Out Of Scope
The following items are out of scope for the Pinniped project.
* Authorization.
* Standalone identity provider for general use.
* Machine-to-machine (service) identity.
* Running outside of Kubernetes.
## Roadmap
More details coming soon!
For more details on proposing features and bugs, check out our
[contributing](https://github.com/vmware-tanzu/pinniped/blob/main/CONTRIBUTING.md) doc.

View File

@ -0,0 +1,15 @@
---
cascade:
layout: docs
menu:
docs:
name: Tutorials
identifier: tutorials
weight: 40
---
# Pinniped tutorials
These tutorials demonstrate how to use the Pinniped command-line tool, Concierge, and Supervisor:
{{< docsmenu "tutorials" >}}

View File

@ -1,11 +1,14 @@
---
title: "Pinniped Concierge and Supervisor Demo"
title: Learn to use the Pinniped Supervisor alongside the Concierge
description: See how the Pinniped Supervisor streamlines login to multiple Kubernetes clusters.
cascade:
layout: docs
menu:
docs:
name: Concierge with Supervisor
parent: tutorials
---
# Trying Pinniped Supervisor and Concierge
## Prerequisites
1. A Kubernetes cluster of a type supported by Pinniped Concierge as described in [architecture](/docs/architecture).
@ -13,18 +16,18 @@ cascade:
Don't have a cluster handy? Consider using [kind](https://kind.sigs.k8s.io/) on your local machine.
See below for an example of using kind.
1. A Kubernetes cluster of a type supported by Pinniped Supervisor (this can be the same cluster as the above, or different).
1. A Kubernetes cluster of a type supported by Pinniped Supervisor (this can be the same cluster as the first, or different).
1. A kubeconfig that has admin-like privileges on each cluster.
1. A kubeconfig that has administrator-like privileges on each cluster.
1. An external OIDC identity provider to use as the source of identity for Pinniped.
## Overview
Installing and trying Pinniped on any cluster will consist of the following general steps. See the next section below
Installing and trying Pinniped on any cluster consists of the following general steps. See the next section below
for a more specific example, including the commands to use for that case.
1. Install the Pinniped Supervisor. See [deploy/supervisor/README.md](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/supervisor/README.md).
1. [Install the Supervisor]({{< ref "../howto/install-supervisor" >}}).
1. Create a
[`FederationDomain`](https://github.com/vmware-tanzu/pinniped/blob/main/generated/1.20/README.adoc#k8s-api-go-pinniped-dev-generated-1-19-apis-supervisor-config-v1alpha1-federationdomain)
via the installed Pinniped Supervisor.
@ -35,31 +38,31 @@ for a more specific example, including the commands to use for that case.
1. Create a
[`JWTAuthenticator`](https://github.com/vmware-tanzu/pinniped/blob/main/generated/1.20/README.adoc#k8s-api-go-pinniped-dev-generated-1-19-apis-concierge-authentication-v1alpha1-jwtauthenticator)
via the installed Pinniped Concierge.
1. Download the Pinniped CLI from [Pinniped's github Releases page](https://github.com/vmware-tanzu/pinniped/releases/latest).
1. Generate a kubeconfig using the Pinniped CLI. Run `pinniped get kubeconfig --help` for more information.
1. Run `kubectl` commands using the generated kubeconfig. The Pinniped Supervisor and Concierge will automatically be used for authentication during those commands.
1. [Install the Pinniped command-line tool]({{< ref "../howto/install-cli" >}}).
1. Generate a kubeconfig using the Pinniped command-line tool. Run `pinniped get kubeconfig --help` for more information.
1. Run `kubectl` commands using the generated kubeconfig. The Pinniped Supervisor and Concierge are automatically used for authentication during those commands.
## Example of Deploying on Multiple kind Clusters
## Example of deploying on multiple kind clusters
[kind](https://kind.sigs.k8s.io) is a tool for creating and managing Kubernetes clusters on your local machine
which uses Docker containers as the cluster's "nodes". This is a convenient way to try out Pinniped on local
which uses Docker containers as the cluster's nodes. This is a convenient way to try out Pinniped on local
non-production clusters.
The following steps will deploy the latest release of Pinniped on kind. It will deploy the Pinniped
The following steps deploy the latest release of Pinniped on kind. They deploy the Pinniped
Supervisor on one cluster, and the Pinniped Concierge on another cluster. A multi-cluster deployment
strategy is typical for Pinniped. The Pinniped Concierge will use a
strategy is typical for Pinniped. The Pinniped Concierge uses a
[`JWTAuthenticator`](https://github.com/vmware-tanzu/pinniped/blob/main/generated/1.20/README.adoc#k8s-api-go-pinniped-dev-generated-1-19-apis-concierge-authentication-v1alpha1-jwtauthenticator)
to authenticate federated identities from the Supervisor.
1. Install the tools required for the following steps.
- [Install kind](https://kind.sigs.k8s.io/docs/user/quick-start/), if not already installed. e.g. `brew install kind` on MacOS.
- [Install kind](https://kind.sigs.k8s.io/docs/user/quick-start/), if not already installed. For example, `brew install kind` on macOS.
- kind depends on Docker. If not already installed, [install Docker](https://docs.docker.com/get-docker/), e.g. `brew cask install docker` on MacOS.
- kind depends on Docker. If not already installed, [install Docker](https://docs.docker.com/get-docker/), for example `brew cask install docker` on macOS.
- This demo requires `kubectl`, which comes with Docker, or can be [installed separately](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
- This demo requires `openssl`, which is installed on MacOS by default, or can be [installed separately](https://www.openssl.org/).
- This demo requires `openssl`, which is installed on macOS by default, or can be [installed separately](https://www.openssl.org/).
1. Create a new Kubernetes cluster for the Pinniped Supervisor using `kind create cluster --name pinniped-supervisor`.
@ -68,10 +71,10 @@ to authenticate federated identities from the Supervisor.
1. Deploy the Pinniped Supervisor with a valid serving certificate and network path. See
[deploy/supervisor/README.md](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/supervisor/README.md).
For purposes of this demo, the following issuer will be used. This issuer is specific to DNS and
TLS infrastructure set up for this demo.
For purposes of this demo, the following issuer is used. This issuer is specific to DNS and
TLS infrastructure set up for this demo:
```bash
```sh
issuer=https://my-supervisor.demo.pinniped.dev
```
@ -88,7 +91,7 @@ to authenticate federated identities from the Supervisor.
[`FederationDomain`](https://github.com/vmware-tanzu/pinniped/blob/main/generated/1.20/README.adoc#k8s-api-go-pinniped-dev-generated-1-19-apis-supervisor-config-v1alpha1-federationdomain)
object to configure the Pinniped Supervisor to issue federated identities.
```bash
```sh
cat <<EOF | kubectl create --context kind-pinniped-supervisor --namespace pinniped-supervisor -f -
apiVersion: config.supervisor.pinniped.dev/v1alpha1
kind: FederationDomain
@ -104,7 +107,7 @@ to authenticate federated identities from the Supervisor.
1. Create a `Secret` with the external OIDC identity provider OAuth 2.0 client credentials named
`my-oidc-identity-provider-client` in the pinniped-supervisor namespace.
```bash
```sh
kubectl create secret generic my-oidc-identity-provider-client \
--context kind-pinniped-supervisor \
--namespace pinniped-supervisor \
@ -121,7 +124,7 @@ to authenticate federated identities from the Supervisor.
Replace the `issuer` with your external identity provider's issuer and
adjust any other configuration on the spec.
```bash
```sh
cat <<EOF | kubectl create --context kind-pinniped-supervisor --namespace pinniped-supervisor -f -
apiVersion: idp.supervisor.pinniped.dev/v1alpha1
kind: OIDCIdentityProvider
@ -140,21 +143,19 @@ to authenticate federated identities from the Supervisor.
1. Deploy the Pinniped Concierge.
```bash
```sh
kubectl apply \
--context kind-pinniped-concierge \
-f https://get.pinniped.dev/latest/install-pinniped-concierge.yaml
```
The `install-pinniped-concierge.yaml` file includes the default deployment options.
If you would prefer to customize the available options, please see [deploy/concierge/README.md](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/concierge/README.md)
If you would prefer to customize the available options, please see the [Concierge installation guide]({{< ref "../howto/install-concierge" >}})
for instructions on how to deploy using `ytt`.
If you prefer to install a specific version, replace `latest` in the above URL with the version number such as `v0.4.1`.
1. Generate a random audience value for this cluster.
```bash
```sh
audience="$(openssl rand -hex 8)"
```
@ -162,7 +163,7 @@ to authenticate federated identities from the Supervisor.
[`JWTAuthenticator`](https://github.com/vmware-tanzu/pinniped/blob/main/generated/1.20/README.adoc#k8s-api-go-pinniped-dev-generated-1-19-apis-concierge-authentication-v1alpha1-jwtauthenticator)
object to configure the Pinniped Concierge to authenticate using the Pinniped Supervisor.
```bash
```sh
cat <<EOF | kubectl create --context kind-pinniped-concierge -f -
apiVersion: authentication.concierge.pinniped.dev/v1alpha1
kind: JWTAuthenticator
@ -175,30 +176,28 @@ to authenticate federated identities from the Supervisor.
certificateAuthorityData: $(cat /tmp/pinniped-supervisor-ca-bundle-base64-encoded.pem)
EOF
```
1. Download the latest version of the Pinniped CLI binary for your platform
from Pinniped's [latest release](https://github.com/vmware-tanzu/pinniped/releases/latest).
1. Move the Pinniped CLI binary to your preferred filename and directory. Add the executable bit,
e.g. `chmod +x /usr/local/bin/pinniped`.
1. Download the latest version of the Pinniped command-line tool for your platform.
On macOS or Linux, you can do this using Homebrew:
```sh
brew install vmware-tanzu/pinniped/pinniped-cli
```
On other platforms, see the [command-line installation guide]({{< ref "../howto/install-cli" >}}) for more details.
1. Generate a kubeconfig for the current cluster.
```bash
```sh
pinniped get kubeconfig \
--kubeconfig-context kind-pinniped-concierge \
> /tmp/pinniped-kubeconfig
```
If you are using MacOS, you may get an error dialog that says
`“pinniped” cannot be opened because the developer cannot be verified`. Cancel this dialog, open System Preferences,
click on Security & Privacy, and click the Allow Anyway button next to the Pinniped message.
Run the above command again and another dialog will appear saying
`macOS cannot verify the developer of “pinniped”. Are you sure you want to open it?`.
Click Open to allow the command to proceed.
1. Try using the generated kubeconfig to issue arbitrary `kubectl` commands. The `pinniped` command-line tool
opens a browser page that can be used to login to the external OIDC identity provider configured earlier.
1. Try using the generated kubeconfig to issue arbitrary `kubectl` commands. The `pinniped` CLI will
open a browser page that can be used to login to the external OIDC identity provider configured earlier.
```bash
```sh
kubectl --kubeconfig /tmp/pinniped-kubeconfig get pods -n pinniped-concierge
```
@ -209,30 +208,28 @@ to authenticate federated identities from the Supervisor.
to the upstream OIDC identity provider. However, this does prove that you are authenticated and
acting as the `pinny` user.
1. As the admin user, create RBAC rules for the test user to give them permissions to perform actions on the cluster.
1. As the administrator user, create RBAC rules for the test user to give them permissions to perform actions on the cluster.
For example, grant the test user permission to view all cluster resources.
```bash
```sh
kubectl --context kind-pinniped-concierge create clusterrolebinding pinny-can-read --clusterrole view --user pinny
```
1. Use the generated kubeconfig to issue arbitrary `kubectl` commands as the `pinny` user.
```bash
```sh
kubectl --kubeconfig /tmp/pinniped-kubeconfig get pods -n pinniped-concierge
```
The user has permission to list pods, so the command succeeds this time.
Pinniped has provided authentication into the cluster for your `kubectl` command! 🎉
Pinniped has provided authentication into the cluster for your `kubectl` command. 🎉
1. Carry on issuing as many `kubectl` commands as you'd like as the `pinny` user.
Each invocation will use Pinniped for authentication.
Each invocation uses Pinniped for authentication.
You may find it convenient to set the `KUBECONFIG` environment variable rather than passing `--kubeconfig` to each invocation.
```bash
```sh
export KUBECONFIG=/tmp/pinniped-kubeconfig
kubectl get namespaces
kubectl get pods -A
```
1. Profit! 💰

View File

@ -1,11 +1,15 @@
---
title: "Pinniped Concierge Only Demo"
title: Learn to use the Pinniped Concierge
description: See how the Pinniped Concierge works to provide a uniform login flow across different Kubernetes clusters.
cascade:
layout: docs
menu:
docs:
name: Concierge with Webhook
parent: tutorials
weight: 100
---
# Trying Pinniped Concierge
## Prerequisites
1. A Kubernetes cluster of a type supported by Pinniped as described in [architecture](/docs/architecture).
@ -20,48 +24,53 @@ cascade:
by following the directions in [deploy/local-user-authenticator/README.md](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/local-user-authenticator/README.md).
See below for an example of deploying this on kind.
1. A kubeconfig where the current context points to the cluster and has admin-like
1. A kubeconfig where the current context points to the cluster and has administrator-like
privileges on that cluster.
## Overview
Installing and trying Pinniped on any cluster will consist of the following general steps. See the next section below
Installing and trying the Pinniped Concierge on any cluster consists of the following general steps. See the next section below
for a more specific example of installing onto a local kind cluster, including the exact commands to use for that case.
1. Install the Pinniped Concierge. See [deploy/concierge/README.md](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/concierge/README.md).
1. Download the Pinniped CLI from [Pinniped's github Releases page](https://github.com/vmware-tanzu/pinniped/releases/latest).
1. Generate a kubeconfig using the Pinniped CLI. Run `pinniped get kubeconfig --help` for more information.
1. Run `kubectl` commands using the generated kubeconfig. The Pinniped Concierge will automatically be used for authentication during those commands.
1. [Install the Concierge]({{< ref "../howto/install-concierge" >}}).
1. [Install the Pinniped command-line tool]({{< ref "../howto/install-cli" >}}).
1. Configure the Concierge with a
[JWT]({{< ref "../howto/configure-concierge-jwt" >}}) or
[webhook]({{< ref "../howto/configure-concierge-webhook" >}}) authenticator.
1. Generate a kubeconfig using the Pinniped command-line tool (run `pinniped get kubeconfig --help` for more information).
1. Run `kubectl` commands using the generated kubeconfig.
## Example of Deploying on kind
The Pinniped Concierge is automatically be used for authentication during those commands.
## Example of deploying on kind
[kind](https://kind.sigs.k8s.io) is a tool for creating and managing Kubernetes clusters on your local machine
which uses Docker containers as the cluster's "nodes". This is a convenient way to try out Pinniped on a local
which uses Docker containers as the cluster's nodes. This is a convenient way to try out Pinniped on a local
non-production cluster.
The following steps will deploy the latest release of Pinniped on kind using the local-user-authenticator component
The following steps deploy the latest release of Pinniped on kind using the local-user-authenticator component
as the authenticator.
1. Install the tools required for the following steps.
- [Install kind](https://kind.sigs.k8s.io/docs/user/quick-start/), if not already installed. e.g. `brew install kind` on MacOS.
- [Install kind](https://kind.sigs.k8s.io/docs/user/quick-start/), if not already installed. For example, `brew install kind` on macOS.
- kind depends on Docker. If not already installed, [install Docker](https://docs.docker.com/get-docker/), e.g. `brew cask install docker` on MacOS.
- kind depends on Docker. If not already installed, [install Docker](https://docs.docker.com/get-docker/), for example `brew cask install docker` on macOS.
- This demo requires `kubectl`, which comes with Docker, or can be [installed separately](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
- This demo requires a tool capable of generating a `bcrypt` hash in order to interact with
- This demo requires a tool capable of generating a `bcrypt` hash to interact with
the webhook. The example below uses `htpasswd`, which is installed on most macOS systems, and can be
installed on some Linux systems via the `apache2-utils` package (e.g., `apt-get install
installed on some Linux systems via the `apache2-utils` package (for example, `apt-get install
apache2-utils`).
1. Create a new Kubernetes cluster using `kind create cluster`. Optionally provide a cluster name using the `--name` flag.
kind will automatically update your kubeconfig to point to the new cluster as a user with admin-like permissions.
kind automatically updates your kubeconfig to point to the new cluster as a user with administrator-like permissions.
1. Deploy the local-user-authenticator app. This is a demo authenticator. In production, you would configure
an authenticator that works with your real identity provider, and therefore would not need to deploy or configure local-user-authenticator.
```bash
```sh
kubectl apply -f https://get.pinniped.dev/latest/install-local-user-authenticator.yaml
```
@ -70,11 +79,11 @@ as the authenticator.
see [deploy/local-user-authenticator/README.md](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/local-user-authenticator/README.md)
for instructions on how to deploy using `ytt`.
If you prefer to install a specific version, replace `latest` in the above URL with the version number such as `v0.4.1`.
If you prefer to install a specific version, replace `latest` in the URL with the version number such as `v0.4.1`.
1. Create a test user named `pinny-the-seal` in the local-user-authenticator namespace.
```bash
```sh
kubectl create secret generic pinny-the-seal \
--namespace local-user-authenticator \
--from-literal=groups=group1,group2 \
@ -83,7 +92,7 @@ as the authenticator.
1. Fetch the auto-generated CA bundle for the local-user-authenticator's HTTP TLS endpoint.
```bash
```sh
kubectl get secret local-user-authenticator-tls-serving-certificate --namespace local-user-authenticator \
-o jsonpath={.data.caCertificate} \
| tee /tmp/local-user-authenticator-ca-base64-encoded
@ -91,12 +100,12 @@ as the authenticator.
1. Deploy the Pinniped Concierge.
```bash
```sh
kubectl apply -f https://get.pinniped.dev/latest/install-pinniped-concierge.yaml
```
The `install-pinniped-concierge.yaml` file includes the default deployment options.
If you would prefer to customize the available options, please see [deploy/concierge/README.md](https://github.com/vmware-tanzu/pinniped/blob/main/deploy/concierge/README.md)
If you would prefer to customize the available options, please see the [Concierge installation guide]({{< ref "../howto/install-concierge" >}})
for instructions on how to deploy using `ytt`.
1. Create a `WebhookAuthenticator` object to configure the Pinniped Concierge to authenticate using local-user-authenticator.
@ -114,61 +123,63 @@ as the authenticator.
EOF
```
1. Download the latest version of the Pinniped CLI binary for your platform
from Pinniped's [latest release](https://github.com/vmware-tanzu/pinniped/releases/latest).
1. Download the latest version of the Pinniped command-line tool for your platform.
On macOS or Linux, you can do this using Homebrew:
1. Move the Pinniped CLI binary to your preferred filename and directory. Add the executable bit,
e.g. `chmod +x /usr/local/bin/pinniped`.
1. Generate a kubeconfig for the current cluster. Use `--static-token` to include a token which should
allow you to authenticate as the user that you created above.
```bash
pinniped get kubeconfig --static-token "pinny-the-seal:password123" --concierge-authenticator-type webhook --concierge-authenticator-name local-user-authenticator > /tmp/pinniped-kubeconfig
```sh
brew install vmware-tanzu/pinniped/pinniped-cli
```
If you are using MacOS, you may get an error dialog that says
`“pinniped” cannot be opened because the developer cannot be verified`. Cancel this dialog, open System Preferences,
click on Security & Privacy, and click the Allow Anyway button next to the Pinniped message.
Run the above command again and another dialog will appear saying
`macOS cannot verify the developer of “pinniped”. Are you sure you want to open it?`.
Click Open to allow the command to proceed.
On other platforms, see the [command-line installation guide]({{< ref "../howto/install-cli" >}}) for more details.
1. Generate a kubeconfig for the current cluster. Use `--static-token` to include a token which should
allow you to authenticate as the user that you created previously.
```sh
pinniped get kubeconfig \
--static-token "pinny-the-seal:password123" \
--concierge-authenticator-type webhook \
--concierge-authenticator-name local-user-authenticator \
> /tmp/pinniped-kubeconfig
```
1. Try using the generated kubeconfig to issue arbitrary `kubectl` commands as
the `pinny-the-seal` user.
```bash
kubectl --kubeconfig /tmp/pinniped-kubeconfig get pods -n pinniped-concierge
```sh
kubectl --kubeconfig /tmp/pinniped-kubeconfig \
get pods -n pinniped-concierge
```
Because this user has no RBAC permissions on this cluster, the previous command
results in the error `Error from server (Forbidden): pods is forbidden: User "pinny-the-seal" cannot list resource "pods" in API group "" in the namespace "pinniped"`.
results in the error `Error from server (Forbidden): pods is forbidden: User "pinny-the-seal" cannot list resource "pods" in API group "" in the namespace "pinniped-concierge"`.
However, this does prove that you are authenticated and acting as the `pinny-the-seal` user.
1. As the admin user, create RBAC rules for the test user to give them permissions to perform actions on the cluster.
1. As the administrator user, create RBAC rules for the test user to give them permissions to perform actions on the cluster.
For example, grant the test user permission to view all cluster resources.
```bash
kubectl create clusterrolebinding pinny-can-read --clusterrole view --user pinny-the-seal
```sh
kubectl create clusterrolebinding pinny-can-read \
--clusterrole view \
--user pinny-the-seal
```
1. Use the generated kubeconfig to issue arbitrary `kubectl` commands as the `pinny-the-seal` user.
```bash
kubectl --kubeconfig /tmp/pinniped-kubeconfig get pods -n pinniped-concierge
```sh
kubectl --kubeconfig /tmp/pinniped-kubeconfig \
get pods -n pinniped-concierge
```
The user has permission to list pods, so the command succeeds this time.
Pinniped has provided authentication into the cluster for your `kubectl` command! 🎉
Pinniped has provided authentication into the cluster for your `kubectl` command. 🎉
1. Carry on issuing as many `kubectl` commands as you'd like as the `pinny-the-seal` user.
Each invocation will use Pinniped for authentication.
Each invocation uses Pinniped for authentication.
You may find it convenient to set the `KUBECONFIG` environment variable rather than passing `--kubeconfig` to each invocation.
```bash
```sh
export KUBECONFIG=/tmp/pinniped-kubeconfig
kubectl get namespaces
kubectl get pods -A
```
1. Profit! 💰

View File

@ -5,7 +5,7 @@ date: 2020-11-12
author: Pablo Schuhmacher
image: /img/logo.svg
excerpt: "Pinniped intends to bring that dream state — log in once and youre done — to reality."
tags: ['Pablo Schuhmacher']
tags: ['Pablo Schuhmacher', 'release']
---
Kubernetes, containers, microservices: Theyve all turned conventional application development wisdom inside out. But for all the wonders introduced and new technologies released, there are still a few things that remain difficult, cumbersome, or just really really frustrating when it comes to Kubernetes. We have set out to make one of those things easier and more understandable: authentication.

View File

@ -87,7 +87,7 @@ The default behavior of Pinniped remains unchanged, and we made sure to implemen
### Advantages and Disadvantages
With v0.5.0, each instance of Pinniped to be upgraded and operated 100% independently, with no coordination or shared state needed.
With v0.5.0, each instance of Pinniped can be upgraded and operated 100% independently, with no coordination or shared state needed.
One remaining constraint is that each instance should be deployed into its own namespace.
This ensures that any other standard Kubernetes objects such as Secrets and ConfigMaps referenced by the configuration do not overlap.

View File

@ -28,3 +28,16 @@ HUGO_VERSION = "0.78.0"
[context.next.environment]
HUGO_ENABLEGITINFO = "true"
[[headers]]
for = "/fonts/*"
[headers.values]
Access-Control-Allow-Origin = "*"
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = "default-src 'self'; img-src *"
X-Content-Type-Options = "nosniff"
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"

View File

@ -1,3 +1,8 @@
[[redirects]]
from = "/"
to = "https://pinniped.dev"
status = 302
force = true
[[redirects]]
from = "/latest/*"

File diff suppressed because one or more lines are too long

View File

@ -97,6 +97,13 @@ button {
&.tertiary {
border: 1px solid $blue;
}
img.button-icon {
margin-left: 5px;
margin-right: 5px;
margin-bottom: -8px;
width: 24px;
height: 24px;
}
}
.buttons {
margin-top: 40px;

View File

@ -273,9 +273,8 @@
list-style-type: unset;
display: list-item;
margin-bottom: 10px;
font-size: 14px;
font-size: 16px;
color: $darkgrey;
line-height: 1.6em;
list-style-image: url(/img/arrow.svg);
}
}
@ -408,9 +407,19 @@
.side-nav {
width: 25%;
float: left;
@include breakpoint(small-medium) {
width: 100%;
float: none;
}
ul {
padding-left: 0px;
margin-bottom: 35px;
ul {
padding-left: 15px;
margin-top: 10px;
margin-bottom: 15px;
}
li {
display: list-item;
margin-bottom: 15px;
@ -431,8 +440,12 @@
.docs-content {
width: 75%;
float: right;
@include breakpoint(small-medium) {
width: 100%;
float: none;
}
a {
font-size: 14px;
font-size: 16px;
}
ul {
list-style-type: disc;
@ -486,10 +499,37 @@
border: 15px solid #EFEFEF;
padding: 15px;
margin-bottom: 30px;
font-size: 14px;
}
}
img {
max-width: 100%;
}
strong {
font-family: $metropolis-medium;
}
}
.danger {
.danger-icon {
float: left;
padding: 40px;
width: 24px;
height: 24px;
}
padding: 10px;
font-family: $metropolis-light-italic;
}
.button {
white-space: nowrap;
a {
font-size: 14px;
}
}
table {
td {
padding: 10px 30px;
}
}
}

View File

@ -19,7 +19,6 @@
<body>
{{ partial "header" . }}
{{ block "main" . }}{{ end }}
{{ partial "getting-started" . }}
{{ partial "footer" . }}
</body>
</html>

View File

@ -7,8 +7,10 @@
</div>
<div class="wrapper docs clearfix">
{{ partial "docs-sidebar.html" . }}
<div class="docs-content">
{{- with .Title -}}
<h1>{{.}}</h1>
{{- end -}}
{{ .Content }}
</div>
</div>

View File

@ -2,7 +2,7 @@
<main>
<div class="hero subpage">
<div class="wrapper">
<h2>Pinniped Blog</h2>
<h2>Pinniped blog</h2>
</div>
</div>
<div class="wrapper blog landing">
@ -14,4 +14,5 @@
{{ partial "pagination.html" . }}
</div>
</main>
{{ partial "getting-started" . }}
{{ end }}

View File

@ -2,6 +2,7 @@
<main>
{{ .Content }}
</main>
{{ partial "getting-started" . }}
{{ end }}

View File

@ -3,7 +3,7 @@
<article>
<div class="hero subpage">
<div class="wrapper">
<h1>Pinniped Blog</h1>
<h1>Pinniped blog</h1>
</div>
</div>
<div class="wrapper blog">
@ -15,18 +15,19 @@
<p class="date">{{ dateFormat "Jan 2, 2006" .Date }}</p>
{{ .Content }}
</div>
<h2>Related Content</h2>
<div class="grid three">
{{ $related := (where (.Site.RegularPages.Related .) "Type" "posts") | first 3 }}
{{ with $related }}
{{ $related := (where (.Site.RegularPages.Related .) "Type" "posts") | first 3 }}
{{ with $related }}
<h2>Related content</h2>
<div class="grid three">
{{ range . }}
{{ partial "blog-post-card.html" . }}
{{ end }}
{{ end }}
</div>
</div>
{{ end }}
</div>
</article>
</main>
{{ partial "getting-started" . }}
{{ end }}

View File

@ -13,4 +13,5 @@
</div>
</div>
</main>
{{ partial "getting-started" . }}
{{ end }}

View File

@ -6,7 +6,7 @@
<div class="wrapper grid two">
<div class="col">
<p class="strong">Introduction to Pinniped</p>
<p><a href="https://pinniped.dev/docs/demo/">Learn how Pinniped</a> provides identity services to Kubernetes</p>
<p><a href="https://pinniped.dev/docs/">Learn how Pinniped</a> provides identity services to Kubernetes</p>
</div>
<div class="col">
<p class="strong">How do you use Pinniped?</p>
@ -17,4 +17,5 @@
{{ partial "use-cases.html" . }}
{{ partial "team.html" . }}
</main>
{{ partial "getting-started" . }}
{{ end }}

View File

@ -4,6 +4,7 @@
</div>
<div class="content">
<h3><a href="{{ .RelPermalink }}">{{ .Title }}</a></h3>
<time>{{ .Date.Format "January 2, 2006" }}</time>
<p>{{ .Params.Excerpt }}</p>
</div>
</div>

View File

@ -1,8 +1,17 @@
<div class="side-nav">
<ul>
{{ $currentPage := . }}
{{ range .Site.Menus.docs }}
<li><a href="{{ .URL }}" {{ if (eq $currentPage.RelPermalink .URL) }}class="active"{{ end }}>{{ .Name }}</a></li>
{{ end }}
{{- $currentPage := . }}
{{- range .Site.Menus.docs }}
<li>
<a href="{{ .URL }}" class="{{ cond ($currentPage.IsMenuCurrent "docs" .) "active" "" }}">{{ .Name }}</a>
{{- if .HasChildren }}
<ul class="sub-menu">
{{- range .Children }}
<li><a href="{{ .URL }}"{{ if $currentPage.IsMenuCurrent "docs" . }} class="active"{{ end }} >{{ .Name }}</a></li>
{{- end }}
</ul>
{{- end }}
</li>
{{- end }}
</ul>
</div>

View File

@ -2,10 +2,10 @@
<div class="wrapper clearfix">
<div class="left-side">
<h2>Getting started</h2>
<p>To help you get started, see the documentation.</p>
<p>Learn how Pinniped works, see how to use it on your clusters, and dive into internals of Pinniped's APIs and architecture.</p>
</div>
<div class="right-side">
<a href="/docs/" class="button">Get started</a>
<a href="/docs/" class="button">Read the docs</a>
</div>
</div>
</div>

View File

@ -7,7 +7,7 @@
<li><a href="/blog/" {{ if or (eq .Page.Section "posts") (eq .Page.Section "tags") }}class="active"{{ end }}>Blog</a></li>
<li><a href="/docs/" {{ if (eq .Page.Section "docs") }}class="active"{{ end }}>Docs</a></li>
</ul>
<button type="button" class="mobile" onclick="mobileNavToggle()">
<button type="button" class="mobile" id="mobile-menu-button">
<img class="collapsed-icon" src="/img/hamburger.svg" alt="Mobile nav icon">
<img class="expanded-icon" src="/img/close.svg" alt="Mobile nav icon">
</button>

View File

@ -1,10 +1,10 @@
<div class="hero homepage">
<div class="wrapper">
<div class="text-block">
<h2>Pinniped - Simplify user authentication for any Kubernetes cluster: log in once and youre done.</h2>
<p>Pinniped delivers a consistent Kubernetes user authentication experience while prioritizing security, interoperability and low-effort management at scale.</p>
<h2>Batteries-included for Kubernetes authentication</h2>
<p>Pinniped is the easy, secure way to log in to your Kubernetes clusters.</p>
<div class="buttons">
<a class="button" href="https://github.com/vmware-tanzu/pinniped/blob/main/README.md">Get Started with Pinniped</a>
<a class="button" href="/docs/">Get Started with Pinniped</a>
<a class="button secondary" href="https://github.com/vmware-tanzu/pinniped/releases">Download Latest Release</a>
</div>
</div>

View File

@ -4,17 +4,17 @@
<div class="card">
<img src="/img/simple.svg" />
<h3>Simple</h3>
<p>Install and integrate with nearly any cluster in one step</p>
<p>Easily install on almost any Kubernetes cluster</p>
</div>
<div class="card">
<img src="/img/frictionless.svg" />
<h3>Frictionless</h3>
<p>Log in once to safely access many clusters</p>
<p>Use native command-line tools like kubectl</p>
</div>
<div class="card">
<img src="/img/seamless.svg" />
<h3>Seamless</h3>
<p>Leverage first class integration with Kubernetes and kubectl CLI</p>
<p>Log in once to safely access all your clusters</p>
</div>
</div>
</div>

View File

@ -2,13 +2,6 @@
<div class="wrapper">
<h2>The Pinniped Project Team:</h2>
<div class="grid three">
<div class="bio">
<div class="image"><img src="/img/matt-moyer.png" /></div>
<div class="info">
<p class="name">Matt Moyer</p>
<p class="position">Engineer</p>
</div>
</div>
<div class="bio">
<div class="image"><img src="/img/andrew-keesler.png" /></div>
<div class="info">
@ -17,9 +10,16 @@
</div>
</div>
<div class="bio">
<div class="image"><img src="/img/ryan-richard.png" /></div>
<div class="image"><img src="/img/margo-crawford.png" /></div>
<div class="info">
<p class="name">Ryan Richard</p>
<p class="name">Margo Crawford</p>
<p class="position">Engineer</p>
</div>
</div>
<div class="bio">
<div class="image"><img src="/img/matt-moyer.png" /></div>
<div class="info">
<p class="name">Matt Moyer</p>
<p class="position">Engineer</p>
</div>
</div>
@ -30,6 +30,13 @@
<p class="position">Engineer</p>
</div>
</div>
<div class="bio">
<div class="image"><img src="/img/nanci-lancaster.png" /></div>
<div class="info">
<p class="name">Nanci Lancaster</p>
<p class="position">Community Manager</p>
</div>
</div>
<div class="bio">
<div class="image"><img src="/img/pablo-schuhmacher.png" /></div>
<div class="info">
@ -37,8 +44,15 @@
<p class="position">Product Manager</p>
</div>
</div>
<div class="bio">
<div class="image"><img src="/img/ryan-richard.png" /></div>
<div class="info">
<p class="name">Ryan Richard</p>
<p class="position">Engineer</p>
</div>
</div>
</div>
<h3>Contributing:</h3>
<p>The Pinniped project team welcomes contributions from the community, please see our <a href="https://github.com/vmware-tanzu/pinniped/blob/main/CONTRIBUTING.md">contributors guide</a> for more information.</p>
<p>The Pinniped project team welcomes contributions from the community, please see the <a href="https://github.com/vmware-tanzu/pinniped/blob/main/CONTRIBUTING.md">contributors guide</a> for more information.</p>
</div>
</div>

View File

@ -1,18 +1,18 @@
<div class="wrapper use-cases">
<h2>Use Cases</h2>
<h2>Use cases</h2>
<div class="grid two">
<div class="col image">
<img src="/img/administration.svg" />
</div>
<div class="col text">
<p class="strong">Cluster Administration</p>
<p>Easily plug in external IDPs into Kubernetes clusters while offering a simple install and configuration experience. Leverage first class integration with Kubernetes and kubectl CLI.</p>
<p class="strong">Cluster administration</p>
<p>Easily plug in external identity providers into Kubernetes clusters while offering a simple install and configuration experience. Leverage first class integration with Kubernetes and kubectl command-line.</p>
<!-- <p><a href="#" class="button tertiary">Read More</a></p> -->
</div>
</div>
<div class="grid two image-right">
<div class="col text">
<p class="strong">Seamless Authentication</p>
<p class="strong">Seamless authentication</p>
<p>Give users a consistent, unified login experience across all your clusters, including on-premises and managed cloud environments.</p>
<!-- <p><a href="#" class="button tertiary">Read More</a></p> -->
</div>
@ -25,8 +25,8 @@
<img src="/img/security.svg" />
</div>
<div class="col text">
<p class="strong">Security for Enterprises & Teams Alike</p>
<p>Securely integrate with an enterprise IDP using standard protocols or use secure, externally-managed identities instead of relying on simple, shared credentials.</p>
<p class="strong">Security for enterprises & teams alike</p>
<p>Securely integrate with an enterprise IDP using standard protocols or use secure, externally managed identities instead of relying on simple, shared credentials.</p>
<!-- <p><a href="#" class="button tertiary">Read More</a></p> -->
</div>
</div>

View File

@ -0,0 +1 @@
<img class="button-icon" src="/img/{{.Get 0 }}" />

View File

@ -0,0 +1,2 @@
{{- $href := .Get "href" -}}
<div class="button"><a href="{{ $href }}" class="button secondary">{{.Inner}}</a></div>

View File

@ -0,0 +1,4 @@
<div class="danger">
<img class="danger-icon" src="/img/alert-circle-outline.svg" />
<p>{{ .Inner | markdownify }}</p>
</div>

View File

@ -0,0 +1,15 @@
{{- $subsection := .Get 0 -}}
<ul>
{{- range .Site.Menus.docs -}}
{{- range .Children }}
{{- if eq $subsection .Parent -}}
<li>
<a href="{{ .URL }}">{{- .Page.Title -}}</a>
{{- with .Page.Description }}
<p>{{ . | markdownify }}</p>
{{- end -}}
</li>
{{- end -}}
{{- end -}}
{{- end }}
</ul>

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M11,15H13V17H11V15M11,7H13V13H11V7M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20Z" /></svg>

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -4,3 +4,6 @@ function mobileNavToggle() {
var menu = document.getElementById("mobile-menu").parentElement;
menu.classList.toggle('mobile-menu-visible');
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('mobile-menu-button').addEventListener('click', mobileNavToggle);
});