github.com/Axway/agent-sdk@v1.1.101/pkg/apic/specoas2processor.go (about)

     1  package apic
     2  
     3  import (
     4  	"encoding/json"
     5  	"net"
     6  	"sort"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/Axway/agent-sdk/pkg/util"
    11  	coreerrors "github.com/Axway/agent-sdk/pkg/util/errors"
    12  	"github.com/getkin/kin-openapi/openapi2"
    13  )
    14  
    15  var validOA2Schemes = map[string]bool{"http": true, "https": true, "ws": true, "wss": true}
    16  
    17  const (
    18  	oasSecurityAPIKey = "apiKey"
    19  	oasSecurityOauth  = "oauth2"
    20  	oasSecurityBasic  = "basic"
    21  	oasSecurityHttp   = "http"
    22  )
    23  
    24  // oas2SpecProcessor parses and validates an OAS2 spec, and exposes methods to modify the content of the spec.
    25  type oas2SpecProcessor struct {
    26  	spec         *openapi2.T
    27  	scopes       map[string]string
    28  	authPolicies []string
    29  	apiKeyInfo   []APIKeyInfo
    30  }
    31  
    32  func newOas2Processor(oas2Spec *openapi2.T) *oas2SpecProcessor {
    33  	return &oas2SpecProcessor{spec: oas2Spec}
    34  }
    35  
    36  func (p *oas2SpecProcessor) GetResourceType() string {
    37  	return Oas2
    38  }
    39  
    40  // GetVersion -
    41  func (p *oas2SpecProcessor) GetVersion() string {
    42  	return p.spec.Info.Version
    43  }
    44  
    45  // GetEndpoints -
    46  func (p *oas2SpecProcessor) GetEndpoints() ([]EndpointDefinition, error) {
    47  	endPoints := []EndpointDefinition{}
    48  	swaggerHostElements := strings.Split(p.spec.Host, ":")
    49  	host := swaggerHostElements[0]
    50  	port := 0
    51  	if len(swaggerHostElements) > 1 {
    52  		swaggerPort, err := strconv.Atoi(swaggerHostElements[1])
    53  		if err == nil {
    54  			port = swaggerPort
    55  		}
    56  	}
    57  
    58  	if host == "" {
    59  		return nil, coreerrors.Wrap(ErrSetSpecEndPoints, "no host defined in the specification")
    60  	}
    61  
    62  	// If schemes are specified create endpoint for each scheme
    63  	if len(p.spec.Schemes) > 0 {
    64  		for _, protocol := range p.spec.Schemes {
    65  			if !validOA2Schemes[protocol] {
    66  				return nil, coreerrors.Wrap(ErrSetSpecEndPoints, "invalid endpoint scheme defined in specification")
    67  			}
    68  			endPoint := createEndpointDefinition(protocol, host, port, p.spec.BasePath)
    69  			endPoints = append(endPoints, endPoint)
    70  		}
    71  	}
    72  
    73  	// If no schemes are specified create endpoint with default scheme
    74  	if len(endPoints) == 0 {
    75  		endPoint := createEndpointDefinition("https", host, port, p.spec.BasePath)
    76  		endPoints = append(endPoints, endPoint)
    77  	}
    78  	return endPoints, nil
    79  }
    80  
    81  func (p *oas2SpecProcessor) ParseAuthInfo() {
    82  	authPolicies := []string{}
    83  	keyInfo := []APIKeyInfo{}
    84  	scopes := make(map[string]string)
    85  	for _, scheme := range p.spec.SecurityDefinitions {
    86  		switch scheme.Type {
    87  		case oasSecurityBasic:
    88  			authPolicies = append(authPolicies, Basic)
    89  		case oasSecurityAPIKey:
    90  			authPolicies = append(authPolicies, Apikey)
    91  			keyInfo = append(keyInfo, APIKeyInfo{
    92  				Location: scheme.In,
    93  				Name:     scheme.Name,
    94  			})
    95  		case oasSecurityOauth:
    96  			authPolicies = append(authPolicies, Oauth)
    97  			for scope, val := range scheme.Scopes {
    98  				scopes[strings.TrimSpace(scope)] = strings.TrimSpace(val)
    99  			}
   100  		}
   101  	}
   102  	p.authPolicies = util.RemoveDuplicateValuesFromStringSlice(authPolicies)
   103  	sort.Strings(p.authPolicies)
   104  	p.apiKeyInfo = keyInfo
   105  	p.scopes = scopes
   106  }
   107  
   108  func (p *oas2SpecProcessor) GetAuthPolicies() []string {
   109  	return p.authPolicies
   110  }
   111  
   112  func (p *oas2SpecProcessor) GetOAuthScopes() map[string]string {
   113  	return p.scopes
   114  }
   115  
   116  func (p *oas2SpecProcessor) GetAPIKeyInfo() []APIKeyInfo {
   117  	return p.apiKeyInfo
   118  }
   119  
   120  func (p *oas2SpecProcessor) GetTitle() string {
   121  	return p.spec.Info.Title
   122  }
   123  
   124  func (p *oas2SpecProcessor) GetDescription() string {
   125  	return p.spec.Info.Description
   126  }
   127  
   128  func (p *oas2SpecProcessor) StripSpecAuth() {
   129  	p.spec.SecurityDefinitions = map[string]*openapi2.SecurityScheme{}
   130  	p.spec.Security = make(openapi2.SecurityRequirements, 0)
   131  }
   132  
   133  func (p *oas2SpecProcessor) GetSecurityBuilder() SecurityBuilder {
   134  	return newSpecSecurityBuilder(oas2)
   135  }
   136  func (p *oas2SpecProcessor) AddSecuritySchemes(authSchemes map[string]interface{}) {
   137  	// order authSchemas by name
   138  	for _, name := range util.OrderedKeys(authSchemes) {
   139  		scheme := authSchemes[name]
   140  		p.spec.SecurityDefinitions[name], _ = scheme.(*openapi2.SecurityScheme)
   141  
   142  		// get scopes in array
   143  		scopes := []string{}
   144  		for s := range p.spec.SecurityDefinitions[name].Scopes {
   145  			scopes = append(scopes, s)
   146  		}
   147  
   148  		// order the scopes
   149  		sort.Strings(scopes)
   150  
   151  		// add security to spec
   152  		p.spec.Security = append(p.spec.Security, map[string][]string{
   153  			name: scopes,
   154  		})
   155  	}
   156  }
   157  
   158  func (p *oas2SpecProcessor) GetSpecBytes() []byte {
   159  	s, _ := json.Marshal(p.spec)
   160  	return s
   161  }
   162  
   163  func createEndpointDefinition(scheme, host string, port int, basePath string) EndpointDefinition {
   164  	path := "/"
   165  	if basePath != "" {
   166  		path = basePath
   167  	}
   168  	// If a port is not given, use lookup the default
   169  	if port == 0 {
   170  		port, _ = net.LookupPort("tcp", scheme)
   171  	}
   172  	return EndpointDefinition{
   173  		Host:     host,
   174  		Port:     int32(port),
   175  		Protocol: scheme,
   176  		BasePath: path,
   177  	}
   178  }