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/builders_test.go b/jamf/jamfprointegration/test/builders_test.go new file mode 100644 index 0000000..3066d08 --- /dev/null +++ b/jamf/jamfprointegration/test/builders_test.go @@ -0,0 +1,179 @@ +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" +) + +// 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. + +func Test_BuildWithOAuth(t *testing.T) { + logger := NewSugaredDevelopmentLogger() + 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: logger, + }, + 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: logger, + }, + 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: logger, + }, + 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: logger, + }, + 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 + } + // Only testing for error as cannot predict pointers inside Integration output. Error is enough to deem success. + }) + } +} + +func TestBuildWithBasicAuth(t *testing.T) { + logger := NewSugaredDevelopmentLogger() + 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: logger, + }, + 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: logger, + }, + 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: logger, + }, + 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: logger, + }, + 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. + }) + } +} diff --git a/jamf/jamfprointegration/test/cookies_test.go b/jamf/jamfprointegration/test/cookies_test.go new file mode 100644 index 0000000..ead9a5c --- /dev/null +++ b/jamf/jamfprointegration/test/cookies_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 + } + }) + } +} diff --git a/jamf/jamfprointegration/test/helpers.go b/jamf/jamfprointegration/test/helpers.go new file mode 100644 index 0000000..d98947f --- /dev/null +++ b/jamf/jamfprointegration/test/helpers.go @@ -0,0 +1,42 @@ +package test + +import ( + "net/http" + "os" + "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 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 +}