AuthServer
represents the request for an OIDC authorization server. It results in the deployment of an authorization server backed by Redis over mTLS.
An AuthServer
should have labels which allow to uniquely match it amongst others. ClientRegistration
selects an AuthServer
by label selector and needs a unique match to be successful.
To allow ClientRegistrations
from all or a restricted set of Namespaces, the annotation sso.apps.tanzu.vmware.com/allow-client-namespaces
must be set. Its value is a comma-separated list of allowed Namespaces, e.g. "app-team-red,app-team-green"
, or "*"
if it should allow clients from all namespaces. If the annotation is missing, no clients are allowed.
An AuthServer
has a spec.issuerURI
which is the entry point for clients and end-users. A form of Ingress needs to be configured for this issuer URI.
Token signature keys are configured through spec.tokenSignature
. If no keys are configured, no tokens can be minted.
Identity providers are configured under spec.identityProviders
. If there are none, end-users won’t be able to log in.
The deployment can be further customized by configuring replicas, resources, http server and logging properties.
An AuthServer
reconciles into the following resources in its namespace:
AuthServer/my-authserver
├─Certificate/my-authserver-redis-client
├─Certificate/my-authserver-redis-server
├─Certificate/my-authserver-root
├─ConfigMap/my-authserver-ca-cert
├─Deployment/my-authserver-auth-server
├─Deployment/my-authserver-redis
├─Issuer/my-authserver-bootstrap
├─Issuer/my-authserver-root
├─Role/my-authserver-auth-server
├─RoleBinding/my-authserver-auth-server
├─Secret/my-authserver-auth-server-clients
├─Secret/my-authserver-auth-server-keys
├─Secret/my-authserver-auth-server-properties
├─Secret/my-authserver-redis-client-cert-keystore-password
├─Secret/my-authserver-registry-credentials
├─Service/my-authserver-redis
└─ServiceAccount/my-authserver-auth-server
apiVersion: sso.apps.tanzu.vmware.com/v1alpha1
kind: AuthServer
metadata:
name: ""
namespace: ""
labels: { } # required, must uniquely identify this AuthServer
annotations:
sso.apps.tanzu.vmware.com/allow-client-namespaces: "" # required, must be "*" or a comma-separated list of allowed client namespaces
sso.apps.tanzu.vmware.com/allow-unsafe-issuer-uri: "" # optional
sso.apps.tanzu.vmware.com/allow-unsafe-identity-provider: "" # optional
spec:
issuerURI: "" # required
tokenSignature: # optional
signAndVerifyKeyRef:
name: ""
extraVerifyKeyRefs:
- name: ""
identityProviders: # optional
# each must be one and only one of internalUnsafe, ldap, openID or saml
- name: "" # must be unique
internalUnsafe: # requires annotation `sso.apps.tanzu.vmware.com/allow-unsafe-identity-provider: ""`
users:
- username: ""
password: ""
givenName: ""
familyName: ""
email: ""
emailVerified: false
roles:
- ""
- name: "" # must be unique
ldap:
server:
scheme: ""
host: ""
port: 0
base: ""
bind:
dn: ""
passwordRef:
name: ldap-password
user:
searchFilter: ""
searchBase: ""
group:
searchFilter: ""
searchBase: ""
searchSubTree: false
searchDepth: 0
roleAttribute: ""
- name: "" # must be unique
openID:
issuerURI: ""
clientID: ""
clientSecretRef:
name: ""
scopes:
- ""
- name: "" # must be unique
saml:
metadataURI: ""
claimMappings: { }
replicas: 1 # optional, default 2
logging: "" # optional, must be valid YAML
server: "" # optional, must be valid YAML
resources: # optional, default {requests: {cpu: "256m", memory: "300Mi"}, limits: {cpu: "2", memory: "768Mi"}}
requests:
cpu: ""
mem: ""
limits:
cpu: ""
mem: ""
redisResources: # optional, default {requests: {cpu: "50m", memory: "100Mi"}, limits: {cpu: "100m", memory: "256Mi"}}
requests:
cpu: ""
mem: ""
limits:
cpu: ""
mem: ""
status:
observedGeneration: 0
clientRegistrationCount: 1
tokenSignatureKeyCount: 0
deployments:
authServer:
LastParentGenerationWithRestart: 0
configHash: ""
image: ""
replicas: 0
redis:
image: ""
conditions:
- lastTransitionTime:
message: ""
reason: ""
status: "True" # or "False"
type: ""
Alternatively, you can interactively discover the spec with:
kubectl explain authservers.sso.apps.tanzu.vmware.com
The .status
subresource helps you to learn the AuthServer
’s readiness, resulting deployments, attached clients and to troubleshoot issues.
.status.tokenSignatureKeyCount
is the number of currently configured token signature keys.
.status.clientRegistrationCount
is the number of currently registered clients.
.status.deployments.authServer
describes the current authorization server deployment by listing the running image, its replicas, the hash of the current configuration and the generation which has last resulted in a restart.
.status.deployments.redis
describes the current Redis deployment by listing its running image.
.status.conditions
documents each step in the reconciliation:
Valid
: Is the spec valid?ImagePullSecretApplied
: Has the image pull secret been applied?SignAndVerifyKeyResolved
: Has the single sign-and-verify key been resolved?ExtraVerifyKeysResolved
: Have the single extra verify keys been resolved?IdentityProvidersResolved
: Has all identity provider configuration been resolved?ConfigResolved
: Has the complete configuration for the authorization server been resolved?AuthServerConfigured
: Has the complete configuration for the authorization server been applied?IssuerURIReady
: Is the authorization server yet responding to {spec.issuerURI}/.well-known/openid-configuration
?Ready
: whether all the previous conditions are “True”The super condition Ready
denotes a fully successful reconciliation of a given ClientRegistration
.
If everything goes well you will see something like this:
status:
observedGeneration: 1
tokenSignatureKeyCount: 3
clientRegistrationCount: 1
deployments:
authServer:
LastParentGenerationWithRestart: 1
configHash: "13146309071473757471"
image: dev.registry.tanzu.vmware.com/sso-for-kubernetes/authserver@sha256:9c761dd21bdd54cf8bf0de3cb23e04d75dcdedbbeee82bb78f6d3419c1c748ea
replicas: 1
redis:
image: dev.registry.tanzu.vmware.com/sso-for-kubernetes/redis@sha256:3906dfa3d49b340ffc85c05890ddca7e5a9c775344c9b9d3bacda9bb6efac191
conditions:
- lastTransitionTime: "2022-05-13T08:29:55Z"
message: ""
reason: KeysConfigSecretUpdated
status: "True"
type: AuthServerConfigured
- lastTransitionTime: "2022-05-13T08:29:54Z"
message: ""
reason: Resolved
status: "True"
type: ConfigResolved
- lastTransitionTime: "2022-05-13T08:29:54Z"
message: ""
reason: ExtraVerifyKeysResolved
status: "True"
type: ExtraVerifyKeysResolved
- lastTransitionTime: "2022-05-13T08:29:54Z"
message: ""
reason: Resolved
status: "True"
type: IdentityProvidersResolved
- lastTransitionTime: "2022-05-13T08:29:54Z"
message: ""
reason: ImagePullSecretApplied
status: "True"
type: ImagePullSecretApplied
- lastTransitionTime: "2022-05-13T09:04:22Z"
message: ""
reason: Ready
status: "True"
type: IssuerURIReady
- lastTransitionTime: "2022-05-13T09:04:22Z"
message: ""
reason: Ready
status: "True"
type: Ready
- lastTransitionTime: "2022-05-13T08:29:54Z"
message: ""
reason: SignAndVerifyKeyResolved
status: "True"
type: SignAndVerifyKeyResolved
- lastTransitionTime: "2022-05-13T08:29:54Z"
message: ""
reason: Valid
status: "True"
type: Valid
The ServiceAccount
of the authorization server has a Role
with the following permissions:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
resourceNames:
- { name }-auth-server-keys
- { name }-auth-server-clients
This example requests an authorization server with the issuer URI http://authserver-sample.default
, two token signature keys and two identity providers. It also configures ingress as you would on a local Kind cluster.
---
apiVersion: sso.apps.tanzu.vmware.com/v1alpha1
kind: AuthServer
metadata:
name: authserver-sample
namespace: default
labels:
name: authserver-sample
sample: "true"
annotations:
sso.apps.tanzu.vmware.com/allow-client-namespaces: "*"
sso.apps.tanzu.vmware.com/allow-unsafe-identity-provider: ""
sso.apps.tanzu.vmware.com/allow-unsafe-issuer-uri: ""
spec:
replicas: 1
issuerURI: http://authserver-sample.default
tokenSignature:
signAndVerifyKeyRef:
name: sample-token-signing-key
extraVerifyKeyRefs:
- name: sample-token-verification-key
identityProviders:
- name: internal
internalUnsafe:
users:
- username: test-user-1
password: $2a$10$201z9o/tHlocFsHFTo0plukh03ApBYe4dRiXcqeyRQH6CNNtS8jWK #! bcrypt-encoded "password"
roles:
- message.write
- username: test-user-2
password: $2a$10$201z9o/tHlocFsHFTo0plukh03ApBYe4dRiXcqeyRQH6CNNtS8jWK #! bcrypt-encoded "password"
roles:
- message.read
- name: okta
openID:
issuerURI: https://dev-xxxxxx.okta.com
clientID: xxxxxxxxxxxxx
clientSecretRef:
name: okta-client-secret
authorizationUri: https://dev-xxxxxx.okta.com/oauth2/v1/authorize
tokenUri: https://dev-xxxxxx.okta.com/oauth2/v1/token
jwksUri: https://dev-xxxxxx.okta.com/oauth2/v1/keys
scopes:
- openid
claimMappings:
roles: my_custom_okta_roles_claim
---
apiVersion: secretgen.k14s.io/v1alpha1
kind: RSAKey
metadata:
name: sample-token-signing-key
namespace: default
spec:
secretTemplate:
type: Opaque
stringData:
key.pem: $(privateKey)
pub.pem: $(publicKey)
---
apiVersion: secretgen.k14s.io/v1alpha1
kind: RSAKey
metadata:
name: sample-token-verification-key
namespace: default
spec:
secretTemplate:
type: Opaque
stringData:
key.pem: $(privateKey)
pub.pem: $(publicKey)
---
apiVersion: v1
kind: Secret
metadata:
name: okta-client-secret
namespace: default
stringData:
clientSecret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
---
apiVersion: v1
kind: Service
metadata:
name: authserver-sample
namespace: default
spec:
selector:
app.kubernetes.io/part-of: authserver-sample
app.kubernetes.io/component: authorization-server
ports:
- port: 80
targetPort: 8080
---
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: authserver-sample
namespace: default
spec:
virtualhost:
fqdn: authserver-sample.default
routes:
- conditions:
- prefix: /
services:
- name: authserver-sample
port: 80