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
e8ba8489
Commit
e8ba8489
authored
Dec 20, 2018
by
Krzysztof Balka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
keystone: fetching groups only if requested, refactoring.
parent
88d1e2b0
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
212 additions
and
165 deletions
+212
-165
.travis.yml
.travis.yml
+7
-3
keystone.go
connector/keystone/keystone.go
+133
-49
keystone_test.go
connector/keystone/keystone_test.go
+72
-26
types.go
connector/keystone/types.go
+0
-87
No files found.
.travis.yml
View file @
e8ba8489
...
@@ -13,14 +13,18 @@ services:
...
@@ -13,14 +13,18 @@ services:
-
docker
-
docker
env
:
env
:
-
DEX_POSTGRES_DATABASE=postgres DEX_POSTGRES_USER=postgres DEX_POSTGRES_HOST="localhost" DEX_ETCD_ENDPOINTS=http://localhost:2379 DEX_LDAP_TESTS=1 DEBIAN_FRONTEND=noninteractive DEX_KEYSTONE_URL=http://localhost:5000 DEX_KEYSTONE_ADMIN_URL=http://localhost:35357
-
DEX_POSTGRES_DATABASE=postgres DEX_POSTGRES_USER=postgres DEX_POSTGRES_HOST="localhost" DEX_ETCD_ENDPOINTS=http://localhost:2379 DEX_LDAP_TESTS=1 DEBIAN_FRONTEND=noninteractive DEX_KEYSTONE_URL=http://localhost:5000 DEX_KEYSTONE_ADMIN_URL=http://localhost:35357
DEX_KEYSTONE_ADMIN_USER=demo DEX_KEYSTONE_ADMIN_PASS=DEMO_PASS
install
:
install
:
-
sudo -E apt-get install -y --force-yes slapd time ldap-utils
-
sudo -E apt-get install -y --force-yes slapd time ldap-utils
-
sudo /etc/init.d/slapd stop
-
sudo /etc/init.d/slapd stop
-
docker run -d --net=host gcr.io/etcd-development/etcd:v3.2.9
-
docker run -d --net=host gcr.io/etcd-development/etcd:v3.2.9
-
docker run -d -p 0.0.0.0:5000:5000 -p 0.0.0.0:35357:35357 openio/openstack-keystone
-
docker run -d -p 0.0.0.0:5000:5000 -p 0.0.0.0:35357:35357 openio/openstack-keystone:pike
-
sleep 60s
-
|
until curl --fail http://localhost:5000/v3; do
echo 'Waiting for keystone...'
sleep 1;
done;
script
:
script
:
-
make testall
-
make testall
...
...
connector/keystone/keystone.go
View file @
e8ba8489
...
@@ -14,65 +14,148 @@ import (
...
@@ -14,65 +14,148 @@ import (
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/connector"
)
)
type
conn
struct
{
Domain
string
Host
string
AdminUsername
string
AdminPassword
string
Logger
logrus
.
FieldLogger
}
type
userKeystone
struct
{
Domain
domainKeystone
`json:"domain"`
ID
string
`json:"id"`
Name
string
`json:"name"`
}
type
domainKeystone
struct
{
ID
string
`json:"id"`
Name
string
`json:"name"`
}
// Config holds the configuration parameters for Keystone connector.
// Keystone should expose API v3
// An example config:
// connectors:
// type: keystone
// id: keystone
// name: Keystone
// config:
// keystoneHost: http://example:5000
// domain: default
// keystoneUsername: demo
// keystonePassword: DEMO_PASS
type
Config
struct
{
Domain
string
`json:"domain"`
Host
string
`json:"keystoneHost"`
AdminUsername
string
`json:"keystoneUsername"`
AdminPassword
string
`json:"keystonePassword"`
}
type
loginRequestData
struct
{
auth
`json:"auth"`
}
type
auth
struct
{
Identity
identity
`json:"identity"`
}
type
identity
struct
{
Methods
[]
string
`json:"methods"`
Password
password
`json:"password"`
}
type
password
struct
{
User
user
`json:"user"`
}
type
user
struct
{
Name
string
`json:"name"`
Domain
domain
`json:"domain"`
Password
string
`json:"password"`
}
type
domain
struct
{
ID
string
`json:"id"`
}
type
token
struct
{
User
userKeystone
`json:"user"`
}
type
tokenResponse
struct
{
Token
token
`json:"token"`
}
type
group
struct
{
ID
string
`json:"id"`
Name
string
`json:"name"`
}
type
groupsResponse
struct
{
Groups
[]
group
`json:"groups"`
}
var
(
var
(
_
connector
.
PasswordConnector
=
&
keystoneConnector
{}
_
connector
.
PasswordConnector
=
&
conn
{}
_
connector
.
RefreshConnector
=
&
keystoneConnector
{}
_
connector
.
RefreshConnector
=
&
conn
{}
)
)
// Open returns an authentication strategy using Keystone.
// Open returns an authentication strategy using Keystone.
func
(
c
*
Config
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
func
(
c
*
Config
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
return
&
keystoneConnector
{
c
.
Domain
,
c
.
KeystoneHost
,
return
&
conn
{
c
.
KeystoneUsername
,
c
.
KeystonePassword
,
logger
},
nil
c
.
Domain
,
c
.
Host
,
c
.
AdminUsername
,
c
.
AdminPassword
,
logger
},
nil
}
}
func
(
p
*
keystoneConnector
)
Close
()
error
{
return
nil
}
func
(
p
*
conn
)
Close
()
error
{
return
nil
}
func
(
p
*
keystoneConnector
)
Login
(
ctx
context
.
Context
,
s
connector
.
Scopes
,
username
,
password
string
)
(
func
(
p
*
conn
)
Login
(
ctx
context
.
Context
,
scopes
connector
.
Scopes
,
username
,
password
string
)
(
identity
connector
.
Identity
,
validPassword
bool
,
err
error
)
{
identity
connector
.
Identity
,
validPassword
bool
,
err
error
)
{
resp
,
err
:=
p
.
getTokenResponse
(
ctx
,
username
,
password
)
resp
,
err
:=
p
.
getTokenResponse
(
ctx
,
username
,
password
)
if
err
!=
nil
{
if
err
!=
nil
{
return
identity
,
false
,
fmt
.
Errorf
(
"keystone: error %v"
,
err
)
return
identity
,
false
,
fmt
.
Errorf
(
"keystone: error %v"
,
err
)
}
}
if
resp
.
StatusCode
/
100
!=
2
{
// Providing wrong password or wrong keystone URI throws error
return
identity
,
false
,
fmt
.
Errorf
(
"keystone login: error %v"
,
resp
.
StatusCode
)
if
resp
.
StatusCode
==
201
{
}
token
:=
resp
.
Header
.
Get
(
"X-Subject-Token"
)
if
resp
.
StatusCode
!=
201
{
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
return
identity
,
false
,
nil
if
err
!=
nil
{
}
return
identity
,
false
,
err
token
:=
resp
.
Header
.
Get
(
"X-Subject-Token"
)
}
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
defer
resp
.
Body
.
Close
()
if
err
!=
nil
{
return
identity
,
false
,
err
var
tokenResp
=
new
(
tokenResponse
)
}
err
=
json
.
Unmarshal
(
data
,
&
tokenResp
)
defer
resp
.
Body
.
Close
()
if
err
!=
nil
{
var
tokenResp
=
new
(
tokenResponse
)
return
identity
,
false
,
fmt
.
Errorf
(
"keystone: invalid token response: %v"
,
err
)
err
=
json
.
Unmarshal
(
data
,
&
tokenResp
)
}
if
err
!=
nil
{
return
identity
,
false
,
fmt
.
Errorf
(
"keystone: invalid token response: %v"
,
err
)
}
if
scopes
.
Groups
{
groups
,
err
:=
p
.
getUserGroups
(
ctx
,
tokenResp
.
Token
.
User
.
ID
,
token
)
groups
,
err
:=
p
.
getUserGroups
(
ctx
,
tokenResp
.
Token
.
User
.
ID
,
token
)
if
err
!=
nil
{
if
err
!=
nil
{
return
identity
,
false
,
err
return
identity
,
false
,
err
}
}
identity
.
Username
=
username
identity
.
UserID
=
tokenResp
.
Token
.
User
.
ID
identity
.
Groups
=
groups
identity
.
Groups
=
groups
return
identity
,
true
,
nil
}
}
identity
.
Username
=
username
return
identity
,
false
,
nil
identity
.
UserID
=
tokenResp
.
Token
.
User
.
ID
return
identity
,
true
,
nil
}
}
func
(
p
*
keystoneConnector
)
Prompt
()
string
{
return
"username"
}
func
(
p
*
conn
)
Prompt
()
string
{
return
"username"
}
func
(
p
*
keystoneConnector
)
Refresh
(
func
(
p
*
conn
)
Refresh
(
ctx
context
.
Context
,
s
connector
.
Scopes
,
identity
connector
.
Identity
)
(
connector
.
Identity
,
error
)
{
ctx
context
.
Context
,
s
copes
connector
.
Scopes
,
identity
connector
.
Identity
)
(
connector
.
Identity
,
error
)
{
token
,
err
:=
p
.
getAdminToken
(
ctx
)
token
,
err
:=
p
.
getAdminToken
(
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
return
identity
,
fmt
.
Errorf
(
"keystone: failed to obtain admin token: %v"
,
err
)
return
identity
,
fmt
.
Errorf
(
"keystone: failed to obtain admin token: %v"
,
err
)
}
}
ok
,
err
:=
p
.
checkIfUserExists
(
ctx
,
identity
.
UserID
,
token
)
ok
,
err
:=
p
.
checkIfUserExists
(
ctx
,
identity
.
UserID
,
token
)
if
err
!=
nil
{
if
err
!=
nil
{
return
identity
,
err
return
identity
,
err
...
@@ -80,17 +163,17 @@ func (p *keystoneConnector) Refresh(
...
@@ -80,17 +163,17 @@ func (p *keystoneConnector) Refresh(
if
!
ok
{
if
!
ok
{
return
identity
,
fmt
.
Errorf
(
"keystone: user %q does not exist"
,
identity
.
UserID
)
return
identity
,
fmt
.
Errorf
(
"keystone: user %q does not exist"
,
identity
.
UserID
)
}
}
if
scopes
.
Groups
{
groups
,
err
:=
p
.
getUserGroups
(
ctx
,
identity
.
UserID
,
token
)
groups
,
err
:=
p
.
getUserGroups
(
ctx
,
identity
.
UserID
,
token
)
if
err
!=
nil
{
if
err
!=
nil
{
return
identity
,
err
return
identity
,
err
}
identity
.
Groups
=
groups
}
}
identity
.
Groups
=
groups
return
identity
,
nil
return
identity
,
nil
}
}
func
(
p
*
keystoneConnector
)
getTokenResponse
(
ctx
context
.
Context
,
username
,
pass
string
)
(
response
*
http
.
Response
,
err
error
)
{
func
(
p
*
conn
)
getTokenResponse
(
ctx
context
.
Context
,
username
,
pass
string
)
(
response
*
http
.
Response
,
err
error
)
{
client
:=
&
http
.
Client
{}
client
:=
&
http
.
Client
{}
jsonData
:=
loginRequestData
{
jsonData
:=
loginRequestData
{
auth
:
auth
{
auth
:
auth
{
...
@@ -110,8 +193,8 @@ func (p *keystoneConnector) getTokenResponse(ctx context.Context, username, pass
...
@@ -110,8 +193,8 @@ func (p *keystoneConnector) getTokenResponse(ctx context.Context, username, pass
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
// https://developer.openstack.org/api-ref/identity/v3/#password-authentication-with-unscoped-authorization
authTokenURL
:=
p
.
Keystone
Host
+
"/v3/auth/tokens/"
authTokenURL
:=
p
.
Host
+
"/v3/auth/tokens/"
req
,
err
:=
http
.
NewRequest
(
"POST"
,
authTokenURL
,
bytes
.
NewBuffer
(
jsonValue
))
req
,
err
:=
http
.
NewRequest
(
"POST"
,
authTokenURL
,
bytes
.
NewBuffer
(
jsonValue
))
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -123,8 +206,8 @@ func (p *keystoneConnector) getTokenResponse(ctx context.Context, username, pass
...
@@ -123,8 +206,8 @@ func (p *keystoneConnector) getTokenResponse(ctx context.Context, username, pass
return
client
.
Do
(
req
)
return
client
.
Do
(
req
)
}
}
func
(
p
*
keystoneConnector
)
getAdminToken
(
ctx
context
.
Context
)
(
string
,
error
)
{
func
(
p
*
conn
)
getAdminToken
(
ctx
context
.
Context
)
(
string
,
error
)
{
resp
,
err
:=
p
.
getTokenResponse
(
ctx
,
p
.
KeystoneUsername
,
p
.
Keystone
Password
)
resp
,
err
:=
p
.
getTokenResponse
(
ctx
,
p
.
AdminUsername
,
p
.
Admin
Password
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
err
return
""
,
err
}
}
...
@@ -132,8 +215,9 @@ func (p *keystoneConnector) getAdminToken(ctx context.Context) (string, error) {
...
@@ -132,8 +215,9 @@ func (p *keystoneConnector) getAdminToken(ctx context.Context) (string, error) {
return
token
,
nil
return
token
,
nil
}
}
func
(
p
*
keystoneConnector
)
checkIfUserExists
(
ctx
context
.
Context
,
userID
string
,
token
string
)
(
bool
,
error
)
{
func
(
p
*
conn
)
checkIfUserExists
(
ctx
context
.
Context
,
userID
string
,
token
string
)
(
bool
,
error
)
{
userURL
:=
p
.
KeystoneHost
+
"/v3/users/"
+
userID
// https://developer.openstack.org/api-ref/identity/v3/#show-user-details
userURL
:=
p
.
Host
+
"/v3/users/"
+
userID
client
:=
&
http
.
Client
{}
client
:=
&
http
.
Client
{}
req
,
err
:=
http
.
NewRequest
(
"GET"
,
userURL
,
nil
)
req
,
err
:=
http
.
NewRequest
(
"GET"
,
userURL
,
nil
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -153,10 +237,10 @@ func (p *keystoneConnector) checkIfUserExists(ctx context.Context, userID string
...
@@ -153,10 +237,10 @@ func (p *keystoneConnector) checkIfUserExists(ctx context.Context, userID string
return
false
,
err
return
false
,
err
}
}
func
(
p
*
keystoneConnector
)
getUserGroups
(
ctx
context
.
Context
,
userID
string
,
token
string
)
([]
string
,
error
)
{
func
(
p
*
conn
)
getUserGroups
(
ctx
context
.
Context
,
userID
string
,
token
string
)
([]
string
,
error
)
{
client
:=
&
http
.
Client
{}
client
:=
&
http
.
Client
{}
groupsURL
:=
p
.
KeystoneHost
+
"/v3/users/"
+
userID
+
"/groups"
// https://developer.openstack.org/api-ref/identity/v3/#list-groups-to-which-a-user-belongs
groupsURL
:=
p
.
Host
+
"/v3/users/"
+
userID
+
"/groups"
req
,
err
:=
http
.
NewRequest
(
"GET"
,
groupsURL
,
nil
)
req
,
err
:=
http
.
NewRequest
(
"GET"
,
groupsURL
,
nil
)
req
.
Header
.
Set
(
"X-Auth-Token"
,
token
)
req
.
Header
.
Set
(
"X-Auth-Token"
,
token
)
req
=
req
.
WithContext
(
ctx
)
req
=
req
.
WithContext
(
ctx
)
...
...
connector/keystone/keystone_test.go
View file @
e8ba8489
...
@@ -16,8 +16,6 @@ import (
...
@@ -16,8 +16,6 @@ import (
)
)
const
(
const
(
adminUser
=
"demo"
adminPass
=
"DEMO_PASS"
invalidPass
=
"WRONG_PASS"
invalidPass
=
"WRONG_PASS"
testUser
=
"test_user"
testUser
=
"test_user"
...
@@ -30,6 +28,8 @@ const (
...
@@ -30,6 +28,8 @@ const (
var
(
var
(
keystoneURL
=
""
keystoneURL
=
""
keystoneAdminURL
=
""
keystoneAdminURL
=
""
adminUser
=
""
adminPass
=
""
authTokenURL
=
""
authTokenURL
=
""
usersURL
=
""
usersURL
=
""
groupsURL
=
""
groupsURL
=
""
...
@@ -213,24 +213,31 @@ func addUserToGroup(t *testing.T, token, groupID, userID string) error {
...
@@ -213,24 +213,31 @@ func addUserToGroup(t *testing.T, token, groupID, userID string) error {
}
}
func
TestIncorrectCredentialsLogin
(
t
*
testing
.
T
)
{
func
TestIncorrectCredentialsLogin
(
t
*
testing
.
T
)
{
c
:=
keystoneConnector
{
KeystoneHost
:
keystoneURL
,
Domain
:
testDomain
,
setupVariables
(
t
)
KeystoneUsername
:
adminUser
,
KeystonePassword
:
adminPass
}
c
:=
conn
{
Host
:
keystoneURL
,
Domain
:
testDomain
,
AdminUsername
:
adminUser
,
AdminPassword
:
adminPass
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
_
,
validPW
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
adminUser
,
invalidPass
)
_
,
validPW
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
adminUser
,
invalidPass
)
if
err
!=
nil
{
t
.
Fatal
(
err
.
Error
())
}
if
validPW
{
if
validPW
{
t
.
Fail
()
t
.
Fatal
(
"Incorrect password check"
)
}
if
err
==
nil
{
t
.
Fatal
(
"Error should be returned when invalid password is provided"
)
}
if
!
strings
.
Contains
(
err
.
Error
(),
"401"
)
{
t
.
Fatal
(
"Unrecognized error, expecting 401"
)
}
}
}
}
func
TestValidUserLogin
(
t
*
testing
.
T
)
{
func
TestValidUserLogin
(
t
*
testing
.
T
)
{
setupVariables
(
t
)
token
,
_
:=
getAdminToken
(
t
,
adminUser
,
adminPass
)
token
,
_
:=
getAdminToken
(
t
,
adminUser
,
adminPass
)
userID
:=
createUser
(
t
,
token
,
testUser
,
testEmail
,
testPass
)
userID
:=
createUser
(
t
,
token
,
testUser
,
testEmail
,
testPass
)
c
:=
keystoneConnector
{
Keystone
Host
:
keystoneURL
,
Domain
:
testDomain
,
c
:=
conn
{
Host
:
keystoneURL
,
Domain
:
testDomain
,
KeystoneUsername
:
adminUser
,
Keystone
Password
:
adminPass
}
AdminUsername
:
adminUser
,
Admin
Password
:
adminPass
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
identity
,
validPW
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
testUser
,
testPass
)
identity
,
validPW
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
testUser
,
testPass
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -239,18 +246,19 @@ func TestValidUserLogin(t *testing.T) {
...
@@ -239,18 +246,19 @@ func TestValidUserLogin(t *testing.T) {
t
.
Log
(
identity
)
t
.
Log
(
identity
)
if
!
validPW
{
if
!
validPW
{
t
.
Fa
il
(
)
t
.
Fa
tal
(
"Valid password was not accepted"
)
}
}
delete
(
t
,
token
,
userID
,
usersURL
)
delete
(
t
,
token
,
userID
,
usersURL
)
}
}
func
TestUseRefreshToken
(
t
*
testing
.
T
)
{
func
TestUseRefreshToken
(
t
*
testing
.
T
)
{
setupVariables
(
t
)
token
,
adminID
:=
getAdminToken
(
t
,
adminUser
,
adminPass
)
token
,
adminID
:=
getAdminToken
(
t
,
adminUser
,
adminPass
)
groupID
:=
createGroup
(
t
,
token
,
"Test group description"
,
testGroup
)
groupID
:=
createGroup
(
t
,
token
,
"Test group description"
,
testGroup
)
addUserToGroup
(
t
,
token
,
groupID
,
adminID
)
addUserToGroup
(
t
,
token
,
groupID
,
adminID
)
c
:=
keystoneConnector
{
Keystone
Host
:
keystoneURL
,
Domain
:
testDomain
,
c
:=
conn
{
Host
:
keystoneURL
,
Domain
:
testDomain
,
KeystoneUsername
:
adminUser
,
Keystone
Password
:
adminPass
}
AdminUsername
:
adminUser
,
Admin
Password
:
adminPass
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
identityLogin
,
_
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
adminUser
,
adminPass
)
identityLogin
,
_
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
adminUser
,
adminPass
)
...
@@ -270,11 +278,12 @@ func TestUseRefreshToken(t *testing.T) {
...
@@ -270,11 +278,12 @@ func TestUseRefreshToken(t *testing.T) {
}
}
func
TestUseRefreshTokenUserDeleted
(
t
*
testing
.
T
)
{
func
TestUseRefreshTokenUserDeleted
(
t
*
testing
.
T
)
{
setupVariables
(
t
)
token
,
_
:=
getAdminToken
(
t
,
adminUser
,
adminPass
)
token
,
_
:=
getAdminToken
(
t
,
adminUser
,
adminPass
)
userID
:=
createUser
(
t
,
token
,
testUser
,
testEmail
,
testPass
)
userID
:=
createUser
(
t
,
token
,
testUser
,
testEmail
,
testPass
)
c
:=
keystoneConnector
{
Keystone
Host
:
keystoneURL
,
Domain
:
testDomain
,
c
:=
conn
{
Host
:
keystoneURL
,
Domain
:
testDomain
,
KeystoneUsername
:
adminUser
,
Keystone
Password
:
adminPass
}
AdminUsername
:
adminUser
,
Admin
Password
:
adminPass
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
identityLogin
,
_
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
testUser
,
testPass
)
identityLogin
,
_
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
testUser
,
testPass
)
...
@@ -296,11 +305,12 @@ func TestUseRefreshTokenUserDeleted(t *testing.T) {
...
@@ -296,11 +305,12 @@ func TestUseRefreshTokenUserDeleted(t *testing.T) {
}
}
func
TestUseRefreshTokenGroupsChanged
(
t
*
testing
.
T
)
{
func
TestUseRefreshTokenGroupsChanged
(
t
*
testing
.
T
)
{
setupVariables
(
t
)
token
,
_
:=
getAdminToken
(
t
,
adminUser
,
adminPass
)
token
,
_
:=
getAdminToken
(
t
,
adminUser
,
adminPass
)
userID
:=
createUser
(
t
,
token
,
testUser
,
testEmail
,
testPass
)
userID
:=
createUser
(
t
,
token
,
testUser
,
testEmail
,
testPass
)
c
:=
keystoneConnector
{
Keystone
Host
:
keystoneURL
,
Domain
:
testDomain
,
c
:=
conn
{
Host
:
keystoneURL
,
Domain
:
testDomain
,
KeystoneUsername
:
adminUser
,
Keystone
Password
:
adminPass
}
AdminUsername
:
adminUser
,
Admin
Password
:
adminPass
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
true
}
identityLogin
,
_
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
testUser
,
testPass
)
identityLogin
,
_
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
testUser
,
testPass
)
...
@@ -315,7 +325,7 @@ func TestUseRefreshTokenGroupsChanged(t *testing.T) {
...
@@ -315,7 +325,7 @@ func TestUseRefreshTokenGroupsChanged(t *testing.T) {
expectEquals
(
t
,
0
,
len
(
identityRefresh
.
Groups
))
expectEquals
(
t
,
0
,
len
(
identityRefresh
.
Groups
))
groupID
:=
createGroup
(
t
,
token
,
"Test group
description
"
,
testGroup
)
groupID
:=
createGroup
(
t
,
token
,
"Test group"
,
testGroup
)
addUserToGroup
(
t
,
token
,
groupID
,
userID
)
addUserToGroup
(
t
,
token
,
groupID
,
userID
)
identityRefresh
,
err
=
c
.
Refresh
(
context
.
Background
(),
s
,
identityLogin
)
identityRefresh
,
err
=
c
.
Refresh
(
context
.
Background
(),
s
,
identityLogin
)
...
@@ -329,26 +339,62 @@ func TestUseRefreshTokenGroupsChanged(t *testing.T) {
...
@@ -329,26 +339,62 @@ func TestUseRefreshTokenGroupsChanged(t *testing.T) {
expectEquals
(
t
,
1
,
len
(
identityRefresh
.
Groups
))
expectEquals
(
t
,
1
,
len
(
identityRefresh
.
Groups
))
}
}
func
TestMain
(
m
*
testing
.
M
)
{
func
TestNoGroupsInScope
(
t
*
testing
.
T
)
{
setupVariables
(
t
)
token
,
_
:=
getAdminToken
(
t
,
adminUser
,
adminPass
)
userID
:=
createUser
(
t
,
token
,
testUser
,
testEmail
,
testPass
)
c
:=
conn
{
Host
:
keystoneURL
,
Domain
:
testDomain
,
AdminUsername
:
adminUser
,
AdminPassword
:
adminPass
}
s
:=
connector
.
Scopes
{
OfflineAccess
:
true
,
Groups
:
false
}
groupID
:=
createGroup
(
t
,
token
,
"Test group"
,
testGroup
)
addUserToGroup
(
t
,
token
,
groupID
,
userID
)
identityLogin
,
_
,
err
:=
c
.
Login
(
context
.
Background
(),
s
,
testUser
,
testPass
)
if
err
!=
nil
{
t
.
Fatal
(
err
.
Error
())
}
expectEquals
(
t
,
0
,
len
(
identityLogin
.
Groups
))
identityRefresh
,
err
:=
c
.
Refresh
(
context
.
Background
(),
s
,
identityLogin
)
if
err
!=
nil
{
t
.
Fatal
(
err
.
Error
())
}
expectEquals
(
t
,
0
,
len
(
identityRefresh
.
Groups
))
delete
(
t
,
token
,
groupID
,
groupsURL
)
delete
(
t
,
token
,
userID
,
usersURL
)
}
func
setupVariables
(
t
*
testing
.
T
)
{
keystoneURLEnv
:=
"DEX_KEYSTONE_URL"
keystoneURLEnv
:=
"DEX_KEYSTONE_URL"
keystoneAdminURLEnv
:=
"DEX_KEYSTONE_ADMIN_URL"
keystoneAdminURLEnv
:=
"DEX_KEYSTONE_ADMIN_URL"
keystoneAdminUserEnv
:=
"DEX_KEYSTONE_ADMIN_USER"
keystoneAdminPassEnv
:=
"DEX_KEYSTONE_ADMIN_PASS"
keystoneURL
=
os
.
Getenv
(
keystoneURLEnv
)
keystoneURL
=
os
.
Getenv
(
keystoneURLEnv
)
if
keystoneURL
==
""
{
if
keystoneURL
==
""
{
fmt
.
Printf
(
"variable %q not set, skipping keystone connector tests
\n
"
,
keystoneURLEnv
)
t
.
Skip
(
fmt
.
Sprintf
(
"variable %q not set, skipping keystone connector tests
\n
"
,
keystoneURLEnv
)
)
return
return
}
}
keystoneAdminURL
:
=
os
.
Getenv
(
keystoneAdminURLEnv
)
keystoneAdminURL
=
os
.
Getenv
(
keystoneAdminURLEnv
)
if
keystoneAdminURL
==
""
{
if
keystoneAdminURL
==
""
{
fmt
.
Printf
(
"variable %q not set, skipping keystone connector tests
\n
"
,
keystoneAdminURLEnv
)
t
.
Skip
(
fmt
.
Sprintf
(
"variable %q not set, skipping keystone connector tests
\n
"
,
keystoneAdminURLEnv
))
return
}
adminUser
=
os
.
Getenv
(
keystoneAdminUserEnv
)
if
adminUser
==
""
{
t
.
Skip
(
fmt
.
Sprintf
(
"variable %q not set, skipping keystone connector tests
\n
"
,
keystoneAdminUserEnv
))
return
}
adminPass
=
os
.
Getenv
(
keystoneAdminPassEnv
)
if
adminPass
==
""
{
t
.
Skip
(
fmt
.
Sprintf
(
"variable %q not set, skipping keystone connector tests
\n
"
,
keystoneAdminPassEnv
))
return
return
}
}
authTokenURL
=
keystoneURL
+
"/v3/auth/tokens/"
authTokenURL
=
keystoneURL
+
"/v3/auth/tokens/"
fmt
.
Printf
(
"Auth token url %q
\n
"
,
authTokenURL
)
fmt
.
Printf
(
"Keystone URL %q
\n
"
,
keystoneURL
)
usersURL
=
keystoneAdminURL
+
"/v3/users/"
usersURL
=
keystoneAdminURL
+
"/v3/users/"
groupsURL
=
keystoneAdminURL
+
"/v3/groups/"
groupsURL
=
keystoneAdminURL
+
"/v3/groups/"
// run all tests
m
.
Run
()
}
}
func
expectEquals
(
t
*
testing
.
T
,
a
interface
{},
b
interface
{})
{
func
expectEquals
(
t
*
testing
.
T
,
a
interface
{},
b
interface
{})
{
...
...
connector/keystone/types.go
deleted
100644 → 0
View file @
88d1e2b0
package
keystone
import
(
"github.com/sirupsen/logrus"
)
type
keystoneConnector
struct
{
Domain
string
KeystoneHost
string
KeystoneUsername
string
KeystonePassword
string
Logger
logrus
.
FieldLogger
}
type
userKeystone
struct
{
Domain
domainKeystone
`json:"domain"`
ID
string
`json:"id"`
Name
string
`json:"name"`
}
type
domainKeystone
struct
{
ID
string
`json:"id"`
Name
string
`json:"name"`
}
// Config holds the configuration parameters for Keystone connector.
// Keystone should expose API v3
// An example config:
// connectors:
// type: keystone
// id: keystone
// name: Keystone
// config:
// keystoneHost: http://example:5000
// domain: default
// keystoneUsername: demo
// keystonePassword: DEMO_PASS
type
Config
struct
{
Domain
string
`json:"domain"`
KeystoneHost
string
`json:"keystoneHost"`
KeystoneUsername
string
`json:"keystoneUsername"`
KeystonePassword
string
`json:"keystonePassword"`
}
type
loginRequestData
struct
{
auth
`json:"auth"`
}
type
auth
struct
{
Identity
identity
`json:"identity"`
}
type
identity
struct
{
Methods
[]
string
`json:"methods"`
Password
password
`json:"password"`
}
type
password
struct
{
User
user
`json:"user"`
}
type
user
struct
{
Name
string
`json:"name"`
Domain
domain
`json:"domain"`
Password
string
`json:"password"`
}
type
domain
struct
{
ID
string
`json:"id"`
}
type
token
struct
{
User
userKeystone
`json:"user"`
}
type
tokenResponse
struct
{
Token
token
`json:"token"`
}
type
group
struct
{
ID
string
`json:"id"`
Name
string
`json:"name"`
}
type
groupsResponse
struct
{
Groups
[]
group
`json:"groups"`
}
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