MSAL Golang how to get user profile - go

I am trying to integrate my Golang app with Azure using MSAL. I created Azure app and I wrote sample code to create public client . Below code worked.
package main
import (
"fmt"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
)
func main() {
publicClientApp, err := public.New("client_id", public.WithAuthority("https://login.microsoftonline.com/Enter_The_Tenant_Name_Here"))
if err != nil {
panic(err)
}
fmt.Println(publicClientApp)
}
I would like to know how I can use this publicClientApp to get user profile. I could not find anything much in MSAL documentation

I used Microsoft graph API to get the profile.

Related

Logging to stderr and stdout golang Google Cloud Platform

Currently running a go service on GCP however in the logs viewer every message is treated as an error.
Is there a generally advised way of logging to stderr and stdout depending on the log level. Ie errors to stderr and anything else to stdout.
I'm currently using the logrus package and have come across this implementation. Other ways i see achieving this while still using the same package is to pass the logger to each package that needs it or to create a global log object, neither of which i am too keen on.
https://github.com/microsoft/fabrikate/pull/252/commits/bd24d62d7c2b851ad6e7b36653eb0a6dc364474b#diff-ed0770fdbf87b0c6d536e33a99a8df9c
You can use Stackdriver library package for GoLang:
go get -u cloud.google.com/go/logging
Then you can use StandardLogger:
// Sample stdlogging writes log.Logger logs to the Stackdriver Logging.
package main
import (
"context"
"log"
"cloud.google.com/go/logging"
)
func main() {
ctx := context.Background()
// Sets your Google Cloud Platform project ID.
projectID := "YOUR_PROJECT_ID"
// Creates a client.
client, err := logging.NewClient(ctx, projectID)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
defer client.Close()
// Sets the name of the log to write to.
logName := "my-log"
logger := client.Logger(logName).StandardLogger(logging.Info)
// Logs "hello world", log entry is visible at
// Stackdriver Logs.
logger.Println("hello world")
}
Here you can find documentation on Google Cloud website
Update:
Alternatively you could give a try GCP formatter for logrus
This will not tie your app to Google Cloud Platform. However, it does not mean that on another platform you will not need to change your code to format output.
Using StackDriver library is the recommended solution for Google Cloud.
We use https://github.com/rs/zerolog with the following method called in our Init() method to setup the logging options at global level:
package main
import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"os"
)
// initializeLogging sets up the logging configuration for the service.
// Invoke this method in your Init() method.
func initializeLogging() {
// Set logging options for production development
if os.Getenv("ENV") != "DEV" {
// change the level field name to ensure these are parsed correctly in Stackdriver
zerolog.LevelFieldName = "severity"
// UNIX Time is faster and smaller than most timestamps
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
} else {
// Set logging options for local development
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
// Example log
log.Info().Msg("This is how you log at Info level")
}
I recommend the https://github.com/apsystole/log. You can swap either log and logrus imports for it. It is a small zero-dependency module, hence much lighter than logrus.

how to create a context object in google cloud run for firebase

I'm trying to create a context object, so that I can connect to firestore from cloud run, however, all the examples I find on the net basically say I need a context objects, examples I find online usually look like this:
ctx := context.Background()
client, err := firestore.NewClient(ctx, "projectID")
if err != nil {
fail(w, err.Error())
// TODO: Handle error.
}
You can find these examples in places like this one:
https://godoc.org/cloud.google.com/go/firestore#example-NewClient
Nowhere in this example is there an explanation of where to find the context object.
so I just get this error:
undefined: context
I think the documentation is just too confusing.
You should use r.Context() of http.Request object in the request handler instead of initializing a new detached context like context.Background().
The main purpose of contexts is to propagate them, and in Cloud Run you always process requests, so if you pass the request’s context, it’s the right thing to do.
I think in your case, “context” package is not imported. Make sure to use go 1.11+ in your Dockerfile and say:
import “context”
In Go, you need to import packages. For this statement ctx := context.Background() add to the top of your source file import "context" or merge with your existing import set.
Like most languages, the more experience you have the more the language makes sense and you just know what to do. Most languages are the same. In C/C++ you have the include statement, C# the using statement, in Python the import statement, etc.
Google has a large package of examples for using Go and Google Cloud Platform:
Google Cloud Examples in Go
I wrote an article that documents my 30-day journey to learn Go and Google Cloud Platform.
Google Cloud and Go – My Journey to Learn a new Language in 30 days
Given the plethora of 3 lines of code examples that are hard for beginners, and the lack of complete working examples online, like myself, here is a full working example, which is kinda what I needed when I started this task, I hope this helps anybody in the future.
package main
import (
"cloud.google.com/go/firestore" // https://godoc.org/cloud.google.com/go/firestore"
"context" // https://blog.golang.org/context
firebase "firebase.google.com/go"
"fmt"
"log"
"net/http"
"os"
)
func fail(w http.ResponseWriter, msg string) {
fmt.Fprintln(w, "fail:"+msg)
log.Println("fail:" + msg)
}
// State example code
type State struct {
Capital string `firestore:"capital"`
Population float64 `firestore:"pop"` // in millions
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
override := make(map[string]interface{})
ctx := context.Background()
client, err := firestore.NewClient(ctx, "YOURPID")// set GOOGLE_APPLICATION_CREDENTIALS env var
if err != nil {
fail(w, err.Error())
return
}
states := client.Collection("States")
ny := states.Doc("NewYork")
wr, err := ny.Create(ctx, State{
Capital: "Albany",
Population: 19.8,
})
fmt.Println(wr)
})
log.Fatal(http.ListenAndServe("0.0.0.0:8082", nil))
}

