Reference
API
Go

Go Client API

💡

Before going through this guide, make sure you follow the Oso Cloud Quickstart to get your Oso Cloud API Key properly set in your environment.

First, install the go-oso-cloud package:

go get github.com/osohq/go-oso-cloud

Instantiating an Oso Cloud client

Oso Cloud library provides an oso.NewClient function that takes your Oso Cloud URL and API key:

import (
  ...
 
  oso "github.com/osohq/go-oso-cloud"
)
 
osoClient := oso.NewClient("https://cloud.osohq.com", YOUR_API_KEY)
 
// Later:
e := osoClient.Tell("has_role", user, role, resource)
if e != nil {
	// Handle error.
}
 
// Wherever authorization needs to be performed:
allowed, e := osoClient.Authorize(user, action, resource)
if e != nil {
	// Handle error.
}
 
if allowed {
	// Action is allowed.
}

Passing application entities into the client

Under the hood, Oso Cloud represents an entity in your application as a combination of a type and an ID, which together uniquely identify the entity. The Go client represents these entities as oso.Instance structs with both Type and ID properties. For example:

alice := oso.Instance{Type: "User", ID: "alice"}
anvilsRepository := oso.Instance{Type: "Repository", ID: "anvils"}

You will pass structs like these into nearly every function call you make to the Go client.

Management API

Add fact: osoClient.Tell(name, ...args)

Adds a fact named name with the provided arguments. Example:

osoClient.Tell(
  "has_role",
  oso.Instance{Type: "User", ID: "bob"},
  oso.String("owner"),
  oso.Instance{Type: "Organization", ID: "acme"}
)

Add many facts: osoClient.BulkTell(facts)

ℹ️

For Oso Cloud sandbox accounts, BulkTell, BulkDelete, and Bulk calls are limited to 20 facts. If you attempt to send more than 20 facts, the CLI will return an error.

Adds many facts at once. Example:

osoClient.BulkTell([]oso.Fact{
  oso.Fact{
    Name: "has_role",
    Args: []oso.Instance{
      oso.Instance{Type: "User", ID: "bob"},
      oso.String("owner"),
      oso.Instance{Type: "Organization", ID: "acme"}
    },
  },
  oso.Fact{
    Name: "has_role",
    Args: []oso.Instance{
      oso.Instance{Type: "User", ID: "bob"},
      oso.String("maintainer"),
      oso.Instance{Type: "Repository", ID: "anvil"}
    },
  },
})

Delete fact: osoClient.Delete(name, ...args)

Deletes a fact. Does not throw an error if the fact is not found. Example:

osoClient.Delete(
  "has_role",
  oso.Instance{Type: "User", ID: "bob"},
  oso.String("maintainer"),
  oso.Instance{Type: "Repository", ID: "anvil"}
)

Delete many facts: osoClient.BulkDelete(facts)

Deletes many facts at once. Does not throw an error when some of the facts are not found. Example:

osoClient.BulkDelete([]oso.Fact{
  oso.Fact{
    Name: "has_role",
    Args: []oso.Instance{
      oso.Instance{Type: "User", ID: "bob"},
      oso.String("owner"),
      oso.Instance{Type: "Organization", ID: "acme"}
    },
  },
  oso.Fact{
    Name: "has_role",
    Args: []oso.Instance{
      oso.Instance{Type: "User", ID: "bob"},
      oso.String("maintainer"),
      oso.Instance{Type: "Repository", ID: "anvil"}
    },
  },
})
 

Transactionally delete and add facts: oso.Bulk(delete, tell)

Deletes and adds many facts in one atomic transaction. The deletions are performed before the adds. Does not throw an error when the facts to delete are not found. Example:

oso.Bulk([]oso.Fact{
  oso.Fact{
    Name: "has_role",
    Args: []oso.Instance{
      oso.Instance{Type: "User", ID: "bob"},
      oso.String("viewer"),
      oso.Instance{Type: "Repository", ID: "anvil"}
    },
  }
}, []oso.Fact{
  oso.Fact{
    Name: "has_role",
    Args: []oso.Instance{
      oso.Instance{Type: "User", ID: "bob"},
      oso.String("maintainer"),
      oso.Instance{Type: "Repository", ID: "anvil"}
    },
  }
})

List facts: oso.Get(name, ...args)

ℹ️

For Oso Cloud sandbox accounts, Get calls are limited to 1000 results. If you have more than 1000 facts, the function will return an error.

Lists facts that are stored in Oso Cloud. Can be used to check the existence of a particular fact, or used to fetch all facts that have a particular argument:

// Get one fact:
oso.Get(
  "has_role",
  oso.Instance{Type: "User", ID: "bob"},
  oso.String("admin"),
  oso.Instance{Type: "Repository", ID: "anvils"}
)
// => []oso.Fact{oso.Fact{
//   Name: "has_role",
//   Args: []oso.Instance{
//     {Type: "User", ID: "bob"},
//     {Type: "String", ID: "admin"},
//     {Type: "Repository", ID: "anvils"}
//   }
// }}
 
// List all roles on the `anvils` repo
oso.Get("has_role", nil, nil, oso.Instance{Type: "Repository", ID: "anvils"})
// => []oso.Fact{oso.Fact{
//   Name: "has_role",
//   Args: []oso.Instance{
//     {Type: "User", ID: "bob"},
//     {Type: "String", ID: "admin"},
//     {Type: "Repository", ID: "anvils"}
//   }
// },
// ...other has_role facts
// }

