Support of certificate based authentication in RAFT for Restler #233 (#234)

Co-authored-by: stas <statis@microsoft.com>
This commit is contained in:
Stas 2021-08-23 14:19:54 -07:00 коммит произвёл GitHub
Родитель f2b624ab83
Коммит 6fcfefc832
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 73 добавлений и 27 удалений

Просмотреть файл

@ -74,9 +74,30 @@ key vault is expected to be a string.
The string is passed to the container in an environment variable. The string is passed to the container in an environment variable.
## Certificate (RESTler only at this time)
Authentication using a certificate is supported by RESTler.
You have to pass the authentication certificate using file shares in RAFT.
Using **Cert** as the authentication method key, use the path to the certificate as the value.
The certificate must be an X.509 certificate in PEM format.
See `ReadOnlyFileShareMounts` section in [JobDefinition documentation](./schema/jobdefinition.md)
for details on how to mount file shares.
```
"tasks": [
{
"toolName" : "RESTler",
"authenticationMethod": {
"Cert": "/path/to/cert"
}
},
```
## Agent-Utilities container ## Agent-Utilities container
Starting with v4 of RAFT - a deicated utilities docker container is deployed with every job run. This container is responsible Starting with v4 of RAFT - a dedicated utilities docker container is deployed with every job run. This container is responsible
for performing authentication with a service under test and processing events from tools. for performing authentication with a service under test and processing events from tools.
You do not need to do anything special to update agent utilites when running RAFT local, since agent utilities used directly from your CLI folder. To update agent utiliites when You do not need to do anything special to update agent utilites when running RAFT local, since agent utilities used directly from your CLI folder. To update agent utiliites when

Просмотреть файл

@ -260,22 +260,29 @@ let createRESTlerEngineParameters
match task.AuthenticationMethod with match task.AuthenticationMethod with
| Some c -> | Some c ->
if c.IsEmpty then if c.IsEmpty then
None Raft.RESTlerTypes.Engine.NoAuth
else else
let authConfig : Raft.RESTlerTypes.Engine.RefreshableTokenOptions = let auth = Seq.head c
{ let authType, authSecret = auth.Key, auth.Value
RefreshInterval = Option.defaultValue (int <| TimeSpan.FromHours(1.0).TotalSeconds) runConfiguration.AuthenticationTokenRefreshIntervalSeconds
RefreshExec = "python3" if authType.ToLower().Trim() = "cert" then
RefreshArgs = if IO.File.Exists authSecret then
let url = Raft.RESTlerTypes.Engine.Cert {CertificatePath = authSecret}
let auth = Seq.head c else
let authType, authSecretName = auth.Key, auth.Value failwithf "Failed to find authentication certificate: %s" authSecret
System.Uri(authenicationUrl, sprintf "auth/%s/%s" authType authSecretName) else
sprintf """-c "import requests; import json; r=requests.get('%s'); assert r.ok, r.text; print(\"{u'user1':{}}\nAuthorization: \" + json.loads(r.text)['token'])" """ url.AbsoluteUri let authConfig : Raft.RESTlerTypes.Engine.RefreshableTokenOptions =
} {
printfn "Refreshable token configuration : %A" authConfig RefreshInterval = Option.defaultValue (int <| TimeSpan.FromHours(1.0).TotalSeconds) runConfiguration.AuthenticationTokenRefreshIntervalSeconds
Some authConfig RefreshExec = "python3"
| None -> None RefreshArgs =
let url =
System.Uri(authenicationUrl, sprintf "auth/%s/%s" authType authSecret)
sprintf """-c "import requests; import json; r=requests.get('%s'); assert r.ok, r.text; print(\"{u'user1':{}}\nAuthorization: \" + json.loads(r.text)['token'])" """ url.AbsoluteUri
}
printfn "Refreshable token configuration : %A" authConfig
Raft.RESTlerTypes.Engine.Token authConfig
| None -> Raft.RESTlerTypes.Engine.NoAuth
/// The delay in seconds after invoking an API that creates a new resource /// The delay in seconds after invoking an API that creates a new resource
ProducerTimingDelay = Option.defaultValue 10 runConfiguration.ProducerTimingDelay ProducerTimingDelay = Option.defaultValue 10 runConfiguration.ProducerTimingDelay

Просмотреть файл

