sdk

package module
v0.2.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 14, 2024 License: MIT Imports: 18 Imported by: 3

README

go-sdk

A lightweight Go SDK for use within OpenFaaS functions and to control the OpenFaaS gateway.

For use within any Go code (not just OpenFaaS Functions):

  • Client - A client for the OpenFaaS REST API

For use within functions:

  • ReadSecret() - Read a named secret from within an OpenFaaS Function
  • ReadSecrets() - Read all available secrets returning a queryable map

Authentication helpers (See: Authentication with IAM):

  • ServiceAccountTokenSource - An implementation of the TokenSource interface to get an ID token by reading a Kubernetes projected service account token from /var/secrets/tokens/openfaas-token or the path set by the token_mount_path environment variable.

Usage

import "github.com/openfaas/go-sdk"

Construct a new OpenFaaS client and use it to access the OpenFaaS gateway API.

gatewayURL, _ := url.Parse("http://127.0.0.1:8080")
auth := &sdk.BasicAuth{
    Username: username,
    Password: password,
}

client := sdk.NewClient(gatewayURL, auth, http.DefaultClient)

namespace, err := client.GetNamespaces(context.Background())

Authentication with IAM

To authenticate with an OpenFaaS deployment that has Identity and Access Management (IAM) enabled, the client needs to exchange an ID token for an OpenFaaS ID token.

To get a token that can be exchanged for an OpenFaaS token you need to implement the TokenSource interface.

This is an example of a token source that gets a service account token mounted into a pod with ServiceAccount token volume projection.

type ServiceAccountTokenSource struct{}

func (ts *ServiceAccountTokenSource) Token() (string, error) {
	tokenMountPath := getEnv("token_mount_path", "/var/secrets/tokens")
	if len(tokenMountPath) == 0 {
		return "", fmt.Errorf("invalid token_mount_path specified for reading the service account token")
	}

	idTokenPath := path.Join(tokenMountPath, "openfaas-token")
	idToken, err := os.ReadFile(idTokenPath)
	if err != nil {
		return "", fmt.Errorf("unable to load service account token: %s", err)
	}

	return string(idToken), nil
}

The service account token returned by the TokenSource is automatically exchanged for an OpenFaaS token that is then used in the Authorization header for all requests made to the API.

If the OpenFaaS token is expired the TokenSource is asked for a token and the token exchange will run again.

gatewayURL, _ := url.Parse("https://gw.openfaas.example.com")

auth := &sdk.TokenAuth{
    TokenURL "https://gw.openfaas.example.com/oauth/token",
    TokenSource: &ServiceAccountTokenSource{}
}

client := sdk.NewClient(gatewayURL, auth, http.DefaultClient)

Authentication with Federated Gateway

func Test_ClientCredentials(t *testing.T) {
	clientID := ""
	clientSecret := ""
	tokenURL := "https://keycloak.example.com/realms/openfaas/protocol/openid-connect/token"
	scope := "email"
	grantType := "client_credentials"

	audience = "" // Optional

	auth := NewClientCredentialsTokenSource(clientID, clientSecret, tokenURL, scope, grantType, audience)

	token, err := auth.Token()
	if err != nil {
		t.Fatal(err)
	}

	if token == "" {
		t.Fatal("token is empty")
	}

	u, _ := url.Parse("https://fed-gw.example.com")

	client := NewClient(u, &ClientCredentialsAuth{tokenSource: auth}, http.DefaultClient)

	fns, err := client.GetFunctions(context.Background(), "openfaas-fn")
	if err != nil {
		t.Fatal(err)
	}

	if len(fns) == 0 {
		t.Fatal("no functions found")
	}
}

Deploy Function


status, err := client.Deploy(context.Background(), types.FunctionDeployment{
	Service:    "env-store-test",
	Image:      "ghcr.io/openfaas/alpine:latest",
	Namespace:  "openfaas-fn",
	EnvProcess: "env",
})

// non 200 status value will have some error
if err != nil {
	log.Printf("Deploy Failed: %s", err)
}

Delete Function


err := client.DeleteFunction(context.Background(),"env-store-test", "openfaas-fn")
if err != nil {
	log.Printf("Deletion Failed: %s", err)
}

Please refer examples folder for code examples of each operation

Invoke functions

body := strings.NewReader("OpenFaaS")
req, err := http.NewRequestWithContext(context.TODO(), http.MethodPost, "/", body)
if err != nil {
	panic(err)
}

req.Header.Set("Content-Type", "text/plain")

async := false
authenticate := false

