Skip to content

Commit

Permalink
feat: add authentication helpers for Ruby and Go (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
markphelps authored Jan 24, 2024
1 parent 1dbb888 commit d41a1a8
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 27 deletions.
16 changes: 10 additions & 6 deletions flipt-client-go/evaluation.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,21 @@ func WithUpdateInterval(updateInterval int) clientOption {
}
}

// WithAuthentication allows for configuring an authentication method to communicate with a protected Flipt server.
func WithAuthentication(authentication any) clientOption {
// WithClientTokenAuthentication allows authenticating with Flipt using a static client token.
func WithClientTokenAuthentication(token string) clientOption {
return func(c *Client) {
c.authentication = authentication
c.authentication = clientTokenAuthentication{
Token: token,
}
}
}

// WithReference allows for specifying a reference to fetch flag state data from.
func WithReference(ref string) clientOption {
// WithJWTAuthentication allows authenticating with Flipt using a JSON Web Token.
func WithJWTAuthentication(token string) clientOption {
return func(c *Client) {
c.ref = ref
c.authentication = jwtAuthentication{
Token: token,
}
}
}

Expand Down
24 changes: 9 additions & 15 deletions flipt-client-go/evaluation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
evaluation "go.flipt.io/flipt-client"
flipt "go.flipt.io/flipt-client"
)

var fliptUrl string
var authToken string
var (
fliptUrl string
authToken string
)

func init() {
fliptUrl = os.Getenv("FLIPT_URL")
Expand All @@ -26,9 +28,7 @@ func init() {
}

func TestVariant(t *testing.T) {
evaluationClient, err := evaluation.NewClient(evaluation.WithURL(fliptUrl), evaluation.WithAuthentication(evaluation.ClientTokenAuthentication{
Token: authToken,
}))
evaluationClient, err := flipt.NewClient(flipt.WithURL(fliptUrl), flipt.WithClientTokenAuthentication(authToken))
require.NoError(t, err)

variant, err := evaluationClient.EvaluateVariant(context.TODO(), "flag1", "someentity", map[string]string{
Expand All @@ -45,9 +45,7 @@ func TestVariant(t *testing.T) {
}

func TestBoolean(t *testing.T) {
evaluationClient, err := evaluation.NewClient(evaluation.WithURL(fliptUrl), evaluation.WithAuthentication(evaluation.ClientTokenAuthentication{
Token: authToken,
}))
evaluationClient, err := flipt.NewClient(flipt.WithURL(fliptUrl), flipt.WithClientTokenAuthentication(authToken))
require.NoError(t, err)

boolean, err := evaluationClient.EvaluateBoolean(context.TODO(), "flag_boolean", "someentity", map[string]string{
Expand All @@ -63,9 +61,7 @@ func TestBoolean(t *testing.T) {
}

func TestVariantFailure(t *testing.T) {
evaluationClient, err := evaluation.NewClient(evaluation.WithURL(fliptUrl), evaluation.WithAuthentication(evaluation.ClientTokenAuthentication{
Token: authToken,
}))
evaluationClient, err := flipt.NewClient(flipt.WithURL(fliptUrl), flipt.WithClientTokenAuthentication(authToken))
require.NoError(t, err)

variant, err := evaluationClient.EvaluateVariant(context.TODO(), "nonexistent", "someentity", map[string]string{
Expand All @@ -79,9 +75,7 @@ func TestVariantFailure(t *testing.T) {
}

func TestBooleanFailure(t *testing.T) {
evaluationClient, err := evaluation.NewClient(evaluation.WithURL(fliptUrl), evaluation.WithAuthentication(evaluation.ClientTokenAuthentication{
Token: authToken,
}))
evaluationClient, err := flipt.NewClient(flipt.WithURL(fliptUrl), flipt.WithClientTokenAuthentication(authToken))
require.NoError(t, err)

boolean, err := evaluationClient.EvaluateBoolean(context.TODO(), "nonexistent", "someentity", map[string]string{
Expand Down
4 changes: 2 additions & 2 deletions flipt-client-go/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ type evaluationRequest struct {
Context map[string]string `json:"context"`
}

type ClientTokenAuthentication struct {
type clientTokenAuthentication struct {
Token string `json:"client_token"`
}

type JWTAuthentication struct {
type jwtAuthentication struct {
Token string `json:"jwt_token"`
}

Expand Down
10 changes: 9 additions & 1 deletion flipt-client-ruby/lib/flipt_client.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'flipt_client/version'
require 'flipt_client/models'
require 'ffi'
require 'json'

Expand Down Expand Up @@ -41,11 +42,18 @@ def self.libfile
# @param namespace [String] namespace
# @param opts [Hash] options
# @option opts [String] :url Flipt server url
# @option opts [String] :auth_token Flipt api key
# @option opts [AuthenticationStrategy] :authentication strategy to authenticate with Flipt
# @option opts [Integer] :update_interval interval in seconds to update the cache
# @option opts [String] :reference reference to use for namespace data
def initialize(namespace = 'default', opts = {})
@namespace = namespace

# set default no auth if not provided
authentication = opts.fetch(:authentication, Flipt::NoAuthentication.new)
raise ArgumentError, "invalid authentication strategy" unless authentication && authentication.is_a?(Flipt::AuthenticationStrategy)

opts[:authentication] = authentication.strategy

namespace_list = [namespace]
ns = FFI::MemoryPointer.new(:pointer, namespace_list.size)
namespace_list.each_with_index do |namespace, i|
Expand Down
39 changes: 39 additions & 0 deletions flipt-client-ruby/lib/flipt_client/models.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

module Flipt
class AuthenticationStrategy
def strategy
raise NotImplementedError
end
end

class NoAuthentication < AuthenticationStrategy
def strategy
nil
end
end

class ClientTokenAuthentication < AuthenticationStrategy
def initialize(token)
@token = token
end

def strategy
{
client_token: @token
}
end
end

class JWTAuthentication < AuthenticationStrategy
def initialize(token)
@token = token
end

def strategy
{
jwt_token: @token
}
end
end
end
2 changes: 1 addition & 1 deletion flipt-client-ruby/spec/evaluation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
before(:all) do
url = ENV.fetch('FLIPT_URL', 'http://localhost:8080')
auth_token = ENV.fetch('FLIPT_AUTH_TOKEN', 'secret')
@client = Flipt::EvaluationClient.new('default', { url: url, authentication: { client_token: auth_token } })
@client = Flipt::EvaluationClient.new('default', { url: url, authentication: Flipt::ClientTokenAuthentication.new(auth_token)} )
end

describe '#evaluate_variant' do
Expand Down
13 changes: 11 additions & 2 deletions flipt-evaluation/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,20 @@ mod tests {
);
}

#[test]
fn test_deserialize_no_auth() {
let json = r#""#;

let unwrapped_string: Authentication = serde_json::from_str(&json).unwrap_or_default();

assert_eq!(unwrapped_string, Authentication::None);
}

#[test]
fn test_deserialize_client_token() {
let json = r#"{"client_token":"secret"}"#;

let unwrapped_string: Authentication = serde_json::from_str(&json).unwrap();
let unwrapped_string: Authentication = serde_json::from_str(&json).unwrap_or_default();

assert_eq!(
unwrapped_string,
Expand All @@ -250,7 +259,7 @@ mod tests {
fn test_deserialize_jwt_token() {
let json = r#"{"jwt_token":"secret"}"#;

let unwrapped_string: Authentication = serde_json::from_str(&json).unwrap();
let unwrapped_string: Authentication = serde_json::from_str(&json).unwrap_or_default();

assert_eq!(unwrapped_string, Authentication::JwtToken("secret".into()));
}
Expand Down

0 comments on commit d41a1a8

Please sign in to comment.