Note that nil behaves like a wildcard: passing nil, nil, anvils means "find all facts where anvils is the third argument, regardless of other arguments".

Query for anything: oso.Query(rule)

Query Oso Cloud for any predicate and any combination of concrete and wildcard arguments. Unlike oso.Get, which only lists facts you've added, you can use oso.query to list derived information about any rule in your policy. Example:

// Query for all the repos `User:bob` can `read`
osoClient.Query(
  "allow",
  &oso.Instance{Type: "User", ID: "bob"},
  &oso.String("read"),
  &oso.Instance{Type: "Repository"}
)
// => []oso.Fact{{
//   Name: "allow",
//   Args: []oso.Instance{
//     {Type: "User", ID: "bob"},
//     {Type: "String", ID: "read"},
//     {Type: "Repository", ID: "acme"}
//   }
// }, {
//   Name: "allow",
//   Args: []oso.Instance{
//     {Type: "User", ID: "bob"},
//     {Type: "String", ID: "read"},
//     {Type: "Repository", ID: "anvils"}
//   }
// }
 
// Query for all the objects `User:admin` can `read`
osoClient.Query(
  "allow",
  &oso.Instance{Type: "User", ID: "admin"},
  &oso.String("read"),
  nil
)
// => []oso.Fact{{
//   // `User:admin` can `read` anything
//   Name: "allow",
//   Args: []oso.Instance{
//     oso.Instance{Type: "User", ID: "admin"},
//     oso.Instance{Type: "String", ID: "read"},
//     nil
//   }
// }}

Note that nil behaves like a wildcard. Passing "allow", nil, nil, anvils means "find anyone who can do anything to anvils". nil also behaves like a wildcard in return values from osoClient.Query. Additionally, if you want to query over all instances of a particular type, pass an oso.Instance with a Type but no ID. For example, "allow", bob, "read", oso.Instance{Type: "Repository"} will query for all the objects of type "Repository" that bob can read.

Learn more about how to query Oso Cloud.

Check API

Context facts

ℹ️

For Oso Cloud sandbox accounts, the number of context facts per request is limited to 20.

Each Check API method has a WithContext variant to which you may provide a slice of context facts. When Oso Cloud performs a check, it will consider these context facts in addition to any other facts you've previously added. Context facts are only used in the API call in which they're provided-- they do not persist across requests. Learn more about context facts.

Check a permission: osoClient.Authorize(actor, action, resource)

Determines whether or not an action is allowed, based on a combination of authorization data and policy logic. Example:

allowed, e := osoClient.Authorize(user, "read", anvilsRepository)
if e != nil {
	// Handle error.
}
if allowed {
	// Action is allowed.
}

You may use osoClient.AuthorizeWithContext to provide a slice of context facts. Example:

allowed, e := osoClient.AuthorizeWithContext(user, "read", issueOnAnvilsRepository, []Fact{
  { // a context fact
    Name: "has_relation",
    Args: []oso.Instance{issueOnAnvilsRepository, oso.String("parent"), anvilsRepository},
  },
})

Check authorized resources: osoClient.AuthorizeResources(actor, action, resources)

Returns a subset of resources on which an actor can perform a particular action. Ordering and duplicates, if any exist, are preserved. Example:

results, e := osoClient.AuthorizeResources(user, "read", []oso.Instance{anvilsRepository, acmeRepository})

You may use osoClient.AuthorizeResourcesWithContext to provide a slice of context facts. Example:

results, e := osoClient.AuthorizeResourcesWithContext(user, "read", []oso.Instance{issueOnAnvilsRepository, issueOnAcmeRepository}, []Fact{
  // context facts
  {
    Name: "has_relation",
    Args: []oso.Instance{issueOnAnvilsRepository, oso.String("parent"), anvilsRepository},
  },
  {
    Name: "has_relation",
    Args: []oso.Instance{issueOnAcmeRepository, oso.String("parent"), acmeRepository},
  },
})

List authorized resources: osoClient.List(actor, action, resourceType)

Fetches a list of resource IDs on which an actor can perform a particular action. Example:

repositoryIds, e := osoClient.List(user, "read", "Repository")

You may use osoClient.ListWithContext to provide a slice of context facts. Example:

repositoryIds, e := osoClient.ListWithContext(user, "read", "Issue", []Fact{
  // context facts
  Fact{
    Name: "has_relation",
    Args: []oso.Instance{issueOnAnvilsRepository, oso.String("parent"), anvilsRepository},
  },
  {
    Name: "has_relation",
    Args: []oso.Instance{issueOnAcmeRepository, oso.String("parent"), acmeRepository},
  },
})

List authorized actions: osoClient.Actions(actor, resource)

Fetches a list of actions which an actor can perform on a particular resource. Example:

actions, e := osoClient.Actions(user, anvilsRepository)

You may use osoClient.ActionsWithContext to provide a slice of context facts. Example:

actions, e := osoClient.ActionsWithContext(user, issueOnAnvilsRepository, []Fact{
  { // a context fact
    Name: "has_relation",
    Args: []oso.Instance{issueOnAnvilsRepository, oso.String("parent"), anvilsRepository},
  },
})

Policy API

Update the active policy: oso.Policy(policy)

Updates the policy in Oso Cloud. The string passed into this method should be written in Polar. Example:

e := oso.Policy("actor User {}")

Talk to an Oso Engineer

Our team is happy to help you get started with Oso Cloud. If you'd like to learn more about using Oso Cloud in your app or have any questions about this guide, schedule a 1x1 with an Oso engineer.

Get started with Oso Cloud →

Last updated on September 30, 2022