Skip to content

Instantly share code, notes, and snippets.

@prasincs
Created April 22, 2018 07:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prasincs/610b2d9b26d83972d9d3969415bdeb3a to your computer and use it in GitHub Desktop.
Save prasincs/610b2d9b26d83972d9d3969415bdeb3a to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"net/url"
"time"
duo_api "github.com/duosecurity/duo_api_golang"
)
type EnrollResponse struct {
Response struct {
ActivationBarcode string `json:"activation_barcode"`
ActivationCode string `json:"activation_code"`
Expiration int `json:"expiration"`
UserID string `json:"user_id"`
Username string `json:"username"`
} `json:"response"`
Stat string `json:"stat"`
}
type EnrollStatusResponse struct {
Response string `json:"response"`
Stat string `json:"stat"`
}
func main() {
duoIKey := flag.String("duo-ikey", "", "Duo Server Key")
duoSKey := flag.String("duo-skey", "", "Duo Server Key")
duoHost := flag.String("duo-host", "", "Duo Host")
userAgent := flag.String("user-agent", "cerberus-vpn", "Name of the client")
user := flag.String("user", "", "User to enroll")
enroll := flag.Bool("enroll", false, "Enroll the user email")
flag.Parse()
duoApi := duo_api.NewDuoApi(*duoIKey, *duoSKey, *duoHost, *userAgent)
req, contents, err := duoApi.Call("GET", "/auth/v2/ping", url.Values{})
if err != nil {
log.Printf("Failed to call /auth/v2/ping: %s", err)
}
fmt.Println("/auth/v2/ping", req.Status, string(contents))
req, contents, err = duoApi.SignedCall("GET", "/auth/v2/check", nil)
if err != nil {
log.Printf("Failed to call /auth/v2/ping: %s", err)
}
fmt.Println("/auth/v2/check", req.Status, string(contents))
if *user == "" {
return
}
preAuthValues := url.Values{}
preAuthValues.Set("username", *user)
req, contents, err = duoApi.SignedCall("POST", "/auth/v2/preauth", preAuthValues)
if err != nil {
log.Printf("Failed to call /auth/v2/preauth: %s", err)
}
fmt.Println("/auth/v2/preauth", req.Status, string(contents))
if *enroll {
enrollValues := url.Values{}
enrollValues.Set("username", *user)
req, contents, err = duoApi.SignedCall("POST", "/auth/v2/enroll", enrollValues)
if err != nil {
log.Printf("Failed to call /auth/v2/enroll: %s", err)
}
fmt.Println("/auth/v2/enroll", req.Status, string(contents))
enrollResponse := EnrollResponse{}
err := json.Unmarshal(contents, &enrollResponse)
if err != nil {
log.Printf("Failed to unmarshall response: %s", err)
}
fmt.Println("Navigate to this URL and sign up ", enrollResponse.Response.ActivationBarcode)
check:
// give the user some time
time.Sleep(10 * time.Second)
enrollStatusValues := url.Values{}
enrollStatusValues.Set("user_id", enrollResponse.Response.UserID)
enrollStatusValues.Set("activation_code", enrollResponse.Response.ActivationCode)
_, contents, err = duoApi.SignedCall("POST", "/auth/v2/enroll_status", enrollStatusValues)
if err != nil {
log.Printf("Failed to call /auth/v2/enroll_status: %s", err)
}
enrollStatusResponse := EnrollStatusResponse{}
err = json.Unmarshal(contents, &enrollStatusResponse)
if err != nil {
log.Printf("Failed to unmarshall response: %s", err)
}
switch enrollStatusResponse.Response {
case "success":
case "invalid":
log.Printf("Expired token")
case "waiting":
goto check
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment