From e9d0758e55c3436b3d67e02647b7c042189cabe2 Mon Sep 17 00:00:00 2001 From: Joseph Little Date: Tue, 30 Jul 2024 12:02:23 +0100 Subject: [PATCH 1/5] BaseDomain > FQDN Integration tests for oauth builder implemented --- jamf/jamfprointegration/auth_oauth.go | 2 +- jamf/jamfprointegration/builders.go | 12 ++-- jamf/jamfprointegration/interfaces.go | 4 +- jamf/jamfprointegration/marshall_test.go | 4 +- jamf/jamfprointegration/test/helpers.go | 8 +++ jamf/jamfprointegration/test/init_test.go | 77 +++++++++++++++++++++++ 6 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 jamf/jamfprointegration/test/helpers.go create mode 100644 jamf/jamfprointegration/test/init_test.go diff --git a/jamf/jamfprointegration/auth_oauth.go b/jamf/jamfprointegration/auth_oauth.go index 5f688a5..ee62ab6 100644 --- a/jamf/jamfprointegration/auth_oauth.go +++ b/jamf/jamfprointegration/auth_oauth.go @@ -92,7 +92,7 @@ func (a *oauth) getNewToken() error { a.expiryTime = time.Now().Add(expiresIn) a.token = oauthResp.AccessToken - a.Sugar.Info("Token obtained successfully", zap.Time("Expiry", a.expiryTime)) + a.Sugar.Infow("Token obtained successfully", "expiry", a.expiryTime) return nil } diff --git a/jamf/jamfprointegration/builders.go b/jamf/jamfprointegration/builders.go index 8f0c813..ca9d362 100644 --- a/jamf/jamfprointegration/builders.go +++ b/jamf/jamfprointegration/builders.go @@ -8,9 +8,9 @@ import ( ) // BuildWithOAuth is a helper function allowing the full construct of a Jamf Integration using OAuth2 -func BuildWithOAuth(jamfBaseDomain string, Sugar *zap.SugaredLogger, bufferPeriod time.Duration, clientId string, clientSecret string, hideSensitiveData bool, executor httpclient.HTTPExecutor) (*Integration, error) { +func BuildWithOAuth(jamfProFQDN string, Sugar *zap.SugaredLogger, bufferPeriod time.Duration, clientId string, clientSecret string, hideSensitiveData bool, executor httpclient.HTTPExecutor) (*Integration, error) { integration := Integration{ - BaseDomain: jamfBaseDomain, + JamfProFQDN: jamfProFQDN, Sugar: Sugar, AuthMethodDescriptor: "oauth2", httpExecutor: executor, @@ -23,10 +23,10 @@ func BuildWithOAuth(jamfBaseDomain string, Sugar *zap.SugaredLogger, bufferPerio } // BuildWithBasicAuth is a helper function allowing the full construct of a Jamf Integration using BasicAuth -func BuildWithBasicAuth(jamfBaseDomain string, Sugar *zap.SugaredLogger, bufferPeriod time.Duration, username string, password string, hideSensitiveData bool, executor httpclient.HTTPExecutor) (*Integration, error) { +func BuildWithBasicAuth(jamfProFQDN string, Sugar *zap.SugaredLogger, bufferPeriod time.Duration, username string, password string, hideSensitiveData bool, executor httpclient.HTTPExecutor) (*Integration, error) { integration := Integration{ - BaseDomain: jamfBaseDomain, + JamfProFQDN: jamfProFQDN, Sugar: Sugar, AuthMethodDescriptor: "basic", httpExecutor: executor, @@ -44,7 +44,7 @@ func (j *Integration) BuildOAuth(clientId string, clientSecret string, bufferPer clientId: clientId, clientSecret: clientSecret, bufferPeriod: bufferPeriod, - baseDomain: j.BaseDomain, + baseDomain: j.JamfProFQDN, Sugar: j.Sugar, hideSensitiveData: hideSensitiveData, httpExecutor: executor, @@ -60,7 +60,7 @@ func (j *Integration) BuildBasicAuth(username string, password string, bufferPer password: password, bufferPeriod: bufferPeriod, Sugar: j.Sugar, - baseDomain: j.BaseDomain, + baseDomain: j.JamfProFQDN, hideSensitiveData: hideSensitiveData, httpExecutor: executor, } diff --git a/jamf/jamfprointegration/interfaces.go b/jamf/jamfprointegration/interfaces.go index 5915adf..aeb49d4 100644 --- a/jamf/jamfprointegration/interfaces.go +++ b/jamf/jamfprointegration/interfaces.go @@ -9,7 +9,7 @@ import ( // JamfAPIHandler implements the APIHandler interface for the Jamf Pro API. type Integration struct { - BaseDomain string + JamfProFQDN string AuthMethodDescriptor string Sugar *zap.SugaredLogger auth authInterface @@ -18,7 +18,7 @@ type Integration struct { // getFQDN returns just the FQDN // TODO remove the "get" func (j *Integration) GetFQDN() string { - return j.BaseDomain + return j.JamfProFQDN } // constructURL appends any endpoint to the FQDN diff --git a/jamf/jamfprointegration/marshall_test.go b/jamf/jamfprointegration/marshall_test.go index 3b48cca..394a68e 100644 --- a/jamf/jamfprointegration/marshall_test.go +++ b/jamf/jamfprointegration/marshall_test.go @@ -10,7 +10,7 @@ import ( func TestIntegration_marshalRequest(t *testing.T) { type fields struct { - BaseDomain string + jamfProFQDN string AuthMethodDescriptor string Sugar *zap.SugaredLogger auth authInterface @@ -33,7 +33,7 @@ func TestIntegration_marshalRequest(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { j := &Integration{ - BaseDomain: tt.fields.BaseDomain, + JamfProFQDN: tt.fields.jamfProFQDN, AuthMethodDescriptor: tt.fields.AuthMethodDescriptor, Sugar: tt.fields.Sugar, auth: tt.fields.auth, diff --git a/jamf/jamfprointegration/test/helpers.go b/jamf/jamfprointegration/test/helpers.go new file mode 100644 index 0000000..635c643 --- /dev/null +++ b/jamf/jamfprointegration/test/helpers.go @@ -0,0 +1,8 @@ +package test + +import "go.uber.org/zap" + +func newSugaredDevelopmentLogger() *zap.SugaredLogger { + logger, _ := zap.NewDevelopment() + return logger.Sugar() +} diff --git a/jamf/jamfprointegration/test/init_test.go b/jamf/jamfprointegration/test/init_test.go new file mode 100644 index 0000000..8cc7c84 --- /dev/null +++ b/jamf/jamfprointegration/test/init_test.go @@ -0,0 +1,77 @@ +package test + +import ( + "net/http" + "os" + "testing" + "time" + + "github.com/deploymenttheory/go-api-http-client-integrations/jamf/jamfprointegration" + "github.com/deploymenttheory/go-api-http-client/httpclient" + "go.uber.org/zap" +) + +const ( + ENV_KEY_JAMFPRO_FQDN = "TEST_JAMFPRO_FQDN" + ENV_KEY_CLIENT_ID = "TEST_JAMFPRO_CLIENT_ID" + ENV_KEY_CLIENT_SECRET = "TEST_JAMFPRO_CLIENT_SECRET" + ENV_KEY_USERNAME = "TEST_JAMFPRO_USERNAME" + ENV_KEY_PASSWORD = "TEST_JAMFPRO_PASSWORD" +) + +func Test_BuildWithOAuth(t *testing.T) { + type args struct { + jamfProFQDN string + Sugar *zap.SugaredLogger + bufferPeriod time.Duration + clientId string + clientSecret string + hideSensitiveData bool + executor httpclient.HTTPExecutor + } + tests := []struct { + name string + args args + want *jamfprointegration.Integration + wantErr bool + }{ + { + name: "All vars set correctly", + args: args{ + jamfProFQDN: os.Getenv(ENV_KEY_JAMFPRO_FQDN), + clientId: os.Getenv(ENV_KEY_CLIENT_ID), + clientSecret: os.Getenv(ENV_KEY_CLIENT_SECRET), + bufferPeriod: 10 * time.Second, + hideSensitiveData: true, + executor: &httpclient.ProdExecutor{Client: &http.Client{}}, + Sugar: newSugaredDevelopmentLogger(), + }, + wantErr: false, + }, + { + name: "buffer period too long", + args: args{ + jamfProFQDN: os.Getenv(ENV_KEY_JAMFPRO_FQDN), + clientId: os.Getenv(ENV_KEY_CLIENT_ID), + clientSecret: os.Getenv(ENV_KEY_CLIENT_SECRET), + bufferPeriod: 10 * time.Minute, + hideSensitiveData: true, + executor: &httpclient.ProdExecutor{Client: &http.Client{}}, + Sugar: newSugaredDevelopmentLogger(), + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := jamfprointegration.BuildWithOAuth(tt.args.jamfProFQDN, tt.args.Sugar, tt.args.bufferPeriod, tt.args.clientId, tt.args.clientSecret, tt.args.hideSensitiveData, tt.args.executor) + if (err != nil) != tt.wantErr { + t.Errorf("BuildWithOAuth() error = %v, wantErr %v", err, tt.wantErr) + return + } + // if !reflect.DeepEqual(got, tt.want) { + // t.Errorf("BuildWithOAuth() = %v, want %v", got, tt.want) + // } + }) + } +} From 40e3dfb976235777a917d359d199626eb0e75cf1 Mon Sep 17 00:00:00 2001 From: Joseph Little Date: Tue, 30 Jul 2024 14:17:46 +0100 Subject: [PATCH 2/5] integration testing complete for builders --- jamf/jamfprointegration/test/init_test.go | 116 +++++++++++++++++++++- 1 file changed, 112 insertions(+), 4 deletions(-) diff --git a/jamf/jamfprointegration/test/init_test.go b/jamf/jamfprointegration/test/init_test.go index 8cc7c84..9b54e04 100644 --- a/jamf/jamfprointegration/test/init_test.go +++ b/jamf/jamfprointegration/test/init_test.go @@ -11,6 +11,9 @@ import ( "go.uber.org/zap" ) +// API integration has a settable expiry period and is set to 60s +// Account tokens do not have this. I think the expiry is an hour. + const ( ENV_KEY_JAMFPRO_FQDN = "TEST_JAMFPRO_FQDN" ENV_KEY_CLIENT_ID = "TEST_JAMFPRO_CLIENT_ID" @@ -36,7 +39,7 @@ func Test_BuildWithOAuth(t *testing.T) { wantErr bool }{ { - name: "All vars set correctly", + name: "all vars set correctly", args: args{ jamfProFQDN: os.Getenv(ENV_KEY_JAMFPRO_FQDN), clientId: os.Getenv(ENV_KEY_CLIENT_ID), @@ -61,6 +64,32 @@ func Test_BuildWithOAuth(t *testing.T) { }, wantErr: true, }, + { + name: "no client id", + args: args{ + jamfProFQDN: os.Getenv(ENV_KEY_JAMFPRO_FQDN), + clientId: "", + clientSecret: os.Getenv(ENV_KEY_CLIENT_SECRET), + bufferPeriod: 10 * time.Minute, + hideSensitiveData: true, + executor: &httpclient.ProdExecutor{Client: &http.Client{}}, + Sugar: newSugaredDevelopmentLogger(), + }, + wantErr: true, + }, + { + name: "no client secret", + args: args{ + jamfProFQDN: os.Getenv(ENV_KEY_JAMFPRO_FQDN), + clientId: os.Getenv(ENV_KEY_CLIENT_ID), + clientSecret: "", + bufferPeriod: 10 * time.Minute, + hideSensitiveData: true, + executor: &httpclient.ProdExecutor{Client: &http.Client{}}, + Sugar: newSugaredDevelopmentLogger(), + }, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -69,9 +98,88 @@ func Test_BuildWithOAuth(t *testing.T) { t.Errorf("BuildWithOAuth() error = %v, wantErr %v", err, tt.wantErr) return } - // if !reflect.DeepEqual(got, tt.want) { - // t.Errorf("BuildWithOAuth() = %v, want %v", got, tt.want) - // } + // Only testing for error as cannot predict pointers inside Integration output. Error is enough to deem success. + }) + } +} + +func TestBuildWithBasicAuth(t *testing.T) { + type args struct { + jamfProFQDN string + Sugar *zap.SugaredLogger + bufferPeriod time.Duration + username string + password string + hideSensitiveData bool + executor httpclient.HTTPExecutor + } + tests := []struct { + name string + args args + want *jamfprointegration.Integration + wantErr bool + }{ + { + name: "all vars set correctly", + args: args{ + jamfProFQDN: os.Getenv(ENV_KEY_JAMFPRO_FQDN), + username: os.Getenv(ENV_KEY_USERNAME), + password: os.Getenv(ENV_KEY_PASSWORD), + bufferPeriod: 10 * time.Second, + hideSensitiveData: true, + executor: &httpclient.ProdExecutor{Client: &http.Client{}}, + Sugar: newSugaredDevelopmentLogger(), + }, + wantErr: false, + }, + { + name: "buffer period too long", + args: args{ + jamfProFQDN: os.Getenv(ENV_KEY_JAMFPRO_FQDN), + username: os.Getenv(ENV_KEY_USERNAME), + password: os.Getenv(ENV_KEY_PASSWORD), + bufferPeriod: 100 * time.Minute, + hideSensitiveData: true, + executor: &httpclient.ProdExecutor{Client: &http.Client{}}, + Sugar: newSugaredDevelopmentLogger(), + }, + wantErr: true, + }, + { + name: "no username", + args: args{ + jamfProFQDN: os.Getenv(ENV_KEY_JAMFPRO_FQDN), + username: "", + password: os.Getenv(ENV_KEY_PASSWORD), + bufferPeriod: 100 * time.Minute, + hideSensitiveData: true, + executor: &httpclient.ProdExecutor{Client: &http.Client{}}, + Sugar: newSugaredDevelopmentLogger(), + }, + wantErr: true, + }, + { + name: "no password", + args: args{ + jamfProFQDN: os.Getenv(ENV_KEY_JAMFPRO_FQDN), + username: os.Getenv(ENV_KEY_USERNAME), + password: "", + bufferPeriod: 100 * time.Minute, + hideSensitiveData: true, + executor: &httpclient.ProdExecutor{Client: &http.Client{}}, + Sugar: newSugaredDevelopmentLogger(), + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + _, err := jamfprointegration.BuildWithBasicAuth(tt.args.jamfProFQDN, tt.args.Sugar, tt.args.bufferPeriod, tt.args.username, tt.args.password, tt.args.hideSensitiveData, tt.args.executor) + if (err != nil) != tt.wantErr { + t.Errorf("BuildWithBasicAuth() error = %v, wantErr %v", err, tt.wantErr) + return + } + // Only testing for error as cannot predict pointers inside Integration output. Error is enough to deem success. }) } } From 5ae4e7dc73a1125c44462f7b30c5fac447c16e3f Mon Sep 17 00:00:00 2001 From: Joseph Little Date: Tue, 30 Jul 2024 14:36:57 +0100 Subject: [PATCH 3/5] more integration tests added --- jamf/jamfprointegration/test/helpers.go | 38 ++++++++++++++++++- jamf/jamfprointegration/test/init_test.go | 26 +++++-------- .../test/loadbalancer_test.go | 38 +++++++++++++++++++ 3 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 jamf/jamfprointegration/test/loadbalancer_test.go diff --git a/jamf/jamfprointegration/test/helpers.go b/jamf/jamfprointegration/test/helpers.go index 635c643..d98947f 100644 --- a/jamf/jamfprointegration/test/helpers.go +++ b/jamf/jamfprointegration/test/helpers.go @@ -1,8 +1,42 @@ package test -import "go.uber.org/zap" +import ( + "net/http" + "os" + "time" -func newSugaredDevelopmentLogger() *zap.SugaredLogger { + "github.com/deploymenttheory/go-api-http-client-integrations/jamf/jamfprointegration" + "github.com/deploymenttheory/go-api-http-client/httpclient" + "go.uber.org/zap" +) + +const ( + ENV_KEY_JAMFPRO_FQDN = "TEST_JAMFPRO_FQDN" + ENV_KEY_CLIENT_ID = "TEST_JAMFPRO_CLIENT_ID" + ENV_KEY_CLIENT_SECRET = "TEST_JAMFPRO_CLIENT_SECRET" + ENV_KEY_USERNAME = "TEST_JAMFPRO_USERNAME" + ENV_KEY_PASSWORD = "TEST_JAMFPRO_PASSWORD" +) + +func NewSugaredDevelopmentLogger() *zap.SugaredLogger { logger, _ := zap.NewDevelopment() return logger.Sugar() } + +func NewIntegrationFromEnv() *jamfprointegration.Integration { + integration, err := jamfprointegration.BuildWithOAuth( + os.Getenv(ENV_KEY_JAMFPRO_FQDN), + NewSugaredDevelopmentLogger(), + 10*time.Second, + os.Getenv(ENV_KEY_CLIENT_ID), + os.Getenv(ENV_KEY_CLIENT_SECRET), + false, + &httpclient.ProdExecutor{Client: &http.Client{}}, + ) + + if err != nil { + panic("we have a problem") + } + + return integration +} diff --git a/jamf/jamfprointegration/test/init_test.go b/jamf/jamfprointegration/test/init_test.go index 9b54e04..3066d08 100644 --- a/jamf/jamfprointegration/test/init_test.go +++ b/jamf/jamfprointegration/test/init_test.go @@ -14,15 +14,8 @@ import ( // API integration has a settable expiry period and is set to 60s // Account tokens do not have this. I think the expiry is an hour. -const ( - ENV_KEY_JAMFPRO_FQDN = "TEST_JAMFPRO_FQDN" - ENV_KEY_CLIENT_ID = "TEST_JAMFPRO_CLIENT_ID" - ENV_KEY_CLIENT_SECRET = "TEST_JAMFPRO_CLIENT_SECRET" - ENV_KEY_USERNAME = "TEST_JAMFPRO_USERNAME" - ENV_KEY_PASSWORD = "TEST_JAMFPRO_PASSWORD" -) - func Test_BuildWithOAuth(t *testing.T) { + logger := NewSugaredDevelopmentLogger() type args struct { jamfProFQDN string Sugar *zap.SugaredLogger @@ -47,7 +40,7 @@ func Test_BuildWithOAuth(t *testing.T) { bufferPeriod: 10 * time.Second, hideSensitiveData: true, executor: &httpclient.ProdExecutor{Client: &http.Client{}}, - Sugar: newSugaredDevelopmentLogger(), + Sugar: logger, }, wantErr: false, }, @@ -60,7 +53,7 @@ func Test_BuildWithOAuth(t *testing.T) { bufferPeriod: 10 * time.Minute, hideSensitiveData: true, executor: &httpclient.ProdExecutor{Client: &http.Client{}}, - Sugar: newSugaredDevelopmentLogger(), + Sugar: logger, }, wantErr: true, }, @@ -73,7 +66,7 @@ func Test_BuildWithOAuth(t *testing.T) { bufferPeriod: 10 * time.Minute, hideSensitiveData: true, executor: &httpclient.ProdExecutor{Client: &http.Client{}}, - Sugar: newSugaredDevelopmentLogger(), + Sugar: logger, }, wantErr: true, }, @@ -86,7 +79,7 @@ func Test_BuildWithOAuth(t *testing.T) { bufferPeriod: 10 * time.Minute, hideSensitiveData: true, executor: &httpclient.ProdExecutor{Client: &http.Client{}}, - Sugar: newSugaredDevelopmentLogger(), + Sugar: logger, }, wantErr: true, }, @@ -104,6 +97,7 @@ func Test_BuildWithOAuth(t *testing.T) { } func TestBuildWithBasicAuth(t *testing.T) { + logger := NewSugaredDevelopmentLogger() type args struct { jamfProFQDN string Sugar *zap.SugaredLogger @@ -128,7 +122,7 @@ func TestBuildWithBasicAuth(t *testing.T) { bufferPeriod: 10 * time.Second, hideSensitiveData: true, executor: &httpclient.ProdExecutor{Client: &http.Client{}}, - Sugar: newSugaredDevelopmentLogger(), + Sugar: logger, }, wantErr: false, }, @@ -141,7 +135,7 @@ func TestBuildWithBasicAuth(t *testing.T) { bufferPeriod: 100 * time.Minute, hideSensitiveData: true, executor: &httpclient.ProdExecutor{Client: &http.Client{}}, - Sugar: newSugaredDevelopmentLogger(), + Sugar: logger, }, wantErr: true, }, @@ -154,7 +148,7 @@ func TestBuildWithBasicAuth(t *testing.T) { bufferPeriod: 100 * time.Minute, hideSensitiveData: true, executor: &httpclient.ProdExecutor{Client: &http.Client{}}, - Sugar: newSugaredDevelopmentLogger(), + Sugar: logger, }, wantErr: true, }, @@ -167,7 +161,7 @@ func TestBuildWithBasicAuth(t *testing.T) { bufferPeriod: 100 * time.Minute, hideSensitiveData: true, executor: &httpclient.ProdExecutor{Client: &http.Client{}}, - Sugar: newSugaredDevelopmentLogger(), + Sugar: logger, }, wantErr: true, }, diff --git a/jamf/jamfprointegration/test/loadbalancer_test.go b/jamf/jamfprointegration/test/loadbalancer_test.go new file mode 100644 index 0000000..ead9a5c --- /dev/null +++ b/jamf/jamfprointegration/test/loadbalancer_test.go @@ -0,0 +1,38 @@ +package test + +import ( + "net/http" + "testing" + + "github.com/deploymenttheory/go-api-http-client-integrations/jamf/jamfprointegration" +) + +func TestIntegration_getSessionCookies(t *testing.T) { + type fields struct { + Integration *jamfprointegration.Integration + } + tests := []struct { + name string + fields fields + want []*http.Cookie + wantErr bool + }{ + { + name: "get session cookies ok", + fields: fields{ + Integration: NewIntegrationFromEnv(), + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + j := tt.fields.Integration + _, err := j.GetSessionCookies() + if (err != nil) != tt.wantErr { + t.Errorf("Integration.getSessionCookies() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} From d06850db8e5e4a270a780372dd5268d80a83d3f4 Mon Sep 17 00:00:00 2001 From: Joseph Little Date: Tue, 30 Jul 2024 16:24:03 +0100 Subject: [PATCH 4/5] tidying --- jamf/jamfprointegration/test/{init_test.go => builders_test.go} | 0 .../test/{loadbalancer_test.go => main_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename jamf/jamfprointegration/test/{init_test.go => builders_test.go} (100%) rename jamf/jamfprointegration/test/{loadbalancer_test.go => main_test.go} (100%) diff --git a/jamf/jamfprointegration/test/init_test.go b/jamf/jamfprointegration/test/builders_test.go similarity index 100% rename from jamf/jamfprointegration/test/init_test.go rename to jamf/jamfprointegration/test/builders_test.go diff --git a/jamf/jamfprointegration/test/loadbalancer_test.go b/jamf/jamfprointegration/test/main_test.go similarity index 100% rename from jamf/jamfprointegration/test/loadbalancer_test.go rename to jamf/jamfprointegration/test/main_test.go From 8562b52fe5a98aee90da6107a31094c42ad21c26 Mon Sep 17 00:00:00 2001 From: Joseph Little Date: Wed, 31 Jul 2024 09:46:19 +0100 Subject: [PATCH 5/5] file renamed --- jamf/jamfprointegration/test/{main_test.go => cookies_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename jamf/jamfprointegration/test/{main_test.go => cookies_test.go} (100%) diff --git a/jamf/jamfprointegration/test/main_test.go b/jamf/jamfprointegration/test/cookies_test.go similarity index 100% rename from jamf/jamfprointegration/test/main_test.go rename to jamf/jamfprointegration/test/cookies_test.go