How to set broker.SubscriberOptions in go-micro

I am trying to configure a RabbitMQ broker using the go-micro framework. I have noticed that the broker interface in go-micro has a broker.SubscriberOptions struct which allows configuring the parameters I am looking for (AutoAck, Queue name and so on) however I am unable to figure out how to pass this when starting a broker.
This is how a simple rabbit go-micro setup would look like
package main
import (
"log"
"github.com/micro/go-micro/server"
"github.com/micro/go-plugins/broker/rabbitmq"
micro "github.com/micro/go-micro"
)
func main() {
// Create a new service. Optionally include some options here.
service := micro.NewService(
micro.Name("go-micro-rabbit"),
micro.Broker(rabbitmq.NewBroker()),
)
// Init will parse the command line flags.
service.Init()
// Register handler
proto.RegisterGreeterHandler(service.Server(), new(Greeter))
micro.RegisterSubscriber("micro-exchange", service.Server(), myFunc, server.SubscriberQueue("my-queue"))
// Run the server
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
The micro.RegisterSubscriber method takes in a list of server.SubscriberOption but does not allow me to set the broker.SubscriberOptions and the rabbitmq.NewBroker allows setting broker.Options but once again, not broker.SubscriberOptions
I have dug in the code of go-micro but have been unable to figure out how the broker.Subscribe method (Which exposes the correct struct) is called or by who.
Is this possible at all? Is it maybe something not yet fully fleshed out in the API?

How do I change the import file?

I have the following function in golang:
import (
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/aws/session"
"fmt"
)
func NewIAM() *SphinxIAM {
// awsConfig := aws.NewConfig()
sess, err := session.NewSession()
if err != nil {
fmt.Println("Failed to create session,", err)
return nil
}
session := &SphinxIAM{iam: iam.New(sess)}
return session
}
Now, I am getting the following error when I run this:
cannot use sess (type *session.Session) as type "github.com/aws/aws-sdk-go/aws/client".ConfigProvider in argument to iam.New:
*session.Session does not implement "github.com/aws/aws-sdk-go/aws/client".ConfigProvider (wrong type for ClientConfig method)
have ClientConfig(string, ...*"stash/cloud/sphinx/vendor/github.com/aws/aws-sdk-go/aws".Config) "stash/cloud/sphinx/vendor/github.com/aws/aws-sdk-go/aws/client".Config
want ClientConfig(string, ...*"github.com/aws/aws-sdk-go/aws".Config) "github.com/aws/aws-sdk-go/aws/client".Config
I have to change the method getting imported but how do I exactly do that?
Thanks!
The problem here is that your github.com/aws/aws-sdk-go/aws/session package is vendored, it is loaded from the folder stash/cloud/sphinx/vendor/github.com/aws/aws-sdk-go/aws.
But the function you want to pass it: iam.New() is not vendored, it does not come from the same vendor folder (stash/cloud/sphinx/vendor/xxx) but it comes directly from github.com/aws/aws-sdk-go/service/iam.
Either put both packages under the same vendor folder, or none. It is possible that one of your dependency tool does this, (e.g. glide), in which case you should instruct your tool to handle both as vendored.

Google Cloud Bigtable authentication with Go

I'm trying to insert a simple record as in GoDoc. But this returns,
rpc error: code = 7 desc = "User can't access project: tidy-groove"
When I searched for grpc codes, it says..
PermissionDenied Code = 7
// Unauthenticated indicates the request does not have valid
// authentication credentials for the operation.
I've enabled Big table in my console and created a cluster and a service account and recieved the json. What I'm doing wrong here?
package main
import (
"fmt"
"golang.org/x/net/context"
"golang.org/x/oauth2/google"
"google.golang.org/cloud"
"google.golang.org/cloud/bigtable"
"io/ioutil"
)
func main() {
fmt.Println("Start!")
put()
}
func getClient() *bigtable.Client {
jsonKey, err := ioutil.ReadFile("TestProject-7854ea9op741.json")
if err != nil {
fmt.Println(err.Error())
}
config, err := google.JWTConfigFromJSON(
jsonKey,
bigtable.Scope,
) // or bigtable.AdminScope, etc.
if err != nil {
fmt.Println(err.Error())
}
ctx := context.Background()
client, err := bigtable.NewClient(ctx, "tidy-groove", "asia-east1-b", "test1-bigtable", cloud.WithTokenSource(config.TokenSource(ctx)))
if err != nil {
fmt.Println(err.Error())
}
return client
}
func put() {
ctx := context.Background()
client := getClient()
tbl := client.Open("table1")
mut := bigtable.NewMutation()
mut.Set("links", "maps.google.com", bigtable.Now(), []byte("1"))
mut.Set("links", "golang.org", bigtable.Now(), []byte("1"))
err := tbl.Apply(ctx, "com.google.cloud", mut)
if err != nil {
fmt.Println(err.Error())
}
}
I've solved the problem. It's nothing wrong with the code, but config json itself. So anyone who out there want to authenticate and came here by google search... This code is correct and working perfectly. What I've done wrong is follows.
First I made a service account and got the json. But google warned me that im not an owner of project hence it wont be added to accept list but anyway it let me download the json.
Then I deleted that key from console and requested project owner to create a key for me.
There he has created another key with the same name I given.. And since he's the owner no error/warning msgs displayed and successfully json file was downloaded.
When I tried with that... my question begun. That's when i posted this question.
After that with no solutions. I asked owner to delete that key and create another key but with a different name..
Then it worked! It seems if you try to create a key with non-owner account and then again create with same name ( after deleting original of course ) has no effect. Hope this helps everyone out there :)
Take a look at: helloworld.go or search.go which uses GOOGLE_APPLICATION_CREDENTIALS environment variable.
For most environments, you no longer even need to set GOOGLE_APPLICATION_CREDENTIALS. Google Cloud Platform, Managed VMs or Google App Engine all have the right thing set for you. Your desktop environment will also be correct if you've used gcloud init or it's predecessor gcloud auth login followed by gcloud config set project <projectID>.

Resources