As we reevaluate how to best support and maintain Staging Ref in the future, we encourage development teams using this environment to highlight their use cases in the following issue: https://gitlab.com/gitlab-com/gl-infra/software-delivery/framework/software-delivery-framework-issue-tracker/-/issues/36.

Skip to content
Snippets Groups Projects
Commit d791ce33 authored by James Sandlin's avatar James Sandlin
Browse files

add temp files

parent ac9d9bd7
No related branches found
No related tags found
No related merge requests found
package twofactorverify
import (
"context"
"fmt"
"io"
"sync"
"time"
"gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/gitlab-shell/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/internal/command/readwriter"
"gitlab.com/gitlab-org/gitlab-shell/internal/config"
"gitlab.com/gitlab-org/gitlab-shell/internal/gitlabnet/twofactorverify"
)
type Command struct {
Config *config.Config
Client *twofactorverify.Client
Args *commandargs.Shell
ReadWriter *readwriter.ReadWriter
}
type Result struct {
Error error
Status string
Success bool
}
// A context to be used as a merged context for both push && OTP entry
type waitContext struct {
mu sync.Mutex
mainCtx context.Context
ctx context.Context
done chan struct {}
err error
}
var (
mu sync.RWMutex
// TODO: make timeout configurable
ctxMaxTime = time.Second + 30
)
func (c *Command) Execute(ctx context.Context) error {
ctxlog := log.ContextLogger(ctx)
// config.GetHTTPClient isn't thread-safe so save Client in struct for concurrency
// workaround until #518 is fixed
var err error
c.Client, err = twofactorverify.NewClient(c.Config)
if err != nil {
ctxlog.WithError(err).Error("twofactorverify: execute: OTP verification failed")
return err
}
//var mainCancel context.CancelFunc
//mainContext, mainCancel = context.WithCancel(ctx)
timeoutCtx, timeoutCancel := context.WithTimeout(ctx, ctxMaxTime)
defer timeoutCancel()
// Create Result Channel
// It seems to me that if we use the same channel for each request & defer it multiple times things will fail. So I'm not doing that.
//resultChannel := make(chan Result)
// Time before forced task cancellation
timeoutCh := time.After(ctxMaxTime)
// Send push Auth Request
pushAuth := make(chan Result)
go func() {
defer close(pushAuth)
status, success, err := c.pushAuth(timeoutCtx)
ctxlog.Info("pushAuth.status = ", status)
ctxlog.Info("pushAuth.success = ", success)
ctxlog.Info("pushAuth.err = ", err)
select {
case <-timeoutCtx.Done(): // push cancelled by manual OTP
resultC <- Result{Error: nil, Status: "cancelled", Success: false}
default:
resultC <- Result{Error: err, Status: status, Success: success}
cancelTimeout()
}
}()
// Send OTP Auth Request
otpAuth := make(chan Result)
go func(){
defer close(otpAuth)
ctxlog.Info("twofactorverify: waiting for user input.")
otpAnswer := c.getOTP(mainCtx)
ctxlog.Info("otpAnswer = ", otpAnswer)
}()
//
//// Wait until tasks completed or time.After event occurred.
select {
case <- tasksCancelled:
ctxlog.Info("case tasksCancelled")
ctxlog.Info(pushAuth)
case <- timeoutCh:
ctxlog.Info("case Timeout")
// Wait until all done.
<-tasksCancelled
}
//
////timeoutCtx, cancelTimeout := context.WithTimeout(ctx, ctxTimeout)
//context, cancelVerify := context.WithCancel(timeoutCtx)
//pushCtx, cancelPush := context.WithCancel(timeoutCtx)
//defer cancelTimeout()
//
//// Background push notification with timeout
//pushauth := make(chan Result)
//go func() {
// defer close(pushauth)
// status, success, err := c.pushAuth(pushCtx)
//
// select {
// case <-pushCtx.Done(): // push cancelled by manual OTP
// pushauth <- Result{Error: nil, Status: "cancelled", Success: false}
// default:
// pushauth <- Result{Error: err, Status: status, Success: success}
// cancelVerify()
// }
//}()
//
//// Also allow manual OTP entry while waiting for push, with same timeout as push
//verify := make(chan Result)
//go func() {
// defer close(verify)
// ctxlog.Info("twofactorverify: execute: waiting for user input")
// answer := ""
// answer = c.getOTP(verifyCtx)
//
// select {
// case <-verifyCtx.Done(): // manual OTP cancelled by push
// verify <- Result{Error: nil, Status: "cancelled", Success: false}
// default:
// cancelPush()
// ctxlog.Info("twofactorverify: execute: verifying entered OTP")
// status, success, err := c.verifyOTP(verifyCtx, answer)
// ctxlog.WithError(err).Info("twofactorverify: execute: OTP verified")
// verify <- Result{Error: err, Status: status, Success: success}
// }
//}()
//
//for {
// select {
// case res := <-verify: // manual OTP
// if res.Status == "cancelled" {
// // verify cancelled; don't print anything
// } else if res.Status == "" {
// // channel closed; don't print anything
// } else {
// fmt.Fprint(c.ReadWriter.Out, res.Status)
// return nil
// }
// case res := <-pushauth: // push
// if res.Status == "cancelled" {
// // push cancelled; don't print anything
// } else if res.Status == "" {
// // channel closed; don't print anything
// } else {
// fmt.Fprint(c.ReadWriter.Out, res.Status)
// return nil
// }
// case <-timeoutCtx.Done(): // push timed out
// fmt.Fprint(c.ReadWriter.Out, "\nOTP verification timed out\n")
// return nil
// }
//}
//
return nil
}
func (c *Command) getOTP(ctx context.Context) string {
prompt := "OTP: "
fmt.Fprint(c.ReadWriter.Out, prompt)
var answer string
otpLength := int64(64)
reader := io.LimitReader(c.ReadWriter.In, otpLength)
if _, err := fmt.Fscanln(reader, &answer); err != nil {
log.ContextLogger(ctx).WithError(err).Debug("twofactorverify: getOTP: Failed to get user input")
}
return answer
}
func (c *Command) verifyOTP(ctx context.Context, otp string) (status string, success bool, err error) {
reason := ""
success, reason, err = c.Client.VerifyOTP(ctx, c.Args, otp)
fmt.Println("success = " , success)
fmt.Println("reason = ", reason)
fmt.Println("err = ", err)
if success {
status = fmt.Sprintf("\nOTP validation successful. Git operations are now allowed.\n")
} else {
if err != nil {
status = fmt.Sprintf("\nOTP validation failed.\n%v\n", err)
} else {
status = fmt.Sprintf("\nOTP validation failed.\n%v\n", reason)
}
}
err = nil
return
}
func (c *Command) pushAuth(ctx context.Context) (status string, success bool, err error) {
reason := ""
success, reason, err = c.Client.PushAuth(ctx, c.Args)
if success {
status = fmt.Sprintf("\nPush OTP validation successful. Git operations are now allowed.\n")
} else {
if err != nil {
status = fmt.Sprintf("\nPush OTP validation failed.\n%v\n", err)
} else {
status = fmt.Sprintf("\nPush OTP validation failed.\n%v\n", reason)
}
}
return
}
package twofactorverify
import (
"context"
"fmt"
"io"
"time"
"gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/gitlab-shell/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/internal/command/readwriter"
"gitlab.com/gitlab-org/gitlab-shell/internal/config"
"gitlab.com/gitlab-org/gitlab-shell/internal/gitlabnet/twofactorverify"
)
type Command struct {
Config *config.Config
Client *twofactorverify.Client
Args *commandargs.Shell
ReadWriter *readwriter.ReadWriter
}
type Result struct {
Error error
Status string
Success bool
}
func (c *Command) Execute(ctx context.Context) error {
ctxlog := log.ContextLogger(ctx)
// config.GetHTTPClient isn't thread-safe so save Client in struct for concurrency
// workaround until #518 is fixed
var err error
c.Client, err = twofactorverify.NewClient(c.Config)
if err != nil {
ctxlog.WithError(err).Error("twofactorverify: execute: OTP verification failed")
return err
}
// Create timeout context
// TODO: make timeout configurable
const ctxTimeout = 30
timeoutCtx, cancelTimeout := context.WithTimeout(ctx, ctxTimeout*time.Second)
defer cancelTimeout()
// Create result channel
resultC := make(chan Result)
// Background push notification with timeout
go func() {
defer close(resultC)
status, success, err := c.pushAuth(timeoutCtx)
select {
case <-timeoutCtx.Done(): // push cancelled by manual OTP
resultC <- Result{Error: nil, Status: "cancelled", Success: false}
default:
resultC <- Result{Error: err, Status: status, Success: success}
cancelTimeout()
}
}()
// Also allow manual OTP entry while waiting for push, with same timeout as push
go func() {
defer close(resultC)
ctxlog.Info("twofactorverify: execute: waiting for user input")
answer := ""
answer = c.getOTP(timeoutCtx)
select {
case <-timeoutCtx.Done(): // manual OTP cancelled by push
resultC <- Result{Error: nil, Status: "cancelled", Success: false}
default:
cancelTimeout()
ctxlog.Info("twofactorverify: execute: verifying entered OTP")
status, success, err := c.verifyOTP(timeoutCtx, answer)
ctxlog.WithError(err).Info("twofactorverify: execute: OTP verified")
resultC <- Result{Error: err, Status: status, Success: success}
}
}()
for {
select {
case res := <-resultC:
if res.Status == "cancelled" {
// request cancelled; don't print anything
} else if res.Status == "" {
// channel closed; don't print anything
} else {
fmt.Fprint(c.ReadWriter.Out, res.Status)
return nil
}
case <-timeoutCtx.Done(): // push timed out
fmt.Fprint(c.ReadWriter.Out, "\nOTP verification timed out\n")
return nil
}
}
return nil
}
func (c *Command) getOTP(ctx context.Context) string {
prompt := "OTP: "
fmt.Fprint(c.ReadWriter.Out, prompt)
var answer string
otpLength := int64(64)
reader := io.LimitReader(c.ReadWriter.In, otpLength)
if _, err := fmt.Fscanln(reader, &answer); err != nil {
log.ContextLogger(ctx).WithError(err).Debug("twofactorverify: getOTP: Failed to get user input")
}
return answer
}
func (c *Command) verifyOTP(ctx context.Context, otp string) (status string, success bool, err error) {
fmt.Sprintf("verifyOTP")
reason := ""
success, reason, err = c.Client.VerifyOTP(ctx, c.Args, otp)
fmt.Sprintf("\nSUCCESS = #{success}\n")
fmt.Sprintf("\nREASON = #{reason}\n")
fmt.Sprintf("\nERR = #{err}\n")
if success {
status = fmt.Sprintf("\nOTP validation successful. Git operations are now allowed.\n")
} else {
if err != nil {
status = fmt.Sprintf("\nOTP validation failed.\n%v\n", err)
} else {
status = fmt.Sprintf("\nOTP validation failed.\n%v\n", reason)
}
}
err = nil
return
}
func (c *Command) pushAuth(ctx context.Context) (status string, success bool, err error) {
reason := ""
success, reason, err = c.Client.PushAuth(ctx, c.Args)
if success {
status = fmt.Sprintf("\nPush OTP validation successful. Git operations are now allowed.\n")
} else {
if err != nil {
status = fmt.Sprintf("\nPush OTP validation failed.\n%v\n", err)
} else {
status = fmt.Sprintf("\nPush OTP validation failed.\n%v\n", reason)
}
}
return
}
package twofactorverify
import (
"context"
"fmt"
"io"
"time"
"gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/gitlab-shell/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/internal/command/readwriter"
"gitlab.com/gitlab-org/gitlab-shell/internal/config"
"gitlab.com/gitlab-org/gitlab-shell/internal/gitlabnet/twofactorverify"
)
type Command struct {
Config *config.Config
Client *twofactorverify.Client
Args *commandargs.Shell
ReadWriter *readwriter.ReadWriter
}
type Result struct {
Error error
Status string
Success bool
}
func (c *Command) Execute(ctx context.Context) error {
ctxlog := log.ContextLogger(ctx)
// config.GetHTTPClient isn't thread-safe so save Client in struct for concurrency
// workaround until #518 is fixed
var err error
c.Client, err = twofactorverify.NewClient(c.Config)
if err != nil {
ctxlog.WithError(err).Error("twofactorverify: execute: OTP verification failed")
return err
}
// Create timeout context
// TODO: make timeout configurable
const ctxTimeout = 30
timeoutCtx, cancelTimeout := context.WithTimeout(ctx, ctxTimeout*time.Second)
verifyCtx, cancelVerify := context.WithCancel(timeoutCtx)
pushCtx, cancelPush := context.WithCancel(timeoutCtx)
defer cancelTimeout()
// Background push notification with timeout
pushauth := make(chan Result)
go func() {
defer close(pushauth)
status, success, err := c.pushAuth(pushCtx)
select {
case <-pushCtx.Done(): // push cancelled by manual OTP
pushauth <- Result{Error: nil, Status: "cancelled", Success: false}
default:
pushauth <- Result{Error: err, Status: status, Success: success}
cancelVerify()
}
}()
// Also allow manual OTP entry while waiting for push, with same timeout as push
verify := make(chan Result)
go func() {
defer close(verify)
ctxlog.Info("twofactorverify: execute: waiting for user input")
answer := ""
answer = c.getOTP(verifyCtx)
select {
case <-verifyCtx.Done(): // manual OTP cancelled by push
verify <- Result{Error: nil, Status: "cancelled", Success: false}
default:
cancelPush()
ctxlog.Info("twofactorverify: execute: verifying entered OTP")
status, success, err := c.verifyOTP(verifyCtx, answer)
ctxlog.WithError(err).Info("twofactorverify: execute: OTP verified")
verify <- Result{Error: err, Status: status, Success: success}
}
}()
for {
select {
case res := <-verify: // manual OTP
if res.Status == "cancelled" {
// verify cancelled; don't print anything
} else if res.Status == "" {
// channel closed; don't print anything
} else {
fmt.Fprint(c.ReadWriter.Out, res.Status)
return nil
}
case res := <-pushauth: // push
if res.Status == "cancelled" {
// push cancelled; don't print anything
} else if res.Status == "" {
// channel closed; don't print anything
} else {
fmt.Fprint(c.ReadWriter.Out, res.Status)
return nil
}
case <-timeoutCtx.Done(): // push timed out
fmt.Fprint(c.ReadWriter.Out, "\nOTP verification timed out\n")
return nil
}
}
return nil
}
func (c *Command) getOTP(ctx context.Context) string {
prompt := "OTP: "
fmt.Fprint(c.ReadWriter.Out, prompt)
var answer string
otpLength := int64(64)
reader := io.LimitReader(c.ReadWriter.In, otpLength)
if _, err := fmt.Fscanln(reader, &answer); err != nil {
log.ContextLogger(ctx).WithError(err).Debug("twofactorverify: getOTP: Failed to get user input")
}
return answer
}
func (c *Command) verifyOTP(ctx context.Context, otp string) (status string, success bool, err error) {
reason := ""
success, reason, err = c.Client.VerifyOTP(ctx, c.Args, otp)
if success {
status = fmt.Sprintf("\nOTP validation successful. Git operations are now allowed.\n")
} else {
if err != nil {
status = fmt.Sprintf("\nOTP validation failed.\n%v\n", err)
} else {
status = fmt.Sprintf("\nOTP validation failed.\n%v\n", reason)
}
}
err = nil
return
}
func (c *Command) pushAuth(ctx context.Context) (status string, success bool, err error) {
reason := ""
success, reason, err = c.Client.PushAuth(ctx, c.Args)
if success {
status = fmt.Sprintf("\nPush OTP validation successful. Git operations are now allowed.\n")
} else {
if err != nil {
status = fmt.Sprintf("\nPush OTP validation failed.\n%v\n", err)
} else {
status = fmt.Sprintf("\nPush OTP validation failed.\n%v\n", reason)
}
}
return
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment