83 lines
2.1 KiB
Go
83 lines
2.1 KiB
Go
// Copyright (C) MongoDB, Inc. 2017-present.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
// not use this file except in compliance with the License. You may obtain
|
|
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
package auth
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
)
|
|
|
|
// MongoDBAWS is the mechanism name for MongoDBAWS.
|
|
const MongoDBAWS = "MONGODB-AWS"
|
|
|
|
func newMongoDBAWSAuthenticator(cred *Cred) (Authenticator, error) {
|
|
if cred.Source != "" && cred.Source != "$external" {
|
|
return nil, newAuthError("MONGODB-AWS source must be empty or $external", nil)
|
|
}
|
|
return &MongoDBAWSAuthenticator{
|
|
source: cred.Source,
|
|
username: cred.Username,
|
|
password: cred.Password,
|
|
sessionToken: cred.Props["AWS_SESSION_TOKEN"],
|
|
}, nil
|
|
}
|
|
|
|
// MongoDBAWSAuthenticator uses AWS-IAM credentials over SASL to authenticate a connection.
|
|
type MongoDBAWSAuthenticator struct {
|
|
source string
|
|
username string
|
|
password string
|
|
sessionToken string
|
|
}
|
|
|
|
// Auth authenticates the connection.
|
|
func (a *MongoDBAWSAuthenticator) Auth(ctx context.Context, cfg *Config) error {
|
|
httpClient := cfg.HTTPClient
|
|
if httpClient == nil {
|
|
return errors.New("cfg.HTTPClient must not be nil")
|
|
}
|
|
adapter := &awsSaslAdapter{
|
|
conversation: &awsConversation{
|
|
username: a.username,
|
|
password: a.password,
|
|
token: a.sessionToken,
|
|
httpClient: httpClient,
|
|
},
|
|
}
|
|
err := ConductSaslConversation(ctx, cfg, a.source, adapter)
|
|
if err != nil {
|
|
return newAuthError("sasl conversation error", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type awsSaslAdapter struct {
|
|
conversation *awsConversation
|
|
}
|
|
|
|
var _ SaslClient = (*awsSaslAdapter)(nil)
|
|
|
|
func (a *awsSaslAdapter) Start() (string, []byte, error) {
|
|
step, err := a.conversation.Step(nil)
|
|
if err != nil {
|
|
return MongoDBAWS, nil, err
|
|
}
|
|
return MongoDBAWS, step, nil
|
|
}
|
|
|
|
func (a *awsSaslAdapter) Next(challenge []byte) ([]byte, error) {
|
|
step, err := a.conversation.Step(challenge)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return step, nil
|
|
}
|
|
|
|
func (a *awsSaslAdapter) Completed() bool {
|
|
return a.conversation.Done()
|
|
}
|