// Make a POST request to a figlet function in the openfaas-fn namespace
res, err := client.InvokeFunction(context.Background(), "figlet", "openfaas-fn", async, authenticate, req)
if err != nil {
	log.Printf("Failed to invoke function: %s", err)
	return
}

if res.Body != nil {
	defer res.Body.Close()
}

// Read the response body
body, err := io.ReadAll(res.Body)
if err != nil {
	log.Printf("Error reading response body: %s", err)
	return
}

// Print the response
fmt.Printf("Response status code: %s\n", res.Status)
fmt.Printf("Response body: %s\n", string(body))

Authenticate function invocations

The SDK supports invoking functions if you are using OpenFaaS IAM with built-in authentication for functions.

Set the auth argument to true when calling InvokeFunction to authenticate the request with an OpenFaaS function access token.

The Client needs a TokenSource to get an ID token that can be exchanged for a function access token to make authenticated function invocations. By default the TokenAuth provider that was set when constructing a new Client is used.

It is also possible to provide a custom TokenSource for the function token exchange:

ts := sdk.NewClientCredentialsTokenSource(clientID, clientSecret, tokenURL, scope, grantType, audience)

client := sdk.NewClientWithOpts(gatewayURL, http.DefaultClient, sdk.WithFunctionTokenSource(ts))

Optionally a TokenCache can be configured to cache function access tokens and prevent the client from having to do a token exchange each time a function is invoked.

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

fnTokenCache := sdk.NewMemoryTokenCache()
// Start garbage collection to remove expired tokens from the cache.
go fnTokenCache.StartGC(ctx, time.Second*10)

client := sdk.NewClientWithOpts(
    gatewayUrl,
    httpClient,
    sdk.WithAuthentication(auth),
    sdk.WithFunctionTokenCache(fnTokenCache),
)

License

License: MIT

Documentation

Index

Constants

View Source
const DefaultNamespace = "openfaas-fn"

Variables

This section is empty.

Functions

func ReadSecret

func ReadSecret(key string) (string, error)

ReadSecrets reads a single secrets from /var/openfaas/secrets or from the environment "secret_mount_path" if set.

Types

type BasicAuth added in v0.1.0

type BasicAuth struct {
	Username string
	Password string
}

BasicAuth basic authentication for the the OpenFaaS client

func (*BasicAuth) Set added in v0.1.0

func (auth *BasicAuth) Set(req *http.Request) error

Set Authorization Basic header on request

type Client

type Client struct {
	// URL of the OpenFaaS gateway
	GatewayURL *url.URL

	// Authentication provider for authenticating request to the OpenFaaS API.
	ClientAuth ClientAuth

	// TokenSource for getting an ID token that can be exchanged for an
	// OpenFaaS function access token to invoke functions.
	FunctionTokenSource TokenSource
	// contains filtered or unexported fields
}

Client is used to manage OpenFaaS and invoke functions

func NewClient

func NewClient(gatewayURL *url.URL, auth ClientAuth, client *http.Client) *Client

NewClient creates a Client for managing OpenFaaS and invoking functions

func NewClientWithOpts added in v0.2.11

func NewClientWithOpts(gatewayURL *url.URL, client *http.Client, options ...ClientOption) *Client

NewClientWithOpts creates a Client for managing OpenFaaS and invoking functions It takes a list of ClientOptions to configure the client.

func (*Client) CreateNamespace added in v0.2.5

func (s *Client) CreateNamespace(ctx context.Context, spec types.FunctionNamespace) (int, error)

CreateNamespace creates a namespace

func (*Client) CreateSecret added in v0.2.9

func (s *Client) CreateSecret(ctx context.Context, spec types.Secret) (int, error)

CreateSecret creates a secret

func (*Client) DeleteFunction added in v0.2.1

func (s *Client) DeleteFunction(ctx context.Context, functionName, namespace string) error

DeleteFunction deletes a function

func (*Client) DeleteNamespace added in v0.2.5

func (s *Client) DeleteNamespace(ctx context.Context, namespace string) error

DeleteNamespace deletes a namespace

func (*Client) DeleteSecret added in v0.2.9

func (s *Client) DeleteSecret(ctx context.Context, secretName, namespace string) error

DeleteSecret deletes a secret

func (*Client) Deploy added in v0.0.2

func (s *Client) Deploy(ctx context.Context, spec types.FunctionDeployment) (int, error)

func (*Client) GetFunction added in v0.0.2

func (s *Client) GetFunction(ctx context.Context, name, namespace string) (types.FunctionStatus, error)

GetFunction gives a richer payload than GetFunctions, but for a specific function

func (*Client) GetFunctions

func (s *Client) GetFunctions(ctx context.Context, namespace string) ([]types.FunctionStatus, error)

GetFunctions lists all functions

func (*Client) GetInfo added in v0.0.2

func (s *Client) GetInfo(ctx context.Context) (SystemInfo, error)

func (*Client) GetLogs added in v0.2.9

func (s *Client) GetLogs(ctx context.Context, functionName, namespace string, follow bool, tail int, since *time.Time) (<-chan logs.Message, error)

func (*Client) GetNamespace added in v0.2.5

func (s *Client) GetNamespace(ctx context.Context, namespace string) (types.FunctionNamespace, error)

GetNamespaces get openfaas namespaces

func (*Client) GetNamespaces

func (s *Client) GetNamespaces(ctx context.Context) ([]string, error)

GetNamespaces get openfaas namespaces

func (*Client) GetSecrets added in v0.2.9

func (s *Client) GetSecrets(ctx context.Context, namespace string) ([]types.Secret, error)

GetSecrets list all secrets

func (*Client) InvokeFunction added in v0.2.11

func (c *Client) InvokeFunction(name, namespace string, async bool, auth bool, req *http.Request) (*http.Response, error)

func (*Client) ScaleFunction

func (s *Client) ScaleFunction(ctx context.Context, functionName, namespace string, replicas uint64) error

ScaleFunction scales a function to a number of replicas

func (*Client) Update added in v0.0.2

func (s *Client) Update(ctx context.Context, spec types.FunctionDeployment) (int, error)

func (*Client) UpdateNamespace added in v0.2.5

func (s *Client) UpdateNamespace(ctx context.Context, spec types.FunctionNamespace) (int, error)

UpdateNamespace updates a namespace

func (*Client) UpdateSecret added in v0.2.9

func (s *Client) UpdateSecret(ctx context.Context, spec types.Secret) (int, error)

UpdateSecret updates a secret

type ClientAuth added in v0.1.0

type ClientAuth interface {
	Set(req *http.Request) error
}

ClientAuth an interface for client authentication. to add authentication to the client implement this interface

type ClientCredentialsAuth added in v0.2.3

type ClientCredentialsAuth struct {
	// contains filtered or unexported fields
}

func NewClientCredentialsAuth added in v0.2.3

func NewClientCredentialsAuth(ts TokenSource) *ClientCredentialsAuth

func (*ClientCredentialsAuth) Set added in v0.2.3

func (cca *ClientCredentialsAuth) Set(req *http.Request) error

type ClientCredentialsTokenSource added in v0.2.3

type ClientCredentialsTokenSource struct {
	// contains filtered or unexported fields
}

ClientCredentialsTokenSource can be used to obtain an access token using the client credentials grant type. Tested with Keycloak's token endpoint, additional changes may be required for additional OIDC token endpoints.

func (*ClientCredentialsTokenSource) Token added in v0.2.3

func (ts *ClientCredentialsTokenSource) Token() (string, error)

type ClientOption added in v0.2.11

type ClientOption func(*Client)

func WithAuthentication added in v0.2.11

func WithAuthentication(auth ClientAuth) ClientOption

WithAuthentication configures the authentication provider fot the client.

func WithFunctionTokenCache added in v0.2.11

func WithFunctionTokenCache(cache TokenCache) ClientOption

WithFunctionTokenCache configures the token cache used by the client to cache access tokens for function invocations.

func WithFunctionTokenSource added in v0.2.11

func WithFunctionTokenSource(tokenSource TokenSource) ClientOption

WithFunctionTokenSource configures the function token source for the client.

type ExchangeConfig added in v0.2.11

type ExchangeConfig struct {
	Audience []string
	Scope    []string
	Client   *http.Client
}

type ExchangeOption added in v0.2.11

type ExchangeOption func(*ExchangeConfig)

ExchangeOption is used to implement functional-style options that modify the config setting for the OpenFaaS token exchange.

func WithAudience added in v0.2.11

func WithAudience(audience []string) ExchangeOption

WithAudience is an option to configure the audience requested in the token exchange.

func WithHttpClient added in v0.2.11

func WithHttpClient(client *http.Client) ExchangeOption

WithHttpClient is an option to configure the http client used to make the token exchange request.

func WithScope added in v0.2.11

func WithScope(scope []string) ExchangeOption

WithScope is an option to configure the scope requested in the token exchange.

type MemoryTokenCache added in v0.2.11

type MemoryTokenCache struct {
	// contains filtered or unexported fields
}

MemoryTokenCache is a basic in-memory token cache implementation.

func NewMemoryTokenCache added in v0.2.11

func NewMemoryTokenCache() *MemoryTokenCache

