Skip to content

Commit

Permalink
Merge pull request #23 from flipt-io/support-auth-token
Browse files Browse the repository at this point in the history
feat: support passing auth token down to engine
  • Loading branch information
yquansah authored Dec 6, 2023
2 parents a3438c9 + 93e5907 commit f1793f3
Show file tree
Hide file tree
Showing 19 changed files with 102 additions and 30 deletions.
7 changes: 7 additions & 0 deletions build/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ func getTestDependencies(ctx context.Context, client *dagger.Client, hostDirecto
WithUser("flipt").
WithEnvVariable("FLIPT_STORAGE_TYPE", "local").
WithEnvVariable("FLIPT_STORAGE_LOCAL_PATH", "/var/data/flipt").
WithEnvVariable("FLIPT_AUTHENTICATION_METHODS_TOKEN_ENABLED", "1").
WithEnvVariable("FLIPT_AUTHENTICATION_METHODS_TOKEN_BOOTSTRAP_TOKEN", "secret").
WithEnvVariable("FLIPT_AUTHENTICATION_REQUIRED", "1").
WithExposedPort(8080)

return flipt, rust.File("/app/target/release/libfliptengine.so"), rust.File("/app/target/release/flipt_engine.h")
Expand All @@ -133,6 +136,7 @@ func pythonTests(ctx context.Context, client *dagger.Client, flipt *dagger.Conta
WithFile("/app/libfliptengine.so", dynamicLibrary).
WithServiceBinding("flipt", flipt.WithExec(nil).AsService()).
WithEnvVariable("FLIPT_URL", "http://flipt:8080").
WithEnvVariable("FLIPT_AUTH_TOKEN", "secret").
WithEnvVariable("FLIPT_ENGINE_LIB_PATH", "/app/libfliptengine.so").
WithExec([]string{"poetry", "install", "--without=dev"}).
WithExec([]string{"poetry", "run", "test"}).
Expand All @@ -152,6 +156,7 @@ func goTests(ctx context.Context, client *dagger.Client, flipt *dagger.Container
WithFile("/app/flipt_engine.h", headerFile).
WithServiceBinding("flipt", flipt.WithExec(nil).AsService()).
WithEnvVariable("FLIPT_URL", "http://flipt:8080").
WithEnvVariable("FLIPT_AUTH_TOKEN", "secret").
// Since the dynamic library is being sourced from a "non-standard location" we can
// modify the LD_LIBRARY_PATH variable to inform the linker different locations for
// dynamic libraries.
Expand All @@ -175,6 +180,7 @@ func nodeTests(ctx context.Context, client *dagger.Client, flipt *dagger.Contain
WithFile("/app/libfliptengine.so", dynamicLibrary).
WithServiceBinding("flipt", flipt.WithExec(nil).AsService()).
WithEnvVariable("FLIPT_URL", "http://flipt:8080").
WithEnvVariable("FLIPT_AUTH_TOKEN", "secret").
WithEnvVariable("FLIPT_ENGINE_LIB_PATH", "/app/libfliptengine.so").
WithExec([]string{"npm", "install"}).
WithExec([]string{"npm", "test"}).
Expand All @@ -191,6 +197,7 @@ func rubyTests(ctx context.Context, client *dagger.Client, flipt *dagger.Contain
WithFile("/app/lib/ext/libfliptengine.so", dynamicLibrary).
WithServiceBinding("flipt", flipt.WithExec(nil).AsService()).
WithEnvVariable("FLIPT_URL", "http://flipt:8080").
WithEnvVariable("FLIPT_AUTH_TOKEN", "secret").
WithExec([]string{"bundle", "install"}).
WithExec([]string{"bundle", "exec", "rspec"}).
Sync(ctx)
Expand Down
1 change: 1 addition & 0 deletions flipt-client-go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func main() {
// evaluation.WithNamespace(string): configures which namespace you will be making evaluations on
// evaluation.WithURL(string): configures which upstream Flipt data should be fetched from
// evaluation.WithUpdateInterval(int): configures how often data should be fetched from the upstream
// evaluation.WithAuthToken(string): configures an auth token if your upstream Flipt instance requires it
evaluationClient, err := evaluation.NewClient()
if err != nil {
log.Fatal(err)
Expand Down
9 changes: 9 additions & 0 deletions flipt-client-go/evaluation.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Client struct {
engine unsafe.Pointer
namespace string
url string
authToken string
updateInterval int
}

Expand All @@ -34,6 +35,7 @@ func NewClient(opts ...clientOption) (*Client, error) {
engOpts := &EngineOpts{
URL: client.url,
UpdateInterval: client.updateInterval,
AuthToken: client.authToken,
}

b, err := json.Marshal(engOpts)
Expand Down Expand Up @@ -83,6 +85,13 @@ func WithUpdateInterval(updateInterval int) clientOption {
}
}

// WithAuthToken allows for configuring an auth token to communicate with a protected Flipt server.
func WithAuthToken(authToken string) clientOption {
return func(c *Client) {
c.authToken = authToken
}
}

// EvaluateVariant makes an evaluation on a variant flag.
func (e *Client) EvaluateVariant(_ context.Context, flagKey, entityID string, evalContext map[string]string) (*VariantResult, error) {
ereq, err := json.Marshal(evaluationRequest{
Expand Down
10 changes: 8 additions & 2 deletions flipt-client-go/evaluation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,22 @@ import (
)

var fliptUrl string
var authToken string

func init() {
fliptUrl = os.Getenv("FLIPT_URL")
if fliptUrl == "" {
panic("set FLIPT_URL")
}

authToken = os.Getenv("FLIPT_AUTH_TOKEN")
if authToken == "" {
panic("set FLIPT_AUTH_TOKEN")
}
}

func TestVariant(t *testing.T) {
evaluationClient, err := evaluation.NewClient(evaluation.WithURL(fliptUrl))
evaluationClient, err := evaluation.NewClient(evaluation.WithURL(fliptUrl), evaluation.WithAuthToken(authToken))
require.NoError(t, err)

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

func TestBoolean(t *testing.T) {
evaluationClient, err := evaluation.NewClient(evaluation.WithURL(fliptUrl))
evaluationClient, err := evaluation.NewClient(evaluation.WithURL(fliptUrl), evaluation.WithAuthToken(authToken))
require.NoError(t, err)

boolean, err := evaluationClient.EvaluateBoolean(context.TODO(), "flag_boolean", "someentity", map[string]string{
Expand Down
1 change: 1 addition & 0 deletions flipt-client-go/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type evaluationRequest struct {

type EngineOpts struct {
URL string `json:"url,omitempty"`
AuthToken string `json:"auth_token,omitempty"`
UpdateInterval int `json:"update_interval,omitempty"`
}

Expand Down
7 changes: 4 additions & 3 deletions flipt-client-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ import { FliptEvaluationClient } from 'flipt-client-node';
// engine_opts is the second positional argument and is also optional, the structure is:
// {
// "url": "http://localhost:8080",
// "update_interval": 120
// "update_interval": 120,
// "auth_token": "secret"
// }
//
// You can replace the url with where your upstream Flipt instance points to, and the update interval for how long you are willing
// to wait for updated flag state.
// You can replace the url with where your upstream Flipt instance points to, the update interval for how long you are willing
// to wait for updated flag state, and the auth token if your Flipt instance requires it.
const fliptEvaluationClient = new FliptEvaluationClient();

const variant = fliptEvaluationClient.evaluateVariant("flag1", "someentity", {"fizz": "buzz"});
Expand Down
2 changes: 1 addition & 1 deletion flipt-client-node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions flipt-client-node/src/evaluation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@ if (!fliptUrl) {
process.exit(1);
}

const authToken = process.env['FLIPT_AUTH_TOKEN'];
if (!authToken) {
console.error('please set the FLIPT_AUTH_TOKEN environment variable');
process.exit(1);
}

test('variant', () => {
const fec = new FliptEvaluationClient('default', { url: fliptUrl });
const fec = new FliptEvaluationClient('default', {
url: fliptUrl,
auth_token: authToken
});

const variant = fec.evaluateVariant('flag1', 'someentity', { fizz: 'buzz' });

Expand All @@ -22,7 +31,10 @@ test('variant', () => {
});

test('boolean', () => {
const fec = new FliptEvaluationClient('default', { url: fliptUrl });
const fec = new FliptEvaluationClient('default', {
url: fliptUrl,
auth_token: authToken
});

const boolean = fec.evaluateBoolean('flag_boolean', 'someentity', {
fizz: 'buzz'
Expand Down
3 changes: 2 additions & 1 deletion flipt-client-node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export class FliptEvaluationClient {
namespace?: string,
engine_opts: EngineOpts = {
url: 'http://localhost:8080',
update_interval: 120
update_interval: 120,
auth_token: ''
}
) {
const engine = engineLib.initialize_engine(
Expand Down
1 change: 1 addition & 0 deletions flipt-client-node/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface EvaluationRequest {
interface EngineOpts {
url?: string;
update_interval?: number;
auth_token?: string;
}

interface VariantEvaluationResponse {
Expand Down
4 changes: 2 additions & 2 deletions flipt-client-python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ In your Python code you can import this client and use it as so:
```python
from flipt_client_python import FliptEvaluationClient

# "namespace" and "engine_opts" are two keyword arguments that this constructor accepts.
# "namespace" and "engine_opts" are two keyword arguments that this constructor accepts
# namespace: which namespace to fetch flag state from
# engine_opts: follows the model EngineOpts in the models.py file. Configures the url of the upstream Flipt instance, and the interval in which to fetch new flag state
# engine_opts: follows the model EngineOpts in the models.py file. Configures the url of the upstream Flipt instance, the interval in which to fetch new flag state, and the auth token if your upstream Flipt instance requires it
flipt_evaluation_client = FliptEvaluationClient()

variant_result = flipt_evaluation_client.evaluate_variant(flag_key="flag1", entity_id="entity", context={"fizz": "buzz"})
Expand Down
1 change: 1 addition & 0 deletions flipt-client-python/flipt_client_python/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class EvaluationRequest(BaseModel):
class EngineOpts(BaseModel):
url: Optional[str] = None
update_interval: Optional[int] = None
auth_token: Optional[str] = None


class VariantEvaluationResponse(BaseModel):
Expand Down
6 changes: 5 additions & 1 deletion flipt-client-python/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ def setUp(self) -> None:
if engine_url is None:
raise Exception("FLIPT_URL not set")

auth_token = os.environ.get("FLIPT_AUTH_TOKEN")
if auth_token is None:
raise Exception("FLIPT_AUTH_TOKEN not set")

self.flipt_client = FliptEvaluationClient(
engine_opts=EngineOpts(url=engine_url)
engine_opts=EngineOpts(url=engine_url, auth_token=auth_token)
)

def test_variant(self):
Expand Down
9 changes: 6 additions & 3 deletions flipt-client-ruby/spec/evaluation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
describe '#initialize' do
it 'initializes the engine' do
url = ENV.fetch('FLIPT_URL', 'http://localhost:8080')
client = Flipt::EvaluationClient.new('default', { url: url })
auth_token = ENV.fetch('FLIPT_AUTH_TOKEN', 'secret')
client = Flipt::EvaluationClient.new('default', { url: url, auth_token: auth_token })
expect(client).to be_a(Flipt::EvaluationClient)
end
end

describe '#evaluate_variant' do
it 'returns a variant result' do
url = ENV.fetch('FLIPT_URL', 'http://localhost:8080')
client = Flipt::EvaluationClient.new('default', { url: url })
auth_token = ENV.fetch('FLIPT_AUTH_TOKEN', 'secret')
client = Flipt::EvaluationClient.new('default', { url: url, auth_token: auth_token })

resp = client.evaluate_variant({ flag_key: 'flag1', entity_id: 'someentity', context: { "fizz": 'buzz' } })

Expand All @@ -32,7 +34,8 @@
describe '#evaluate_boolean' do
it 'returns a boolean result' do
url = ENV.fetch('FLIPT_URL', 'http://localhost:8080')
client = Flipt::EvaluationClient.new('default', { url: url })
auth_token = ENV.fetch('FLIPT_AUTH_TOKEN', 'secret')
client = Flipt::EvaluationClient.new('default', { url: url, auth_token: auth_token })

resp = client.evaluate_boolean({ flag_key: 'flag_boolean', entity_id: 'someentity', context: { "fizz": 'buzz' } })

Expand Down
2 changes: 1 addition & 1 deletion flipt-engine/examples/evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::collections::HashMap;
fn main() {
let evaluator = evaluator::Evaluator::new_snapshot_evaluator(
vec!["default".into()],
parser::HTTPParser::new("http://localhost:8080"),
parser::HTTPParser::new("http://localhost:8080", Some("secret")),
);

let eng = fliptengine::Engine::new(evaluator.unwrap(), Default::default());
Expand Down
18 changes: 9 additions & 9 deletions flipt-engine/src/evaluator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ mod tests {
"blah",
);

assert!(!result.is_ok());
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
"error parsing boolean blah: err provided string was not `true` or `false`"
Expand All @@ -895,7 +895,7 @@ mod tests {
"notanumber",
);

assert!(!result_one.is_ok());
assert!(result_one.is_err());
assert_eq!(
result_one.err().unwrap().to_string(),
"error parsing number notanumber, err: invalid digit found in string"
Expand All @@ -911,7 +911,7 @@ mod tests {
"9",
);

assert!(!result_two.is_ok());
assert!(result_two.is_err());
assert_eq!(
result_two.err().unwrap().to_string(),
"error parsing number notanumber, err: invalid digit found in string"
Expand All @@ -930,7 +930,7 @@ mod tests {
"2006-01-02T15:04:05Z",
);

assert!(!result_one.is_ok());
assert!(result_one.is_err());
assert_eq!(
result_one.err().unwrap().to_string(),
"error parsing time blah, err: input contains invalid characters"
Expand All @@ -946,7 +946,7 @@ mod tests {
"blah",
);

assert!(!result_two.is_ok());
assert!(result_two.is_err());
assert_eq!(
result_two.err().unwrap().to_string(),
"error parsing time blah, err: input contains invalid characters"
Expand Down Expand Up @@ -1028,7 +1028,7 @@ mod tests {
let v = variant.unwrap();

assert_eq!(v.flag_key, String::from("foo"));
assert_eq!(v.r#match, true);
assert!(v.r#match);
assert_eq!(v.reason, common::EvaluationReason::Match);
assert_eq!(v.segment_keys, vec![String::from("segment1")]);
}
Expand Down Expand Up @@ -1671,7 +1671,7 @@ mod tests {
namespace_key: String::from("default"),
flag_key: String::from("foo"),
entity_id: String::from("01"),
context: context,
context,
});

assert!(variant.is_ok());
Expand Down Expand Up @@ -1759,7 +1759,7 @@ mod tests {
let v = variant.unwrap();

assert_eq!(v.flag_key, String::from("foo"));
assert_eq!(v.r#match, true);
assert!(v.r#match);
assert_eq!(v.reason, common::EvaluationReason::Match);
assert_eq!(v.segment_keys, vec![String::from("segment1")]);
}
Expand Down Expand Up @@ -2407,7 +2407,7 @@ mod tests {
namespace_key: String::from("default"),
flag_key: String::from("foo"),
entity_id: String::from("01"),
context: context,
context,
});

assert!(variant.is_ok());
Expand Down
6 changes: 5 additions & 1 deletion flipt-engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ fn result_to_json_ptr<T: Serialize>(result: Result<T, Whatever>) -> *mut c_char
#[derive(Deserialize)]
pub struct EngineOpts {
url: Option<String>,
auth_token: Option<String>,
update_interval: Option<u64>,
}

impl Default for EngineOpts {
fn default() -> Self {
Self {
url: Some("http://localhost:8080".into()),
auth_token: None,
update_interval: Some(120),
}
}
Expand Down Expand Up @@ -179,7 +181,9 @@ pub unsafe extern "C" fn initialize_engine(
.to_owned()
.unwrap_or("http://localhost:8080".into());

let parser = parser::HTTPParser::new(&http_url);
let auth_token = engine_opts.auth_token.to_owned();

let parser = parser::HTTPParser::new(&http_url, auth_token.clone().as_deref());
let evaluator = evaluator::Evaluator::new_snapshot_evaluator(namespaces_vec, parser);

Box::into_raw(Box::new(Engine::new(evaluator.unwrap(), engine_opts))) as *mut c_void
Expand Down
Loading

0 comments on commit f1793f3

Please sign in to comment.