Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dex
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
dex
Commits
14648137
Commit
14648137
authored
Sep 13, 2017
by
rithu john
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[WIP]: add CRD support
parent
38d0de20
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
342 additions
and
6 deletions
+342
-6
client.go
storage/kubernetes/client.go
+8
-2
crd_extensions.go
storage/kubernetes/k8sapi/crd_extensions.go
+138
-0
storage.go
storage/kubernetes/storage.go
+64
-4
types.go
storage/kubernetes/types.go
+132
-0
No files found.
storage/kubernetes/client.go
View file @
14648137
...
...
@@ -249,7 +249,7 @@ func (c *client) put(resource, name string, v interface{}) error {
return
checkHTTPErr
(
resp
,
http
.
StatusOK
)
}
func
newClient
(
cluster
k8sapi
.
Cluster
,
user
k8sapi
.
AuthInfo
,
namespace
string
,
logger
logrus
.
FieldLogger
)
(
*
client
,
error
)
{
func
newClient
(
cluster
k8sapi
.
Cluster
,
user
k8sapi
.
AuthInfo
,
namespace
string
,
logger
logrus
.
FieldLogger
,
apiVersion
string
)
(
*
client
,
error
)
{
tlsConfig
:=
cryptopasta
.
DefaultTLSConfig
()
data
:=
func
(
b
string
,
file
string
)
([]
byte
,
error
)
{
if
b
!=
""
{
...
...
@@ -325,13 +325,19 @@ func newClient(cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string, l
}
}
// if the apiVersion is not configured default to `oidc.coreos.com/v1`
if
apiVersion
==
""
{
apiVersion
=
"oidc.coreos.com/v1"
}
logger
.
Infof
(
"kubernetes client apiVersion = %s"
,
apiVersion
)
// TODO(ericchiang): make API Group and version configurable.
return
&
client
{
client
:
&
http
.
Client
{
Transport
:
t
},
baseURL
:
cluster
.
Server
,
hash
:
func
()
hash
.
Hash
{
return
fnv
.
New64
()
},
namespace
:
namespace
,
apiVersion
:
"oidc.coreos.com/v1"
,
apiVersion
:
apiVersion
,
logger
:
logger
,
},
nil
}
...
...
storage/kubernetes/k8sapi/crd_extensions.go
0 → 100644
View file @
14648137
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
k8sapi
// CustomResourceDefinitionSpec describes how a user wants their resource to appear
type
CustomResourceDefinitionSpec
struct
{
// Group is the group this resource belongs in
Group
string
`json:"group" protobuf:"bytes,1,opt,name=group"`
// Version is the version this resource belongs in
Version
string
`json:"version" protobuf:"bytes,2,opt,name=version"`
// Names are the names used to describe this custom resource
Names
CustomResourceDefinitionNames
`json:"names" protobuf:"bytes,3,opt,name=names"`
// Scope indicates whether this resource is cluster or namespace scoped. Default is namespaced
Scope
ResourceScope
`json:"scope" protobuf:"bytes,4,opt,name=scope,casttype=ResourceScope"`
}
// CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition
type
CustomResourceDefinitionNames
struct
{
// Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration
// too: plural.group and it must be all lowercase.
Plural
string
`json:"plural" protobuf:"bytes,1,opt,name=plural"`
// Singular is the singular name of the resource. It must be all lowercase Defaults to lowercased <kind>
Singular
string
`json:"singular,omitempty" protobuf:"bytes,2,opt,name=singular"`
// ShortNames are short names for the resource. It must be all lowercase.
ShortNames
[]
string
`json:"shortNames,omitempty" protobuf:"bytes,3,opt,name=shortNames"`
// Kind is the serialized kind of the resource. It is normally CamelCase and singular.
Kind
string
`json:"kind" protobuf:"bytes,4,opt,name=kind"`
// ListKind is the serialized kind of the list for this resource. Defaults to <kind>List.
ListKind
string
`json:"listKind,omitempty" protobuf:"bytes,5,opt,name=listKind"`
}
// ResourceScope is an enum defining the different scopes availabe to a custom resource
type
ResourceScope
string
const
(
ClusterScoped
ResourceScope
=
"Cluster"
NamespaceScoped
ResourceScope
=
"Namespaced"
)
type
ConditionStatus
string
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
// can't decide if a resource is in the condition or not. In the future, we could add other
// intermediate conditions, e.g. ConditionDegraded.
const
(
ConditionTrue
ConditionStatus
=
"True"
ConditionFalse
ConditionStatus
=
"False"
ConditionUnknown
ConditionStatus
=
"Unknown"
)
// CustomResourceDefinitionConditionType is a valid value for CustomResourceDefinitionCondition.Type
type
CustomResourceDefinitionConditionType
string
const
(
// Established means that the resource has become active. A resource is established when all names are
// accepted without a conflict for the first time. A resource stays established until deleted, even during
// a later NamesAccepted due to changed names. Note that not all names can be changed.
Established
CustomResourceDefinitionConditionType
=
"Established"
// NamesAccepted means the names chosen for this CustomResourceDefinition do not conflict with others in
// the group and are therefore accepted.
NamesAccepted
CustomResourceDefinitionConditionType
=
"NamesAccepted"
// Terminating means that the CustomResourceDefinition has been deleted and is cleaning up.
Terminating
CustomResourceDefinitionConditionType
=
"Terminating"
)
// CustomResourceDefinitionCondition contains details for the current condition of this pod.
type
CustomResourceDefinitionCondition
struct
{
// Type is the type of the condition.
Type
CustomResourceDefinitionConditionType
`json:"type" protobuf:"bytes,1,opt,name=type,casttype=CustomResourceDefinitionConditionType"`
// Status is the status of the condition.
// Can be True, False, Unknown.
Status
ConditionStatus
`json:"status" protobuf:"bytes,2,opt,name=status,casttype=ConditionStatus"`
// Last time the condition transitioned from one status to another.
// +optional
LastTransitionTime
Time
`json:"lastTransitionTime,omitempty" protobuf:"bytes,3,opt,name=lastTransitionTime"`
// Unique, one-word, CamelCase reason for the condition's last transition.
// +optional
Reason
string
`json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"`
// Human-readable message indicating details about last transition.
// +optional
Message
string
`json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
}
// CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition
type
CustomResourceDefinitionStatus
struct
{
// Conditions indicate state for particular aspects of a CustomResourceDefinition
Conditions
[]
CustomResourceDefinitionCondition
`json:"conditions" protobuf:"bytes,1,opt,name=conditions"`
// AcceptedNames are the names that are actually being used to serve discovery
// They may be different than the names in spec.
AcceptedNames
CustomResourceDefinitionNames
`json:"acceptedNames" protobuf:"bytes,2,opt,name=acceptedNames"`
}
// CustomResourceCleanupFinalizer is the name of the finalizer which will delete instances of
// a CustomResourceDefinition
const
CustomResourceCleanupFinalizer
=
"customresourcecleanup.apiextensions.k8s.io"
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format
// <.spec.name>.<.spec.group>.
type
CustomResourceDefinition
struct
{
TypeMeta
`json:",inline"`
ObjectMeta
`json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec describes how the user wants the resources to appear
Spec
CustomResourceDefinitionSpec
`json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Status indicates the actual state of the CustomResourceDefinition
Status
CustomResourceDefinitionStatus
`json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CustomResourceDefinitionList is a list of CustomResourceDefinition objects.
type
CustomResourceDefinitionList
struct
{
TypeMeta
`json:",inline"`
ListMeta
`json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Items individual CustomResourceDefinitions
Items
[]
CustomResourceDefinition
`json:"items" protobuf:"bytes,2,rep,name=items"`
}
storage/kubernetes/storage.go
View file @
14648137
...
...
@@ -38,6 +38,8 @@ const (
type
Config
struct
{
InCluster
bool
`json:"inCluster"`
KubeConfigFile
string
`json:"kubeConfigFile"`
APIVersion
string
`json:"apiVersion"`
// API Group and version
UseCRD
bool
`json:"useCRD"`
// Flag option to use CRDs instead of TPRs
}
// Open returns a storage using Kubernetes third party resource.
...
...
@@ -52,9 +54,9 @@ func (c *Config) Open(logger logrus.FieldLogger) (storage.Storage, error) {
// open returns a kubernetes client, initializing the third party resources used
// by dex.
//
// errOn
TPR
s controls if errors creating the resources cause this method to return
// errOn
Resource
s controls if errors creating the resources cause this method to return
// immediately (used during testing), or if the client will asynchronously retry.
func
(
c
*
Config
)
open
(
logger
logrus
.
FieldLogger
,
errOn
TPR
s
bool
)
(
*
client
,
error
)
{
func
(
c
*
Config
)
open
(
logger
logrus
.
FieldLogger
,
errOn
Resource
s
bool
)
(
*
client
,
error
)
{
if
c
.
InCluster
&&
(
c
.
KubeConfigFile
!=
""
)
{
return
nil
,
errors
.
New
(
"cannot specify both 'inCluster' and 'kubeConfigFile'"
)
}
...
...
@@ -77,15 +79,46 @@ func (c *Config) open(logger logrus.FieldLogger, errOnTPRs bool) (*client, error
return
nil
,
err
}
cli
,
err
:=
newClient
(
cluster
,
user
,
namespace
,
logger
)
cli
,
err
:=
newClient
(
cluster
,
user
,
namespace
,
logger
,
c
.
APIVersion
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"create client: %v"
,
err
)
}
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
if
c
.
UseCRD
{
if
!
cli
.
createCustomResourceDefinitions
()
{
if
errOnResources
{
cancel
()
return
nil
,
fmt
.
Errorf
(
"failed creating custom resource definitions"
)
}
}
// Try to synchronously create the custom resource definitions once. This doesn't mean
// they'll immediately be available, but ensures that the client will actually try
// once.
logger
.
Errorf
(
"failed creating custom resource definitions: %v"
,
err
)
go
func
()
{
for
{
if
cli
.
createCustomResourceDefinitions
()
{
return
}
select
{
case
<-
ctx
.
Done
()
:
return
case
<-
time
.
After
(
30
*
time
.
Second
)
:
}
}
}()
// If the client is closed, stop trying to create third party resources.
cli
.
cancel
=
cancel
return
cli
,
nil
}
if
!
cli
.
createThirdPartyResources
()
{
if
errOn
TPR
s
{
if
errOn
Resource
s
{
cancel
()
return
nil
,
fmt
.
Errorf
(
"failed creating third party resources"
)
}
...
...
@@ -144,6 +177,33 @@ func (cli *client) createThirdPartyResources() (ok bool) {
return
ok
}
// createCustomResourceDefinitions attempts to create the custom resource definitions(CRDs)
// required by dex. If the CRDs exist, this information is logged. It logs all errors,
// returning true if the CRDs were created successfully.
//
// TODO: Provide an option to wait for the CRDs to actually be available.
func
(
cli
*
client
)
createCustomResourceDefinitions
()
(
ok
bool
)
{
ok
=
true
for
_
,
r
:=
range
customResourceDefinitions
{
err
:=
cli
.
postResource
(
"apiextensions.k8s.io/v1beta1"
,
""
,
"customresourcedefinition"
,
r
)
if
err
!=
nil
{
switch
err
{
case
storage
.
ErrAlreadyExists
:
cli
.
logger
.
Infof
(
"custom resource definition already created %s"
,
r
.
ObjectMeta
.
Name
)
case
storage
.
ErrNotFound
:
cli
.
logger
.
Errorf
(
"custom resource definition not found, please enable API group apiextensions.k8s.io/v1beta1"
)
ok
=
false
default
:
cli
.
logger
.
Errorf
(
"creating custom resource definition %s: %v"
,
r
.
ObjectMeta
.
Name
,
err
)
ok
=
false
}
continue
}
cli
.
logger
.
Errorf
(
"create custom resource definition %s"
,
r
.
ObjectMeta
.
Name
)
}
return
ok
}
func
(
cli
*
client
)
Close
()
error
{
if
cli
.
cancel
!=
nil
{
cli
.
cancel
()
...
...
storage/kubernetes/types.go
View file @
14648137
...
...
@@ -84,6 +84,138 @@ var thirdPartyResources = []k8sapi.ThirdPartyResource{
},
}
var
crdMeta
=
k8sapi
.
TypeMeta
{
APIVersion
:
"apiextensions.k8s.io/v1beta1"
,
Kind
:
"CustomResourceDefinition"
,
}
const
apiGroup
=
"dex.coreos.com"
// The set of custom resource definitions required by the storage. These are managed by
// the storage so it can migrate itself by creating new resources.
var
customResourceDefinitions
=
[]
k8sapi
.
CustomResourceDefinition
{
{
ObjectMeta
:
k8sapi
.
ObjectMeta
{
Name
:
"authcodes.dex.coreos.com"
,
},
TypeMeta
:
crdMeta
,
Spec
:
k8sapi
.
CustomResourceDefinitionSpec
{
Group
:
apiGroup
,
Version
:
"v1"
,
Names
:
k8sapi
.
CustomResourceDefinitionNames
{
Plural
:
"authcodes"
,
Singular
:
"authcode"
,
Kind
:
"AuthCode"
,
},
},
},
{
ObjectMeta
:
k8sapi
.
ObjectMeta
{
Name
:
"authrequests.dex.coreos.com"
,
},
TypeMeta
:
crdMeta
,
Spec
:
k8sapi
.
CustomResourceDefinitionSpec
{
Group
:
apiGroup
,
Version
:
"v1"
,
Names
:
k8sapi
.
CustomResourceDefinitionNames
{
Plural
:
"authrequests"
,
Singular
:
"authcodrequest"
,
Kind
:
"AuthRequests"
,
},
},
},
{
ObjectMeta
:
k8sapi
.
ObjectMeta
{
Name
:
"oauth2clients.dex.coreos.com"
,
},
TypeMeta
:
crdMeta
,
Spec
:
k8sapi
.
CustomResourceDefinitionSpec
{
Group
:
apiGroup
,
Version
:
"v1"
,
Names
:
k8sapi
.
CustomResourceDefinitionNames
{
Plural
:
"oauth2clients"
,
Singular
:
"oauth2client"
,
Kind
:
"Oauth2Client"
,
},
},
},
{
ObjectMeta
:
k8sapi
.
ObjectMeta
{
Name
:
"signingkeies.dex.coreos.com"
,
},
TypeMeta
:
crdMeta
,
Spec
:
k8sapi
.
CustomResourceDefinitionSpec
{
Group
:
apiGroup
,
Version
:
"v1"
,
Names
:
k8sapi
.
CustomResourceDefinitionNames
{
Plural
:
"signingkeies"
,
Singular
:
"signingkey"
,
Kind
:
"SigningKey"
,
},
},
},
{
ObjectMeta
:
k8sapi
.
ObjectMeta
{
Name
:
"refreshtokens.dex.coreos.com"
,
},
TypeMeta
:
crdMeta
,
Spec
:
k8sapi
.
CustomResourceDefinitionSpec
{
Group
:
apiGroup
,
Version
:
"v1"
,
Names
:
k8sapi
.
CustomResourceDefinitionNames
{
Plural
:
"refreshtokens"
,
Singular
:
"refreshtoken"
,
Kind
:
"RefreshToken"
,
},
},
},
{
ObjectMeta
:
k8sapi
.
ObjectMeta
{
Name
:
"passwords.dex.coreos.com"
,
},
TypeMeta
:
crdMeta
,
Spec
:
k8sapi
.
CustomResourceDefinitionSpec
{
Group
:
apiGroup
,
Version
:
"v1"
,
Names
:
k8sapi
.
CustomResourceDefinitionNames
{
Plural
:
"passwords"
,
Singular
:
"password"
,
Kind
:
"Password"
,
},
},
},
{
ObjectMeta
:
k8sapi
.
ObjectMeta
{
Name
:
"offlinesessionses.dex.coreos.com"
,
},
TypeMeta
:
crdMeta
,
Spec
:
k8sapi
.
CustomResourceDefinitionSpec
{
Group
:
apiGroup
,
Version
:
"v1"
,
Names
:
k8sapi
.
CustomResourceDefinitionNames
{
Plural
:
"offlinesessionses"
,
Singular
:
"offlinesessions"
,
Kind
:
"OfflineSessions"
,
},
},
},
{
ObjectMeta
:
k8sapi
.
ObjectMeta
{
Name
:
"connectors.dex.coreos.com"
,
},
TypeMeta
:
crdMeta
,
Spec
:
k8sapi
.
CustomResourceDefinitionSpec
{
Group
:
apiGroup
,
Version
:
"v1"
,
Names
:
k8sapi
.
CustomResourceDefinitionNames
{
Plural
:
"connectors"
,
Singular
:
"connector"
,
Kind
:
"Connector"
,
},
},
},
}
// There will only ever be a single keys resource. Maintain this by setting a
// common name.
const
keysName
=
"openid-connect-keys"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment