Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
id
auth
Commits
a430981a
Commit
a430981a
authored
Dec 17, 2017
by
ale
Browse files
Support partitioned user-meta-server
Uses the clientutil.Backend abstraction for the user-meta-server client API.
parent
1ac213f9
Changes
7
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
a430981a
...
...
@@ -55,7 +55,7 @@ The YAML file should contain a dictionary with the following attributes:
see the
*LDAP Backend*
section below
*
`user_meta_server`
holds the configuration for the user-meta-server
backend:
*
`
backend_
url`
is the URL of the service
*
`url`
is the URL of the service
*
`tls_config`
configures TLS for the client:
*
`cert`
is the path to the client certificate
*
`key`
is the path to the client private key
...
...
server/authserver.go
View file @
a430981a
...
...
@@ -15,8 +15,7 @@ import (
"github.com/tstranex/u2f"
"gopkg.in/yaml.v2"
usermetadbclient
"git.autistici.org/id/usermetadb/client"
"git.autistici.org/ai3/go-common/clientutil"
"git.autistici.org/id/auth"
)
...
...
@@ -214,7 +213,7 @@ type Config struct {
RateLimiters
map
[
string
]
*
authRatelimiterConfig
`yaml:"rate_limits"`
// Configuration for the user-meta-server backend.
UserMetaDBConfig
*
usermetadbclient
.
Config
`yaml:"user_meta_server"`
UserMetaDBConfig
*
clientutil
.
Backend
Config
`yaml:"user_meta_server"`
// Runtime versions of the above. These objects are shared by
// all services, as they contain the actual map data.
...
...
server/devices.go
View file @
a430981a
...
...
@@ -5,6 +5,7 @@ import (
"log"
"time"
"git.autistici.org/ai3/go-common/clientutil"
"git.autistici.org/id/usermetadb/client"
"git.autistici.org/id/auth"
...
...
@@ -12,7 +13,7 @@ import (
// Inject an interface for testing purposes.
type
checkDeviceClient
interface
{
CheckDevice
(
context
.
Context
,
string
,
*
auth
.
DeviceInfo
)
(
bool
,
error
)
CheckDevice
(
context
.
Context
,
string
,
string
,
*
auth
.
DeviceInfo
)
(
bool
,
error
)
}
type
deviceFilter
struct
{
...
...
@@ -21,7 +22,7 @@ type deviceFilter struct {
var
usermetadbTimeout
=
3
*
time
.
Second
func
newDeviceFilter
(
config
*
client
.
Config
)
(
*
deviceFilter
,
error
)
{
func
newDeviceFilter
(
config
*
client
util
.
Backend
Config
)
(
*
deviceFilter
,
error
)
{
c
,
err
:=
client
.
New
(
config
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -39,7 +40,7 @@ func (f *deviceFilter) Filter(user *User, req *auth.Request, resp *auth.Response
// OK and don't need to do anything else.
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
usermetadbTimeout
)
defer
cancel
()
seen
,
err
:=
f
.
client
.
CheckDevice
(
ctx
,
user
.
Name
,
req
.
DeviceInfo
)
seen
,
err
:=
f
.
client
.
CheckDevice
(
ctx
,
user
.
Shard
,
user
.
Name
,
req
.
DeviceInfo
)
if
err
!=
nil
{
log
.
Printf
(
"usermetadb error for %s: %v"
,
user
.
Name
,
err
)
return
resp
...
...
vendor/git.autistici.org/ai3/go-common/clientutil/backend.go
0 → 100644
View file @
a430981a
package
clientutil
import
(
"crypto/tls"
"fmt"
"net/http"
"net/url"
"sync"
"time"
)
// BackendConfig specifies the configuration to access a service.
//
// Services with multiple backends can be replicated or partitioned,
// depending on a configuration switch, making it a deployment-time
// decision. Clients are expected to compute their own sharding
// function (either by database lookup or other methods), and expose a
// 'shard' parameter on their APIs.
type
BackendConfig
struct
{
URL
string
`yaml:"url"`
Sharded
bool
`yaml:"sharded"`
TLSConfig
*
TLSClientConfig
`yaml:"tls_config"`
}
// Backend is a runtime class that provides http Clients for use with
// a specific service backend. If the service can't be partitioned,
// pass an empty string to the Client method.
type
Backend
interface
{
// URL for the service for a specific shard.
URL
(
string
)
string
// Client that can be used to make a request to the service.
Client
(
string
)
*
http
.
Client
}
// NewBackend returns a new Backend with the given config.
func
NewBackend
(
config
*
BackendConfig
)
(
Backend
,
error
)
{
u
,
err
:=
url
.
Parse
(
config
.
URL
)
if
err
!=
nil
{
return
nil
,
err
}
var
tlsConfig
*
tls
.
Config
if
config
.
TLSConfig
!=
nil
{
tlsConfig
,
err
=
config
.
TLSConfig
.
TLSConfig
()
if
err
!=
nil
{
return
nil
,
err
}
}
if
config
.
Sharded
{
return
&
replicatedClient
{
u
:
u
,
c
:
newHTTPClient
(
u
,
tlsConfig
),
},
nil
}
return
&
shardedClient
{
baseURL
:
u
,
tlsConfig
:
tlsConfig
,
urls
:
make
(
map
[
string
]
*
url
.
URL
),
shards
:
make
(
map
[
string
]
*
http
.
Client
),
},
nil
}
type
replicatedClient
struct
{
c
*
http
.
Client
u
*
url
.
URL
}
func
(
r
*
replicatedClient
)
Client
(
_
string
)
*
http
.
Client
{
return
r
.
c
}
func
(
r
*
replicatedClient
)
URL
(
_
string
)
string
{
return
r
.
u
.
String
()
}
type
shardedClient
struct
{
baseURL
*
url
.
URL
tlsConfig
*
tls
.
Config
mx
sync
.
Mutex
urls
map
[
string
]
*
url
.
URL
shards
map
[
string
]
*
http
.
Client
}
func
(
s
*
shardedClient
)
getShardURL
(
shard
string
)
*
url
.
URL
{
if
shard
==
""
{
return
s
.
baseURL
}
u
,
ok
:=
s
.
urls
[
shard
]
if
!
ok
{
var
tmp
=
*
s
.
baseURL
tmp
.
Host
=
fmt
.
Sprintf
(
"%s.%s"
,
shard
,
tmp
.
Host
)
u
=
&
tmp
s
.
urls
[
shard
]
=
u
}
return
u
}
func
(
s
*
shardedClient
)
URL
(
shard
string
)
string
{
s
.
mx
.
Lock
()
defer
s
.
mx
.
Unlock
()
return
s
.
getShardURL
(
shard
)
.
String
()
}
func
(
s
*
shardedClient
)
Client
(
shard
string
)
*
http
.
Client
{
s
.
mx
.
Lock
()
defer
s
.
mx
.
Unlock
()
client
,
ok
:=
s
.
shards
[
shard
]
if
!
ok
{
u
:=
s
.
getShardURL
(
shard
)
client
=
newHTTPClient
(
u
,
s
.
tlsConfig
)
s
.
shards
[
shard
]
=
client
}
return
client
}
func
newHTTPClient
(
u
*
url
.
URL
,
tlsConfig
*
tls
.
Config
)
*
http
.
Client
{
return
&
http
.
Client
{
Transport
:
NewTransport
([]
string
{
u
.
Host
},
tlsConfig
,
nil
),
Timeout
:
30
*
time
.
Second
,
}
}
vendor/git.autistici.org/ai3/go-common/clientutil/transport.go
View file @
a430981a
...
...
@@ -125,6 +125,9 @@ func (b *balancer) dial(ctx context.Context, network, addr string) (net.Conn, er
if
err
==
nil
{
return
conn
,
nil
}
else
if
err
==
context
.
Canceled
{
// A timeout might be bad, set the error bit
// on the connection.
b
.
notify
(
addr
,
false
)
return
nil
,
err
}
b
.
notify
(
addr
,
false
)
...
...
vendor/git.autistici.org/id/usermetadb/client/client.go
View file @
a430981a
...
...
@@ -2,10 +2,6 @@ package client
import
(
"context"
"crypto/tls"
"net/http"
"net/url"
"time"
"git.autistici.org/ai3/go-common/clientutil"
"git.autistici.org/id/auth"
...
...
@@ -14,73 +10,56 @@ import (
)
// Client for the user-meta-server API.
type
Client
struct
{
*
http
.
Client
backendURL
string
type
Client
interface
{
CheckDevice
(
context
.
Context
,
string
,
string
,
*
auth
.
DeviceInfo
)
(
bool
,
error
)
AddLog
(
context
.
Context
,
string
,
*
usermetadb
.
LogEntry
)
error
GetUserDevices
(
context
.
Context
,
string
,
string
)
([]
*
usermetadb
.
MetaDeviceInfo
,
error
)
GetUserLogs
(
context
.
Context
,
string
,
string
,
int
,
int
)
([]
*
usermetadb
.
LogEntry
,
error
)
}
// Config for a user-meta-server API client.
type
Config
struct
{
BackendURL
string
`yaml:"backend_url"`
TLSConfig
*
clientutil
.
TLSClientConfig
`yaml:"tls_config"`
type
udbClient
struct
{
be
clientutil
.
Backend
}
// New returns a new Client with the given Config.
func
New
(
config
*
Config
)
(
*
Client
,
error
)
{
u
,
err
:=
url
.
Parse
(
config
.
BackendURL
)
func
New
(
config
*
clientutil
.
Backend
Config
)
(
Client
,
error
)
{
be
,
err
:=
clientutil
.
NewBackend
(
config
)
if
err
!=
nil
{
return
nil
,
err
}
var
tlsConfig
*
tls
.
Config
if
config
.
TLSConfig
!=
nil
{
tlsConfig
,
err
=
config
.
TLSConfig
.
TLSConfig
()
if
err
!=
nil
{
return
nil
,
err
}
}
c
:=
&
http
.
Client
{
Transport
:
clientutil
.
NewTransport
([]
string
{
u
.
Host
},
tlsConfig
,
nil
),
Timeout
:
10
*
time
.
Second
,
}
return
&
Client
{
Client
:
c
,
backendURL
:
config
.
BackendURL
,
},
nil
return
&
udbClient
{
be
},
nil
}
func
(
c
*
Client
)
CheckDevice
(
ctx
context
.
Context
,
username
string
,
dev
*
auth
.
DeviceInfo
)
(
bool
,
error
)
{
func
(
c
*
udb
Client
)
CheckDevice
(
ctx
context
.
Context
,
shard
,
username
string
,
dev
*
auth
.
DeviceInfo
)
(
bool
,
error
)
{
req
:=
usermetadb
.
CheckDeviceRequest
{
Username
:
username
,
DeviceInfo
:
dev
,
}
var
resp
usermetadb
.
CheckDeviceResponse
err
:=
clientutil
.
DoJSONHTTPRequest
(
ctx
,
c
.
Client
,
c
.
backendURL
+
"/api/check_device"
,
&
req
,
&
resp
)
err
:=
clientutil
.
DoJSONHTTPRequest
(
ctx
,
c
.
be
.
Client
(
shard
),
c
.
be
.
URL
(
shard
)
+
"/api/check_device"
,
&
req
,
&
resp
)
return
resp
.
Seen
,
err
}
func
(
c
*
Client
)
AddLog
(
ctx
context
.
Context
,
entry
*
usermetadb
.
LogEntry
)
error
{
func
(
c
*
udb
Client
)
AddLog
(
ctx
context
.
Context
,
shard
string
,
entry
*
usermetadb
.
LogEntry
)
error
{
req
:=
usermetadb
.
AddLogRequest
{
Log
:
entry
}
return
clientutil
.
DoJSONHTTPRequest
(
ctx
,
c
.
Client
,
c
.
backendURL
+
"/api/add_log"
,
&
req
,
nil
)
return
clientutil
.
DoJSONHTTPRequest
(
ctx
,
c
.
be
.
Client
(
shard
),
c
.
be
.
URL
(
shard
)
+
"/api/add_log"
,
&
req
,
nil
)
}
func
(
c
*
Client
)
GetUserDevices
(
ctx
context
.
Context
,
username
string
)
([]
*
usermetadb
.
MetaDeviceInfo
,
error
)
{
func
(
c
*
udb
Client
)
GetUserDevices
(
ctx
context
.
Context
,
shard
,
username
string
)
([]
*
usermetadb
.
MetaDeviceInfo
,
error
)
{
req
:=
usermetadb
.
GetUserDevicesRequest
{
Username
:
username
}
var
resp
usermetadb
.
GetUserDevicesResponse
err
:=
clientutil
.
DoJSONHTTPRequest
(
ctx
,
c
.
Client
,
c
.
backendURL
+
"/api/get_user_devices"
,
&
req
,
&
resp
)
err
:=
clientutil
.
DoJSONHTTPRequest
(
ctx
,
c
.
be
.
Client
(
shard
),
c
.
be
.
URL
(
shard
)
+
"/api/get_user_devices"
,
&
req
,
&
resp
)
return
resp
.
Devices
,
err
}
func
(
c
*
Client
)
GetUserLogs
(
ctx
context
.
Context
,
username
string
,
maxDays
,
limit
int
)
([]
*
usermetadb
.
LogEntry
,
error
)
{
func
(
c
*
udb
Client
)
GetUserLogs
(
ctx
context
.
Context
,
shard
,
username
string
,
maxDays
,
limit
int
)
([]
*
usermetadb
.
LogEntry
,
error
)
{
req
:=
usermetadb
.
GetUserLogsRequest
{
Username
:
username
,
MaxDays
:
maxDays
,
Limit
:
limit
,
}
var
resp
usermetadb
.
GetUserLogsResponse
err
:=
clientutil
.
DoJSONHTTPRequest
(
ctx
,
c
.
Client
,
c
.
backendURL
+
"/api/get_user_logs"
,
&
req
,
&
resp
)
err
:=
clientutil
.
DoJSONHTTPRequest
(
ctx
,
c
.
be
.
Client
(
shard
),
c
.
be
.
URL
(
shard
)
+
"/api/get_user_logs"
,
&
req
,
&
resp
)
return
resp
.
Results
,
err
}
vendor/vendor.json
View file @
a430981a
...
...
@@ -9,10 +9,10 @@
"revisionTime"
:
"2017-12-16T15:39:23Z"
},
{
"checksumSHA1"
:
"
jFlhSIit/5+VAIUu1cc7EVVlw0M
="
,
"checksumSHA1"
:
"
o+rWKVQIDy79ZwrItwa5/whAL6g
="
,
"path"
:
"git.autistici.org/ai3/go-common/clientutil"
,
"revision"
:
"
86a36cf5da88919ee7d9ec12d1a92043b16fcc9c
"
,
"revisionTime"
:
"2017-12-1
0T11:04:55
Z"
"revision"
:
"
9b20acad90c411c48f7ddc837a35ef3d0d6f98d4
"
,
"revisionTime"
:
"2017-12-1
7T20:32:41
Z"
},
{
"checksumSHA1"
:
"mEnXMNziH82HFtGngHU19VHTVHs="
,
...
...
@@ -29,14 +29,14 @@
{
"checksumSHA1"
:
"7Kbb9vTjqcQhhxtSGpmp9rk6PUk="
,
"path"
:
"git.autistici.org/id/usermetadb"
,
"revision"
:
"
870324b771df3ab35be9b881a1c4981260e18b5d
"
,
"revisionTime"
:
"2017-12-
09T12:27:05
Z"
"revision"
:
"
438e07d22e6891ae0c371c31003c66756c1f0ffa
"
,
"revisionTime"
:
"2017-12-
17T21:36:12
Z"
},
{
"checksumSHA1"
:
"
WkbTf01lQyXPIjdrmQLNQSCGauE
="
,
"checksumSHA1"
:
"
eEUTBX7C9TjnWcY2O9kT/88SClQ
="
,
"path"
:
"git.autistici.org/id/usermetadb/client"
,
"revision"
:
"
870324b771df3ab35be9b881a1c4981260e18b5d
"
,
"revisionTime"
:
"2017-12-
09T12:27:05
Z"
"revision"
:
"
438e07d22e6891ae0c371c31003c66756c1f0ffa
"
,
"revisionTime"
:
"2017-12-
17T21:36:12
Z"
},
{
"checksumSHA1"
:
"spyv5/YFBjYyZLZa1U2LBfDR8PM="
,
...
...
Write
Preview
Supports
Markdown
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