Skip to content

Commit

Permalink
APIGOV-23815 - add basic auth support in sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
jcollins-axway committed Oct 19, 2022
1 parent d491532 commit bafab32
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 28 deletions.
9 changes: 4 additions & 5 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,10 @@ type agentData struct {
proxyResourceHandler *handler.StreamWatchProxyHandler
isInitialized bool

instanceValidatorJobID string
provisioner provisioning.Provisioning
marketplaceMigration migrate.Migrator
streamer *stream.StreamerClient
authProviderRegistry oauth.ProviderRegistry
provisioner provisioning.Provisioning
marketplaceMigration migrate.Migrator
streamer *stream.StreamerClient
authProviderRegistry oauth.ProviderRegistry

// profiling
profileDone chan struct{}
Expand Down
34 changes: 32 additions & 2 deletions pkg/agent/provisioning.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package agent

import (
"github.com/Axway/agent-sdk/pkg/agent/handler"
apiv1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1"
v1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1"
management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1"
"github.com/Axway/agent-sdk/pkg/apic/definitions"
Expand Down Expand Up @@ -45,7 +44,7 @@ func createOrUpdateDefinition(data v1.Interface, marketplaceMigration migrate.Mi

func runMarketplaceMigration(ri *v1.ResourceInstance, marketplaceMigration migrate.Migrator) bool {
// check if the KIND and ID combo have an item in the cache
var existingRI *apiv1.ResourceInstance
var existingRI *v1.ResourceInstance

switch ri.Kind {
case management.AccessRequestDefinitionGVK().Kind:
Expand Down Expand Up @@ -385,6 +384,32 @@ func NewAPIKeyCredentialRequestBuilder(options ...func(*crdBuilderOptions)) prov
return NewCredentialRequestBuilder(apiKeyOptions...)
}

// NewBasicAuthCredentialRequestBuilder - add basic auth base properties for provisioning schema
func NewBasicAuthCredentialRequestBuilder(options ...func(*crdBuilderOptions)) provisioning.CredentialRequestBuilder {
apiKeyOptions := []func(*crdBuilderOptions){
WithCRDName(provisioning.BasicAuthCRD),
WithCRDTitle("Basic Auth"),
WithCRDProvisionSchemaProperty(
provisioning.NewSchemaPropertyBuilder().
SetName(provisioning.BasicAuthUsername).
SetLabel("Username").
SetRequired().
IsString().
IsEncrypted()),
WithCRDProvisionSchemaProperty(
provisioning.NewSchemaPropertyBuilder().
SetName(provisioning.BasicAuthPassword).
SetLabel("Password").
SetRequired().
IsString().
IsEncrypted()),
}

apiKeyOptions = append(apiKeyOptions, options...)

return NewCredentialRequestBuilder(apiKeyOptions...)
}

// NewOAuthCredentialRequestBuilder - add oauth base properties for provisioning schema
func NewOAuthCredentialRequestBuilder(options ...func(*crdBuilderOptions)) provisioning.CredentialRequestBuilder {
oauthOptions := []func(*crdBuilderOptions){
Expand Down Expand Up @@ -419,6 +444,11 @@ func NewAccessRequestBuilder() provisioning.AccessRequestBuilder {
return provisioning.NewAccessRequestBuilder(createOrUpdateAccessRequestDefinition)
}

// NewBasicAuthAccessRequestBuilder - called by the agents
func NewBasicAuthAccessRequestBuilder() provisioning.AccessRequestBuilder {
return NewAccessRequestBuilder().SetName(provisioning.BasicAuthARD)
}

// NewAPIKeyAccessRequestBuilder - called by the agents
func NewAPIKeyAccessRequestBuilder() provisioning.AccessRequestBuilder {
return NewAccessRequestBuilder().SetName(provisioning.APIKeyARD)
Expand Down
6 changes: 6 additions & 0 deletions pkg/agent/provisioning_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ func TestNewCredentialRequestBuilder(t *testing.T) {
name string
expectedName string
}{
{
name: "Test Basic Auth Helper",
expectedName: "http-basic",
},
{
name: "Test APIKey Helper",
expectedName: "api-key",
Expand All @@ -57,6 +61,8 @@ func TestNewCredentialRequestBuilder(t *testing.T) {
var err error
var crd *management.CredentialRequestDefinition
switch test.expectedName {
case "http-basic":
crd, err = NewBasicAuthCredentialRequestBuilder().Register()
case "api-key":
crd, err = NewAPIKeyCredentialRequestBuilder().Register()
case "oauth":
Expand Down
3 changes: 2 additions & 1 deletion pkg/apic/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
Apikey = "verify-api-key"
Passthrough = "pass-through"
Oauth = "verify-oauth-token"
Basic = "http-basic"
)

// other consts
Expand All @@ -38,7 +39,7 @@ const (
)

// ValidPolicies - list of valid auth policies supported by Central. Add to this list as more policies are supported.
var ValidPolicies = []string{Apikey, Passthrough, Oauth}
var ValidPolicies = []string{Apikey, Passthrough, Oauth, Basic}

// SubscriptionProcessor - callback method type to process subscriptions
type SubscriptionProcessor func(subscription Subscription)
Expand Down
18 changes: 14 additions & 4 deletions pkg/apic/provisioning/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ package provisioning
import "time"

const (
apiKey = "api-key"
oauth = "oauth"
other = "other"
oauth = "oauth"
other = "other"
)

// Credential - holds the details about the credential to send to encrypt and send to platform
Expand Down Expand Up @@ -35,6 +34,7 @@ type CredentialBuilder interface {
SetOAuthID(id string) Credential
SetOAuthIDAndSecret(id, secret string) Credential
SetAPIKey(key string) Credential
SetHTTPBasic(username, password string) Credential
SetCredential(data map[string]interface{}) Credential
}

Expand Down Expand Up @@ -70,13 +70,23 @@ func (c *credentialBuilder) SetOAuthIDAndSecret(id, secret string) Credential {

// SetAPIKey - set the credential as an API Key type
func (c *credentialBuilder) SetAPIKey(key string) Credential {
c.credential.credentialType = apiKey
c.credential.credentialType = APIKeyCRD
c.credential.data = map[string]interface{}{
APIKey: key,
}
return c.credential
}

// SetHTTPBasic - set the credential as an API Key type
func (c *credentialBuilder) SetHTTPBasic(username, password string) Credential {
c.credential.credentialType = BasicAuthCRD
c.credential.data = map[string]interface{}{
BasicAuthUsername: username,
BasicAuthPassword: password,
}
return c.credential
}

// SetExpirationTime - set the credential expiration time
func (c *credentialBuilder) SetExpirationTime(expTime time.Time) CredentialBuilder {
c.credential.expTime = expTime
Expand Down
19 changes: 14 additions & 5 deletions pkg/apic/provisioning/credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,19 @@ import (

func TestCredentialBuilder(t *testing.T) {
tests := []struct {
name string
key string
id string
secret string
other map[string]interface{}
name string
username string
password string
key string
id string
secret string
other map[string]interface{}
}{
{
name: "Build Basic Auth Credential",
username: "basic-user",
password: "basic-pass",
},
{
name: "Build API Key Credential",
key: "api-key-data",
Expand Down Expand Up @@ -44,6 +51,8 @@ func TestCredentialBuilder(t *testing.T) {
switch {
case tt.key != "":
cred = builder.SetAPIKey(tt.key)
case tt.username != "":
cred = builder.SetHTTPBasic(tt.username, tt.password)
case tt.id != "" && tt.secret != "":
cred = builder.SetOAuthIDAndSecret(tt.key, tt.secret)
case tt.id != "":
Expand Down
5 changes: 5 additions & 0 deletions pkg/apic/provisioning/definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package provisioning
// default names of ARD and CRDs
const (
APIKeyARD = "api-key"
BasicAuthARD = "http-basic"
APIKeyCRD = "api-key"
BasicAuthCRD = "http-basic"
OAuthSecretCRD = "oauth-secret"
OAuthPublicKeyCRD = "oauth-public-key"
OAuthIDPCRD = "oauth-idp"
Expand All @@ -22,6 +24,9 @@ const (

APIKey = "apiKey"

BasicAuthUsername = "username"
BasicAuthPassword = "password"

CredExpDetail = "Agent: CredentialExpired"
)

Expand Down
7 changes: 5 additions & 2 deletions pkg/apic/servicebody.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ type ServiceBody struct {
accessRequestDefinition *management.AccessRequestDefinition
}

//SetAccessRequestDefinitionName - set the name of the access request definition for this service body
// SetAccessRequestDefinitionName - set the name of the access request definition for this service body
func (s *ServiceBody) SetAccessRequestDefinitionName(ardName string, isUnique bool) {
s.ardName = ardName
s.uniqueARD = isUnique
Expand All @@ -73,7 +73,7 @@ func (s *ServiceBody) GetAPIKeyInfo() []APIKeyInfo {
return s.apiKeyInfo
}

//GetScopes - returns the array of scopes for this service instance
// GetScopes - returns the array of scopes for this service instance
func (s *ServiceBody) GetScopes() map[string]string {
return s.scopes
}
Expand All @@ -84,6 +84,9 @@ func (s *ServiceBody) GetCredentialRequestDefinitions() []string {
return s.credentialRequestPolicies
}
for _, policy := range s.authPolicies {
if policy == Basic {
s.credentialRequestPolicies = append(s.credentialRequestPolicies, provisioning.BasicAuthCRD)
}
if policy == Apikey {
s.credentialRequestPolicies = append(s.credentialRequestPolicies, provisioning.APIKeyCRD)
}
Expand Down
26 changes: 17 additions & 9 deletions pkg/apic/servicebuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package apic
import (
"fmt"

"github.com/Axway/agent-sdk/pkg/apic/provisioning"
"github.com/Axway/agent-sdk/pkg/config"
)

Expand Down Expand Up @@ -311,16 +312,23 @@ func (b *serviceBodyBuilder) Build() (ServiceBody, error) {
// get oauth scopes
b.serviceBody.scopes = val.GetOAuthScopes()

// only set ard name based on spec if not already set
if b.serviceBody.ardName == "" {
if len(b.serviceBody.apiKeyInfo) > 0 {
b.serviceBody.ardName = "api-key"
}
// if the spec has multiple then use the oauth ard
err := b.serviceBody.createAccessRequestDefinition()
if err != nil {
return b.serviceBody, err
}

// if the spec has api key and oauth use the oauth ard
err := b.serviceBody.createAccessRequestDefinition()
if err != nil {
return b.serviceBody, err
// only set ard name based on spec if not already set, use first auth we find
if b.serviceBody.ardName == "" {
for _, p := range b.serviceBody.authPolicies {
if p == Basic {
b.serviceBody.ardName = provisioning.BasicAuthARD
break
}
if p == Apikey {
b.serviceBody.ardName = provisioning.APIKeyARD
break
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/apic/specoas2processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ var validOA2Schemes = map[string]bool{"http": true, "https": true, "ws": true, "
const (
oasSecurityAPIKey = "apiKey"
oasSecurityOauth = "oauth2"
oasSecurityBasic = "basic"
oasSecurityHttp = "http"
)

// oas2SpecProcessor parses and validates an OAS2 spec, and exposes methods to modify the content of the spec.
Expand Down Expand Up @@ -75,6 +77,8 @@ func (p *oas2SpecProcessor) ParseAuthInfo() {
scopes := make(map[string]string)
for _, scheme := range p.spec.SecurityDefinitions {
switch scheme.Type {
case oasSecurityBasic:
authPolicies = append(authPolicies, Basic)
case oasSecurityAPIKey:
authPolicies = append(authPolicies, Apikey)
keyInfo = append(keyInfo, APIKeyInfo{
Expand Down
4 changes: 4 additions & 0 deletions pkg/apic/specoas3processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ func (p *oas3SpecProcessor) ParseAuthInfo() {
scopes := make(map[string]string)
for _, scheme := range p.spec.Components.SecuritySchemes {
switch scheme.Value.Type {
case oasSecurityHttp:
if scheme.Value.Scheme == oasSecurityBasic {
authPolicies = append(authPolicies, Basic)
}
case oasSecurityAPIKey:
authPolicies = append(authPolicies, Apikey)
keyInfo = append(keyInfo, APIKeyInfo{
Expand Down

0 comments on commit bafab32

Please sign in to comment.