NewMemoryTokenCache creates a new in memory token cache instance.

func (*MemoryTokenCache) Get added in v0.2.11

func (c *MemoryTokenCache) Get(key string) (*Token, bool)

Get retrieves the token associated with the given key from the cache. The bool return value will be false if no matching key is found, and true otherwise.

func (*MemoryTokenCache) Set added in v0.2.11

func (c *MemoryTokenCache) Set(key string, token *Token)

Set adds or updates a token with the given key in the cache.

func (*MemoryTokenCache) StartGC added in v0.2.11

func (c *MemoryTokenCache) StartGC(ctx context.Context, gcInterval time.Duration)

StartGC starts garbage collection of expired tokens.

type OAuthError added in v0.2.11

type OAuthError struct {
	Err         string `json:"error"`
	Description string `json:"error_description,omitempty"`
}

OAuthError represents an OAuth error response.

func (*OAuthError) Error added in v0.2.11

func (e *OAuthError) Error() string

type Provider added in v0.0.2

type Provider struct {
	Provider      string            `json:"provider,omitempty"`
	Version       types.VersionInfo `json:"version,omitempty"`
	Orchestration string            `json:"orchestration,omitempty"`
}

type SecretMap

type SecretMap struct {
	// contains filtered or unexported fields
}

func ReadSecrets

func ReadSecrets() (SecretMap, error)

ReadSecrets reads all secrets from /var/openfaas/secrets or from the environment "secret_mount_path" if set. The results are returned in a map of key/value pairs.

func (*SecretMap) Exists

func (s *SecretMap) Exists(key string) bool

func (*SecretMap) Get

func (s *SecretMap) Get(key string) (string, error)

type ServiceAccountTokenSource added in v0.2.2

type ServiceAccountTokenSource struct{}

A TokenSource to get ID token by reading a Kubernetes projected service account token from /var/secrets/tokens/openfaas-token or the path set by the token_mount_path environment variable.

func (*ServiceAccountTokenSource) Token added in v0.2.2

func (ts *ServiceAccountTokenSource) Token() (string, error)

Token returns a Kubernetes projected service account token read from /var/secrets/tokens/openfaas-token or the path set by the token_mount_path environment variable.

type SystemInfo added in v0.0.2

type SystemInfo struct {
	Arch     string            `json:"arch,omitempty"`
	Provider Provider          `json:"provider,omitempty"`
	Version  types.VersionInfo `json:"version,omitempty"`
}

type Token added in v0.1.0

type Token struct {
	// IDToken is the OIDC access token that authorizes and authenticates
	// the requests.
	IDToken string

	// Expiry is the expiration time of the access token.
	//
	// A zero value means the token never expires.
	Expiry time.Time

	// Scope is the scope of the access token
	Scope []string
}

Token represents an OIDC token

func ExchangeIDToken added in v0.1.0

func ExchangeIDToken(tokenURL, rawIDToken string, options ...ExchangeOption) (*Token, error)

Exchange an OIDC ID Token from an IdP for OpenFaaS token using the token exchange grant type. tokenURL should be the OpenFaaS token endpoint within the internal OIDC service

func (*Token) Expired added in v0.1.0

func (t *Token) Expired() bool

Expired reports whether the token is expired, and will start to return false 10s before the actual expiration time.

type TokenAuth added in v0.1.0

type TokenAuth struct {
	// TokenURL represents the OpenFaaS gateways token endpoint URL.
	TokenURL string

	// TokenSource used to get an ID token that can be exchanged for an OpenFaaS ID token.
	TokenSource TokenSource
	// contains filtered or unexported fields
}

TokenAuth bearer token authentication for OpenFaaS deployments with OpenFaaS IAM enabled.

func (*TokenAuth) Set added in v0.1.0

func (a *TokenAuth) Set(req *http.Request) error

Set Authorization Bearer header on request. Set validates the token expiry on each call. If it's expired it will exchange an ID token from the TokenSource for a new OpenFaaS token.

func (*TokenAuth) Token added in v0.2.11

func (a *TokenAuth) Token() (string, error)

type TokenCache added in v0.2.11

type TokenCache interface {
	Get(key string) (*Token, bool)
	Set(key string, token *Token)
}

type TokenSource added in v0.1.0

type TokenSource interface {
	// Token returns a token or an error.
	Token() (string, error)
}

A TokenSource is anything that can return an OIDC ID token that can be exchanged for an OpenFaaS token.

func NewClientCredentialsTokenSource added in v0.2.3

func NewClientCredentialsTokenSource(clientID, clientSecret, tokenURL, scope, grantType, audience string) TokenSource

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL