Skip to main content

Use the Lattice SDK for gRPC in Go

This page shows you how to set up the Lattice SDK for gRPC in Go and make a request.

Click to go to the gRPC SDK repository. By downloading and/or using, you agree to the terms of use. If you do not agree, do not use the SDK.

Install the SDK

To install the SDK:

  1. Start a new Go project.

  2. Initialize a new Go module with your specific module path.

    go mod init <your-module-path>
  3. Fetch the Go gRPC SDK and make it available to your integration:

    go get github.com/anduril/lattice-sdk-go
  4. Make any additional dependencies available in your integration. For the following example, you would need:

    go get google.golang.org/grpc
    go get google.golang.org/grpc/credentials

Connect to Lattice APIs

Establish a gRPC channel to connect to Lattice APIs:

  1. Implement the PerRPCCredentials interface that takes a bearer token:

    package main

    import (
    "context"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
    )

    // BearerTokenAuth supplies PerRPCCredentials from a given token.
    type BearerTokenAuth struct {
    Token string
    }

    // GetRequestMetadata gets the current request metadata, adding the bearer token.
    func (b *BearerTokenAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
    return map[string]string{
    "authorization": "Bearer " + b.Token,
    }, nil
    }

    // RequireTransportSecurity indicates whether the credentials requires transport security.
    func (b *BearerTokenAuth) RequireTransportSecurity() bool {
    return true // or false if you are developing/testing without TLS
    }
  2. Create the Entities API client instance with the authenticated gRPC channel. Replace $YOUR_BEARER_TOKEN with the token that you previously generated.


package main

import (
"log"

entitymanagerv1 "github.com/anduril/lattice-sdk-go/src/anduril/entitymanager/v1"
)

// ...PerRPCCredentials interface

func main() {
bearerToken := "$YOUR_BEARER_TOKEN" // Replace $YOUR_BEARER_TOKEN with your token. You must keep the word, Bearer, in the metadata string.
opts := []grpc.DialOption{
grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
grpc.WithPerRPCCredentials(&BearerTokenAuth{Token: bearerToken}),
}
conn, err := grpc.NewClient("$YOUR_LATTICE_URL:443", opts...)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()

em := entitymanagerv1.NewEntityManagerAPIClient(conn)
}

Allowing self-signed certificates

warning

Make sure you understand the implications of using self-signed certificates. This should only be used for testing.

In order to connect to a server that is using a self-signed certificate, please update the sample code above to not require transport security.

- grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
+ grpc.WithTransportCredentials(credentials.NewTLS(
&tls.Config{
InsecureSkipVerify: true,
})),

Example request

The following example combines the code snippets from above and makes a GetEntity request to the Entities API to fetch an entity from the Common Operational Picture

package main

import (
"context"
"log"

entitymanagerv1 "github.com/anduril/lattice-sdk-go/src/anduril/entitymanager/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)

// BearerTokenAuth supplies PerRPCCredentials from a given token.
type BearerTokenAuth struct {
Token string
}

// GetRequestMetadata gets the current request metadata, adding the bearer token.
func (b *BearerTokenAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{
"authorization": "Bearer " + b.Token,
}, nil
}

// RequireTransportSecurity indicates whether the credentials requires transport security.
func (b *BearerTokenAuth) RequireTransportSecurity() bool {
return true // or false if you are developing/testing without TLS
}

func main() {
bearerToken := "$YOUR_BEARER_TOKEN" // Replace $YOUR_BEARER_TOKEN with your token. You must keep the word, Bearer, in the metadata string.
opts := []grpc.DialOption{
grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")),
grpc.WithPerRPCCredentials(&BearerTokenAuth{Token: bearerToken}),
}
conn, err := grpc.NewClient("$YOUR_LATTICE_URL:443", opts...)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()

em := entitymanagerv1.NewEntityManagerAPIClient(conn)


ctx := context.Background()
request := &entitymanagerv1.GetEntityRequest{
EntityId: "$ENTITY_ID", // Replace $ENTITY_ID with the ID of the entity you published previously.
}
response, err := em.GetEntity(ctx, request)

if err != nil {
log.Fatalf("Error fetching entity: %v", err)
}
log.Printf("Response: %v", response)
}

Clean up your go.mod file and construct the vendor directory to store all your dependencies

go mod tidy
go mod vendor

Build and run the example

go build
go run .

If the request is successful and you replaced the entity ID then you should see the entity object you created when setting up your development environment. If you did not change the entity ID to a valid, existing entity, then you will get the following error:

ConnectError: [not_found] entity not found ENTITY_ID

This means you successfully authenticated and completed the call to your environment, but the entity does not exist. This is an expected error. If you get any other error then there is a problem with your code. Check that your Lattice environment URL and our bearer token are correct.

What's next