1// Package mongodb provides Mongo DB dataplane clients for Microsoft Azure CosmosDb Services. 2package mongodb 3 4// Copyright 2017 Microsoft Corporation 5// 6// Licensed under the Apache License, Version 2.0 (the "License"); 7// you may not use this file except in compliance with the License. 8// You may obtain a copy of the License at 9// 10// http://www.apache.org/licenses/LICENSE-2.0 11// 12// Unless required by applicable law or agreed to in writing, software 13// distributed under the License is distributed on an "AS IS" BASIS, 14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15// See the License for the specific language governing permissions and 16// limitations under the License. 17 18import ( 19 "context" 20 "crypto/tls" 21 "fmt" 22 "net" 23 "strings" 24 25 "github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2015-04-08/documentdb" 26 "github.com/Azure/go-autorest/autorest" 27 "github.com/Azure/go-autorest/autorest/adal" 28 "github.com/Azure/go-autorest/autorest/azure" 29 "github.com/globalsign/mgo" 30) 31 32const ( 33 cosmosDbConnectionPort = 10255 34) 35 36// NewMongoDBClientWithConnectionString returns a MongoDb session to communicate with CosmosDB using a connection string. 37func NewMongoDBClientWithConnectionString(connectionString string) (*mgo.Session, error) { 38 39 // strip out the "ssl=true" option as MongoDb driver does not support by default SSL. 40 connectionString = strings.Replace(connectionString, "ssl=true", "", -1) 41 dialInfo, err := mgo.ParseURL(connectionString) 42 43 if err != nil { 44 return nil, err 45 } 46 47 return NewMongoDBClient(dialInfo) 48} 49 50// NewMongoDBClientWithCredentials returns a MongoDb session to communicate with CosmosDB using a username and a password. 51func NewMongoDBClientWithCredentials(username, password, host string) (*mgo.Session, error) { 52 53 dialInfo := &mgo.DialInfo{ 54 Addrs: []string{fmt.Sprintf("%s:%d", host, cosmosDbConnectionPort)}, 55 Username: username, 56 Password: password, 57 } 58 59 return NewMongoDBClient(dialInfo) 60} 61 62// NewMongoDBClientWithSPToken returns a session to communicate with CosmosDB using an auth token. 63func NewMongoDBClientWithSPToken(spToken *adal.ServicePrincipalToken, subscriptionID, resourceGroup, account string, environment azure.Environment) (*mgo.Session, error) { 64 65 authorizer := autorest.NewBearerAuthorizer(spToken) 66 67 cosmosDbClient := documentdb.NewDatabaseAccountsClientWithBaseURI(environment.ResourceManagerEndpoint, subscriptionID) 68 cosmosDbClient.Authorizer = authorizer 69 cosmosDbClient.AddToUserAgent("dataplane mongodb") 70 71 result, err := cosmosDbClient.ListConnectionStrings(context.Background(), resourceGroup, account) 72 73 if err != nil { 74 return nil, err 75 } 76 77 connectionStrings := *result.ConnectionStrings 78 79 for _, connectionString := range connectionStrings { 80 session, err := NewMongoDBClientWithConnectionString(*connectionString.ConnectionString) 81 82 if session != nil && err == nil { 83 return session, nil 84 } 85 } 86 87 return nil, err 88} 89 90// NewMongoDBClientWithMSI returns a MongoDB session to communicate with CosmosDB using MSI. 91func NewMongoDBClientWithMSI(subscriptionID, resourceGroup, account string, environment azure.Environment) (*mgo.Session, error) { 92 93 msiEndpoint, err := adal.GetMSIVMEndpoint() 94 spToken, err := adal.NewServicePrincipalTokenFromMSI(msiEndpoint, environment.ResourceManagerEndpoint) 95 96 if err != nil { 97 return nil, err 98 } 99 100 return NewMongoDBClientWithSPToken(spToken, subscriptionID, resourceGroup, account, environment) 101} 102 103// NewMongoDBClient returns a MongoDB session to communicate with CosmosDB. 104func NewMongoDBClient(dialInfo *mgo.DialInfo) (*mgo.Session, error) { 105 106 dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) { 107 return tls.Dial("tcp", addr.String(), &tls.Config{}) 108 } 109 110 session, err := mgo.DialWithInfo(dialInfo) 111 112 if err != nil { 113 return nil, err 114 } 115 116 return session, nil 117} 118