@ -341,8 +341,8 @@ module private RESTlerInternal =
async { async {
do! do!
match parameters.RefreshableTokenOptions with match parameters.RefreshableTokenOptions with
| None -> async.Return() | Raft.RESTlerTypes.Engine.NoAuth | Raft.RESTlerTypes.Engine.Cert _ -> async.Return()
| Some t -> validateAuthentication workingDirectory t | Raft.RESTlerTypes.Engine.Token t -> validateAuthentication workingDirectory t
let testParameters = getCommonParameters workingDirectory (Some testType) parameters let testParameters = getCommonParameters workingDirectory (Some testType) parameters
do! runRestlerEngine restlerRootDirectory workingDirectory testParameters do! runRestlerEngine restlerRootDirectory workingDirectory testParameters
@ -353,8 +353,8 @@ module private RESTlerInternal =
async { async {
do! do!
match parameters.RefreshableTokenOptions with match parameters.RefreshableTokenOptions with
| None -> async.Return() | Raft.RESTlerTypes.Engine.NoAuth | Raft.RESTlerTypes.Engine.Cert _ -> async.Return()
| Some t -> validateAuthentication workingDirectory t | Raft.RESTlerTypes.Engine.Token t -> validateAuthentication workingDirectory t
let fuzzingParameters = getCommonParameters workingDirectory (Some fuzzType) parameters let fuzzingParameters = getCommonParameters workingDirectory (Some fuzzType) parameters
do! runRestlerEngine restlerRootDirectory workingDirectory fuzzingParameters do! runRestlerEngine restlerRootDirectory workingDirectory fuzzingParameters
@ -364,8 +364,8 @@ module private RESTlerInternal =
async { async {
do! do!
match parameters.RefreshableTokenOptions with match parameters.RefreshableTokenOptions with
| None -> async.Return() | Raft.RESTlerTypes.Engine.NoAuth | Raft.RESTlerTypes.Engine.Cert _ -> async.Return()
| Some t -> validateAuthentication workingDirectory t | Raft.RESTlerTypes.Engine.Token t -> validateAuthentication workingDirectory t
let replayParameters = let replayParameters =
(getCommonParameters workingDirectory None parameters) (getCommonParameters workingDirectory None parameters)

Просмотреть файл

@ -20,6 +20,17 @@ module Engine =
RefreshArgs : string RefreshArgs : string
} }
type CertAuthentication =
{
//Path to your X.509 certificate in PEM format. Provide for Certificate Based Authentication
CertificatePath: string
}
type Authentication =
| NoAuth
| Token of RefreshableTokenOptions
| Cert of CertAuthentication
type EnginePerResourceSetting = type EnginePerResourceSetting =
{ {
@ -55,7 +66,7 @@ module Engine =
MaxDurationHours : float option MaxDurationHours : float option
/// The authentication options, when tokens are required /// The authentication options, when tokens are required
RefreshableTokenOptions : RefreshableTokenOptions option RefreshableTokenOptions : Authentication
/// The delay in seconds after invoking an API that creates a new resource /// The delay in seconds after invoking an API that creates a new resource
ProducerTimingDelay : int ProducerTimingDelay : int
@ -161,6 +172,8 @@ module Engine =
//in hours //in hours
time_budget : float option time_budget : float option
client_certificate_path: string option
token_refresh_cmd : string option token_refresh_cmd : string option
//seconds //seconds
@ -229,6 +242,8 @@ module Engine =
//seconds //seconds
token_refresh_interval = None token_refresh_interval = None
client_certificate_path = None
//if set - poll for resource to be created before //if set - poll for resource to be created before
//proceeding //proceeding
wait_for_async_resource_creation = true wait_for_async_resource_creation = true
@ -239,11 +254,13 @@ module Engine =
} }
static member FromEngineParameters (fuzzingMode: string option) (p : EngineParameters) = static member FromEngineParameters (fuzzingMode: string option) (p : EngineParameters) =
let tokenRefreshInterval, tokenRefreshCommand = let tokenRefreshInterval, tokenRefreshCommand, authCertificatePath =
match p.RefreshableTokenOptions with match p.RefreshableTokenOptions with
| None -> None, None | NoAuth -> None, None, None
| Some options -> | Token options ->
(Some options.RefreshInterval), (Some (sprintf "%s %s" options.RefreshExec options.RefreshArgs)) (Some options.RefreshInterval), (Some (sprintf "%s %s" options.RefreshExec options.RefreshArgs)), None
| Cert options ->
None, None, (Some options.CertificatePath)
{ {
Settings.Default with Settings.Default with
host = p.Host host = p.Host
@ -255,6 +272,7 @@ module Engine =
no_ssl = not p.UseSsl no_ssl = not p.UseSsl
no_tokens_in_logs = not p.ShowAuthToken no_tokens_in_logs = not p.ShowAuthToken
fuzzing_mode = fuzzingMode fuzzing_mode = fuzzingMode
client_certificate_path = authCertificatePath
token_refresh_cmd = tokenRefreshCommand token_refresh_cmd = tokenRefreshCommand
token_refresh_interval = tokenRefreshInterval token_refresh_interval = tokenRefreshInterval
max_request_execution_time = Option.defaultValue Settings.Default.max_request_execution_time p.MaxRequestExecutionTime max_request_execution_time = Option.defaultValue Settings.Default.max_request_execution_time p.MaxRequestExecutionTime