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
7ff3ce85
Commit
7ff3ce85
authored
Oct 05, 2016
by
Eric Chiang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
*: add password resource to kubernetes storage implementation
parent
ae3b5ef6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
145 additions
and
7 deletions
+145
-7
thirdpartyresources.yaml
examples/k8s/thirdpartyresources.yaml
+9
-0
client.go
storage/kubernetes/client.go
+24
-3
client.go
storage/kubernetes/k8sapi/client.go
+9
-3
storage.go
storage/kubernetes/storage.go
+35
-0
storage_test.go
storage/kubernetes/storage_test.go
+12
-1
types.go
storage/kubernetes/types.go
+56
-0
No files found.
examples/k8s/thirdpartyresources.yaml
View file @
7ff3ce85
...
@@ -46,3 +46,12 @@ kind: ThirdPartyResource
...
@@ -46,3 +46,12 @@ kind: ThirdPartyResource
description
:
"
Refresh
tokens
for
clients
to
continuously
act
on
behalf
of
an
end
user."
description
:
"
Refresh
tokens
for
clients
to
continuously
act
on
behalf
of
an
end
user."
versions
:
versions
:
-
name
:
v1
-
name
:
v1
---
metadata
:
name
:
password.passwords.oidc.coreos.com
apiVersion
:
extensions/v1beta1
kind
:
ThirdPartyResource
description
:
"
Passwords
managed
by
the
OIDC
server."
versions
:
-
name
:
v1
storage/kubernetes/client.go
View file @
7ff3ce85
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"bytes"
"bytes"
"crypto/tls"
"crypto/tls"
"crypto/x509"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/json"
"errors"
"errors"
"fmt"
"fmt"
...
@@ -165,6 +166,26 @@ func (c *client) delete(resource, name string) error {
...
@@ -165,6 +166,26 @@ func (c *client) delete(resource, name string) error {
return
checkHTTPErr
(
resp
,
http
.
StatusOK
)
return
checkHTTPErr
(
resp
,
http
.
StatusOK
)
}
}
func
(
c
*
client
)
deleteAll
(
resource
string
)
error
{
var
list
struct
{
k8sapi
.
TypeMeta
`json:",inline"`
k8sapi
.
ListMeta
`json:"metadata,omitempty"`
Items
[]
struct
{
k8sapi
.
TypeMeta
`json:",inline"`
k8sapi
.
ObjectMeta
`json:"metadata,omitempty"`
}
`json:"items"`
}
if
err
:=
c
.
list
(
resource
,
&
list
);
err
!=
nil
{
return
err
}
for
_
,
item
:=
range
list
.
Items
{
if
err
:=
c
.
delete
(
resource
,
item
.
Name
);
err
!=
nil
{
return
err
}
}
return
nil
}
func
(
c
*
client
)
put
(
resource
,
name
string
,
v
interface
{})
error
{
func
(
c
*
client
)
put
(
resource
,
name
string
,
v
interface
{})
error
{
body
,
err
:=
json
.
Marshal
(
v
)
body
,
err
:=
json
.
Marshal
(
v
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -190,9 +211,9 @@ func (c *client) put(resource, name string, v interface{}) error {
...
@@ -190,9 +211,9 @@ func (c *client) put(resource, name string, v interface{}) error {
func
newClient
(
cluster
k8sapi
.
Cluster
,
user
k8sapi
.
AuthInfo
,
namespace
string
)
(
*
client
,
error
)
{
func
newClient
(
cluster
k8sapi
.
Cluster
,
user
k8sapi
.
AuthInfo
,
namespace
string
)
(
*
client
,
error
)
{
tlsConfig
:=
cryptopasta
.
DefaultTLSConfig
()
tlsConfig
:=
cryptopasta
.
DefaultTLSConfig
()
data
:=
func
(
b
[]
byte
,
file
string
)
([]
byte
,
error
)
{
data
:=
func
(
b
string
,
file
string
)
([]
byte
,
error
)
{
if
b
!=
nil
{
if
b
!=
""
{
return
b
,
nil
return
b
ase64
.
StdEncoding
.
DecodeString
(
b
)
}
}
if
file
==
""
{
if
file
==
""
{
return
nil
,
nil
return
nil
,
nil
...
...
storage/kubernetes/k8sapi/client.go
View file @
7ff3ce85
...
@@ -62,7 +62,9 @@ type Cluster struct {
...
@@ -62,7 +62,9 @@ type Cluster struct {
// CertificateAuthority is the path to a cert file for the certificate authority.
// CertificateAuthority is the path to a cert file for the certificate authority.
CertificateAuthority
string
`yaml:"certificate-authority,omitempty"`
CertificateAuthority
string
`yaml:"certificate-authority,omitempty"`
// CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority
// CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority
CertificateAuthorityData
[]
byte
`yaml:"certificate-authority-data,omitempty"`
//
// NOTE(ericchiang): Our yaml parser doesn't assume []byte is a base64 encoded string.
CertificateAuthorityData
string
`yaml:"certificate-authority-data,omitempty"`
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
Extensions
[]
NamedExtension
`yaml:"extensions,omitempty"`
Extensions
[]
NamedExtension
`yaml:"extensions,omitempty"`
}
}
...
@@ -72,11 +74,15 @@ type AuthInfo struct {
...
@@ -72,11 +74,15 @@ type AuthInfo struct {
// ClientCertificate is the path to a client cert file for TLS.
// ClientCertificate is the path to a client cert file for TLS.
ClientCertificate
string
`yaml:"client-certificate,omitempty"`
ClientCertificate
string
`yaml:"client-certificate,omitempty"`
// ClientCertificateData contains PEM-encoded data from a client cert file for TLS. Overrides ClientCertificate
// ClientCertificateData contains PEM-encoded data from a client cert file for TLS. Overrides ClientCertificate
ClientCertificateData
[]
byte
`yaml:"client-certificate-data,omitempty"`
//
// NOTE(ericchiang): Our yaml parser doesn't assume []byte is a base64 encoded string.
ClientCertificateData
string
`yaml:"client-certificate-data,omitempty"`
// ClientKey is the path to a client key file for TLS.
// ClientKey is the path to a client key file for TLS.
ClientKey
string
`yaml:"client-key,omitempty"`
ClientKey
string
`yaml:"client-key,omitempty"`
// ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey
// ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey
ClientKeyData
[]
byte
`yaml:"client-key-data,omitempty"`
//
// NOTE(ericchiang): Our yaml parser doesn't assume []byte is a base64 encoded string.
ClientKeyData
string
`yaml:"client-key-data,omitempty"`
// Token is the bearer token for authentication to the kubernetes cluster.
// Token is the bearer token for authentication to the kubernetes cluster.
Token
string
`yaml:"token,omitempty"`
Token
string
`yaml:"token,omitempty"`
// Impersonate is the username to imperonate. The name matches the flag.
// Impersonate is the username to imperonate. The name matches the flag.
...
...
storage/kubernetes/storage.go
View file @
7ff3ce85
...
@@ -20,6 +20,7 @@ const (
...
@@ -20,6 +20,7 @@ const (
kindClient
=
"OAuth2Client"
kindClient
=
"OAuth2Client"
kindRefreshToken
=
"RefreshToken"
kindRefreshToken
=
"RefreshToken"
kindKeys
=
"SigningKey"
kindKeys
=
"SigningKey"
kindPassword
=
"Password"
)
)
const
(
const
(
...
@@ -28,6 +29,7 @@ const (
...
@@ -28,6 +29,7 @@ const (
resourceClient
=
"oauth2clients"
resourceClient
=
"oauth2clients"
resourceRefreshToken
=
"refreshtokens"
resourceRefreshToken
=
"refreshtokens"
resourceKeys
=
"signingkeies"
// Kubernetes attempts to pluralize.
resourceKeys
=
"signingkeies"
// Kubernetes attempts to pluralize.
resourcePassword
=
"passwords"
)
)
// Config values for the Kubernetes storage type.
// Config values for the Kubernetes storage type.
...
@@ -109,6 +111,10 @@ func (cli *client) CreateAuthCode(c storage.AuthCode) error {
...
@@ -109,6 +111,10 @@ func (cli *client) CreateAuthCode(c storage.AuthCode) error {
return
cli
.
post
(
resourceAuthCode
,
cli
.
fromStorageAuthCode
(
c
))
return
cli
.
post
(
resourceAuthCode
,
cli
.
fromStorageAuthCode
(
c
))
}
}
func
(
cli
*
client
)
CreatePassword
(
p
storage
.
Password
)
error
{
return
cli
.
post
(
resourcePassword
,
cli
.
fromStoragePassword
(
p
))
}
func
(
cli
*
client
)
CreateRefresh
(
r
storage
.
RefreshToken
)
error
{
func
(
cli
*
client
)
CreateRefresh
(
r
storage
.
RefreshToken
)
error
{
refresh
:=
RefreshToken
{
refresh
:=
RefreshToken
{
TypeMeta
:
k8sapi
.
TypeMeta
{
TypeMeta
:
k8sapi
.
TypeMeta
{
...
@@ -152,6 +158,14 @@ func (cli *client) GetClient(id string) (storage.Client, error) {
...
@@ -152,6 +158,14 @@ func (cli *client) GetClient(id string) (storage.Client, error) {
return
toStorageClient
(
c
),
nil
return
toStorageClient
(
c
),
nil
}
}
func
(
cli
*
client
)
GetPassword
(
email
string
)
(
storage
.
Password
,
error
)
{
var
p
Password
if
err
:=
cli
.
get
(
resourcePassword
,
emailToID
(
email
),
&
p
);
err
!=
nil
{
return
storage
.
Password
{},
err
}
return
toStoragePassword
(
p
),
nil
}
func
(
cli
*
client
)
GetKeys
()
(
storage
.
Keys
,
error
)
{
func
(
cli
*
client
)
GetKeys
()
(
storage
.
Keys
,
error
)
{
var
keys
Keys
var
keys
Keys
if
err
:=
cli
.
get
(
resourceKeys
,
keysName
,
&
keys
);
err
!=
nil
{
if
err
:=
cli
.
get
(
resourceKeys
,
keysName
,
&
keys
);
err
!=
nil
{
...
@@ -199,6 +213,10 @@ func (cli *client) DeleteRefresh(id string) error {
...
@@ -199,6 +213,10 @@ func (cli *client) DeleteRefresh(id string) error {
return
cli
.
delete
(
resourceRefreshToken
,
id
)
return
cli
.
delete
(
resourceRefreshToken
,
id
)
}
}
func
(
cli
*
client
)
DeletePassword
(
email
string
)
error
{
return
cli
.
delete
(
resourcePassword
,
emailToID
(
email
))
}
func
(
cli
*
client
)
UpdateClient
(
id
string
,
updater
func
(
old
storage
.
Client
)
(
storage
.
Client
,
error
))
error
{
func
(
cli
*
client
)
UpdateClient
(
id
string
,
updater
func
(
old
storage
.
Client
)
(
storage
.
Client
,
error
))
error
{
var
c
Client
var
c
Client
if
err
:=
cli
.
get
(
resourceClient
,
id
,
&
c
);
err
!=
nil
{
if
err
:=
cli
.
get
(
resourceClient
,
id
,
&
c
);
err
!=
nil
{
...
@@ -214,6 +232,23 @@ func (cli *client) UpdateClient(id string, updater func(old storage.Client) (sto
...
@@ -214,6 +232,23 @@ func (cli *client) UpdateClient(id string, updater func(old storage.Client) (sto
return
cli
.
put
(
resourceClient
,
id
,
newClient
)
return
cli
.
put
(
resourceClient
,
id
,
newClient
)
}
}
func
(
cli
*
client
)
UpdatePassword
(
email
string
,
updater
func
(
old
storage
.
Password
)
(
storage
.
Password
,
error
))
error
{
id
:=
emailToID
(
email
)
var
p
Password
if
err
:=
cli
.
get
(
resourcePassword
,
id
,
&
p
);
err
!=
nil
{
return
err
}
updated
,
err
:=
updater
(
toStoragePassword
(
p
))
if
err
!=
nil
{
return
err
}
newPassword
:=
cli
.
fromStoragePassword
(
updated
)
newPassword
.
ObjectMeta
=
p
.
ObjectMeta
return
cli
.
put
(
resourcePassword
,
id
,
newPassword
)
}
func
(
cli
*
client
)
UpdateKeys
(
updater
func
(
old
storage
.
Keys
)
(
storage
.
Keys
,
error
))
error
{
func
(
cli
*
client
)
UpdateKeys
(
updater
func
(
old
storage
.
Keys
)
(
storage
.
Keys
,
error
))
error
{
firstUpdate
:=
false
firstUpdate
:=
false
var
keys
Keys
var
keys
Keys
...
...
storage/kubernetes/storage_test.go
View file @
7ff3ce85
...
@@ -75,7 +75,18 @@ func TestURLFor(t *testing.T) {
...
@@ -75,7 +75,18 @@ func TestURLFor(t *testing.T) {
func
TestStorage
(
t
*
testing
.
T
)
{
func
TestStorage
(
t
*
testing
.
T
)
{
client
:=
loadClient
(
t
)
client
:=
loadClient
(
t
)
conformance
.
RunTestSuite
(
t
,
func
()
storage
.
Storage
{
conformance
.
RunTestSuite
(
t
,
func
()
storage
.
Storage
{
// TODO(erichiang): Tear down namespaces between each iteration.
for
_
,
resource
:=
range
[]
string
{
resourceAuthCode
,
resourceAuthRequest
,
resourceClient
,
resourceRefreshToken
,
resourceKeys
,
resourcePassword
,
}
{
if
err
:=
client
.
deleteAll
(
resource
);
err
!=
nil
{
t
.
Fatalf
(
"delete all %q failed: %v"
,
resource
,
err
)
}
}
return
client
return
client
})
})
}
}
storage/kubernetes/types.go
View file @
7ff3ce85
package
kubernetes
package
kubernetes
import
(
import
(
"encoding/base32"
"strings"
"time"
"time"
jose
"gopkg.in/square/go-jose.v2"
jose
"gopkg.in/square/go-jose.v2"
...
@@ -182,6 +184,60 @@ func (cli *client) fromStorageAuthRequest(a storage.AuthRequest) AuthRequest {
...
@@ -182,6 +184,60 @@ func (cli *client) fromStorageAuthRequest(a storage.AuthRequest) AuthRequest {
return
req
return
req
}
}
// Password is a mirrored struct from the stroage with JSON struct tags and
// Kubernetes type metadata.
type
Password
struct
{
k8sapi
.
TypeMeta
`json:",inline"`
k8sapi
.
ObjectMeta
`json:"metadata,omitempty"`
// The Kubernetes name is actually an encoded version of this value.
//
// This field is IMMUTABLE. Do not change.
Email
string
`json:"email,omitempty"`
Hash
[]
byte
`json:"hash,omitempty"`
Username
string
`json:"username,omitempty"`
UserID
string
`json:"userID,omitempty"`
}
// Kubernetes only allows lower case letters for names.
//
// NOTE(ericchiang): This is currently copied from the storage package's NewID()
// method. Once we refactor those into the storage, just use that instead.
var
encoding
=
base32
.
NewEncoding
(
"abcdefghijklmnopqrstuvwxyz234567"
)
// Map an arbitrary email to a valid Kuberntes name.
func
emailToID
(
email
string
)
string
{
return
strings
.
TrimRight
(
encoding
.
EncodeToString
([]
byte
(
strings
.
ToLower
(
email
))),
"="
)
}
func
(
cli
*
client
)
fromStoragePassword
(
p
storage
.
Password
)
Password
{
email
:=
strings
.
ToLower
(
p
.
Email
)
return
Password
{
TypeMeta
:
k8sapi
.
TypeMeta
{
Kind
:
kindPassword
,
APIVersion
:
cli
.
apiVersionForResource
(
resourcePassword
),
},
ObjectMeta
:
k8sapi
.
ObjectMeta
{
Name
:
emailToID
(
email
),
Namespace
:
cli
.
namespace
,
},
Email
:
email
,
Hash
:
p
.
Hash
,
Username
:
p
.
Username
,
UserID
:
p
.
UserID
,
}
}
func
toStoragePassword
(
p
Password
)
storage
.
Password
{
return
storage
.
Password
{
Email
:
p
.
Email
,
Hash
:
p
.
Hash
,
Username
:
p
.
Username
,
UserID
:
p
.
UserID
,
}
}
// AuthCode is a mirrored struct from storage with JSON struct tags and
// AuthCode is a mirrored struct from storage with JSON struct tags and
// Kubernetes type metadata.
// Kubernetes type metadata.
type
AuthCode
struct
{
type
AuthCode
struct
{
...
...
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